Skip to content

Commit 3d2d2d0

Browse files
committed
feat: add case-insensitive-condition-tracking feature gate
Custom resources whose readiness lives in status.conditions were never tracked by the heuristic, because kubedog built its universal condition rules from lowercase type names while real resources use CamelCase. Fixing that makes previously instantly-ready resources start blocking, so it is opt-in: NELM_FEAT_CASE_INSENSITIVE_CONDITION_TRACKING=true forwards the option to the readiness tracker, and the gate defaults to off. The CloudNativePG Cluster fix that prompted this is deliberately not behind the gate — it is an exact rule in kubedog and applies unconditionally. Signed-off-by: Ilya Lesikov <ilya@lesikov.com>
1 parent 03f2c3d commit 3d2d2d0

6 files changed

Lines changed: 52 additions & 3 deletions

File tree

docs/reference.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
- [NELM_FEAT_RESOURCE_VALIDATION](#nelm_feat_resource_validation)
5858
- [NELM_FEAT_TYPESCRIPT](#nelm_feat_typescript)
5959
- [NELM_FEAT_ADOPT_DECKHOUSE_CONTROLLER_FIELDS](#nelm_feat_adopt_deckhouse_controller_fields)
60+
- [NELM_FEAT_CASE_INSENSITIVE_CONDITION_TRACKING](#nelm_feat_case_insensitive_condition_tracking)
6061

6162
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
6263

@@ -4172,3 +4173,9 @@ Enable TypeScript chart rendering from ts/ directory
41724173
41734174
Adopt managed fields owned by the legacy "deckhouse\-controller" field manager \(the pre\-nelm Helm 3 engine\)\. Unsafe if any resource still has hook\-owned "deckhouse\-controller" entries
41744175
4176+
### NELM_FEAT_CASE_INSENSITIVE_CONDITION_TRACKING
4177+
4178+
**Default:** `false`
4179+
4180+
Match custom resource status condition types case\-insensitively when detecting readiness \(e\.g\. "Ready" in addition to "ready"\)
4181+

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ require (
5858
github.com/tidwall/sjson v1.2.5
5959
github.com/wI2L/jsondiff v0.5.0
6060
github.com/werf/common-go v0.0.0-20251113140850-a1a98e909e9b
61-
github.com/werf/kubedog v0.13.1-0.20260616105957-2c00b08fb99e
61+
github.com/werf/kubedog v0.13.1-0.20260807102355-7594d35e19d0
6262
github.com/werf/lockgate v0.1.1
6363
github.com/werf/logboek v0.6.1
6464
github.com/xeipuuv/gojsonschema v1.2.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,8 @@ github.com/wI2L/jsondiff v0.5.0 h1:RRMTi/mH+R2aXcPe1VYyvGINJqQfC3R+KSEakuU1Ikw=
435435
github.com/wI2L/jsondiff v0.5.0/go.mod h1:qqG6hnK0Lsrz2BpIVCxWiK9ItsBCpIZQiv0izJjOZ9s=
436436
github.com/werf/common-go v0.0.0-20251113140850-a1a98e909e9b h1:58850oFrnw5Jy5YaB8QifXz75qpGotfx6qqZ9Q2my1A=
437437
github.com/werf/common-go v0.0.0-20251113140850-a1a98e909e9b/go.mod h1:MXS0JR9zut+oR9oEM8PEkdXXoEbKDILTmWopt0z1eZs=
438-
github.com/werf/kubedog v0.13.1-0.20260616105957-2c00b08fb99e h1:0GnrtMMti+Qywd4bs4tHtchBS61EzS6t1NYqMPql5dE=
439-
github.com/werf/kubedog v0.13.1-0.20260616105957-2c00b08fb99e/go.mod h1:gu4EY4hxtiYVDy5o6WE2lRZS0YWqrOV0HS//GTYyrUE=
438+
github.com/werf/kubedog v0.13.1-0.20260807102355-7594d35e19d0 h1:RdMaIksB+mPKVEq5zYPA9M5Vd0HwzX67My4CboPAXfE=
439+
github.com/werf/kubedog v0.13.1-0.20260807102355-7594d35e19d0/go.mod h1:gu4EY4hxtiYVDy5o6WE2lRZS0YWqrOV0HS//GTYyrUE=
440440
github.com/werf/lockgate v0.1.1 h1:S400JFYjtWfE4i4LY9FA8zx0fMdfui9DPrBiTciCrx4=
441441
github.com/werf/lockgate v0.1.1/go.mod h1:0yIFSLq9ausy6ejNxF5uUBf/Ib6daMAfXuCaTMZJzIE=
442442
github.com/werf/logboek v0.6.1 h1:oEe6FkmlKg0z0n80oZjLplj6sXcBeLleCkjfOOZEL2g=

pkg/featgate/feat.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ var (
5757
"adopt-deckhouse-controller-fields",
5858
`Adopt managed fields owned by the legacy "deckhouse-controller" field manager (the pre-nelm Helm 3 engine). Unsafe if any resource still has hook-owned "deckhouse-controller" entries`,
5959
)
60+
FeatGateCaseInsensitiveConditionTracking = NewFeatGate(
61+
"case-insensitive-condition-tracking",
62+
`Match custom resource status condition types case-insensitively when detecting readiness (e.g. "Ready" in addition to "ready")`,
63+
)
6064
)
6165

6266
// A feature gate, which enabled/disables a specific feature. Can be toggled via an env var or

pkg/featgate/feat_ai_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//go:build ai_tests
2+
3+
package featgate
4+
5+
import (
6+
"testing"
7+
8+
"github.com/samber/lo"
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestAI_CaseInsensitiveConditionTracking_EnvVarName(t *testing.T) {
14+
assert.Equal(t, "NELM_FEAT_CASE_INSENSITIVE_CONDITION_TRACKING", FeatGateCaseInsensitiveConditionTracking.EnvVarName())
15+
assert.Equal(t, "case-insensitive-condition-tracking", FeatGateCaseInsensitiveConditionTracking.Name)
16+
}
17+
18+
func TestAI_CaseInsensitiveConditionTracking_OnlyTrueEnables(t *testing.T) {
19+
assert.False(t, FeatGateCaseInsensitiveConditionTracking.Default())
20+
21+
for _, value := range []string{"", "1", "yes", "TRUE", "True", "false"} {
22+
t.Setenv(FeatGateCaseInsensitiveConditionTracking.EnvVarName(), value)
23+
assert.False(t, FeatGateCaseInsensitiveConditionTracking.Enabled(), "value %q must not enable the gate", value)
24+
}
25+
26+
t.Setenv(FeatGateCaseInsensitiveConditionTracking.EnvVarName(), "true")
27+
assert.True(t, FeatGateCaseInsensitiveConditionTracking.Enabled())
28+
}
29+
30+
func TestAI_CaseInsensitiveConditionTracking_Registered(t *testing.T) {
31+
_, found := lo.Find(FeatGates, func(fg *FeatGate) bool {
32+
return fg == FeatGateCaseInsensitiveConditionTracking
33+
})
34+
35+
require.True(t, found, "gate must be registered in FeatGates so CLI usage and reference docs pick it up")
36+
}

pkg/plan/plan_execute.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/werf/kubedog/pkg/trackers/dyntracker/statestore"
1616
kdutil "github.com/werf/kubedog/pkg/trackers/dyntracker/util"
1717
"github.com/werf/nelm/pkg/common"
18+
"github.com/werf/nelm/pkg/featgate"
1819
"github.com/werf/nelm/pkg/kube"
1920
"github.com/werf/nelm/pkg/log"
2021
"github.com/werf/nelm/pkg/release"
@@ -273,6 +274,7 @@ func execOpTrackReadiness(ctx context.Context, op *Operation, releaseNamespace s
273274
Timeout: timeout,
274275
NoActivityTimeout: opConfig.NoActivityTimeout,
275276
IgnoreReadinessProbeFailsByContainerName: opConfig.IgnoreReadinessProbeFailsByContainerName,
277+
CaseInsensitiveConditionTracking: featgate.FeatGateCaseInsensitiveConditionTracking.Enabled(),
276278
SaveLogsOnlyForNumberOfReplicas: opConfig.SaveLogsOnlyForNumberOfReplicas,
277279
SaveLogsOnlyForContainers: opConfig.SaveLogsOnlyForContainers,
278280
SaveLogsByRegex: opConfig.SaveLogsByRegex,

0 commit comments

Comments
 (0)