From f0e1fd84d8d3c9edc76b90d6603380d729ddfd32 Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Mon, 11 Dec 2023 12:58:21 +0530 Subject: [PATCH 01/14] feat: Allow merging nested values in plugin config secretRef --- .../apisix/translation/apisix_pluginconfig.go | 22 +++--- pkg/providers/utils/merge.go | 21 ++++++ pkg/providers/utils/merge_test.go | 67 +++++++++++++++++++ 3 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 pkg/providers/utils/merge.go create mode 100644 pkg/providers/utils/merge_test.go diff --git a/pkg/providers/apisix/translation/apisix_pluginconfig.go b/pkg/providers/apisix/translation/apisix_pluginconfig.go index f8b322176b..c58a6e28b0 100644 --- a/pkg/providers/apisix/translation/apisix_pluginconfig.go +++ b/pkg/providers/apisix/translation/apisix_pluginconfig.go @@ -15,12 +15,15 @@ package translation import ( + "encoding/json" + "go.uber.org/zap" "github.com/apache/apisix-ingress-controller/pkg/id" configv2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2" "github.com/apache/apisix-ingress-controller/pkg/log" "github.com/apache/apisix-ingress-controller/pkg/providers/translation" + "github.com/apache/apisix-ingress-controller/pkg/providers/utils" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) @@ -33,14 +36,6 @@ func (t *translator) TranslatePluginConfigV2(config *configv2.ApisixPluginConfig continue } if plugin.Config != nil { - // Here, it will override same key. - if t, ok := pluginMap[plugin.Name]; ok { - log.Infow("TranslatePluginConfigV2 override same plugin key", - zap.String("key", plugin.Name), - zap.Any("old", t), - zap.Any("new", plugin.Config), - ) - } if plugin.SecretRef != "" { sec, err := t.SecretLister.Secrets(config.Namespace).Get(plugin.SecretRef) if err != nil { @@ -52,9 +47,18 @@ func (t *translator) TranslatePluginConfigV2(config *configv2.ApisixPluginConfig log.Debugw("Add new items, then override items with the same plugin key", zap.Any("plugin", plugin.Name), zap.String("secretRef", plugin.SecretRef)) + dataMap := make(map[string]interface{}) + for key, value := range sec.Data { - plugin.Config[key] = string(value) + err := json.Unmarshal(value, dataMap[key]) + if err != nil { + log.Errorw("The config secretRef is invalid", + zap.Any("plugin", plugin.Name), + zap.String("secretRef", plugin.SecretRef)) + break + } } + utils.MergeMaps(dataMap, plugin.Config) } pluginMap[plugin.Name] = plugin.Config } else { diff --git a/pkg/providers/utils/merge.go b/pkg/providers/utils/merge.go new file mode 100644 index 0000000000..4478c6d11d --- /dev/null +++ b/pkg/providers/utils/merge.go @@ -0,0 +1,21 @@ +package utils + +// MergeMaps will iterate recursively in src map and copy the fields over to dest +func MergeMaps(src, dest map[string]interface{}) { + for key, val := range src { + //If destination map already has this key then recursively + //call merge with src[key] and dest[key] + if dest[key] != nil { + switch v := val.(type) { + case map[string]interface{}: + destMap, ok := dest[key].(map[string]interface{}) + if !ok { + destMap = make(map[string]interface{}) + } + MergeMaps(v, destMap) + default: + dest[key] = src[key] + } + } + } +} diff --git a/pkg/providers/utils/merge_test.go b/pkg/providers/utils/merge_test.go new file mode 100644 index 0000000000..19b5c5a930 --- /dev/null +++ b/pkg/providers/utils/merge_test.go @@ -0,0 +1,67 @@ +package utils + +import ( + "encoding/json" + "testing" +) + +func TestMergeMaps(t *testing.T) { + type testCase struct { + src string + dest string + merged string + } + testCases := []testCase{{ + dest: `{ + "a":1, + "b":{ + "c":{ + "d":"e" + }, + "f":"g" + } + }`, + src: `{ + "b":{ + "c": 2 + } + }`, + merged: `{ + "a":1, + "b":{ + "c":2, + "f":"g" + } + }`, + }} + + for _, t0 := range testCases { + srcMap := make(map[string]interface{}) + err := json.Unmarshal([]byte(t0.src), &srcMap) + if err != nil { + t.Fatal(err) + } + destMap := make(map[string]interface{}) + err = json.Unmarshal([]byte(t0.dest), &destMap) + if err != nil { + t.Fatal(err) + } + out := make(map[string]interface{}) + err = json.Unmarshal([]byte(t0.merged), &out) + if err != nil { + t.Fatal(err) + } + outB, err := json.MarshalIndent(out, " ", "") + if err != nil { + t.Fatal(err) + } + MergeMaps(srcMap, destMap) + merged, err := json.MarshalIndent(destMap, " ", "") + if err != nil { + t.Fatal(err) + } + if string(outB) != string(merged) { + t.Errorf("Expected %s but got %s", string(outB), string(merged)) + } + } +} From cb18f43956f038489f7bf4c5bd1e52ad11e3c8c3 Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Mon, 11 Dec 2023 13:18:38 +0530 Subject: [PATCH 02/14] add license --- pkg/providers/apisix/translation/apisix_route.go | 13 ++++++++++++- pkg/providers/utils/merge.go | 14 ++++++++++++++ pkg/providers/utils/merge_test.go | 14 ++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/pkg/providers/apisix/translation/apisix_route.go b/pkg/providers/apisix/translation/apisix_route.go index 50d8b65236..985bc98b19 100644 --- a/pkg/providers/apisix/translation/apisix_route.go +++ b/pkg/providers/apisix/translation/apisix_route.go @@ -16,6 +16,7 @@ package translation import ( "context" + "encoding/json" "errors" "fmt" "strconv" @@ -31,6 +32,7 @@ import ( _const "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/const" "github.com/apache/apisix-ingress-controller/pkg/log" "github.com/apache/apisix-ingress-controller/pkg/providers/translation" + "github.com/apache/apisix-ingress-controller/pkg/providers/utils" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) @@ -101,9 +103,18 @@ func (t *translator) translateHTTPRouteV2(ctx *translation.TranslateContext, ar log.Debugw("Add new items, then override items with the same plugin key", zap.Any("plugin", plugin.Name), zap.String("secretRef", plugin.SecretRef)) + dataMap := make(map[string]interface{}) + for key, value := range sec.Data { - plugin.Config[key] = string(value) + err := json.Unmarshal(value, dataMap[key]) + if err != nil { + log.Errorw("The config secretRef is invalid", + zap.Any("plugin", plugin.Name), + zap.String("secretRef", plugin.SecretRef)) + break + } } + utils.MergeMaps(dataMap, plugin.Config) } pluginMap[plugin.Name] = plugin.Config } else { diff --git a/pkg/providers/utils/merge.go b/pkg/providers/utils/merge.go index 4478c6d11d..32694fb930 100644 --- a/pkg/providers/utils/merge.go +++ b/pkg/providers/utils/merge.go @@ -1,3 +1,17 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. package utils // MergeMaps will iterate recursively in src map and copy the fields over to dest diff --git a/pkg/providers/utils/merge_test.go b/pkg/providers/utils/merge_test.go index 19b5c5a930..5d706472a5 100644 --- a/pkg/providers/utils/merge_test.go +++ b/pkg/providers/utils/merge_test.go @@ -1,3 +1,17 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. package utils import ( From bca83b0d54e51f46d7615b81c0e9cf90bbfaec5f Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Mon, 11 Dec 2023 14:53:34 +0530 Subject: [PATCH 03/14] refactor --- .../apisix/translation/apisix_pluginconfig.go | 12 +----- .../apisix/translation/apisix_route.go | 13 +----- .../utils/{merge.go => insert_map.go} | 43 +++++++++++-------- .../{merge_test.go => insert_map_test.go} | 23 ++++------ 4 files changed, 37 insertions(+), 54 deletions(-) rename pkg/providers/utils/{merge.go => insert_map.go} (55%) rename pkg/providers/utils/{merge_test.go => insert_map_test.go} (80%) diff --git a/pkg/providers/apisix/translation/apisix_pluginconfig.go b/pkg/providers/apisix/translation/apisix_pluginconfig.go index c58a6e28b0..87874bcd2c 100644 --- a/pkg/providers/apisix/translation/apisix_pluginconfig.go +++ b/pkg/providers/apisix/translation/apisix_pluginconfig.go @@ -15,8 +15,6 @@ package translation import ( - "encoding/json" - "go.uber.org/zap" "github.com/apache/apisix-ingress-controller/pkg/id" @@ -47,18 +45,10 @@ func (t *translator) TranslatePluginConfigV2(config *configv2.ApisixPluginConfig log.Debugw("Add new items, then override items with the same plugin key", zap.Any("plugin", plugin.Name), zap.String("secretRef", plugin.SecretRef)) - dataMap := make(map[string]interface{}) for key, value := range sec.Data { - err := json.Unmarshal(value, dataMap[key]) - if err != nil { - log.Errorw("The config secretRef is invalid", - zap.Any("plugin", plugin.Name), - zap.String("secretRef", plugin.SecretRef)) - break - } + utils.InsertKeyInMap(key, value, plugin.Config) } - utils.MergeMaps(dataMap, plugin.Config) } pluginMap[plugin.Name] = plugin.Config } else { diff --git a/pkg/providers/apisix/translation/apisix_route.go b/pkg/providers/apisix/translation/apisix_route.go index 985bc98b19..9df8229d85 100644 --- a/pkg/providers/apisix/translation/apisix_route.go +++ b/pkg/providers/apisix/translation/apisix_route.go @@ -16,7 +16,6 @@ package translation import ( "context" - "encoding/json" "errors" "fmt" "strconv" @@ -103,18 +102,10 @@ func (t *translator) translateHTTPRouteV2(ctx *translation.TranslateContext, ar log.Debugw("Add new items, then override items with the same plugin key", zap.Any("plugin", plugin.Name), zap.String("secretRef", plugin.SecretRef)) - dataMap := make(map[string]interface{}) for key, value := range sec.Data { - err := json.Unmarshal(value, dataMap[key]) - if err != nil { - log.Errorw("The config secretRef is invalid", - zap.Any("plugin", plugin.Name), - zap.String("secretRef", plugin.SecretRef)) - break - } + utils.InsertKeyInMap(key, value, plugin.Config) } - utils.MergeMaps(dataMap, plugin.Config) } pluginMap[plugin.Name] = plugin.Config } else { @@ -547,7 +538,7 @@ func (t *translator) translateStreamRouteV2(ctx *translation.TranslateContext, a zap.Any("plugin", plugin.Name), zap.String("secretRef", plugin.SecretRef)) for key, value := range sec.Data { - plugin.Config[key] = string(value) + utils.InsertKeyInMap(key, value, plugin.Config) } } pluginMap[plugin.Name] = plugin.Config diff --git a/pkg/providers/utils/merge.go b/pkg/providers/utils/insert_map.go similarity index 55% rename from pkg/providers/utils/merge.go rename to pkg/providers/utils/insert_map.go index 32694fb930..5568b76121 100644 --- a/pkg/providers/utils/merge.go +++ b/pkg/providers/utils/insert_map.go @@ -14,22 +14,31 @@ // limitations under the License. package utils -// MergeMaps will iterate recursively in src map and copy the fields over to dest -func MergeMaps(src, dest map[string]interface{}) { - for key, val := range src { - //If destination map already has this key then recursively - //call merge with src[key] and dest[key] - if dest[key] != nil { - switch v := val.(type) { - case map[string]interface{}: - destMap, ok := dest[key].(map[string]interface{}) - if !ok { - destMap = make(map[string]interface{}) - } - MergeMaps(v, destMap) - default: - dest[key] = src[key] - } - } +import ( + "strings" +) + +// InsertKeyInMap takes a dot seperated string and recursively goes inside the destination +// to fill the value +func InsertKeyInMap(key string, value interface{}, dest map[string]interface{}) { + if key == "" { + return + } + keys := strings.SplitN(key, ".", 2) + //base condition. the length of keys will be atleast 1 + if len(keys) < 2 { + dest[keys[0]] = value + return + } + + ikey := keys[0] + restKey := keys[1] + if dest[ikey] == nil { + dest[ikey] = make(map[string]interface{}) + } + newDest, ok := dest[ikey].(map[string]interface{}) + if !ok { + newDest = make(map[string]interface{}) } + InsertKeyInMap(restKey, value, newDest) } diff --git a/pkg/providers/utils/merge_test.go b/pkg/providers/utils/insert_map_test.go similarity index 80% rename from pkg/providers/utils/merge_test.go rename to pkg/providers/utils/insert_map_test.go index 5d706472a5..bbc281a9b3 100644 --- a/pkg/providers/utils/merge_test.go +++ b/pkg/providers/utils/insert_map_test.go @@ -19,9 +19,10 @@ import ( "testing" ) -func TestMergeMaps(t *testing.T) { +func TestInsertKeyInMap(t *testing.T) { type testCase struct { - src string + key string + value interface{} dest string merged string } @@ -35,11 +36,8 @@ func TestMergeMaps(t *testing.T) { "f":"g" } }`, - src: `{ - "b":{ - "c": 2 - } - }`, + key: `b.c`, + value: 2, merged: `{ "a":1, "b":{ @@ -50,13 +48,8 @@ func TestMergeMaps(t *testing.T) { }} for _, t0 := range testCases { - srcMap := make(map[string]interface{}) - err := json.Unmarshal([]byte(t0.src), &srcMap) - if err != nil { - t.Fatal(err) - } destMap := make(map[string]interface{}) - err = json.Unmarshal([]byte(t0.dest), &destMap) + err := json.Unmarshal([]byte(t0.dest), &destMap) if err != nil { t.Fatal(err) } @@ -69,13 +62,13 @@ func TestMergeMaps(t *testing.T) { if err != nil { t.Fatal(err) } - MergeMaps(srcMap, destMap) + InsertKeyInMap(t0.key, t0.value, destMap) merged, err := json.MarshalIndent(destMap, " ", "") if err != nil { t.Fatal(err) } if string(outB) != string(merged) { - t.Errorf("Expected %s but got %s", string(outB), string(merged)) + t.Errorf("Expected \n%s\n but got \n%s\n", string(outB), string(merged)) } } } From 0ed63839c5746384fde697de90622ddb3c02ed91 Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Mon, 11 Dec 2023 22:04:32 +0530 Subject: [PATCH 04/14] fix tests Signed-off-by: Ashish Tiwari --- pkg/providers/apisix/translation/apisix_pluginconfig.go | 2 +- pkg/providers/apisix/translation/apisix_route.go | 4 ++-- pkg/providers/utils/insert_map.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/providers/apisix/translation/apisix_pluginconfig.go b/pkg/providers/apisix/translation/apisix_pluginconfig.go index 87874bcd2c..5ee0e2a4c2 100644 --- a/pkg/providers/apisix/translation/apisix_pluginconfig.go +++ b/pkg/providers/apisix/translation/apisix_pluginconfig.go @@ -47,7 +47,7 @@ func (t *translator) TranslatePluginConfigV2(config *configv2.ApisixPluginConfig zap.String("secretRef", plugin.SecretRef)) for key, value := range sec.Data { - utils.InsertKeyInMap(key, value, plugin.Config) + utils.InsertKeyInMap(key, string(value), plugin.Config) } } pluginMap[plugin.Name] = plugin.Config diff --git a/pkg/providers/apisix/translation/apisix_route.go b/pkg/providers/apisix/translation/apisix_route.go index 9df8229d85..856709e62d 100644 --- a/pkg/providers/apisix/translation/apisix_route.go +++ b/pkg/providers/apisix/translation/apisix_route.go @@ -104,7 +104,7 @@ func (t *translator) translateHTTPRouteV2(ctx *translation.TranslateContext, ar zap.String("secretRef", plugin.SecretRef)) for key, value := range sec.Data { - utils.InsertKeyInMap(key, value, plugin.Config) + utils.InsertKeyInMap(key, string(value), plugin.Config) } } pluginMap[plugin.Name] = plugin.Config @@ -538,7 +538,7 @@ func (t *translator) translateStreamRouteV2(ctx *translation.TranslateContext, a zap.Any("plugin", plugin.Name), zap.String("secretRef", plugin.SecretRef)) for key, value := range sec.Data { - utils.InsertKeyInMap(key, value, plugin.Config) + utils.InsertKeyInMap(key, string(value), plugin.Config) } } pluginMap[plugin.Name] = plugin.Config diff --git a/pkg/providers/utils/insert_map.go b/pkg/providers/utils/insert_map.go index 5568b76121..abe8ffdb8b 100644 --- a/pkg/providers/utils/insert_map.go +++ b/pkg/providers/utils/insert_map.go @@ -18,7 +18,7 @@ import ( "strings" ) -// InsertKeyInMap takes a dot seperated string and recursively goes inside the destination +// InsertKeyInMap takes a dot separated string and recursively goes inside the destination // to fill the value func InsertKeyInMap(key string, value interface{}, dest map[string]interface{}) { if key == "" { From 80b50ea6fb8e5624a78c5bde2019bb5373ce598a Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Tue, 12 Dec 2023 10:39:02 +0530 Subject: [PATCH 05/14] add E2E test --- pkg/providers/utils/insert_map_test.go | 12 +++++ .../suite-plugins-general/secret_ref.go | 53 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/pkg/providers/utils/insert_map_test.go b/pkg/providers/utils/insert_map_test.go index bbc281a9b3..05aa0f5d7a 100644 --- a/pkg/providers/utils/insert_map_test.go +++ b/pkg/providers/utils/insert_map_test.go @@ -45,6 +45,18 @@ func TestInsertKeyInMap(t *testing.T) { "f":"g" } }`, + }, { + dest: `{ + "a":1, + "b":"old" + } + `, + key: "b", + value: "new", + merged: `{ + "a":1, + "b":"new" + }`, }} for _, t0 := range testCases { diff --git a/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go b/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go index c8123890f8..0039f54679 100644 --- a/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go +++ b/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go @@ -87,7 +87,60 @@ spec: resp.Body().Contains("This is the epilogue") resp.Body().Contains("my custom body") }) + + ginkgo.It("suite-plugins-general: nested plugin config with secretRef", func() { + backendSvc, backendPorts := s.DefaultHTTPBackend() + secret := ` +apiVersion: v1 +kind: Secret +metadata: + name: echo +data: + headers.X-Foo: v2 +` + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(secret), "creating echo secret for ApisixRoute") + ar := fmt.Sprintf(` +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: httpbin-route +spec: + http: + - name: rule1 + match: + hosts: + - httpbin.org + paths: + - /ip + backends: + - serviceName: %s + servicePort: %d + weight: 10 + plugins: + - name: echo + enable: true + config: + before_body: "This is the preface" + after_body: "This is the epilogue" + headers: + X-Foo: v1 + secretRef: echo + +`, backendSvc, backendPorts[0]) + + assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(ar)) + + err := s.EnsureNumApisixUpstreamsCreated(1) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams") + err = s.EnsureNumApisixRoutesCreated(1) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes") + + resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").Expect() + resp.Status(http.StatusOK) + resp.Header("X-Foo2").Equal("v2") + }) } + ginkgo.Describe("suite-plugins-general: scaffold v2", func() { suites(scaffold.NewDefaultV2Scaffold) }) From 477d4ddd79de729989ce0a76d06d772f140f801b Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Tue, 12 Dec 2023 10:40:00 +0530 Subject: [PATCH 06/14] fix tests Signed-off-by: Ashish Tiwari --- test/e2e/suite-plugins/suite-plugins-general/secret_ref.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go b/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go index 0039f54679..01401cccd7 100644 --- a/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go +++ b/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go @@ -137,7 +137,7 @@ spec: resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").Expect() resp.Status(http.StatusOK) - resp.Header("X-Foo2").Equal("v2") + resp.Header("X-Foo").Equal("v2") }) } From 80696ffadcd8d3bb32ffcccfe8a0161ec108c46f Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Tue, 12 Dec 2023 11:00:09 +0530 Subject: [PATCH 07/14] fix indentation Signed-off-by: Ashish Tiwari --- test/e2e/suite-plugins/suite-plugins-general/secret_ref.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go b/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go index 01401cccd7..87f621411e 100644 --- a/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go +++ b/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go @@ -94,9 +94,9 @@ spec: apiVersion: v1 kind: Secret metadata: - name: echo + name: echo data: - headers.X-Foo: v2 + headers.X-Foo: v2 ` assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(secret), "creating echo secret for ApisixRoute") ar := fmt.Sprintf(` From b848c56122b7847ee2a6370e2bc017fe53af12b4 Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Tue, 12 Dec 2023 11:24:35 +0530 Subject: [PATCH 08/14] fix indentation Signed-off-by: Ashish Tiwari --- test/e2e/suite-plugins/suite-plugins-general/secret_ref.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go b/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go index 87f621411e..c3b546af27 100644 --- a/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go +++ b/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go @@ -94,9 +94,9 @@ spec: apiVersion: v1 kind: Secret metadata: - name: echo + name: httpbin-route data: - headers.X-Foo: v2 + headers.X-Foo: v2 ` assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(secret), "creating echo secret for ApisixRoute") ar := fmt.Sprintf(` From 9ea0a5182e0fb7e4aa329ff14bc23df7d19d2240 Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Tue, 12 Dec 2023 11:43:10 +0530 Subject: [PATCH 09/14] base64 encode Signed-off-by: Ashish Tiwari --- test/e2e/suite-plugins/suite-plugins-general/secret_ref.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go b/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go index c3b546af27..f8ec899ba4 100644 --- a/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go +++ b/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go @@ -96,7 +96,7 @@ kind: Secret metadata: name: httpbin-route data: - headers.X-Foo: v2 + headers.X-Foo: djI= ` assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(secret), "creating echo secret for ApisixRoute") ar := fmt.Sprintf(` From 29a7621497e01a1c7efde4163a9a6cee14ad92f0 Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Tue, 12 Dec 2023 12:29:45 +0530 Subject: [PATCH 10/14] fix e2e test --- test/e2e/suite-plugins/suite-plugins-general/secret_ref.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go b/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go index f8ec899ba4..733d323871 100644 --- a/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go +++ b/test/e2e/suite-plugins/suite-plugins-general/secret_ref.go @@ -94,9 +94,11 @@ spec: apiVersion: v1 kind: Secret metadata: - name: httpbin-route + name: echo data: headers.X-Foo: djI= + # content is "my custom body" + body: Im15IGN1c3RvbSBib2R5Ig== ` assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(secret), "creating echo secret for ApisixRoute") ar := fmt.Sprintf(` From c859a15540c09f2a567e1a359c98ba552b82e681 Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Tue, 12 Dec 2023 13:12:42 +0530 Subject: [PATCH 11/14] add docs --- docs/en/latest/concepts/apisix_route.md | 40 +++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/docs/en/latest/concepts/apisix_route.md b/docs/en/latest/concepts/apisix_route.md index 5da3982972..7a917e544c 100644 --- a/docs/en/latest/concepts/apisix_route.md +++ b/docs/en/latest/concepts/apisix_route.md @@ -262,6 +262,46 @@ spec: secretRef: echo ``` +## Config with secretRef configuring nested fields + +You can also configure specific fields in the plugin configuration that are deeply nested by passing the path to that field. The path is dot-separated keys that lead to that field. The below example overrides the `X-Foo` header field in the plugin configuration from `v1` to `v2`. + +```yaml +apiVersion: v1 +kind: Secret +metadata: + #content is "v2" + name: echo +data: + headers.X-Foo: djI= +--- +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: httpbin-route +spec: + http: + - name: rule1 + match: + hosts: + - httpbin.org + paths: + - /ip + backends: + - serviceName: %s + servicePort: %d + weight: 10 + plugins: + - name: echo + enable: true + config: + before_body: "This is the preface" + after_body: "This is the epilogue" + headers: + X-Foo: v1 + secretRef: echo +``` + ## Websocket proxy You can route requests to [WebSocket](https://en.wikipedia.org/wiki/WebSocket#:~:text=WebSocket%20is%20a%20computer%20communications,WebSocket%20is%20distinct%20from%20HTTP.) services by setting the `websocket` attribute to `true` as shown below: From 9277b562eaaba23c5d34ad30347309749e216cee Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Wed, 13 Dec 2023 18:07:08 +0530 Subject: [PATCH 12/14] make readable Signed-off-by: Ashish Tiwari --- docs/en/latest/concepts/apisix_route.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/latest/concepts/apisix_route.md b/docs/en/latest/concepts/apisix_route.md index 7a917e544c..f3123f509a 100644 --- a/docs/en/latest/concepts/apisix_route.md +++ b/docs/en/latest/concepts/apisix_route.md @@ -262,7 +262,7 @@ spec: secretRef: echo ``` -## Config with secretRef configuring nested fields +## Config with secretRef where the secret data contains path to a specific key that needs to be overriden in plugin config You can also configure specific fields in the plugin configuration that are deeply nested by passing the path to that field. The path is dot-separated keys that lead to that field. The below example overrides the `X-Foo` header field in the plugin configuration from `v1` to `v2`. From 2d3b9353578e4a5d4c772cf01342f8d5b505441e Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Wed, 13 Dec 2023 18:27:15 +0530 Subject: [PATCH 13/14] fix spelling Signed-off-by: Ashish Tiwari --- docs/en/latest/concepts/apisix_route.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/latest/concepts/apisix_route.md b/docs/en/latest/concepts/apisix_route.md index f3123f509a..c40937fb25 100644 --- a/docs/en/latest/concepts/apisix_route.md +++ b/docs/en/latest/concepts/apisix_route.md @@ -262,7 +262,7 @@ spec: secretRef: echo ``` -## Config with secretRef where the secret data contains path to a specific key that needs to be overriden in plugin config +## Config with secretRef where the secret data contains path to a specific key that needs to be overridden in plugin config You can also configure specific fields in the plugin configuration that are deeply nested by passing the path to that field. The path is dot-separated keys that lead to that field. The below example overrides the `X-Foo` header field in the plugin configuration from `v1` to `v2`. From aa0655ea6d1758ebdfe60bd27394d530e8f0453f Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Fri, 15 Dec 2023 09:27:33 +0530 Subject: [PATCH 14/14] fix bug in logic Signed-off-by: Ashish Tiwari --- pkg/providers/utils/insert_map.go | 1 + pkg/providers/utils/insert_map_test.go | 47 ++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/pkg/providers/utils/insert_map.go b/pkg/providers/utils/insert_map.go index abe8ffdb8b..750564477c 100644 --- a/pkg/providers/utils/insert_map.go +++ b/pkg/providers/utils/insert_map.go @@ -39,6 +39,7 @@ func InsertKeyInMap(key string, value interface{}, dest map[string]interface{}) newDest, ok := dest[ikey].(map[string]interface{}) if !ok { newDest = make(map[string]interface{}) + dest[ikey] = newDest } InsertKeyInMap(restKey, value, newDest) } diff --git a/pkg/providers/utils/insert_map_test.go b/pkg/providers/utils/insert_map_test.go index 05aa0f5d7a..b97bc6dd00 100644 --- a/pkg/providers/utils/insert_map_test.go +++ b/pkg/providers/utils/insert_map_test.go @@ -16,6 +16,7 @@ package utils import ( "encoding/json" + "fmt" "testing" ) @@ -45,6 +46,50 @@ func TestInsertKeyInMap(t *testing.T) { "f":"g" } }`, + }, { + dest: `{ + "a":1, + "b":{ + "c": 2, + "f":"g" + } + }`, + key: `b.c`, + value: map[string]string{ + "d": "e", + }, + merged: `{ + "a":1, + "b":{ + "c":{ + "d":"e" + }, + "f":"g" + } + }`, + }, { + dest: `{ + "a":1, + "b":{ + "c": 2, + "f":"g" + } + }`, + key: `b.c.d`, + value: map[string]string{ + "x": "y", + }, + merged: `{ + "a":1, + "b":{ + "c":{ + "d":{ + "x":"y" + } + }, + "f":"g" + } + }`, }, { dest: `{ "a":1, @@ -74,7 +119,9 @@ func TestInsertKeyInMap(t *testing.T) { if err != nil { t.Fatal(err) } + InsertKeyInMap(t0.key, t0.value, destMap) + fmt.Println(destMap) merged, err := json.MarshalIndent(destMap, " ", "") if err != nil { t.Fatal(err)