diff --git a/internal/gatewayapi/backendtlspolicy.go b/internal/gatewayapi/backendtlspolicy.go index 4564a9b4ab..4f3e01530f 100644 --- a/internal/gatewayapi/backendtlspolicy.go +++ b/internal/gatewayapi/backendtlspolicy.go @@ -476,7 +476,7 @@ func (t *Translator) getCaCertsFromCARefs( case resource.KindConfigMap: cm := t.GetConfigMap(namespace, string(caRef.Name)) if cm != nil { - if crt, dataOk := getOrFirstFromData(cm.Data, caCertKey); dataOk { + if crt, dataOk := getOrFirstFromData(cm.Data, CACertKey); dataOk { if ca != "" { ca += "\n" } @@ -490,7 +490,7 @@ func (t *Translator) getCaCertsFromCARefs( case resource.KindSecret: secret := t.GetSecret(namespace, string(caRef.Name)) if secret != nil { - if crt, dataOk := getOrFirstFromData(secret.Data, caCertKey); dataOk { + if crt, dataOk := getOrFirstFromData(secret.Data, CACertKey); dataOk { if ca != "" { ca += "\n" } diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go index d67171cb79..e1a0c8ea45 100644 --- a/internal/gatewayapi/backendtrafficpolicy.go +++ b/internal/gatewayapi/backendtrafficpolicy.go @@ -32,6 +32,8 @@ import ( const ( MaxConsistentHashTableSize = 5000011 // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster-maglevlbconfig + // ResponseBodyConfigMapKey is the key used in ConfigMaps to store custom response body data + ResponseBodyConfigMapKey = "response.body" ) // deprecatedFieldsUsedInBackendTrafficPolicy returns a map of deprecated field paths to their alternatives. @@ -1561,7 +1563,7 @@ func (t *Translator) getCustomResponseBody( if body.Type != nil && *body.Type == egv1a1.ResponseValueTypeValueRef { cm := t.GetConfigMap(policyNs, string(body.ValueRef.Name)) if cm != nil { - b, dataOk := cm.Data["response.body"] + b, dataOk := cm.Data[ResponseBodyConfigMapKey] switch { case dataOk: data := []byte(b) @@ -1576,7 +1578,7 @@ func (t *Translator) getCustomResponseBody( return binData, nil } default: - return nil, fmt.Errorf("can't find the key response.body in the referenced configmap %s", body.ValueRef.Name) + return nil, fmt.Errorf("can't find the key %s in the referenced configmap %s", ResponseBodyConfigMapKey, body.ValueRef.Name) } } else { return nil, fmt.Errorf("can't find the referenced configmap %s", body.ValueRef.Name) diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index dde8387847..3505752042 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -837,7 +837,7 @@ func (t *Translator) buildListenerTLSParameters( } for _, caCertRef := range tlsParams.ClientValidation.CACertificateRefs { - caCertBytes, err := t.validateAndGetDataAtKeyInRef(caCertRef, caCertKey, resources, from) + caCertBytes, err := t.validateAndGetDataAtKeyInRef(caCertRef, CACertKey, resources, from) if err != nil { return irTLSConfig, fmt.Errorf("failed to get certificate from ref: %w", err) } @@ -867,7 +867,7 @@ func (t *Translator) buildListenerTLSParameters( if tlsParams.ClientValidation.Crl != nil { for _, crlRef := range tlsParams.ClientValidation.Crl.Refs { - crlBytes, err := t.validateAndGetDataAtKeyInRef(crlRef, crlKey, resources, from) + crlBytes, err := t.validateAndGetDataAtKeyInRef(crlRef, CRLKey, resources, from) if err != nil { return irTLSConfig, fmt.Errorf("failed to get crl from ref: %w", err) } diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go index 59e2592feb..bd142ffc37 100644 --- a/internal/gatewayapi/envoyextensionpolicy.go +++ b/internal/gatewayapi/envoyextensionpolicy.go @@ -31,7 +31,11 @@ import ( ) // oci URL prefix -const ociURLPrefix = "oci://" +const ( + ociURLPrefix = "oci://" + // LuaConfigMapKey is the key used in ConfigMaps to store Lua scripts + LuaConfigMapKey = "lua" +) // deprecatedFieldsUsedInEnvoyExtensionPolicy returns a map of deprecated field paths to their alternatives. func deprecatedFieldsUsedInEnvoyExtensionPolicy(policy *egv1a1.EnvoyExtensionPolicy) map[string]string { @@ -725,7 +729,7 @@ func (t *Translator) getLuaBodyFromLocalObjectReference( ) (*string, error) { cm := t.GetConfigMap(policyNs, string(valueRef.Name)) if cm != nil { - b, dataOk := cm.Data["lua"] + b, dataOk := cm.Data[LuaConfigMapKey] switch { case dataOk: return &b, nil @@ -736,7 +740,7 @@ func (t *Translator) getLuaBodyFromLocalObjectReference( } return &b, nil default: - return nil, fmt.Errorf("can't find the key lua in the referenced configmap %s", valueRef.Name) + return nil, fmt.Errorf("can't find the key %s in the referenced configmap %s", LuaConfigMapKey, valueRef.Name) } } else { diff --git a/internal/gatewayapi/helpers.go b/internal/gatewayapi/helpers.go index dc3e73dd28..d676c08e37 100644 --- a/internal/gatewayapi/helpers.go +++ b/internal/gatewayapi/helpers.go @@ -37,8 +37,10 @@ const ( L4Protocol = "L4" L7Protocol = "L7" - caCertKey = "ca.crt" - crlKey = "ca.crl" + // CACertKey is the key used in ConfigMaps and Secrets to store CA certificate data + CACertKey = "ca.crt" + // CRLKey is the key used in ConfigMaps and Secrets to store certificate revocation list data + CRLKey = "ca.crl" ) type NamespacedNameWithSection struct { @@ -464,11 +466,11 @@ func irTLSListenerConfigName(secret *corev1.Secret) string { } func irTLSCACertName(namespace, name string) string { - return fmt.Sprintf("%s/%s/%s", namespace, name, caCertKey) + return fmt.Sprintf("%s/%s/%s", namespace, name, CACertKey) } func irTLSCrlName(namespace, name string) string { - return fmt.Sprintf("%s/%s/%s", namespace, name, crlKey) + return fmt.Sprintf("%s/%s/%s", namespace, name, CRLKey) } func IsMergeGatewaysEnabled(resources *resource.Resources) bool { diff --git a/internal/gatewayapi/helpers_test.go b/internal/gatewayapi/helpers_test.go index aa197d2a0c..9d24569f17 100644 --- a/internal/gatewayapi/helpers_test.go +++ b/internal/gatewayapi/helpers_test.go @@ -757,7 +757,7 @@ func TestGetCaCertFromConfigMap(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - got, found := getOrFirstFromData(tc.cm.Data, caCertKey) + got, found := getOrFirstFromData(tc.cm.Data, CACertKey) require.Equal(t, tc.expectedFound, found) require.Equal(t, tc.expected, got) }) @@ -803,7 +803,7 @@ func TestGetCaCertFromSecret(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - got, found := getOrFirstFromData(tc.s.Data, caCertKey) + got, found := getOrFirstFromData(tc.s.Data, CACertKey) require.Equal(t, tc.expectedFound, found) require.Equal(t, tc.expected, string(got)) }) diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go index 2e937bee7a..97e4fb0ec5 100644 --- a/internal/gatewayapi/securitypolicy.go +++ b/internal/gatewayapi/securitypolicy.go @@ -49,6 +49,8 @@ const ( // nolint: gosec oidcHMACSecretName = "envoy-oidc-hmac" oidcHMACSecretKey = "hmac-secret" + // JWKSConfigMapKey is the key used in ConfigMaps to store JWKS data + JWKSConfigMapKey = "jwks" ) // deprecatedFieldsUsedInSecurityPolicy returns a map of deprecated field paths to their alternatives. @@ -1228,7 +1230,7 @@ func (t *Translator) buildLocalJWKS( return "", fmt.Errorf("local JWKS ConfigMap %s/%s not found", policy.Namespace, localJWKS.ValueRef.Name) } - jwksBytes, ok := cm.Data["jwks"] + jwksBytes, ok := cm.Data[JWKSConfigMapKey] if ok { return jwksBytes, nil } @@ -1240,7 +1242,8 @@ func (t *Translator) buildLocalJWKS( } return "", fmt.Errorf( - "JWKS data not found in ConfigMap %s/%s, no 'jwks' key and no other data found", + "JWKS data not found in ConfigMap %s/%s, no %q key and no other data found", + JWKSConfigMapKey, cm.Namespace, cm.Name) } diff --git a/internal/provider/kubernetes/helpers.go b/internal/provider/kubernetes/helpers.go index cb86dac512..fb9a96c39d 100644 --- a/internal/provider/kubernetes/helpers.go +++ b/internal/provider/kubernetes/helpers.go @@ -12,6 +12,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + toolscache "k8s.io/client-go/tools/cache" "sigs.k8s.io/controller-runtime/pkg/client" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" mcsapiv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" @@ -25,6 +26,33 @@ const ( gatewayClassFinalizer = gwapiv1.GatewayClassFinalizerGatewaysExist ) +var ( + // cachedConfigMapKeys defines the keys to keep in ConfigMap data cache + cachedConfigMapKeys = map[string]bool{ + gatewayapi.JWKSConfigMapKey: true, + gatewayapi.LuaConfigMapKey: true, + gatewayapi.ResponseBodyConfigMapKey: true, + gatewayapi.CACertKey: true, + gatewayapi.CRLKey: true, + } + + // cachedSecretKeys defines the keys to keep in Secret data cache + cachedSecretKeys = map[string]bool{ + corev1.TLSCertKey: true, + corev1.TLSPrivateKeyKey: true, + egv1a1.TLSOCSPKey: true, + egv1a1.OIDCClientIDKey: true, + egv1a1.OIDCClientSecretKey: true, + egv1a1.BasicAuthUsersSecretKey: true, + egv1a1.InjectedCredentialKey: true, + egv1a1.APIKeysSecretKey: true, + corev1.DockerConfigJsonKey: true, + gatewayapi.CACertKey: true, + gatewayapi.CRLKey: true, + hmacSecretKey: true, + } +) + type ObjectKindNamespacedName struct { kind string namespace string @@ -162,3 +190,58 @@ func classAccepted(gc *gwapiv1.GatewayClass) bool { return false } + +// expectedAndFirstFallbackFilter filters a data map to only keep expected keys plus the first key for fallback. +func expectedAndFirstFallbackFilter[T any](data map[string]T, expectedKeys map[string]bool) map[string]T { + filtered := make(map[string]T, min(len(expectedKeys)+1, len(data))) + firstFallbackKey := "" // to track lexicographically first key for fallback + for k := range data { + if expectedKeys[k] { + filtered[k] = data[k] + } + if firstFallbackKey == "" || k < firstFallbackKey { + firstFallbackKey = k + } + } + filtered[firstFallbackKey] = data[firstFallbackKey] + return filtered +} + +// transformConfigMapData filters ConfigMap data to only keep needed keys to reduce memory usage. +func transformConfigMapData(obj interface{}) (interface{}, error) { + cm, ok := obj.(*corev1.ConfigMap) + if !ok || len(cm.Data) <= 1 { + return obj, nil + } + + cm.Data = expectedAndFirstFallbackFilter(cm.Data, cachedConfigMapKeys) + return cm, nil +} + +// transformSecretData filters Secret data to only keep needed keys to reduce memory usage. +func transformSecretData(obj interface{}) (interface{}, error) { + secret, ok := obj.(*corev1.Secret) + if !ok || len(secret.Data) <= 1 { + return obj, nil + } + + secret.Data = expectedAndFirstFallbackFilter(secret.Data, cachedSecretKeys) + return secret, nil +} + +// composeTransforms chains multiple transform functions together. +func composeTransforms(transforms ...toolscache.TransformFunc) toolscache.TransformFunc { + return func(obj interface{}) (interface{}, error) { + var err error + for _, transform := range transforms { + if transform == nil { + continue + } + obj, err = transform(obj) + if err != nil { + return nil, err + } + } + return obj, nil + } +} diff --git a/internal/provider/kubernetes/helpers_test.go b/internal/provider/kubernetes/helpers_test.go index 6a0df0f678..7fb645e634 100644 --- a/internal/provider/kubernetes/helpers_test.go +++ b/internal/provider/kubernetes/helpers_test.go @@ -9,7 +9,9 @@ import ( "testing" "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/cache" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" @@ -434,3 +436,370 @@ func TestClassAccepted(t *testing.T) { }) } } + +func TestTransformConfigMapData(t *testing.T) { + testCases := []struct { + name string + input interface{} + expected map[string]string + }{ + { + name: "nil configmap", + input: nil, + expected: nil, + }, + { + name: "non-configmap object", + input: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + }, + expected: nil, + }, + { + name: "configmap with single key - no filtering", + input: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string]string{ + "key1": "value1", + }, + }, + expected: map[string]string{ + "key1": "value1", + }, + }, + { + name: "configmap with cached keys only", + input: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string]string{ + gatewayapi.JWKSConfigMapKey: "jwks-data", + gatewayapi.LuaConfigMapKey: "lua-data", + gatewayapi.ResponseBodyConfigMapKey: "response-body-data", + }, + }, + expected: map[string]string{ + gatewayapi.JWKSConfigMapKey: "jwks-data", + gatewayapi.LuaConfigMapKey: "lua-data", + gatewayapi.ResponseBodyConfigMapKey: "response-body-data", + }, + }, + { + name: "configmap with cached and non-cached keys", + input: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string]string{ + gatewayapi.JWKSConfigMapKey: "jwks-data", + gatewayapi.LuaConfigMapKey: "lua-data", + "unwanted-key-1": "unwanted-value-1", + "unwanted-key-2": "unwanted-value-2", + gatewayapi.ResponseBodyConfigMapKey: "response-body-data", + }, + }, + expected: map[string]string{ + gatewayapi.JWKSConfigMapKey: "jwks-data", + gatewayapi.LuaConfigMapKey: "lua-data", + gatewayapi.ResponseBodyConfigMapKey: "response-body-data", + // Note: First key "jwks" is expected, so no fallback key is added + }, + }, + { + name: "configmap with only non-cached keys", + input: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string]string{ + "unwanted-key-1": "unwanted-value-1", + "unwanted-key-2": "unwanted-value-2", + "unwanted-key-3": "unwanted-value-3", + }, + }, + expected: map[string]string{ + "unwanted-key-1": "unwanted-value-1", // first fallback key + }, + }, + { + name: "configmap with CACertKey and CRLKey", + input: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string]string{ + gatewayapi.CACertKey: "ca-cert-data", + gatewayapi.CRLKey: "crl-data", + "other-key": "other-value", + }, + }, + expected: map[string]string{ + gatewayapi.CACertKey: "ca-cert-data", + gatewayapi.CRLKey: "crl-data", + // Note: First key "ca.crl" is expected, so no fallback key is added + }, + }, + { + name: "configmap with non-expected key first", + input: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string]string{ + "unwanted-key": "unwanted-value", + gatewayapi.JWKSConfigMapKey: "jwks-data", + gatewayapi.LuaConfigMapKey: "lua-data", + "another-unwanted-key": "another-value", + }, + }, + expected: map[string]string{ + "another-unwanted-key": "another-value", // first key in sorted order, added as fallback + gatewayapi.JWKSConfigMapKey: "jwks-data", + gatewayapi.LuaConfigMapKey: "lua-data", + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + transform := composeTransforms(cache.TransformStripManagedFields(), transformConfigMapData) + + result, err := transform(tc.input) + require.NoError(t, err) + + if tc.expected == nil { + require.Equal(t, tc.input, result) + return + } + + cm, ok := result.(*corev1.ConfigMap) + require.True(t, ok, "result should be a ConfigMap") + if tc.expected != nil { + require.Equal(t, tc.expected, cm.Data) + } + }) + } +} + +func TestTransformSecretData(t *testing.T) { + testCases := []struct { + name string + input interface{} + expected map[string][]byte + }{ + { + name: "nil secret", + input: nil, + expected: nil, + }, + { + name: "non-secret object", + input: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + }, + expected: nil, + }, + { + name: "secret with single key - no filtering", + input: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string][]byte{ + "key1": []byte("value1"), + }, + }, + expected: map[string][]byte{ + "key1": []byte("value1"), + }, + }, + { + name: "secret with cached keys only", + input: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string][]byte{ + corev1.TLSCertKey: []byte("cert-data"), + corev1.TLSPrivateKeyKey: []byte("key-data"), + egv1a1.TLSOCSPKey: []byte("ocsp-data"), + }, + }, + expected: map[string][]byte{ + corev1.TLSCertKey: []byte("cert-data"), + corev1.TLSPrivateKeyKey: []byte("key-data"), + egv1a1.TLSOCSPKey: []byte("ocsp-data"), + }, + }, + { + name: "secret with cached and non-cached keys", + input: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string][]byte{ + corev1.TLSCertKey: []byte("cert-data"), + corev1.TLSPrivateKeyKey: []byte("key-data"), + "unwanted-key-1": []byte("unwanted-value-1"), + "unwanted-key-2": []byte("unwanted-value-2"), + egv1a1.TLSOCSPKey: []byte("ocsp-data"), + }, + }, + expected: map[string][]byte{ + corev1.TLSCertKey: []byte("cert-data"), + corev1.TLSPrivateKeyKey: []byte("key-data"), + egv1a1.TLSOCSPKey: []byte("ocsp-data"), + // Note: First key "tls.crt" is expected, so no fallback key is added + }, + }, + { + name: "secret with only non-cached keys", + input: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string][]byte{ + "unwanted-key-1": []byte("unwanted-value-1"), + "unwanted-key-2": []byte("unwanted-value-2"), + "unwanted-key-3": []byte("unwanted-value-3"), + }, + }, + expected: map[string][]byte{ + "unwanted-key-1": []byte("unwanted-value-1"), // first key in sorted order + }, + }, + { + name: "secret with OIDC keys", + input: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string][]byte{ + egv1a1.OIDCClientIDKey: []byte("client-id"), + egv1a1.OIDCClientSecretKey: []byte("client-secret"), + "other-key": []byte("other-value"), + }, + }, + expected: map[string][]byte{ + egv1a1.OIDCClientIDKey: []byte("client-id"), + egv1a1.OIDCClientSecretKey: []byte("client-secret"), + // Note: First key "client-id" is expected, so no fallback key is added + }, + }, + { + name: "secret with BasicAuth and APIKeys keys", + input: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string][]byte{ + egv1a1.BasicAuthUsersSecretKey: []byte("basic-auth-data"), + egv1a1.APIKeysSecretKey: []byte("api-keys-data"), + "unwanted-key": []byte("unwanted-value"), + }, + }, + expected: map[string][]byte{ + egv1a1.BasicAuthUsersSecretKey: []byte("basic-auth-data"), + egv1a1.APIKeysSecretKey: []byte("api-keys-data"), + // Note: First key ".htpasswd" is expected, so no fallback key is added + }, + }, + { + name: "secret with DockerConfigJsonKey", + input: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string][]byte{ + corev1.DockerConfigJsonKey: []byte("docker-config"), + "other-key": []byte("other-value"), + }, + }, + expected: map[string][]byte{ + corev1.DockerConfigJsonKey: []byte("docker-config"), + // Note: First key ".dockerconfigjson" is expected, so no fallback key is added + }, + }, + { + name: "secret with CACertKey and CRLKey", + input: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string][]byte{ + gatewayapi.CACertKey: []byte("ca-cert-data"), + gatewayapi.CRLKey: []byte("crl-data"), + "other-key": []byte("other-value"), + }, + }, + expected: map[string][]byte{ + gatewayapi.CACertKey: []byte("ca-cert-data"), + gatewayapi.CRLKey: []byte("crl-data"), + // Note: First key "ca.crl" is expected, so no fallback key is added + }, + }, + { + name: "secret with non-expected key first", + input: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Data: map[string][]byte{ + "unwanted-key": []byte("unwanted-value"), + corev1.TLSCertKey: []byte("cert-data"), + corev1.TLSPrivateKeyKey: []byte("key-data"), + "another-unwanted-key": []byte("another-value"), + }, + }, + expected: map[string][]byte{ + "another-unwanted-key": []byte("another-value"), // first key in sorted order, added as fallback + corev1.TLSCertKey: []byte("cert-data"), + corev1.TLSPrivateKeyKey: []byte("key-data"), + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + transform := composeTransforms(cache.TransformStripManagedFields(), transformSecretData) + + result, err := transform(tc.input) + require.NoError(t, err) + + if tc.expected == nil { + require.Equal(t, tc.input, result) + return + } + + secret, ok := result.(*corev1.Secret) + require.True(t, ok, "result should be a Secret") + if tc.expected != nil { + require.Equal(t, tc.expected, secret.Data) + } + }) + } +} diff --git a/internal/provider/kubernetes/kubernetes.go b/internal/provider/kubernetes/kubernetes.go index 8390c7620a..b881f011aa 100644 --- a/internal/provider/kubernetes/kubernetes.go +++ b/internal/provider/kubernetes/kubernetes.go @@ -142,9 +142,11 @@ func newProvider(ctx context.Context, restCfg *rest.Config, svrCfg *ec.Server, // Disable deepcopy for read only resources &corev1.Secret{}: { UnsafeDisableDeepCopy: ptr.To(true), + Transform: composeTransforms(cache.TransformStripManagedFields(), transformSecretData), }, &corev1.ConfigMap{}: { UnsafeDisableDeepCopy: ptr.To(true), + Transform: composeTransforms(cache.TransformStripManagedFields(), transformConfigMapData), }, &corev1.Service{}: { UnsafeDisableDeepCopy: ptr.To(true), diff --git a/release-notes/current.yaml b/release-notes/current.yaml index 19d1962153..786a01cb01 100644 --- a/release-notes/current.yaml +++ b/release-notes/current.yaml @@ -52,6 +52,7 @@ bug fixes: | # Enhancements that improve performance. performance improvements: | + Including only needed keys in Secret and ConfigMap data to reduce memory usage. # Deprecated features or APIs. deprecations: | diff --git a/test/e2e/testdata/lua-http.yaml b/test/e2e/testdata/lua-http.yaml index 37e4252146..d616103a01 100644 --- a/test/e2e/testdata/lua-http.yaml +++ b/test/e2e/testdata/lua-http.yaml @@ -58,8 +58,8 @@ kind: ConfigMap metadata: name: cm-example-lua namespace: gateway-conformance-infra -data: - lua: | +data: # not-lua key is used to test that the it fallbacks to first key + not-lua: | function envoy_on_response(response_handle) response_handle:headers():add("X-Custom-Lua-Header", "lua_value_1") end