From ef63058d6a4460a57cb4e5f41b58f4b8d8109e28 Mon Sep 17 00:00:00 2001 From: Ben Apprederisse Date: Wed, 27 May 2026 08:23:13 -0700 Subject: [PATCH] Set EKS EOL to extended support end Amp-Thread-ID: https://ampcode.com/threads/T-019e51fa-d856-7759-b0c7-80cbedf2f6cc Co-authored-by: Amp --- pkg/config/defaults/resources.yaml | 9 ++++++--- pkg/config/loader_test.go | 3 +++ pkg/eol/endoflife/ADAPTERS.md | 14 +++++++++----- pkg/eol/endoflife/adapters_test.go | 24 +++++++++++++++--------- pkg/eol/endoflife/provider_test.go | 11 +++++++---- pkg/policy/messages_test.go | 11 +++++++++++ 6 files changed, 51 insertions(+), 21 deletions(-) diff --git a/pkg/config/defaults/resources.yaml b/pkg/config/defaults/resources.yaml index 8a74588..501e2db 100644 --- a/pkg/config/defaults/resources.yaml +++ b/pkg/config/defaults/resources.yaml @@ -122,9 +122,12 @@ resources: field: extendedSupport bool_true_fallback: eol deprecated_window: extended_support - # EKS clusters keep running after extended support, but AWS stops - # patching them. Leave eol_date unset and classify post-extended as - # unsupported rather than true EOL. + # EKS true EOL is the end of extended support. The upstream + # extendedSupport field is now a date; if archived data has the old + # boolean shape, eol_date stays unset rather than treating the end of + # standard support as terminal EOL. + eol_date: + field: extendedSupport past_extended_support: unsupported # ElastiCache is split per-engine because each engine has its own diff --git a/pkg/config/loader_test.go b/pkg/config/loader_test.go index ec47218..1a72a34 100644 --- a/pkg/config/loader_test.go +++ b/pkg/config/loader_test.go @@ -109,6 +109,8 @@ resources: extended_support_end: field: extendedSupport bool_true_fallback: eol + eol_date: + field: extendedSupport deprecated_window: extended_support past_extended_support: unsupported ` @@ -127,6 +129,7 @@ resources: assert.Equal(t, "declarative", cfg.Resources[1].EOL.Schema) require.NotNil(t, cfg.Resources[1].EOL.Lifecycle) assert.Equal(t, "eol", cfg.Resources[1].EOL.Lifecycle.DeprecationDate.Field) + assert.Equal(t, "extendedSupport", cfg.Resources[1].EOL.Lifecycle.EOLDate.Field) } // TestLoadResourcesConfig_EmbeddedDefault asserts the binary works diff --git a/pkg/eol/endoflife/ADAPTERS.md b/pkg/eol/endoflife/ADAPTERS.md index fd653cd..d919a89 100644 --- a/pkg/eol/endoflife/ADAPTERS.md +++ b/pkg/eol/endoflife/ADAPTERS.md @@ -88,8 +88,9 @@ Supported actions: ### EKS -EKS cycle `eol` means end of standard support, not true EOL. Clusters -keep running after extended support, but AWS stops patching them. +EKS cycle `eol` means end of standard support, not true EOL. +`extendedSupport` is the end of paid extended support and the terminal +EOL date used in findings. ```yaml eol: @@ -102,6 +103,8 @@ eol: extended_support_end: field: extendedSupport bool_true_fallback: eol + eol_date: + field: extendedSupport deprecated_window: extended_support past_extended_support: unsupported ``` @@ -111,14 +114,15 @@ For amazon-eks cycle 1.30 (`eol: 2025-07-23`, | Field | Value | Source / note | | --- | --- | --- | -| `EOLDate` | `nil` | omitted in YAML | +| `EOLDate` | `2026-07-23` | `cycle.extendedSupport` | | `DeprecationDate` | `2025-07-23` | `cycle.eol` | | `ExtendedSupportEnd` | `2026-07-23` | `cycle.extendedSupport` | | `IsExtendedSupport` | `true` | `deprecated_window: extended_support` | Policy classifies that as YELLOW. Past `extendedSupport`, the -`past_extended_support: unsupported` action makes it RED without -claiming the cluster has a true EOL date. +`EOLDate` check makes it RED. The `past_extended_support: unsupported` +fallback only matters for archived data where `extendedSupport` was a +boolean and no terminal EOL date is available. ### Lambda diff --git a/pkg/eol/endoflife/adapters_test.go b/pkg/eol/endoflife/adapters_test.go index 72ebe98..c30c980 100644 --- a/pkg/eol/endoflife/adapters_test.go +++ b/pkg/eol/endoflife/adapters_test.go @@ -253,6 +253,7 @@ func eksDeclarativeAdapter(t *testing.T) *DeclarativeSchemaAdapter { Field: lifecycleFieldExtendedSupport, BoolTrueFallback: lifecycleFieldEOL, }, + EOLDate: LifecycleDateSource{Field: lifecycleFieldExtendedSupport}, DeprecatedWindow: lifecycleActionExtendedSupport, PastExtendedSupport: lifecycleActionUnsupported, }) @@ -351,12 +352,13 @@ func TestDeclarativeSchemaAdapter_EKSCurrentVersion(t *testing.T) { assert.False(t, lifecycle.IsEOL) assert.False(t, lifecycle.IsExtendedSupport) - // EKS has NO true EOL. - assert.Nil(t, lifecycle.EOLDate) + // EKS true EOL is the end of extended support. + assert.NotNil(t, lifecycle.EOLDate) // DeprecationDate = cycle.eol (end of standard support). assert.NotNil(t, lifecycle.DeprecationDate) - // ExtendedSupportEnd = cycle.extendedSupport. + // ExtendedSupportEnd and EOLDate = cycle.extendedSupport. assert.NotNil(t, lifecycle.ExtendedSupportEnd) + assert.Equal(t, *lifecycle.ExtendedSupportEnd, *lifecycle.EOLDate) } func TestDeclarativeSchemaAdapter_EKSInExtendedSupport(t *testing.T) { @@ -378,8 +380,9 @@ func TestDeclarativeSchemaAdapter_EKSInExtendedSupport(t *testing.T) { assert.True(t, lifecycle.IsSupported) assert.True(t, lifecycle.IsDeprecated) - assert.False(t, lifecycle.IsEOL) // EKS never truly EOL + assert.False(t, lifecycle.IsEOL) assert.True(t, lifecycle.IsExtendedSupport) + assert.NotNil(t, lifecycle.EOLDate) } func TestDeclarativeSchemaAdapter_EKSPastExtendedSupport(t *testing.T) { @@ -398,11 +401,11 @@ func TestDeclarativeSchemaAdapter_EKSPastExtendedSupport(t *testing.T) { assert.False(t, lifecycle.IsSupported) assert.True(t, lifecycle.IsDeprecated) - assert.False(t, lifecycle.IsEOL) // EKS clusters keep running + assert.True(t, lifecycle.IsEOL) assert.False(t, lifecycle.IsExtendedSupport) } -func TestDeclarativeSchemaAdapter_EKSNoTrueEOL(t *testing.T) { +func TestDeclarativeSchemaAdapter_EKSEOLIsExtendedSupportEnd(t *testing.T) { adapter := eksDeclarativeAdapter(t) cycle := &ProductCycle{ @@ -415,12 +418,13 @@ func TestDeclarativeSchemaAdapter_EKSNoTrueEOL(t *testing.T) { lifecycle, err := adapter.AdaptCycle(cycle) require.NoError(t, err) - // Verify EKS has NO true EOL date. - assert.Nil(t, lifecycle.EOLDate) + // Verify EKS true EOL is the end of extended support. + assert.NotNil(t, lifecycle.EOLDate) + expectedDate, _ := time.Parse("2006-01-02", "2022-07-15") + assert.Equal(t, expectedDate, *lifecycle.EOLDate) // ExtendedSupportEnd comes from cycle.extendedSupport (NOT cycle.eol). assert.NotNil(t, lifecycle.ExtendedSupportEnd) - expectedDate, _ := time.Parse("2006-01-02", "2022-07-15") assert.Equal(t, expectedDate, *lifecycle.ExtendedSupportEnd) // DeprecationDate comes from cycle.eol (end of standard support). @@ -453,6 +457,8 @@ func TestDeclarativeSchemaAdapter_EKSLegacyBooleanExtendedSupport(t *testing.T) assert.False(t, lifecycle.IsSupported) assert.True(t, lifecycle.IsDeprecated) assert.False(t, lifecycle.IsExtendedSupport) + // Legacy boolean extendedSupport has no terminal date, so EOLDate stays nil + // rather than using cycle.eol (standard-support end) as true EOL. assert.Nil(t, lifecycle.EOLDate) } diff --git a/pkg/eol/endoflife/provider_test.go b/pkg/eol/endoflife/provider_test.go index 30df91c..c8f1ae8 100644 --- a/pkg/eol/endoflife/provider_test.go +++ b/pkg/eol/endoflife/provider_test.go @@ -340,6 +340,7 @@ func TestProvider_DeclarativeLifecycle(t *testing.T) { Field: lifecycleFieldExtendedSupport, BoolTrueFallback: lifecycleFieldEOL, }, + EOLDate: LifecycleDateSource{Field: lifecycleFieldExtendedSupport}, DeprecatedWindow: lifecycleActionExtendedSupport, PastExtendedSupport: lifecycleActionUnsupported, } @@ -370,14 +371,16 @@ func TestProvider_DeclarativeLifecycle(t *testing.T) { t.Errorf("Expected version 1.32, got %s", v.Version) } // Declarative EKS config: cycle.EOL → DeprecationDate and - // cycle.ExtendedSupport → ExtendedSupportEnd. EOLDate stays nil - // because EKS clusters never truly EOL. - if v.EOLDate != nil { - t.Errorf("EOLDate = %v, want nil (EKS has no true EOL)", v.EOLDate) + // cycle.ExtendedSupport → ExtendedSupportEnd and EOLDate. + if v.EOLDate == nil { + t.Error("EOLDate should be set from cycle.ExtendedSupport") } if v.ExtendedSupportEnd == nil { t.Error("ExtendedSupportEnd should be set from cycle.ExtendedSupport") } + if v.EOLDate != nil && v.ExtendedSupportEnd != nil && !v.EOLDate.Equal(*v.ExtendedSupportEnd) { + t.Errorf("EOLDate = %v, want ExtendedSupportEnd %v", v.EOLDate, v.ExtendedSupportEnd) + } }) } } diff --git a/pkg/policy/messages_test.go b/pkg/policy/messages_test.go index c3d9836..7296564 100644 --- a/pkg/policy/messages_test.go +++ b/pkg/policy/messages_test.go @@ -65,6 +65,17 @@ func TestGetMessage_Yellow_ExtendedSupport(t *testing.T) { assert.Contains(t, got, "extended support") } +func TestGetMessage_Yellow_ExtendedSupport_WithEOL(t *testing.T) { + p := NewDefaultPolicy() + res := &types.Resource{Engine: "eks", CurrentVersion: "1.32"} + eol := time.Date(2027, 3, 23, 0, 0, 0, 0, time.UTC) + lc := &types.VersionLifecycle{IsExtendedSupport: true, EOLDate: &eol} + + got := p.GetMessage(res, lc, types.StatusYellow) + assert.Contains(t, got, "extended support") + assert.NotContains(t, got, "End-of-Life") +} + func TestGetMessage_Yellow_DeprecatedSupport_WithEOL(t *testing.T) { // Lambda-style: IsDeprecatedSupport with a deprecated-support // end date. Exercises the IsDeprecatedSupport+EOLDate branch and