Browse Source

feat: introduce priorityPolicy in merge rewrite (#5329)

* introduce priorityPolicy in merge rewrite

Signed-off-by: Riccardo M. Cefala <riccardo.c@miro.com>

* make reviewable

Signed-off-by: Riccardo M. Cefala <riccardo.c@miro.com>

* update documentation for priorityPolicy

Signed-off-by: Riccardo M. Cefala <riccardo.cefala@gmail.com>

* add some missing kubebuilder Enum validation directives

Signed-off-by: Riccardo M. Cefala <riccardo.c@miro.com>

---------

Signed-off-by: Riccardo M. Cefala <riccardo.c@miro.com>
Signed-off-by: Riccardo M. Cefala <riccardo.cefala@gmail.com>
Riccardo M. Cefala 6 months ago
parent
commit
50af88eab2

+ 16 - 0
apis/externalsecrets/v1/externalsecret_types.go

@@ -340,6 +340,11 @@ type ExternalSecretRewriteMerge struct {
 	// +optional
 	// +optional
 	Priority []string `json:"priority,omitempty"`
 	Priority []string `json:"priority,omitempty"`
 
 
+	// Used to define the policy when a key in the priority list does not exist in the input.
+	// +optional
+	// +kubebuilder:default="Strict"
+	PriorityPolicy ExternalSecretRewriteMergePriorityPolicy `json:"priorityPolicy,omitempty"`
+
 	// Used to define the policy to use in conflict resolution.
 	// Used to define the policy to use in conflict resolution.
 	// +optional
 	// +optional
 	// +kubebuilder:default="Error"
 	// +kubebuilder:default="Error"
@@ -351,6 +356,7 @@ type ExternalSecretRewriteMerge struct {
 	Strategy ExternalSecretRewriteMergeStrategy `json:"strategy,omitempty"`
 	Strategy ExternalSecretRewriteMergeStrategy `json:"strategy,omitempty"`
 }
 }
 
 
+// +kubebuilder:validation:Enum=Ignore;Error
 type ExternalSecretRewriteMergeConflictPolicy string
 type ExternalSecretRewriteMergeConflictPolicy string
 
 
 const (
 const (
@@ -358,6 +364,15 @@ const (
 	ExternalSecretRewriteMergeConflictPolicyError  ExternalSecretRewriteMergeConflictPolicy = "Error"
 	ExternalSecretRewriteMergeConflictPolicyError  ExternalSecretRewriteMergeConflictPolicy = "Error"
 )
 )
 
 
+// +kubebuilder:validation:Enum=IgnoreNotFound;Strict
+type ExternalSecretRewriteMergePriorityPolicy string
+
+const (
+	ExternalSecretRewriteMergePriorityPolicyIgnoreNotFound ExternalSecretRewriteMergePriorityPolicy = "IgnoreNotFound"
+	ExternalSecretRewriteMergePriorityPolicyStrict         ExternalSecretRewriteMergePriorityPolicy = "Strict"
+)
+
+// +kubebuilder:validation:Enum=Extract;JSON
 type ExternalSecretRewriteMergeStrategy string
 type ExternalSecretRewriteMergeStrategy string
 
 
 const (
 const (
@@ -499,6 +514,7 @@ type GeneratorRef struct {
 	Name string `json:"name"`
 	Name string `json:"name"`
 }
 }
 
 
+// +kubebuilder:validation:Enum=Ready;Deleted
 type ExternalSecretConditionType string
 type ExternalSecretConditionType string
 
 
 const (
 const (

+ 15 - 0
config/crds/bases/external-secrets.io_clusterexternalsecrets.yaml

@@ -315,6 +315,9 @@ spec:
                                     default: Error
                                     default: Error
                                     description: Used to define the policy to use
                                     description: Used to define the policy to use
                                       in conflict resolution.
                                       in conflict resolution.
+                                    enum:
+                                    - Ignore
+                                    - Error
                                     type: string
                                     type: string
                                   into:
                                   into:
                                     default: ""
                                     default: ""
@@ -328,10 +331,22 @@ spec:
                                     items:
                                     items:
                                       type: string
                                       type: string
                                     type: array
                                     type: array
+                                  priorityPolicy:
+                                    default: Strict
+                                    description: Used to define the policy when a
+                                      key in the priority list does not exist in the
+                                      input.
+                                    enum:
+                                    - IgnoreNotFound
+                                    - Strict
+                                    type: string
                                   strategy:
                                   strategy:
                                     default: Extract
                                     default: Extract
                                     description: Used to define the strategy to use
                                     description: Used to define the strategy to use
                                       in the merge operation.
                                       in the merge operation.
+                                    enum:
+                                    - Extract
+                                    - JSON
                                     type: string
                                     type: string
                                 type: object
                                 type: object
                               regexp:
                               regexp:

+ 17 - 0
config/crds/bases/external-secrets.io_externalsecrets.yaml

@@ -295,6 +295,9 @@ spec:
                                 default: Error
                                 default: Error
                                 description: Used to define the policy to use in conflict
                                 description: Used to define the policy to use in conflict
                                   resolution.
                                   resolution.
+                                enum:
+                                - Ignore
+                                - Error
                                 type: string
                                 type: string
                               into:
                               into:
                                 default: ""
                                 default: ""
@@ -308,10 +311,21 @@ spec:
                                 items:
                                 items:
                                   type: string
                                   type: string
                                 type: array
                                 type: array
+                              priorityPolicy:
+                                default: Strict
+                                description: Used to define the policy when a key
+                                  in the priority list does not exist in the input.
+                                enum:
+                                - IgnoreNotFound
+                                - Strict
+                                type: string
                               strategy:
                               strategy:
                                 default: Extract
                                 default: Extract
                                 description: Used to define the strategy to use in
                                 description: Used to define the strategy to use in
                                   the merge operation.
                                   the merge operation.
+                                enum:
+                                - Extract
+                                - JSON
                                 type: string
                                 type: string
                             type: object
                             type: object
                           regexp:
                           regexp:
@@ -652,6 +666,9 @@ spec:
                     status:
                     status:
                       type: string
                       type: string
                     type:
                     type:
+                      enum:
+                      - Ready
+                      - Deleted
                       type: string
                       type: string
                   required:
                   required:
                   - status
                   - status

+ 29 - 0
deploy/crds/bundle.yaml

@@ -299,6 +299,9 @@ spec:
                                     conflictPolicy:
                                     conflictPolicy:
                                       default: Error
                                       default: Error
                                       description: Used to define the policy to use in conflict resolution.
                                       description: Used to define the policy to use in conflict resolution.
+                                      enum:
+                                        - Ignore
+                                        - Error
                                       type: string
                                       type: string
                                     into:
                                     into:
                                       default: ""
                                       default: ""
@@ -311,9 +314,19 @@ spec:
                                       items:
                                       items:
                                         type: string
                                         type: string
                                       type: array
                                       type: array
+                                    priorityPolicy:
+                                      default: Strict
+                                      description: Used to define the policy when a key in the priority list does not exist in the input.
+                                      enum:
+                                        - IgnoreNotFound
+                                        - Strict
+                                      type: string
                                     strategy:
                                     strategy:
                                       default: Extract
                                       default: Extract
                                       description: Used to define the strategy to use in the merge operation.
                                       description: Used to define the strategy to use in the merge operation.
+                                      enum:
+                                        - Extract
+                                        - JSON
                                       type: string
                                       type: string
                                   type: object
                                   type: object
                                 regexp:
                                 regexp:
@@ -11682,6 +11695,9 @@ spec:
                                 conflictPolicy:
                                 conflictPolicy:
                                   default: Error
                                   default: Error
                                   description: Used to define the policy to use in conflict resolution.
                                   description: Used to define the policy to use in conflict resolution.
+                                  enum:
+                                    - Ignore
+                                    - Error
                                   type: string
                                   type: string
                                 into:
                                 into:
                                   default: ""
                                   default: ""
@@ -11694,9 +11710,19 @@ spec:
                                   items:
                                   items:
                                     type: string
                                     type: string
                                   type: array
                                   type: array
+                                priorityPolicy:
+                                  default: Strict
+                                  description: Used to define the policy when a key in the priority list does not exist in the input.
+                                  enum:
+                                    - IgnoreNotFound
+                                    - Strict
+                                  type: string
                                 strategy:
                                 strategy:
                                   default: Extract
                                   default: Extract
                                   description: Used to define the strategy to use in the merge operation.
                                   description: Used to define the strategy to use in the merge operation.
+                                  enum:
+                                    - Extract
+                                    - JSON
                                   type: string
                                   type: string
                               type: object
                               type: object
                             regexp:
                             regexp:
@@ -12027,6 +12053,9 @@ spec:
                       status:
                       status:
                         type: string
                         type: string
                       type:
                       type:
+                        enum:
+                          - Ready
+                          - Deleted
                         type: string
                         type: string
                     required:
                     required:
                       - status
                       - status

+ 35 - 0
docs/api/spec.md

@@ -4215,6 +4215,20 @@ Required if strategy is JSON. Ignored otherwise.</p>
 </tr>
 </tr>
 <tr>
 <tr>
 <td>
 <td>
+<code>priorityPolicy</code></br>
+<em>
+<a href="#external-secrets.io/v1.ExternalSecretRewriteMergePriorityPolicy">
+ExternalSecretRewriteMergePriorityPolicy
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>Used to define the policy when a key in the priority list does not exist in the input.</p>
+</td>
+</tr>
+<tr>
+<td>
 <code>conflictPolicy</code></br>
 <code>conflictPolicy</code></br>
 <em>
 <em>
 <a href="#external-secrets.io/v1.ExternalSecretRewriteMergeConflictPolicy">
 <a href="#external-secrets.io/v1.ExternalSecretRewriteMergeConflictPolicy">
@@ -4264,6 +4278,27 @@ ExternalSecretRewriteMergeStrategy
 <td></td>
 <td></td>
 </tr></tbody>
 </tr></tbody>
 </table>
 </table>
+<h3 id="external-secrets.io/v1.ExternalSecretRewriteMergePriorityPolicy">ExternalSecretRewriteMergePriorityPolicy
+(<code>string</code> alias)</p></h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1.ExternalSecretRewriteMerge">ExternalSecretRewriteMerge</a>)
+</p>
+<p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Value</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody><tr><td><p>&#34;IgnoreNotFound&#34;</p></td>
+<td></td>
+</tr><tr><td><p>&#34;Strict&#34;</p></td>
+<td></td>
+</tr></tbody>
+</table>
 <h3 id="external-secrets.io/v1.ExternalSecretRewriteMergeStrategy">ExternalSecretRewriteMergeStrategy
 <h3 id="external-secrets.io/v1.ExternalSecretRewriteMergeStrategy">ExternalSecretRewriteMergeStrategy
 (<code>string</code> alias)</p></h3>
 (<code>string</code> alias)</p></h3>
 <p>
 <p>

+ 4 - 2
docs/guides/datafrom-rewrite.md

@@ -18,10 +18,12 @@ The `Extract` strategy interprets all secret values in the secret map as JSON an
 
 
 The `JSON` strategy interprets all secret values in the secret map as JSON and merges all contained key/value pairs in the key specified by the _required_ parameter `into`. If the key specified by `into` already exists in the original secrets map it will be overwritten.
 The `JSON` strategy interprets all secret values in the secret map as JSON and merges all contained key/value pairs in the key specified by the _required_ parameter `into`. If the key specified by `into` already exists in the original secrets map it will be overwritten.
 
 
-Key collisions can be ignored or cause an error according to `conflictPolicy` which can be either `Ignore` or `Error`.  
+Key collisions can be ignored or cause an error according to `conflictPolicy` which can be either `Ignore` or `Error`.
 
 
 To guarantee deterministic results of the merge operation, secret keys are processed in alphabetical order. Key priority can also be made explicit by providing a list of secret keys in the `priority` parameter. These keys will be processed last in the order they appear while all other keys will still be processed in alphabetical order.
 To guarantee deterministic results of the merge operation, secret keys are processed in alphabetical order. Key priority can also be made explicit by providing a list of secret keys in the `priority` parameter. These keys will be processed last in the order they appear while all other keys will still be processed in alphabetical order.
 
 
+Specifying a key in the `priority` list which is not found in the source secret will cause an error. You can override this behavior setting `priorityPolicy` to `IgnoreNotFound` instead of the default `Strict`.
+
 ## Considerations about Rewrite implementation
 ## Considerations about Rewrite implementation
 
 
 1. The input of a subsequent rewrite operation are the outputs of the previous rewrite.
 1. The input of a subsequent rewrite operation are the outputs of the previous rewrite.
@@ -105,7 +107,7 @@ data:
     foo_baz: MjIyMg== #2222
     foo_baz: MjIyMg== #2222
 ```
 ```
 
 
-### Merging all secrets 
+### Merging all secrets
 
 
 The following ExternalSecret:
 The following ExternalSecret:
 ```yaml
 ```yaml

+ 3 - 0
pkg/utils/utils.go

@@ -164,6 +164,9 @@ func merge(operation esv1.ExternalSecretRewriteMerge, in map[string][]byte) (map
 	for _, key := range keys {
 	for _, key := range keys {
 		value, exists := in[key]
 		value, exists := in[key]
 		if !exists {
 		if !exists {
+			if operation.PriorityPolicy == esv1.ExternalSecretRewriteMergePriorityPolicyIgnoreNotFound {
+				continue
+			}
 			return nil, nil, fmt.Errorf("merge failed with key %q not found in input map", key)
 			return nil, nil, fmt.Errorf("merge failed with key %q not found in input map", key)
 		}
 		}
 		var jsonMap map[string]any
 		var jsonMap map[string]any

+ 22 - 1
pkg/utils/utils_test.go

@@ -714,7 +714,7 @@ func TestRewriteMerge(t *testing.T) {
 			wantErr: false,
 			wantErr: false,
 		},
 		},
 		{
 		{
-			name: "using priority with keys not in input",
+			name: "using priority with keys not in input (default strict)",
 			args: args{
 			args: args{
 				operation: esv1.ExternalSecretRewriteMerge{
 				operation: esv1.ExternalSecretRewriteMerge{
 					ConflictPolicy: esv1.ExternalSecretRewriteMergeConflictPolicyIgnore,
 					ConflictPolicy: esv1.ExternalSecretRewriteMergeConflictPolicyIgnore,
@@ -729,6 +729,27 @@ func TestRewriteMerge(t *testing.T) {
 			wantErr: true,
 			wantErr: true,
 		},
 		},
 		{
 		{
+			name: "using priority with keys not in input and ignore policy",
+			args: args{
+				operation: esv1.ExternalSecretRewriteMerge{
+					ConflictPolicy: esv1.ExternalSecretRewriteMergeConflictPolicyIgnore,
+					Priority:       []string{"non-existent-key", "mongo-credentials"},
+					PriorityPolicy: esv1.ExternalSecretRewriteMergePriorityPolicyIgnoreNotFound,
+				},
+				in: map[string][]byte{
+					"mongo-credentials": []byte(`{"username": "foz", "password": "baz"}`),
+					"redis-credentials": []byte(`{"host": "redis.example.com", "port": "6379"}`),
+				},
+			},
+			want: map[string][]byte{
+				"username": []byte("foz"),
+				"password": []byte("baz"),
+				"host":     []byte("redis.example.com"),
+				"port":     []byte("6379"),
+			},
+			wantErr: false,
+		},
+		{
 			name: "using conflict policy error",
 			name: "using conflict policy error",
 			args: args{
 			args: args{
 				operation: esv1.ExternalSecretRewriteMerge{
 				operation: esv1.ExternalSecretRewriteMerge{