Compare commits

...
3 Commits
Author SHA1 Message Date
replicated-software-factory[bot]andElasticClaw Factory 6560e818d9 [deps] Dependency update: troubleshoot (#2118)
* chore(deps): update go dependencies for troubleshoot

- github.com/aws/aws-sdk-go-v2 v1.43.6 -> v1.43.7
- github.com/aws/aws-sdk-go-v2/credentials v1.19.36 -> v1.19.37
- github.com/aws/aws-sdk-go-v2/service/s3 v1.107.2 -> v1.107.3
- k8s.io/* v0.36.3 -> v0.36.4

* chore(deps): update golang.org/x/exp to v0.0.0-20260820142414-ca536658362e

* chore(ci): re-trigger e2e after sonobuoy timeout flake

* chore(deps): update github.com/microsoft/go-mssqldb to v1.11.0

---------

Co-authored-by: ElasticClaw Factory <factory@replicated.com>
2026-08-31 16:08:38 +12:00
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
Dmitriy Ivolgin 5bf008f7d2 Use all tags when building with securebuild (#2119) 2026-08-21 11:27:04 -07:00
5 changed files with 383 additions and 113 deletions
+9 -2
View File
@@ -1,8 +1,8 @@
name: publish-securebuild
env:
SECUREBUILD_CLI_VERSION: v0.0.496
SECUREBUILD_CLI_SHA256: af016db0fa16d51f68f443dea31a63152ad23504bb296137b01f270102011f79
SECUREBUILD_CLI_VERSION: v0.0.498
SECUREBUILD_CLI_SHA256: d259aa99d85aef957fe1e40c6f26e1983cc7fd72277e08599a82adc6681d3b37
on:
workflow_call:
@@ -88,7 +88,14 @@ jobs:
SECUREBUILD_API_TOKEN: ${{ secrets.SECUREBUILD_API_TOKEN }}
VERSION: ${{ needs.build-package.outputs.version }}
run: |
IMAGE_VERSION="${VERSION#v}"
MAJOR_MINOR_VERSION="${IMAGE_VERSION%.*}"
MAJOR_VERSION="${IMAGE_VERSION%%.*}"
./securebuild build image \
--image-name "$IMAGE_NAME" \
--tag "$VERSION" \
--image-tag "$MAJOR_MINOR_VERSION" \
--image-tag "$MAJOR_VERSION" \
--image-tag latest \
--api-token "$SECUREBUILD_API_TOKEN"
+26 -26
View File
@@ -7,9 +7,9 @@ require (
github.com/Masterminds/sprig/v3 v3.3.0
github.com/ahmetalpbalkan/go-cursor v0.0.0-20131010032410-8136607ea412
github.com/apparentlymart/go-cidr v1.1.1
github.com/aws/aws-sdk-go-v2 v1.43.6
github.com/aws/aws-sdk-go-v2/credentials v1.19.36
github.com/aws/aws-sdk-go-v2/service/s3 v1.107.2
github.com/aws/aws-sdk-go-v2 v1.43.7
github.com/aws/aws-sdk-go-v2/credentials v1.19.37
github.com/aws/aws-sdk-go-v2/service/s3 v1.107.3
github.com/blang/semver/v4 v4.0.0
github.com/casbin/govaluate v1.10.0
github.com/cilium/ebpf v0.22.0
@@ -30,7 +30,7 @@ require (
github.com/longhorn/go-common-libs v0.0.0-20260730002911-add09e6eb92c
github.com/manifoldco/promptui v0.9.0
github.com/mattn/go-isatty v0.0.24
github.com/microsoft/go-mssqldb v1.10.0
github.com/microsoft/go-mssqldb v1.11.0
github.com/miekg/dns v1.1.73
github.com/opencontainers/image-spec v1.1.1
github.com/pkg/errors v0.9.1
@@ -47,18 +47,18 @@ require (
github.com/vmware-tanzu/velero v1.18.2
go.opentelemetry.io/otel v1.45.0
go.opentelemetry.io/otel/sdk v1.45.0
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f
golang.org/x/exp v0.0.0-20260820142414-ca536658362e
golang.org/x/mod v0.40.0
golang.org/x/sync v0.22.0
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.36.3
k8s.io/apiextensions-apiserver v0.36.3
k8s.io/apimachinery v0.36.3
k8s.io/apiserver v0.36.3
k8s.io/cli-runtime v0.36.3
k8s.io/client-go v0.36.3
k8s.io/api v0.36.4
k8s.io/apiextensions-apiserver v0.36.4
k8s.io/apimachinery v0.36.4
k8s.io/apiserver v0.36.4
k8s.io/cli-runtime v0.36.4
k8s.io/client-go v0.36.4
k8s.io/klog/v2 v2.140.0
k8s.io/streaming v0.36.3
k8s.io/streaming v0.36.4
oras.land/oras-go/v2 v2.6.2
sigs.k8s.io/controller-runtime v0.24.1
sigs.k8s.io/e2e-framework v0.7.0
@@ -86,18 +86,18 @@ require (
github.com/avast/retry-go/v4 v4.7.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.18 // indirect
github.com/aws/aws-sdk-go-v2/config v1.32.35 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.37 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.37 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.37 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.38 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.38 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.38 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.38 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.39 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.17 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.30 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.37 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.38 // indirect
github.com/aws/aws-sdk-go-v2/service/signin v1.5.6 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.33.6 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.6 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.45.6 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.31 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.38 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.39 // indirect
github.com/aws/aws-sdk-go-v2/service/signin v1.5.7 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.33.7 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.7 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.45.7 // indirect
github.com/aws/smithy-go v1.27.8 // indirect
github.com/chai2010/gettext-go v1.0.3 // indirect
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
@@ -189,7 +189,7 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d // indirect
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gotest.tools/v3 v3.5.2 // indirect
k8s.io/component-base v0.36.3 // indirect
k8s.io/component-base v0.36.4 // indirect
k8s.io/kubectl v0.36.3 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.4.2 // indirect
@@ -267,8 +267,8 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
helm.sh/helm/v3 v3.21.4
k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad // indirect
k8s.io/kubelet v0.36.3
k8s.io/metrics v0.36.3
k8s.io/kubelet v0.36.4
k8s.io/metrics v0.36.4
k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3
periph.io/x/host/v3 v3.8.5
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
+60 -60
View File
@@ -27,20 +27,20 @@ filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.1 h1:jHb/wfvRikGdxMXYV3QG/SzUOPYN9KEUUuC0Yd0/vC0=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.1/go.mod h1:pzBXCYn05zvYIrwLgtK8Ap8QcjRg+0i76tMQdWN6wOk=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 h1:Hk5QBxZQC1jb2Fwj6mpzme37xbCDdNTxU7O9eb5+LB4=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.23.0 h1:4gRPBpN1f6xt88yi4WR26m7XaD9OlWtVT6bWPdGUIok=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.23.0/go.mod h1:G7QVLxw1j1JVyrO1MA95S8m8HStaaleDZYTcfGgjB2o=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.14.0 h1:CU4+EJeJi3TKYWEcYuSdWsjzw0nVsK/H0MSQOiPcymU=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.14.0/go.mod h1:q0+UTSRvShwUCrR/s5HtyInYphN7Wvxb7snFM3u+SLA=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0 h1:fhqpLE3UEXi9lPaBRpQ6XuRW0nU7hgg4zlmZZa+a9q4=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0/go.mod h1:7dCRMLwisfRH3dBupKeNCioWYUZ4SS09Z14H+7i8ZoY=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.4.0 h1:E4MgwLBGeVB5f2MdcIVD3ELVAWpr+WD6MUe1i+tM/PA=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.4.0/go.mod h1:Y2b/1clN4zsAoUd/pgNAQHjLDnTis/6ROkUfyob6psM=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.5.0 h1:MaKvxE6D0KkjOg6Wd9M00iqP5PR0kUxCfiezes4JweM=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.5.0/go.mod h1:i2h9fsTFKZorh8RdV2IcSUf/Qj98GlTkrTvUbX/s8as=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 h1:nCYfgcSyHZXJI8J0IWE5MsCGlb2xp9fJiXyxWgmOFg4=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0/go.mod h1:ucUjca2JtSZboY8IoUqyQyuuXvwbMBVwFOm0vdQPNhA=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs=
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=
github.com/AzureAD/microsoft-authentication-library-for-go v1.7.2 h1:RHK7bS+HQMslb1sZpAokUt+zTVmue0hKSs2C791hhzU=
github.com/AzureAD/microsoft-authentication-library-for-go v1.7.2/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/ClickHouse/ch-go v0.74.0 h1:uYs2m4wIt0ZHSM1E72rg0maCfzhR2V3xWb/vZEgpeWE=
@@ -81,40 +81,40 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/avast/retry-go/v4 v4.7.0 h1:yjDs35SlGvKwRNSykujfjdMxMhMQQM0TnIjJaHB+Zio=
github.com/avast/retry-go/v4 v4.7.0/go.mod h1:ZMPDa3sY2bKgpLtap9JRUgk2yTAba7cgiFhqxY2Sg6Q=
github.com/aws/aws-sdk-go-v2 v1.43.6 h1:RrmFcqCBxkJuf7g1axVo5krB4jM/AO8r5e5oujrgdoQ=
github.com/aws/aws-sdk-go-v2 v1.43.6/go.mod h1:tXpPM+v0D1lndmga+HqqLDIzUFJlEeR21aspVklHF00=
github.com/aws/aws-sdk-go-v2 v1.43.7 h1:msCzvkeYJA9ehbV8mRRmkZLo/zJg/+yDVLNtflg83hQ=
github.com/aws/aws-sdk-go-v2 v1.43.7/go.mod h1:tXpPM+v0D1lndmga+HqqLDIzUFJlEeR21aspVklHF00=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.18 h1:LAfOuhAH331fmOjTQpAaOlH+Ftn7RzSDJ2VFwjdMMy4=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.18/go.mod h1:4e5xhuXHx1e4U9EthvbPP1r/DIMp5c2823OL8karzcM=
github.com/aws/aws-sdk-go-v2/config v1.32.35 h1:UEzXuET8E42lxBPijuACu/tEK7v5lFPlk0Q+GT5WD9E=
github.com/aws/aws-sdk-go-v2/config v1.32.35/go.mod h1:KaMtJpFa2JlL2BStjjHQVwQpzZEmw+ND/EgVrfFoo2g=
github.com/aws/aws-sdk-go-v2/credentials v1.19.36 h1:84s5xMme6ENYEdKG8rsbSFFg/8+lbHBeM9QYSO0gnDk=
github.com/aws/aws-sdk-go-v2/credentials v1.19.36/go.mod h1:c46BLdagDLIswjgt+GeQOslXgeS0E6wCacs5yZbxPGk=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.37 h1:b5tb+CZItBkydC7r3hTNdSO3pszG1R2EtnA+7TePQPk=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.37/go.mod h1:ZQ+6SU9X0oz6+7MUCSswv9Mjci4eaqZr21HI2RVy/yA=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.37 h1:lznzIOvvbqjfe8UAaciCRJgBgJsxuTROKlhZuXQWfv8=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.37/go.mod h1:otfkzyfQeMMLZAqX59GSXTL3o22BR/l6HFaRzzbWSqA=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.37 h1:zCEORWo0eU0gDjG+IyApE/2B+ZGG1m+GU7B263XV8ds=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.37/go.mod h1:i6c0PEl3TNOWxRbQ++KQcVenPWS/GoQeiklKhNuqzJ8=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.38 h1:A3UAuCmx7LyUcrixBTzKJYYIUZ2yTvn6ZhT8PB+7APk=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.38/go.mod h1:1PDUYG9Z+JrbbsobsAZHjWOm9QBT/djiK3QbykTL5Z4=
github.com/aws/aws-sdk-go-v2/credentials v1.19.37 h1:FJ8Iz4/xISMB/rwLlgfWujfGDFWr0oneQgtA6KPcYLY=
github.com/aws/aws-sdk-go-v2/credentials v1.19.37/go.mod h1:Q6pWOgVUp49x4g5QVi29wHofUoICnZ+Zq4jHbRN/7ec=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.38 h1:Nqo2jU1wz5rnBM9XQyXfVD1RP8txkbP3EDx8hR/hbCE=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.38/go.mod h1:PzJFHhjR2vWFKHe8HmY5Lxhvwyxnr5MERtk0nDxWNbk=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.38 h1:MBMg0zJ6i4TkAJ0dVFLKKn2cOkY6FkicmUDM67BRr6g=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.38/go.mod h1:9MWuJbyiUyj6eA7W1/zm1zuePDPSB3g+xcgRQeMWsXc=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.38 h1:lHm4jPf3k1Lz5ZWc+Vcn3MKVwym+26kWCba9FkJ4f0Y=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.38/go.mod h1:Rn+P2XR+FbyZzjmWKjg/KUZNxmGfr5oZwh5jQiE+CzI=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.39 h1:vo4xvMRs/F6h1E52qsgLqCQgWIQXgIJUauG6rlZEh4U=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.39/go.mod h1:jB03R1ij/A+OE2e1dz6vgj076gd7vlYcfstAzj3HcnU=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.17 h1:OvYZOB3qA6zvfdRFiRFRzVSiElMYrz3GdntkXZxlp1o=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.17/go.mod h1:JgR/2Ew50ACfIWau1oeMRX59tMtC0kM+PYQGEaT04cY=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.30 h1:5437eMoOwqqQpZn2XJy74mlDCuPYL81texMT3mXqgtU=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.30/go.mod h1:xfu2m3dOpvW8lj98wQYa8V9ku/Rta59hsbireGzhh3A=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.37 h1:a3D4AjrOrTrP8+d9ILBthqrElf0z1JNol09Xvnwcys8=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.37/go.mod h1:ky0gTu+ukvUTuUKFIpp6Wid4oninrkCyvbFkVs0kpHM=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.38 h1:gX8B8y3Ho30B1LPxefDKMi/HZqWEb47U9ogs3DtSG0M=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.38/go.mod h1:l5WblZlcmGPe4/O7JY2HO25Z+xqTBvyfTyFbRMf8gYw=
github.com/aws/aws-sdk-go-v2/service/s3 v1.107.2 h1:GNU0/xtPEXMKilJZ/a8BedeuQnvu+Usi6qVm9EFfncc=
github.com/aws/aws-sdk-go-v2/service/s3 v1.107.2/go.mod h1:4jYWUecEsQtE73jPl7p3jrbYXH5ffcR4gegyCygagfg=
github.com/aws/aws-sdk-go-v2/service/signin v1.5.6 h1:i68sFvXidKlkiSvI7d7Ilc1/UvW4CtBOaivH7jhG4fs=
github.com/aws/aws-sdk-go-v2/service/signin v1.5.6/go.mod h1:/h7Obr9WTtzbjTHGASRQwLN7Bupw+TC3x8x7fyx39hE=
github.com/aws/aws-sdk-go-v2/service/sso v1.33.6 h1:tpfGChmjUmv3W9WlRvy+stwKDTbFFdq8Zk9DbFPrfMU=
github.com/aws/aws-sdk-go-v2/service/sso v1.33.6/go.mod h1:CSjiDzmG/lsKkTOYjbkM+duLmRlW+LOxD64Na44ijnI=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.6 h1:49BBtY68A+KJCQ3a2F3eUe6ROsKucxUdfHKoqorc0wI=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.6/go.mod h1:ptG2hbs7QltE1GcQY0MpS4bfrc51KCnBXUr7OT1EEfE=
github.com/aws/aws-sdk-go-v2/service/sts v1.45.6 h1:JvExZWabChDM0qJAirQYGfOYo0ndT3edXj+fqSPNjkE=
github.com/aws/aws-sdk-go-v2/service/sts v1.45.6/go.mod h1:XZcaQkV2cItp6yEkrwljyaPOf22RuX7T43jxap/FOmM=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.31 h1:uZOinZb+h7lZw8IYzP1z1IuEnueB76/EFkcf/fEW4Ag=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.31/go.mod h1:NRtwAM/p5VRt03TlEUs0pH3TeWamWdf4YyJpSrzPYLc=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.38 h1:H/5TI1jqaHsNoDQ60UwvPvJBg4GURkinXI3Qga29t2w=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.38/go.mod h1:PTVFf+XH++7NJOky+RLBYQx0QA5NcaeEYFQ2fsi0nwo=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.39 h1:HLPAVrlLDaN2boN0xJx7MgaQDNEO3Q+c9L6kl/8m47Q=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.39/go.mod h1:Pg/dVfsNkm1hsIDK/gMvCKtmyNfNTV12mrgHqVE/6Oo=
github.com/aws/aws-sdk-go-v2/service/s3 v1.107.3 h1:IKoCZqfWfZzSBi16QFQ+QcbQ3LRQ7QgB1S5tDAyPBQQ=
github.com/aws/aws-sdk-go-v2/service/s3 v1.107.3/go.mod h1:RBpRcXiM4s2pOInVs32GsBonnje+fiAj4mcrStRmlCA=
github.com/aws/aws-sdk-go-v2/service/signin v1.5.7 h1:YcczQ6zNH/ojIzD/ikDrO+RfW06wmdMp18d4NH5hXY4=
github.com/aws/aws-sdk-go-v2/service/signin v1.5.7/go.mod h1:nl9RVnb9ulgAYzOkjLq1NyFxmWcnH2maCUEuOdESy98=
github.com/aws/aws-sdk-go-v2/service/sso v1.33.7 h1:P+bMNiA93gyuYT3Oh+4dWtvrnGcu2bd9Uy5hRJM8BNo=
github.com/aws/aws-sdk-go-v2/service/sso v1.33.7/go.mod h1:zy+397isDFLvleg9H18Zq2MGzMso7uKyJyzR7DWSgFk=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.7 h1:WWkehGZ4nWtOKLMy0yi8+RqzzVqAGe60hGaxwF06JAw=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.7/go.mod h1:T8AI4SbQYm9ybcVmki2T3n7Qg1g3kfWoeQlNwNYOyO8=
github.com/aws/aws-sdk-go-v2/service/sts v1.45.7 h1:yU/9y2r7s9kSUPbHXbpQTa4LA8kt+CMgpu1OBrhx8p4=
github.com/aws/aws-sdk-go-v2/service/sts v1.45.7/go.mod h1:0lQTDEBArMevQXpxu443LVGjKxxEeSsSnrw9n8YiTMg=
github.com/aws/smithy-go v1.27.8 h1:FR0dxZfIlV7Z8eh2iHfIofdunw382XsDV3Mxt9nUvRY=
github.com/aws/smithy-go v1.27.8/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -418,8 +418,8 @@ github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
github.com/microsoft/go-mssqldb v1.10.0 h1:pHEt+Qz6YFPWqREq10mqSE524QQo+/QremwTCQht7TY=
github.com/microsoft/go-mssqldb v1.10.0/go.mod h1:mnG7lGa9iYJbzJqGCXyuQCegStKMr3kogDLD6+bmggg=
github.com/microsoft/go-mssqldb v1.11.0 h1:YbDqolEjGH9hBfvKzONTf5/dbl9RKXmizMJE93lVxNs=
github.com/microsoft/go-mssqldb v1.11.0/go.mod h1:goQLDOPlMN/l1REhnNPElMoY/yX+fUWn1+7UoFJPH9Y=
github.com/miekg/dns v1.1.73 h1:uhT8nJxmTrPJYClxVxTCX+CVn6qnzSiybRk72Z6DgrE=
github.com/miekg/dns v1.1.73/go.mod h1:RW2Obtfd5NZHvOFe3zYG0W8koWOQtAzyHaLo8vASBuQ=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
@@ -651,8 +651,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
golang.org/x/exp v0.0.0-20260820142414-ca536658362e h1:01Ju2A/fZKkci4zqx0eZxw//DnRYOnBiGJG14hFBhO8=
golang.org/x/exp v0.0.0-20260820142414-ca536658362e/go.mod h1:zeBbvyFKDaLwa7CH/zI8KXt7gTl14SF7sO08Pl5jBCM=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs=
@@ -743,32 +743,32 @@ gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
helm.sh/helm/v3 v3.21.4 h1:T/GcIEXU/gNjJnkITlIZ3e9xqkZjhFTmISuStTZ6+Qg=
helm.sh/helm/v3 v3.21.4/go.mod h1:cS2FBb+xfLuaSqvEmbqIeKUVFgHdHVHtVeXb2epof3M=
k8s.io/api v0.36.3 h1:NxB+05W2UGqXWFXcLO0RB5cnqnUPP5v5sVlaOH0Iz4w=
k8s.io/api v0.36.3/go.mod h1:JzLQKqRHC5+I8RVj/lS3lCg0mg6nWI9Fo/Sk3ElxHzg=
k8s.io/apiextensions-apiserver v0.36.3 h1:dPmOAPhwTtqb1bTxbFPsy18KHPhktQeO3WUPXunZIB0=
k8s.io/apiextensions-apiserver v0.36.3/go.mod h1:KTXFqgXiuw2pRoL+Wpmttqc+up9Xt/GohadPWeLLOa4=
k8s.io/apimachinery v0.36.3 h1:PkzMRBRG8joFD8EhCuQAtNPvJlxb82FwplP26HIzvAM=
k8s.io/apimachinery v0.36.3/go.mod h1:cTSjBWgPe/6CQyBKzY/hDIRWCQQQeK0mfLbml0UYFHE=
k8s.io/apiserver v0.36.3 h1:MGSg2SkdfuytiDEcRylT5mQFmmSsbx90XFUO67Y4bsQ=
k8s.io/apiserver v0.36.3/go.mod h1:fVH7zv9EUNUA7Fl7LtDKh8aB9W7u1VQPSGtWV5SjUxg=
k8s.io/cli-runtime v0.36.3 h1:g+eJ+M1sYpnNYp/q5fzaw2KejIL0Q7DH+xFl6YVoL4U=
k8s.io/cli-runtime v0.36.3/go.mod h1:hZpAqK8nSFXvvLaVCbzUPVp8e9TRLSTCfpNzMt7s3tE=
k8s.io/client-go v0.36.3 h1:M4JdVzXxYcZk4fGpfDdYnxSwhLKWCFoQsHW6t+z8Hfg=
k8s.io/client-go v0.36.3/go.mod h1:gcPwr0c87vjjG6HB6pWEqOeuYVoXSsREjzux2j6GF30=
k8s.io/component-base v0.36.3 h1:vc/UFvPCkW0irPz84LAodAL1j3f4xktPM6dDJIEheAY=
k8s.io/component-base v0.36.3/go.mod h1:hZbNFG+gCMl9EbykDGEu73feKP9/Cq6JsV4pTo9GTO8=
k8s.io/api v0.36.4 h1:RxrvqCL6vgH5/+UnTeu1IIFqYmGfy0hnyrod1rn35Oo=
k8s.io/api v0.36.4/go.mod h1:S2B3orCFBDhrgyWbLeuKcT2QdHIpQesBkCYSlWtwUOw=
k8s.io/apiextensions-apiserver v0.36.4 h1:SfvCVt+4CqKWvzuVytYDT5g9hyb9MztoiYELIkPVrFc=
k8s.io/apiextensions-apiserver v0.36.4/go.mod h1:JT9V2Ju7ys1FY4zbSpmX9XOvKB3/BwsODc4hFQEa+Xo=
k8s.io/apimachinery v0.36.4 h1:PT2UzkupGuAx/+xT5XjiMJ1WGpY3fn9/hdAvjweRet4=
k8s.io/apimachinery v0.36.4/go.mod h1:p2I2dipt7JHG+quVwQ1d02d28O4GdDi77RByQ13MTpk=
k8s.io/apiserver v0.36.4 h1:AtKjaf2eUiX5G6TfF2IOlhuUuvMsHh49Ivr1+4fZ2gA=
k8s.io/apiserver v0.36.4/go.mod h1:RyiGghXP67hb0Ll+7iLJ6GGv2JpEzCn7ljbiA+L3cJ0=
k8s.io/cli-runtime v0.36.4 h1:OHvManCwP1k9GiC5tXRFxHhzZIQQFCsrHlt7OspKo3w=
k8s.io/cli-runtime v0.36.4/go.mod h1:qQSj2FJgQos6GHpS/ge7wTdQMZm9XFWlesWgV6h7qZY=
k8s.io/client-go v0.36.4 h1:MDvfDNvMSt0Br94SK8neviVlwL9qifw9B26hJCpD1K0=
k8s.io/client-go v0.36.4/go.mod h1:pNK4WKELbwlEDvtbE8l22lEZL5THYF61H5EealokZmA=
k8s.io/component-base v0.36.4 h1:tz75yC2xgq3kd7vPdBtR8do5iMx0OHf6Zd1kuaxDB84=
k8s.io/component-base v0.36.4/go.mod h1:DCwb306U8ou89NNAp45Csuy8ok+1rp1ELDVPhzN5AWc=
k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc=
k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0=
k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad h1:oXImqH8mQNk7PmvzKhmN3ddJoY6OnyM225MXwGHPm0A=
k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad/go.mod h1:0/mqHCVhlumdJ3BhCfnjSZQE037nAhNodh1/hK0T8/I=
k8s.io/kubectl v0.36.3 h1:TesKp+XYQEjPYoFvuobcVnuvira2+/xAVlq//+kksaI=
k8s.io/kubectl v0.36.3/go.mod h1:W+NEb1CzBGmoaI1Nrpn2ETo9omNBl0AsyxnnMT40N6E=
k8s.io/kubelet v0.36.3 h1:dRzEnhHk35Opy6wjWR4YBcN5RI9lB2npUY37TghFuPU=
k8s.io/kubelet v0.36.3/go.mod h1:4USFGr21Ioka+b964Beq0NvV5b5aca3RWJ1/kfq+RLw=
k8s.io/metrics v0.36.3 h1:NDKceAgWS8CJCdDtM5kFACkBOa9Lxia1jUiibJfvUgQ=
k8s.io/metrics v0.36.3/go.mod h1:NTLS8ybwn+zYGwKqYublWPvmnNp8N4pV3etjtx7XWaM=
k8s.io/streaming v0.36.3 h1:9rAaqBk0C0Pc7+/fqGekj07NV+/Xrew58p647A0JT8w=
k8s.io/streaming v0.36.3/go.mod h1:z6fV3D+NVkoeqRMtWwlUZK6U17SY/LqNzOxWL6GyR/s=
k8s.io/kubelet v0.36.4 h1:mlmXnkrq3H02r/r0H/8M2jdPY7f4I4u4cA0tHnsPzY0=
k8s.io/kubelet v0.36.4/go.mod h1:jcOhk4E8cdUBn7WswW67WH9waQTe37G057ttnYdcaKY=
k8s.io/metrics v0.36.4 h1:jcIx58xCk9NIvoeoh2q1jQidXtNMKlNi2rgJF4QV+uU=
k8s.io/metrics v0.36.4/go.mod h1:pMqC7NtvrNkLiIN38BLqBhizp2DDJdwupqZSQSzP9HI=
k8s.io/streaming v0.36.4 h1:RS5YlhrdBN2pKGVjgygGntdu6SNdsduyjGWGe3cX0vo=
k8s.io/streaming v0.36.4/go.mod h1:tJ6S2bZa2HxIBauguBbCWSCYyd93Grfz1+z3tcOvlDE=
k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3 h1:jVkFFVfXdXP74B/zbO3hM3hpSFD0xvhQ5U686DPurkE=
k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3/go.mod h1:M2s5JB1lIYP3jzZdorPLHXIPJzt9vv2muW5a6L9DtNM=
oras.land/oras-go/v2 v2.6.2 h1:N04RXngAp1LJKTG6ifz3xHPipasEkWr+hFmInja5YKo=
+54 -25
View File
@@ -30,6 +30,9 @@ func (a *AnalyzeSecret) Analyze(getFile getCollectedFileContents, findFiles getC
if err != nil {
return nil, err
}
if result == nil {
return nil, nil
}
result.Strict = a.analyzer.Strict.BoolOrDefaultFalse()
return []*AnalyzeResult{result}, nil
}
@@ -54,42 +57,68 @@ func (a *AnalyzeSecret) analyzeSecret(analyzer *troubleshootv1beta2.AnalyzeSecre
return nil, err
}
// The secret analyzer only supports fail (not found) and pass (found) outcomes
// per https://troubleshoot.sh/docs/analyze/secrets. If the spec contains
// neither, return an explicit error: returning (nil, nil) is swallowed by the
// Analyze wrapper into an empty result slice, so the misconfiguration would
// surface as neither a result nor an error.
// Capture fail and pass independently: a single outcome object may set both,
// so an else-if here would silently drop the second one.
var failOutcome, passOutcome *troubleshootv1beta2.SingleOutcome
for _, outcome := range analyzer.Outcomes {
if outcome.Fail != nil {
failOutcome = outcome.Fail
}
if outcome.Pass != nil {
passOutcome = outcome.Pass
}
}
if failOutcome == nil && passOutcome == nil {
return nil, fmt.Errorf("secret analyzer %s/%s must define at least one pass or fail outcome", analyzer.Namespace, analyzer.SecretName)
}
result := AnalyzeResult{
Title: a.Title(),
IconKey: "kubernetes_analyze_secret",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/secret.svg?w=13&h=16",
}
var failOutcome *troubleshootv1beta2.Outcome
for _, outcome := range analyzer.Outcomes {
if outcome.Fail != nil {
failOutcome = outcome
}
secretFound := foundSecret.SecretExists
if secretFound && analyzer.Key != "" {
secretFound = foundSecret.Key == analyzer.Key && foundSecret.KeyExists
}
if !foundSecret.SecretExists {
// Use the matched branch's configured outcome verbatim, tracking whether one
// was actually present. A configured outcome with an intentionally empty
// message (e.g. a URI-only outcome) is preserved as-is. But when the matched
// branch has NO configured outcome at all — e.g. a pass-only spec that took
// the fail path, or a fail-only spec that passed — the empty message is not
// an intentional choice, so fall back to a default diagnostic. An absent
// outcome is not the same as an intentionally empty one.
outcomeConfigured := false
if secretFound {
result.IsPass = true
if passOutcome != nil {
result.Message = passOutcome.Message
result.URI = passOutcome.URI
outcomeConfigured = true
}
} else {
result.IsFail = true
result.Message = failOutcome.Fail.Message
result.URI = failOutcome.Fail.URI
return &result, nil
}
if analyzer.Key != "" {
if foundSecret.Key != analyzer.Key || !foundSecret.KeyExists {
result.IsFail = true
result.Message = failOutcome.Fail.Message
result.URI = failOutcome.Fail.URI
return &result, nil
if failOutcome != nil {
result.Message = failOutcome.Message
result.URI = failOutcome.URI
outcomeConfigured = true
}
}
result.IsPass = true
for _, outcome := range analyzer.Outcomes {
if outcome.Pass != nil {
result.Message = outcome.Pass.Message
result.URI = outcome.Pass.URI
if !outcomeConfigured {
switch {
case result.IsPass:
result.Message = fmt.Sprintf("Secret %s was found in namespace %s", analyzer.SecretName, analyzer.Namespace)
case analyzer.Key != "" && foundSecret.SecretExists:
result.Message = fmt.Sprintf("Key %s was not found in secret %s/%s", analyzer.Key, analyzer.Namespace, analyzer.SecretName)
default:
result.Message = fmt.Sprintf("Secret %s was not found in namespace %s", analyzer.SecretName, analyzer.Namespace)
}
}
+234
View File
@@ -166,6 +166,118 @@ func Test_analyzeSecret(t *testing.T) {
IconURI: "https://troubleshoot.sh/images/analyzer-icons/secret.svg?w=13&h=16",
},
},
{
name: "not found with no fail outcome falls back to a default message (no configured outcome for this branch)",
analyzer: &troubleshootv1beta2.AnalyzeSecret{
AnalyzeMeta: troubleshootv1beta2.AnalyzeMeta{
CheckName: "Optional Secret",
},
Namespace: "default",
SecretName: "does-not-exist",
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "secret found",
},
},
},
},
mockFiles: map[string][]byte{
"secrets/default/does-not-exist.json": mustJSONMarshalIndent(t, collect.SecretOutput{
Namespace: "default",
Name: "does-not-exist",
SecretExists: false,
}),
},
want: &AnalyzeResult{
IsFail: true,
Message: "Secret does-not-exist was not found in namespace default",
Title: "Optional Secret",
IconKey: "kubernetes_analyze_secret",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/secret.svg?w=13&h=16",
},
},
{
name: "key not found with no fail outcome falls back to a default message (no configured outcome for this branch)",
analyzer: &troubleshootv1beta2.AnalyzeSecret{
AnalyzeMeta: troubleshootv1beta2.AnalyzeMeta{
CheckName: "Optional Secret Key",
},
Namespace: "test-namespace",
SecretName: "test-secret",
Key: "missing-key",
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "key found",
},
},
},
},
mockFiles: map[string][]byte{
"secrets/test-namespace/test-secret/missing-key.json": mustJSONMarshalIndent(t, collect.SecretOutput{
Namespace: "test-namespace",
Name: "test-secret",
Key: "missing-key",
SecretExists: true,
KeyExists: false,
}),
},
want: &AnalyzeResult{
IsFail: true,
Message: "Key missing-key was not found in secret test-namespace/test-secret",
Title: "Optional Secret Key",
IconKey: "kubernetes_analyze_secret",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/secret.svg?w=13&h=16",
},
},
{
name: "found with only fail outcome configured falls back to the default pass message, not the fail outcome's message",
analyzer: &troubleshootv1beta2.AnalyzeSecret{
Namespace: "test-namespace",
SecretName: "test-secret",
Outcomes: []*troubleshootv1beta2.Outcome{
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "Not found",
},
},
},
},
mockFiles: map[string][]byte{
"secrets/test-namespace/test-secret.json": mustJSONMarshalIndent(t, collect.SecretOutput{
Namespace: "test-namespace",
Name: "test-secret",
SecretExists: true,
}),
},
want: &AnalyzeResult{
IsPass: true,
Message: "Secret test-secret was found in namespace test-namespace",
Title: "Secret test-secret",
IconKey: "kubernetes_analyze_secret",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/secret.svg?w=13&h=16",
},
},
{
name: "spec with neither fail nor pass outcome returns an error so the framework surfaces the misconfiguration",
analyzer: &troubleshootv1beta2.AnalyzeSecret{
AnalyzeMeta: troubleshootv1beta2.AnalyzeMeta{
CheckName: "Misconfigured",
},
Namespace: "default",
SecretName: "does-not-exist",
Outcomes: []*troubleshootv1beta2.Outcome{},
},
mockFiles: map[string][]byte{
"secrets/default/does-not-exist.json": mustJSONMarshalIndent(t, collect.SecretOutput{
Namespace: "default",
Name: "does-not-exist",
SecretExists: false,
}),
},
wantErr: true,
},
{
name: "key not found secret not found",
analyzer: &troubleshootv1beta2.AnalyzeSecret{
@@ -190,6 +302,128 @@ func Test_analyzeSecret(t *testing.T) {
},
wantErr: true, // TODO: should this be a not found error? This will not work with selectors.
},
{
name: "combined fail and pass in a single outcome, secret found uses the pass outcome",
analyzer: &troubleshootv1beta2.AnalyzeSecret{
Namespace: "test-namespace",
SecretName: "test-secret",
Outcomes: []*troubleshootv1beta2.Outcome{
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "Not found",
},
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "Found",
URI: "https://example.com/found",
},
},
},
},
mockFiles: map[string][]byte{
"secrets/test-namespace/test-secret.json": mustJSONMarshalIndent(t, collect.SecretOutput{
Namespace: "test-namespace",
Name: "test-secret",
SecretExists: true,
}),
},
want: &AnalyzeResult{
IsPass: true,
Message: "Found",
URI: "https://example.com/found",
Title: "Secret test-secret",
IconKey: "kubernetes_analyze_secret",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/secret.svg?w=13&h=16",
},
},
{
name: "combined fail and pass in a single outcome, secret not found uses the fail outcome",
analyzer: &troubleshootv1beta2.AnalyzeSecret{
Namespace: "test-namespace",
SecretName: "test-secret",
Outcomes: []*troubleshootv1beta2.Outcome{
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "Not found",
},
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "Found",
},
},
},
},
mockFiles: map[string][]byte{
"secrets/test-namespace/test-secret.json": mustJSONMarshalIndent(t, collect.SecretOutput{
Namespace: "test-namespace",
Name: "test-secret",
SecretExists: false,
}),
},
want: &AnalyzeResult{
IsFail: true,
Message: "Not found",
Title: "Secret test-secret",
IconKey: "kubernetes_analyze_secret",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/secret.svg?w=13&h=16",
},
},
{
name: "secret found with URI-only pass outcome preserves the empty message and URI",
analyzer: &troubleshootv1beta2.AnalyzeSecret{
Namespace: "test-namespace",
SecretName: "test-secret",
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
URI: "https://example.com/pass",
},
},
},
},
mockFiles: map[string][]byte{
"secrets/test-namespace/test-secret.json": mustJSONMarshalIndent(t, collect.SecretOutput{
Namespace: "test-namespace",
Name: "test-secret",
SecretExists: true,
}),
},
want: &AnalyzeResult{
IsPass: true,
Message: "",
URI: "https://example.com/pass",
Title: "Secret test-secret",
IconKey: "kubernetes_analyze_secret",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/secret.svg?w=13&h=16",
},
},
{
name: "secret not found with URI-only fail outcome preserves the empty message and URI",
analyzer: &troubleshootv1beta2.AnalyzeSecret{
Namespace: "test-namespace",
SecretName: "test-secret",
Outcomes: []*troubleshootv1beta2.Outcome{
{
Fail: &troubleshootv1beta2.SingleOutcome{
URI: "https://example.com/fail",
},
},
},
},
mockFiles: map[string][]byte{
"secrets/test-namespace/test-secret.json": mustJSONMarshalIndent(t, collect.SecretOutput{
Namespace: "test-namespace",
Name: "test-secret",
SecretExists: false,
}),
},
want: &AnalyzeResult{
IsFail: true,
Message: "",
URI: "https://example.com/fail",
Title: "Secret test-secret",
IconKey: "kubernetes_analyze_secret",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/secret.svg?w=13&h=16",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {