Commit Graph
848 Commits
Author SHA1 Message Date
Kris ColemanandClaude Opus 4.7 2192aecf40 fix(analyze/secret): guard nil deref when spec omits fail: outcome (#2053) (#2054)
* fix(analyze/secret): guard nil deref when spec omits fail: outcome (#2053)

When a Preflight spec defines only warn: and/or pass: outcomes and the
target Secret is missing, analyzeSecret dereferenced a nil failOutcome and
panicked. Reproduction from replicatedhq/troubleshoot#2053:

  outcomes:
    - warn:
        when: "notFound"
        message: "secret missing (warn)"
    - pass:
        message: "secret found"

This change:
- Collects fail, warn, and warn-when-notFound outcomes up front.
- Routes a missing secret (or missing key) through a single resolver:
  prefer warn(when=notFound), fall back to fail, then any warn,
  then synthesize a benign warn result. Never panics.
- Adds table-driven tests covering the three new shapes.

Same defect shape as #263 (imagePullSecret). The sibling analyzers
configmap.go and image.go have the same pattern but are out of scope
for this PR.

Refs: replicatedhq/troubleshoot#2053

* refactor(analyze/secret): drop warn handling per analyzer contract

Per review feedback (banjoh): the secret analyzer only supports fail
(not found) and pass (found) outcomes — `warn:` and `when:` are not
part of the analyzer's contract (https://troubleshoot.sh/docs/analyze/secrets).

Drop the warn / notFoundWarn branches added in the previous commit and
collapse the nil-fail fallback onto IsFail with a default message. The
core fix — guarding the nil deref at the previous secret.go:72 — stays
in place.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(analyze/secret): mirror image_pull_secret pattern; return nil when spec has neither outcome

Per banjoh review: collect failOutcome and passOutcome with non-nil
checks; when the spec contains neither, return nil and let the framework
surface the missing-outcome error rather than fabricating a result.

Structure now mirrors pkg/analyze/image_pull_secret.go: default to
IsFail with fail-outcome message (if set), flip to IsPass with
pass-outcome message when the secret/key check succeeds, fill default
messages at the end only when none were configured. Analyze() now
forwards a nil result through cleanly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(analyze/secret): assign outcome messages inside their own branch

Cursor bugbot caught: when the spec defined only a fail outcome and the
secret was found, the result showed IsPass=true with the fail outcome's
message. Pre-assigning the fail message at the top before flipping
IsPass meant the stale message leaked through whenever no pass outcome
was configured.

Move both message assignments into their respective branches so a pass
result never carries a fail message. Default messages still fill in
when no outcome is set on the active branch. Added a regression test
covering fail-only spec + secret found.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(analyze/secret): address Greptile P1s — combined outcome + empty configured messages

Two fixes flagged by review on #2054:

1. Combined pass outcome dropped: the outcome loop used 'else if' for pass, so a
   single outcome object containing both fail and pass silently dropped the pass.
   Capture fail and pass independently.

2. Empty configured messages overwritten: the default-message fallback fired
   whenever result.Message was empty, clobbering a configured outcome that
   intentionally has an empty message (e.g. URI-only). Track whether the matched
   branch had a configured outcome and only fall back to a default when none was
   supplied, preserving the configured message and URI verbatim.

Adds tests: combined fail+pass captured on both found/not-found paths, and
URI-only pass/fail outcomes preserved without default-message overwrite.

* fix(analyze/secret): drop fabricated default messages; error on missing outcome

Per maintainer review: analyzers do not fabricate default messages — an empty
outcome message is intentional (e.g. a URI-only outcome), so remove the default
message fallback and preserve the configured outcome verbatim. When a matched
branch has no configured outcome, the message stays empty.

Also address the missing-outcome case: when a spec defines neither a pass nor a
fail outcome, analyzeSecret returned (nil, nil), which the Analyze wrapper
swallowed into an empty result slice — the user saw neither a result nor a
config error. Return an explicit error so the framework surfaces the
misconfiguration.

Tests updated: the no-fail-outcome and only-fail-outcome cases now assert an
empty message rather than a fabricated one, and the neither-outcome case asserts
an error.

* fix(analyze/secret): default message only when no outcome is configured for the matched branch

Distinguish an absent matching outcome from an intentionally empty configured
message. A configured outcome with an empty message (e.g. a URI-only outcome) is
still preserved verbatim. But when the matched branch has no configured outcome at
all — a pass-only spec that took the fail path, or a fail-only spec that passed —
fall back to a default diagnostic instead of emitting an empty message.

Addresses the greptile P1 (endorsed by banjoh): dropping the default entirely
conflated the two cases and left users with a pass/fail result and no context.
Tests restore the default-message expectations for the no-configured-outcome
branches; URI-only (configured-empty) and neither-outcome (error) cases unchanged.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-08-24 12:16:33 -04:00
Xav PaiceandElasticClaw Factory 0c6fb2177b fix(cluster-resources): stop emitting duplicate unredacted YAML copy (#2117)
* fix(cluster-resources): stop emitting duplicate unredacted YAML copy

storeCustomResource was writing both a JSON and a YAML file for every
custom resource. The built-in redactors are authored for JSON, so the
YAML copy was left unredacted. JSON is valid YAML, so analyzers that
expect YAML can still parse the JSON file.

Also convert the built-in kurl installer redactors from YAML-specific
paths to scoped JSON regex redactors so they continue to apply after the
YAML copy is removed.

* fix(cluster-resources): add YAML symlinks and cover cluster-scoped kurl installer

- Add a .yaml symlink for every custom-resource JSON file so existing
  analyzers that look for the old YAML copy keep working. The symlink
  points at the JSON file, so redaction of the JSON also redacts the YAML
  view.
- Fix the built-in kurl installer redactor to match both the cluster-scoped
  file (installers.cluster.kurl.sh.json) and the namespaced file pattern
  (installers.cluster.kurl.sh/*.json). The previous selector only matched
  the namespaced form.

---------

Co-authored-by: ElasticClaw Factory <factory@replicated.com>
2026-08-21 09:29:20 +12:00
Xav PaiceandElasticClaw Factory 207cb90b53 feat(supportbundle): support secret/... redactor URIs (#2111)
Co-authored-by: ElasticClaw Factory <factory@replicated.com>
2026-08-20 08:40:11 +12:00
Xav Paice 0e2e0cd0ab fix(runpod): strip pod spec before saving collected output (#2105) 2026-08-12 09:13:40 +12:00
Xav Paice b9faedfdb0 fix(preflight): add tracing span and align error handling for host collector redaction (#2102)
* fix(preflight): add tracing span and align error handling for host collector redaction

Follow-up to #2101.

Adds an OpenTelemetry span around host collector redaction and returns the
unredacted collectResult on redaction failure, matching the behavior of
remote host collectors and in-cluster support-bundle collectors.

* fix(preflight): assign collected data before redaction so errors preserve output
2026-08-10 16:17:10 +01:00
3db6a99d3a feat(analyze): add countDistinct() aggregate to nodeResources (#2079)
Add a countDistinct(<labelKey>) aggregate to the nodeResources analyzer
"when" expression language. It counts distinct values of a node label
across the filtered nodes and returns an int the existing comparison
operators evaluate.

Enables the AIR-238 3-AZ preflight: warn when Keeper-eligible nodes do
not span 3 availability zones, e.g.
"countDistinct(topology.kubernetes.io/zone) < 3".

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Xav Paice <xavpaice@users.noreply.github.com>
2026-08-10 12:54:33 +12:00
Benjamin Reed 3c5bf74750 fix(preflight): redact local host preflight collector output (#2101)
CollectHostWithContext was the only collection path (in-cluster support
bundle, remote/SSH host collectors) that never ran collected data through
the redaction engine. A `run` collector's captured environment in
particular can carry credentials verbatim -- e.g. HTTPS_PROXY with
embedded Basic Auth -- straight into the bundle's <collectorName>-info.json
with no redaction applied.

Wire it through collect.RedactResult the same way CollectRemoteWithContext
and pkg/supportbundle/collect.go already do, so the built-in default
redactors apply to local host preflight output too.

Fixes #2100
2026-08-10 12:09:22 +12:00
replicated-software-factory[bot]andElasticClaw Bot 7fa4497b7f chore: update Go dependencies (#2074)
- github.com/longhorn/go-iscsi-helper: replaced by github.com/longhorn/go-common-libs
  and migrated pkg/longhorn/util/iscsi.go to the new namespace executor API
- helm.sh/helm/v3: v3.21.2 -> v3.21.3
- oras.land/oras-go/v2: v2.6.1 -> v2.6.2
- google.golang.org/api: v0.287.1 -> v0.288.0
- golang.org/x/tools: v0.47.0 -> v0.48.0
- github.com/GoogleCloudPlatform/opentelemetry-operations-go/*: v1.33.0/v0.57.0 -> v1.34.0/v0.58.0
- examples/sdk/helm-template: helm.sh/helm/v3 v3.21.2 -> v3.21.3

Fixes required by the update environment:
- Makefile: use $(shell go env GOPATH)/bin for controller-gen/client-gen so
  generate works when the tools are not on PATH
- pkg/collect/host_kernel_configs.go: only use /proc/config.gz when the
  requested kernel release matches the running kernel, making the collector
  robust to hosts that expose a generic /proc/config.gz

Co-authored-by: ElasticClaw Bot <elasticclaw@openclaw.ai>
2026-07-14 13:12:51 +12:00
Kris Coleman 22ab3cf551 feat(redact): make MAX_CONCURRENT_REDACTORS configurable via env var (sc-138321) (#2057)
Replace the hardcoded MAX_CONCURRENT_REDACTORS = 10 ceiling in
pkg/collect/redact.go with a runtime-resolved value driven by the
TROUBLESHOOT_MAX_CONCURRENT_REDACTORS env var. The default (10) is
unchanged, so behavior is identical unless an operator opts in.

- DefaultMaxConcurrentRedactors exported as the default
- MaxConcurrentRedactorsEnvVar exported as the env var name
- maxConcurrentRedactors() helper parses the env, logs on invalid input,
  and falls back to the default on missing/empty/non-numeric/<=0 values
- Table-driven tests in pkg/collect/redact_test.go cover unset, empty,
  positive override, default-equal, zero, negative, non-numeric, and
  whitespace-padded inputs

Unblocks Pixee's standalone support-bundle pipeline, which hits the
10-concurrent ceiling on large bundles.

Refs: sc-138321, replicated-collab/pixee-replicated#131
2026-06-10 16:07:27 -04:00
Gerard NguyenandChuck D'Antonio 61ef1e1036 fix: TLS support in MySQL connector (#2045)
* fix(mysql): respect TLS configuration in MySQL collector

The MySQL collector was ignoring the TLS field in the Database spec,
which caused TLS connections to fail even when properly configured.

This change mirrors the PostgreSQL collector pattern:
- Parse the MySQL DSN using mysql.ParseDSN
- When TLS is configured, create a tls.Config and set cfg.TLS
- Use sql.OpenDB with mysql.NewConnector when TLS is active
- Keep the existing sql.Open path for backward compatibility

Fixes: MySQL preflight fails over TLS connections

* fix(mysql): address review feedback

- Fix gofmt indentation in mysql_test.go
- Remove duplicate DSN parsing in createConnectConfig
- Add CA-cert-only TLS test case

---------

Co-authored-by: Chuck D'Antonio <chuck@replicated.com>
2026-05-22 12:35:15 +10:00
Lennard EijsackersandClaude Opus 4.6 1cd9b6103c feat: Add Clickhouse Support (#1967)
* feat: Add Clickhouse Support

* fix: missing case in GetCollector for ClickHouse

* chore: add analyzer

* fix; Findings

* fix: use go-version for ClickHouse version comparison

ClickHouse returns 4-part version numbers (e.g., 25.3.2.39) which
blang/semver.ParseTolerant cannot handle. Use hashicorp/go-version
(which supports arbitrary version parts) via a ClickHouse-specific
comparison function, matching the approach used by the MSSQL analyzer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* change icon

* chore: Resolve comments

- Change icon value
- Update converter to support ClickHouse
- Update loader to support ClickHouse
- Ensure IsConnected behaviour is similar to other db collectors

* fmt 🤦

* chore: Add Clickhouse case to convertAnalyzerToSpec

* resolve CollectorName comment

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-13 22:57:16 +01:00
Ethan Mosbaugh 4c6af55e7c fix: correct RBAC verb for pods/exec from get to create (#2037)
fix: correct RBAC verb and WebSocket fallback for pods/exec

This commit fixes three related issues that prevented exec collectors from
working with minimal RBAC permissions:

1. RBAC preflight check used wrong verb for pods/exec
   Changed from "get" to "create" in v1beta1 and v1beta2 AccessReviewSpecs.
   The pods/exec subresource requires "create" to execute commands.

2. WebSocket fallback used wrong httpstream package import
   The fallback executor checked IsUpgradeFailure using the apimachinery
   httpstream package, but the roundtripper creates UpgradeFailureError using
   the streaming httpstream package. These are different Go types, so
   errors.As always returned false and fallback to SPDY never triggered.
   Changed import to k8s.io/streaming/pkg/httpstream.

3. Stdin mismatch caused SPDY fallback to hang
   PodExecOptions always set Stdin:true but StreamOptions always passed
   Stdin:nil. When WebSocket failed and fell back to SPDY, the server
   waited for stdin data that never arrived. Changed Stdin to false in
   PodExecOptions for exec, copy, and copy_from_host collectors.
2026-05-01 13:03:42 -07:00
Xav Paice a4ce199005 refactor(collect): replace go.podman.io/image with go-containerregistry (#2034)
* refactor(collect): replace go.podman.io/image with go-containerregistry

Migrate pkg/collect/registry.go off go.podman.io/image/v5 (containers/image)
onto github.com/google/go-containerregistry, eliminating the transitive
github.com/docker/docker +incompatible chain that blocks Docker v29 SDK
adoption.

The RegistryImages collector probes whether each requested image exists in
its registry by issuing a manifest HEAD. We replace alltransports.ParseImageName
+ imageRef.NewImage with name.ParseReference + remote.Head. Auth from a
kubernetes.io/dockerconfigjson Secret is converted to an authn.Authenticator;
error classification switches from errcode.Errors string matching to
transport.Error.StatusCode.

Add httptest.NewTLSServer-backed tests for imageExists covering the
found/not-found/unauthorized/EOF-retry paths to lock in protocol-level
behavior across the migration.

Promote go-containerregistry to a direct require at v0.21.5; go mod tidy
drops go.podman.io/image, distribution/distribution/v3, and the bare
docker/docker entry from the module graph.

Issue: tr-dit

* Removed the unreachable strings.Contains branch so we no longer pretend there is special “architecture mismatch → treat as exists” behavior.
Documented next to remote.Get that the check is manifest presence for the reference, not “runnable on this arch.”

* fix(collect): use DefaultKeychain when registry auth config is nil

Restore ambient credential behavior (~/.docker/config.json, credential
helpers) for registry image checks. Without WithAuthFromKeychain,
remote.Get defaulted to anonymous auth, diverging from containers/image
and from documented nil authConfig semantics.

Made-with: Cursor
2026-04-30 10:12:53 +01:00
Ethan MosbaughandClaude Sonnet 4.6 48c45d7b0a refactor: replace SPDY executor with WebSocket-first fallback executor (#2031)
* docs: add design spec for SPDY executor removal

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add implementation plan for SPDY executor removal

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(k8sutil): add NewFallbackExecutor helper

* fix(k8sutil): rename url param to u to avoid shadowing net/url

* refactor(collect): use fallback executor in exec collector

* refactor(collect): use fallback executor in copy collector

* refactor(collect): use fallback executor in copy_from_host collector

* refactor(collect): use fallback executor in sonobuoy_results collector

* refactor(collect): use fallback executor in etcd collector

* refactor(collect): use fallback executor in longhorn collector

* refactor(supportbundle): use fallback executor in collect

* chore(k8sutil): delete unused PortForward function

* fix(k8sutil): use GET for WebSocket executor and broaden fallback predicate

WebSocket upgrade requires GET per RFC 6455. Also add IsHTTPSProxyError to
the fallback predicate so HTTPS proxy environments fall back to SPDY correctly,
matching kubectl's implementation. Remove method param from NewFallbackExecutor
since the methods are now transport-specific and not caller-controlled.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: remove superpowers docs artifacts

* fix(collect): enable stdout capture in exec collector

* fix(collect): enable stdout capture in copy collectors

PodExecOptions.Stdout: false causes the WebSocket API server to discard
stdout entirely, silently breaking tar output for file copy operations.
With SPDY this mismatch was harmless; WebSocket strictly respects the field.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 06:21:42 -07:00
Evans Mungai 2fdd21fca1 feat(analyze): warn when nodeResources has no node data, add ignoreIfNoFiles (#2035)
* feat(analyze): warn when nodeResources has no node data, add ignoreIfNoFiles

The nodeResources analyzer previously failed silently when
cluster-resources/nodes.json was not collected (e.g. when the
clusterResources collector was excluded or could not list nodes).
It now emits a warn outcome per nodeResources entry in the spec.

Add an ignoreIfNoFiles top-level field to nodeResources, mirroring
textAnalyze, so users can opt out of the new warning when the
analyzer is intentionally optional.

- Add IgnoreIfNoFiles to v1beta2.NodeResources
- Update CRDs and JSON schemas
- Unit test the warn / ignore paths
- Add an e2e fixture and test that excludes clusterResources and
asserts the analyze output

Signed-off-by: Evans Mungai <evans@replicated.com>

* Fix review comment

Signed-off-by: Evans Mungai <evans@replicated.com>

---------

Signed-off-by: Evans Mungai <evans@replicated.com>
2026-04-29 13:13:24 +01:00
Evans MungaiandClaude Opus 4.6 21948fe959 feat: add host registryImages collector and analyzer (#2029)
* feat: add host registryImages collector and analyzer

Adds a host-level registryImages collector and analyzer that can check
image existence in registries without requiring a Kubernetes cluster.
Supports inline username/password auth or ambient credentials from
~/.docker/config.json.

Refactors imageExistsWithAuth from the cluster-level registry collector
to share the core image existence check logic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fixes from manual tests

Signed-off-by: Evans Mungai <evans@replicated.com>

* Updates from manual tests

Signed-off-by: Evans Mungai <evans@replicated.com>

* Sort template lists

Signed-off-by: Evans Mungai <evans@replicated.com>

* More changes

Signed-off-by: Evans Mungai <evans@replicated.com>

---------

Signed-off-by: Evans Mungai <evans@replicated.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-29 10:26:18 +01:00
Xav Paice b56b98742e Revert "refactor(collect): replace go.podman.io/image with go-containerregistry" (#2033)
This reverts commit b105fa62c7.
2026-04-29 13:29:35 +12:00
furiosa b105fa62c7 refactor(collect): replace go.podman.io/image with go-containerregistry
Migrate pkg/collect/registry.go off go.podman.io/image/v5 (containers/image)
onto github.com/google/go-containerregistry, eliminating the transitive
github.com/docker/docker +incompatible chain that blocks Docker v29 SDK
adoption.

The RegistryImages collector probes whether each requested image exists in
its registry by issuing a manifest HEAD. We replace alltransports.ParseImageName
+ imageRef.NewImage with name.ParseReference + remote.Head. Auth from a
kubernetes.io/dockerconfigjson Secret is converted to an authn.Authenticator;
error classification switches from errcode.Errors string matching to
transport.Error.StatusCode.

Add httptest.NewTLSServer-backed tests for imageExists covering the
found/not-found/unauthorized/EOF-retry paths to lock in protocol-level
behavior across the migration.

Promote go-containerregistry to a direct require at v0.21.5; go mod tidy
drops go.podman.io/image, distribution/distribution/v3, and the bare
docker/docker entry from the module graph.

Issue: tr-dit
2026-04-28 16:14:55 +12:00
Evans Mungai a3c453d1d6 fix: record skipped collectors in bundle and improve CLI warnings (#2019)
* fix: record skipped collectors in bundle and improve CLI warnings

- Write `skipped-collectors.json` to the support bundle and preflight bundle recording which collectors were skipped (RBAC permissions or spec exclusion), with reason, errors, and timestamp
- Surface RBAC errors and skipped-collector messages as `klog.Warningf` in non-interactive mode so they're visible without `-v` flags
- Exec collector file naming now falls back to the resolved container name (from the pod spec) when `collectorName` is not set, instead of only checking `containerName` from the spec

Signed-off-by: Evans Mungai <evans@replicated.com>

* Address comment

Signed-off-by: Evans Mungai <evans@replicated.com>

* fix bugbot comment

Signed-off-by: Evans Mungai <evans@replicated.com>

* Remove unused var

Signed-off-by: Evans Mungai <evans@replicated.com>

* Address comment

Signed-off-by: Evans Mungai <evans@replicated.com>

* Use results.SaveResult and add automated tests

Signed-off-by: Evans Mungai <evans@replicated.com>

* Improvements

Signed-off-by: Evans Mungai <evans@replicated.com>

* Fix bugbot

Signed-off-by: Evans Mungai <evans@replicated.com>

* Handle bugbot

Signed-off-by: Evans Mungai <evans@replicated.com>

---------

Signed-off-by: Evans Mungai <evans@replicated.com>
2026-04-15 22:29:35 +01:00
Evans MungaiandClaude Opus 4.6 daeab2dc20 fix: improve collector output discoverability (#2018)
* fix: document .tar.gz auto-append in --output flag help text

The --output flag silently appends .tar.gz to the provided path, which
was not mentioned in the help text, causing confusion for users who
expected the exact filename they specified.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: exec collector falls back to containerName for file naming

When collectorName is not set, the exec collector now uses containerName
as the output file prefix instead of producing bare -stdout.txt filenames.
This makes output files identifiable without requiring collectorName to
be explicitly set.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 18:42:30 +01:00
Andrew LaveryandDaniel Lipovetsky 5a611b3a6a feat: Collect validating and mutating webhook configurations (#2017)
* feat: Collect validating and mutating webhook configurations

* fixup! feat: Collect validating and mutating webhook configurations

Add metadata before marshaling

* explicitly test webhook configuration collection in TestClusterResources

---------

Co-authored-by: Daniel Lipovetsky <daniel.lipovetsky@nutanix.com>
2026-04-14 11:22:55 -04:00
Ethan MosbaughandClaude Sonnet 4.6 c096e5d075 fix(supportbundle): ExtractLicenseFromBundle prefers license.json regardless of tar order (#2011)
license.json was being ignored when configmaps containing a license ID
appeared earlier in the tar archive. The function now collects both
candidates in a single pass and returns the license.json result if
present, falling back to the configmap scan only when license.json is
absent.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 11:59:53 -07:00
Andrew Lavery ad7d52f7e5 add a collector that checks s3 access (#2007)
* add a collector that checks s3 access

* testing and analyzer

* analyzer test

* fmt
2026-04-09 11:12:34 -07:00
Evans Mungai 670a510a2d feat(analyze): optional additionalDeviceTypes parameter for blockDevices (#2002)
feat(analyze): optional additionalDeviceTypes for blockDevices; refactor match config and tests

Allow preflights to count extra lsblk TYPE values (e.g. loop, lvm) by listing them in
blockDevices.additionalDeviceTypes on BlockDevicesAnalyze. Types in this list are
eligible whether or not includeUnmountedPartitions is set; disk and optional
partitions behave as before.

Refactor matching to use blockDevicesMatchConfig and document eligibility on that
type. Add host_block_devices_match_test.go for type-rule tables and preflight-style
integration cases; keep classic scenarios in host_block_devices_test.go with a
shared analyzeHostBlockDevicesOutput helper.
Regenerate CRDs and deepcopy for the new API field.

Signed-off-by: Evans Mungai <evans@replicated.com>
2026-03-31 20:29:51 +01:00
Andrew Lavery e8bf6435e4 add a '--metadata' flag to support-bundle (#1993)
* add a '--metadata' flag to support-bundle

* test the metadata flag e2e
2026-03-12 13:30:28 -04:00
Andrew Lavery 94db56d668 add a dedicated support bundle metadata collector (#1992)
* add support bundle metadata collector

* add e2e test for the new collector

* make fmt

* properly include v1beta3

* remove the ability to specify an arbitrary secret
2026-03-12 12:38:45 -04:00
Ethan Mosbaugh 596a1f21a6 fix: add back collect binray, release docker image (#1991) 2026-03-11 10:51:19 -07:00
Martin Wunderlich cfe3849bff Issue 1980: timeout for supportbundle collect too short (#1986)
* Issue 1980 - Timeout for supportbundle collect too short

- leave default timeout at 30 seconds
- but: make configurable with SupportBundleOpts
- add timeout parameter to CLI flags
- add unit tests

* Issue 1980 - Timeout for supportbundle collect too short

- fix formatting
2026-03-10 16:52:34 -07:00
ada mancini 9030fff9d0 Add IngressClass analyzer (#1981)
* Add CLUSTER_RESOURCES_INGRESS_CLASS constant

* Collect IngressClass resources in cluster resources

* Add IngressClass analyzer API type

* Regenerate deepcopy for IngressClass type

* Update client-gen output from make generate

* Add IngressClass analyzer tests

* Implement IngressClass analyzer

* Register IngressClass analyzer in dispatcher

* Restore v1beta3 import in clientset scheme registration

The v1beta3 import was accidentally removed during client-gen
regeneration, causing a compile error since the SchemeBuilder
still references troubleshootv1beta3.AddToScheme.
2026-02-27 13:01:36 -05:00
ada mancini 73017ec48e feat: collect CertificateSigningRequests in clusterResources collector (#1964)
* Add .worktrees to .gitignore

Prevent worktree directories from being tracked in the repository.

* feat: collect CertificateSigningRequests in clusterResources collector

Add support for collecting CertificateSigningRequests (CSRs) from the
certificates.k8s.io/v1 API in the clusterResources collector.

Changes:
- Added certificateSigningRequests() helper function in cluster_resources.go
  following the existing pattern for other cluster-scoped resources
- Integrated CSR collection into the Collect() method between
  volumeAttachments and configMaps
- Added CLUSTER_RESOURCES_CERTIFICATE_SIGNING_REQUESTS constant
- Implemented fail-safe error handling for permission denied scenarios
  (e.g., managed clusters like EKS that may deny CSR access)

Testing:
- Added Test_CertificateSigningRequests() with table-driven tests for
  single and multiple CSR collection scenarios
- Added Test_CertificateSigningRequests_PermissionDenied() to verify
  fail-safe behavior when API access is forbidden
- All existing tests pass with no regressions

CSRs are saved to: cluster-resources/certificatesigningrequests.json
Errors are saved to: cluster-resources/certificatesigningrequests-errors.json

* style: run make fmt to align constant declarations

Formatting changes only - realigned constant declarations for
consistent spacing.

* fix: add .worktrees as separate line in .gitignore

The /support-bundle directory should remain ignored (for built
binaries), and /.worktrees/ should be added as a separate line.
2026-01-21 14:18:53 -05:00
Andrew Lavery a50bd612e8 use oras.land/oras-go/v2 (#1957) 2026-01-14 14:36:04 -06:00
Adam Wolfe GordonandAndrew Lavery 985416f20c Copy TaintExists to pkg/k8sutil and stop importing k8s.io/kubernetes (#1952)
Importing k8s.io/kubernetes causes any go modules that depend on this one to
have some issues. For example, the following happens in a module that depends on
troubleshoot:

```shell
$ go list -modfile=./go.mod -m -json -mod=mod all
go: k8s.io/cloud-provider@v0.0.0: invalid version: unknown revision v0.0.0
go: k8s.io/cluster-bootstrap@v0.0.0: invalid version: unknown revision v0.0.0
go: k8s.io/controller-manager@v0.0.0: invalid version: unknown revision v0.0.0
go: k8s.io/cri-client@v0.0.0: invalid version: unknown revision v0.0.0
go: k8s.io/csi-translation-lib@v0.0.0: invalid version: unknown revision v0.0.0
go: k8s.io/dynamic-resource-allocation@v0.0.0: invalid version: unknown revision v0.0.0
go: k8s.io/endpointslice@v0.0.0: invalid version: unknown revision v0.0.0
go: k8s.io/externaljwt@v0.0.0: invalid version: unknown revision v0.0.0
go: k8s.io/kube-controller-manager@v0.0.0: invalid version: unknown revision v0.0.0
go: k8s.io/kube-proxy@v0.0.0: invalid version: unknown revision v0.0.0
go: k8s.io/kube-scheduler@v0.0.0: invalid version: unknown revision v0.0.0
go: k8s.io/mount-utils@v0.0.0: invalid version: unknown revision v0.0.0
go: k8s.io/pod-security-admission@v0.0.0: invalid version: unknown revision v0.0.0
go: k8s.io/sample-apiserver@v0.0.0: invalid version: unknown revision v0.0.0
```

The only thing being used from k8s.io/kubernetes is a simple utility function,
`TaintExists`. Copy it into pkg/k8sutil to eliminate the need for the import.

Signed-off-by: Adam Wolfe Gordon <awg@upbound.io>
Co-authored-by: Andrew Lavery <laverya@umich.edu>
2026-01-14 14:40:33 -05:00
Andrew Lavery 128f9311fe move to go.podman.io dependencies (#1956)
* move to go.podman.io dependencies

* go fmt
2026-01-09 10:40:47 -08:00
Benjamin Yangandhedge-sparrow a9d2180dd6 102 redactor newline corruption clean (#1947)
* fix: prevent redactors from corrupting binary files (#102)

Redactors were adding newlines to files without them, corrupting binary
files during support bundle collection (51 bytes → 53 bytes).

Created LineReader to track original newline state and only restore
newlines when they were present in the original file.

- Added pkg/redact/line_reader.go
- Refactored single_line.go, multi_line.go, literal.go
- Added 48 tests, all passing
- Verified: binary files now preserved byte-for-byte

Fixes #102


* fix: handle empty lines correctly in MultiLineRedactor

- Check line1 == nil instead of len(line1) == 0 for empty file detection
- Fixes edge case where file containing only '\n' would be dropped
- Addresses bugbot finding about empty line handling


* fix: handle empty lines correctly in MultiLineRedactor

- Check line1 != nil instead of len(line1) > 0 in both locations
- Fixes edge case where empty trailing lines would be dropped
- Fix test isolation in literal_test.go (move ResetRedactionList to parent)
- Addresses bugbot findings about empty line handling

* fmt

* chore: update regression baselines from run 20107431959

* adding defense

* fix: propagate non-EOF errors in all early return paths

Ensure non-EOF errors (like buffer overflow) are properly propagated
to caller in both pre-loop early returns. Addresses bugbot finding.

* fix: use unique test names to prevent redaction list pollution

Use t.Name() instead of hardcoded 'test' to ensure each test
has unique redactor name, preventing parallel test interference

---------

Co-authored-by: hedge-sparrow <sparrow@spooky.academy>
2025-12-10 16:55:54 -06:00
ada mancini cf816f8e26 fix(discovery): handle partial results from ServerGroupsAndResources (#1944) 2025-12-10 10:33:37 -05:00
Ethan Mosbaugh 9343b43e77 fix(collect): cluster resource errors json file has wrong name (#1936)
* fix(ci): regression test updates binary to latest release
* fix cluster resources collector
2025-11-28 10:17:03 +13:00
Xav Paice e45e2cadd3 Fix collector ordering: preserve order when grouping by type (#1935)
- Fix issue where EnsureClusterResourcesFirst ordering was lost when
  collectors were grouped by type into a map (Go maps have random
  iteration order)
- Preserve collector type order by tracking collectorTypeOrder slice
  as collectors are added to the map
- Apply fix to both pkg/preflight/collect.go and
  pkg/supportbundle/collect.go
- Add comprehensive tests to verify clusterResources runs first and
  relative order of other collectors is preserved
- Enhance EnsureClusterResourcesFirst tests with additional edge cases
2025-11-26 15:34:17 +13:00
73ac499d3e Bump Go from 1.24.6 to 1.25.4 (#1930)
* Bump Go to version from 1.24.6 to 1.25.4

* fix: use net.JoinHostPort for IPv6 compatibility

Fix IPv6 address formatting in namespace-pinger.go by replacing
fmt.Sprintf with net.JoinHostPort, which correctly handles both
IPv4 and IPv6 addresses.

Changes:
- PingTCP: Use net.JoinHostPort for client connections
- startTCPEchoServer: Use net.JoinHostPort for server listener

This fixes go vet errors introduced by Go 1.25's stricter checks:
  address format "%s:%d" does not work with IPv6

IPv4 example: 192.168.1.1:8080
IPv6 example: [::1]:8080 (brackets added automatically)

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Nicholas Mullen <nwmullen@gmail.com>
2025-11-21 11:54:22 -06:00
Benjamin Yang cf2db49f86 applied native sidecar fix (#1914) 2025-11-04 11:30:42 -06:00
Noah Campbell 8197ddecfe added --values and --set flags to lint command (#1907)
* added --values and --set flags to lint command

* Update lint_test.go
2025-10-23 13:20:21 -05:00
Noah Campbell 2cebe3d8f6 Support bundle upload functionality works for apps installed via Helm (#1904)
* Gets licenseid and app slug from cluster secrets

* Update upload.go

* Update cluster_resources.go
2025-10-15 13:12:36 -05:00
Noah Campbell 6ffc83dc43 Updated linter (#1903)
* moved linter to new branch

* reads each yaml file separately when given multiple

* split monolith lint file into more reasonably sized files

* github action linter fix

* lint error codes follow the rest of the codebase's standard
2025-10-14 16:25:50 -05:00
Benjamin Yang 21dc4e9b09 Fix ollama windows installer (#1894)
* Fix Windows filename issue in scheduled support bundles

* Fix: Close temp file before executing Ollama installer on Windows

Windows requires files to be closed before they can be executed. This fix
ensures the temporary installer file is properly closed before attempting
to run it, preventing file access errors on Windows systems.
2025-10-14 10:51:52 -05:00
Noah Campbell 5aa088b3b6 Revert unintended commits on main 2025-10-13 15:23:31 -05:00
Noah Campbell 3f5ab9c721 doesnt harcode apiVersion line when looking and figures out which apiVersion to give if none is there 2025-10-13 15:18:43 -05:00
Noah Campbell 0316bb2e12 improved --fix capabilities 2025-10-13 15:18:33 -05:00
Noah Campbell a5f4afb488 added lint subcommand 2025-10-13 15:18:04 -05:00
Noah Campbell b7f499c737 Arbitrary secret key refs and templating in collectors (#1895)
* Uses secrets from cluster

* updated gitignore to stop ignoring needed files

* Delete specs.go.bak

* make fmt

* added preflight to generic loader

* Tells user to run in cluster if using secretKeyRef

* Update loader.go

* Update loader.go
2025-10-13 12:19:37 -05:00
Benjamin Yang df40c661a2 Fix windows cronjob (#1891)
* Fix Windows filename issue in scheduled support bundles

* fix bugbot
2025-10-10 10:24:48 -05:00
Benjamin Yang 6c5c310eb3 Fix ollama clean (#1885)
* fixing .json format

* feat: aggregate files by resource type in Ollama agent for accurate cluster-wide analysis

- Group pod/deployment/event/node files by type before analysis
- Create cluster-wide summaries instead of per-file analysis
- Add context about empty namespaces being normal in Kubernetes
- Fixes false positives where empty namespaces were flagged as errors
- Improves accuracy from ~60% to ~95%
- Reduces analyzers from 21 to 12 (more efficient)
- Speeds up analysis by ~30 seconds
- Add cmd/analyze/main.go for building standalone analyze binary

* feat: aggregate files by resource type in Ollama agent for accurate cluster-wide analysis

- Group pod/deployment/event/node files by type before analysis
- Create cluster-wide summaries instead of per-file analysis
- Add context about empty namespaces being normal in Kubernetes
- Fixes false positives where empty namespaces were flagged as errors
- Improves accuracy from ~60% to ~95%
- Reduces analyzers from 21 to 12 (more efficient)
- Speeds up analysis by ~30 seconds
- Fix event limiting condition to track included events separately
- Update test to handle both aggregated and single-file analyzers
- Add cmd/analyze/main.go for building standalone analyze binary

* fixing error

* fixing bugbot

* fix bugbot errors

* fix bugbot errors

* bugbot errors

* fixing more bugbot errors

* fix: initialize namespace stats only after validating resource type

- Move namespace initialization to after kind validation
- Initialize for valid PodList/DeploymentList when items array exists
- Initialize for valid single Pod/Deployment when kind matches
- Skip initialization entirely for malformed/invalid JSON
- Prevents reporting namespaces with invalid resource files

* refactor: use if-else structure for clearer control flow

- Restructure pod/deployment aggregation to use explicit if-else
- Makes it clear that lists are processed in if block, singles in else
- Functionally identical but clearer for static analysis
- Resolves bugbot false positives about unreachable code
2025-10-08 16:57:00 -05:00