Skip to content

Commit

Permalink
update after review
Browse files Browse the repository at this point in the history
Signed-off-by: lou <alex1988@outlook.com>
  • Loading branch information
27149chen committed Oct 18, 2023
1 parent 6d89780 commit d1f5219
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 45 deletions.
30 changes: 21 additions & 9 deletions design/merge-patch-and-strategic-in-resource-modifier.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,17 @@ resourceModifierRules:
namespaces:
- ns1
mergePatches:
- patchData:
metadata:
annotations:
foo: null
- patchData: |
{
"metadata": {
"annotations": {
"foo": null
}
}
}
```
- The above configmap will apply the Merge Patch to all the pods in namespace ns1 and remove the annotation `foo` from the pods.
- Both json and yaml format are supported for the patchData.

### New Field StrategicPatches
StrategicPatches is a list to specify the strategic merge patches to be applied on the resource. The strategic merge patches will be applied in the order specified in the configmap. A subsequent patch is applied in order and if multiple patches are specified for the same path, the last patch will override the previous patches.
Expand All @@ -88,13 +93,20 @@ resourceModifierRules:
namespaces:
- ns1
strategicPatches:
- patchData:
spec:
containers:
- name: nginx
image: repo2/nginx
- patchData: |
{
"spec": {
"containers": [
{
"name": "nginx",
"image": "repo2/nginx"
}
]
}
}
```
- The above configmap will apply the Strategic Merge Patch to the pod with name my-pod in namespace ns1 and update the image of container nginx to `repo2/nginx`.
- Both json and yaml format are supported for the patchData.

### Conditional Patches in ALL Patch Types
Since JSON Merge Patch and Strategic Merge Patch do not support conditional patches, we will use the `test` operation of JSON Patch to support conditional patches in all patch types by adding it to `Conditions` struct in `ResourceModifierRule`.
Expand Down
5 changes: 2 additions & 3 deletions internal/resourcemodifiers/json_merge_patch.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package resourcemodifiers

import (
"encoding/json"
"fmt"

jsonpatch "github.com/evanphx/json-patch"
Expand All @@ -11,7 +10,7 @@ import (
)

type JSONMergePatch struct {
PatchData json.RawMessage `json:"patchData,omitempty"`
PatchData string `json:"patchData,omitempty"`
}

type JSONMergePatcher struct {
Expand All @@ -25,7 +24,7 @@ func (p *JSONMergePatcher) Patch(u *unstructured.Unstructured, _ logrus.FieldLog
}

for _, patch := range p.patches {
patchBytes, err := yaml.YAMLToJSON(patch.PatchData)
patchBytes, err := yaml.YAMLToJSON([]byte(patch.PatchData))
if err != nil {
return nil, fmt.Errorf("error in converting YAML to JSON %s", err)
}
Expand Down
6 changes: 3 additions & 3 deletions internal/resourcemodifiers/json_merge_patch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ import (
func TestJsonMergePatchFailure(t *testing.T) {
tests := []struct {
name string
data []byte
data string
}{
{
name: "patch with bad yaml",
data: []byte("a: b:"),
data: "a: b:",
},
{
name: "patch with bad json",
data: []byte(`{"a"::1}`),
data: `{"a"::1}`,
},
}
for _, tt := range tests {
Expand Down
118 changes: 96 additions & 22 deletions internal/resourcemodifiers/resource_modifiers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func TestGetResourceModifiersFromConfig(t *testing.T) {
Namespace: "test-namespace",
},
Data: map[string]string{
"sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupResource: pods\n namespaces:\n - ns1\n mergePatches:\n - patchData:\n metadata:\n annotations:\n foo: null",
"sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupResource: pods\n namespaces:\n - ns1\n mergePatches:\n - patchData: |\n metadata:\n annotations:\n foo: null",
},
}

Expand All @@ -157,7 +157,7 @@ func TestGetResourceModifiersFromConfig(t *testing.T) {
},
MergePatches: []JSONMergePatch{
{
PatchData: []byte(`{"metadata":{"annotations":{"foo":null}}}`),
PatchData: "metadata:\n annotations:\n foo: null",
},
},
},
Expand All @@ -170,7 +170,7 @@ func TestGetResourceModifiersFromConfig(t *testing.T) {
Namespace: "test-namespace",
},
Data: map[string]string{
"sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupResource: pods\n namespaces:\n - ns1\n strategicPatches:\n - patchData:\n spec:\n containers:\n - name: nginx\n image: repo2/nginx",
"sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupResource: pods\n namespaces:\n - ns1\n strategicPatches:\n - patchData: |\n spec:\n containers:\n - name: nginx\n image: repo2/nginx",
},
}

Expand All @@ -186,7 +186,65 @@ func TestGetResourceModifiersFromConfig(t *testing.T) {
},
StrategicPatches: []StrategicMergePatch{
{
PatchData: []byte(`{"spec":{"containers":[{"image":"repo2/nginx","name":"nginx"}]}}`),
PatchData: "spec:\n containers:\n - name: nginx\n image: repo2/nginx",
},
},
},
},
}

cm7 := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "test-configmap",
Namespace: "test-namespace",
},
Data: map[string]string{
"sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupResource: pods\n namespaces:\n - ns1\n mergePatches:\n - patchData: |\n {\"metadata\":{\"annotations\":{\"foo\":null}}}",
},
}

rules7 := &ResourceModifiers{
Version: "v1",
ResourceModifierRules: []ResourceModifierRule{
{
Conditions: Conditions{
GroupResource: "pods",
Namespaces: []string{
"ns1",
},
},
MergePatches: []JSONMergePatch{
{
PatchData: `{"metadata":{"annotations":{"foo":null}}}`,
},
},
},
},
}

cm8 := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "test-configmap",
Namespace: "test-namespace",
},
Data: map[string]string{
"sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupResource: pods\n namespaces:\n - ns1\n strategicPatches:\n - patchData: |\n {\"spec\":{\"containers\":[{\"name\": \"nginx\",\"image\": \"repo2/nginx\"}]}}",
},
}

rules8 := &ResourceModifiers{
Version: "v1",
ResourceModifierRules: []ResourceModifierRule{
{
Conditions: Conditions{
GroupResource: "pods",
Namespaces: []string{
"ns1",
},
},
StrategicPatches: []StrategicMergePatch{
{
PatchData: `{"spec":{"containers":[{"name": "nginx","image": "repo2/nginx"}]}}`,
},
},
},
Expand Down Expand Up @@ -243,21 +301,37 @@ func TestGetResourceModifiersFromConfig(t *testing.T) {
wantErr: true,
},
{
name: "complex payload with json merge patch",
name: "complex yaml data with json merge patch",
args: args{
cm: cm5,
},
want: rules5,
wantErr: false,
},
{
name: "complex payload with strategic merge patch",
name: "complex yaml data with strategic merge patch",
args: args{
cm: cm6,
},
want: rules6,
wantErr: false,
},
{
name: "complex json data with json merge patch",
args: args{
cm: cm7,
},
want: rules7,
wantErr: false,
},
{
name: "complex json data with strategic merge patch",
args: args{
cm: cm8,
},
want: rules8,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -999,7 +1073,7 @@ func TestResourceModifiers_ApplyResourceModifierRules_StrategicMergePatch(t *tes
},
StrategicPatches: []StrategicMergePatch{
{
PatchData: []byte(`{"spec":{"containers":[{"name":"nginx","image":"nginx1"}]}}`),
PatchData: `{"spec":{"containers":[{"name":"nginx","image":"nginx1"}]}}`,
},
},
},
Expand All @@ -1022,10 +1096,10 @@ func TestResourceModifiers_ApplyResourceModifierRules_StrategicMergePatch(t *tes
},
StrategicPatches: []StrategicMergePatch{
{
PatchData: []byte(`spec:
PatchData: `spec:
containers:
- name: nginx
image: nginx1`),
image: nginx1`,
},
},
},
Expand All @@ -1048,7 +1122,7 @@ func TestResourceModifiers_ApplyResourceModifierRules_StrategicMergePatch(t *tes
},
StrategicPatches: []StrategicMergePatch{
{
PatchData: []byte(`{"spec":{"volumes":[{"nfs":null,"name":"vol1","persistentVolumeClaim":{"claimName":"pvc1"}}]}}`),
PatchData: `{"spec":{"volumes":[{"nfs":null,"name":"vol1","persistentVolumeClaim":{"claimName":"pvc1"}}]}}`,
},
},
},
Expand All @@ -1071,7 +1145,7 @@ func TestResourceModifiers_ApplyResourceModifierRules_StrategicMergePatch(t *tes
},
StrategicPatches: []StrategicMergePatch{
{
PatchData: []byte(`{"spec":{"volumes":[{"$retainKeys":["name","persistentVolumeClaim"],"name":"vol1","persistentVolumeClaim":{"claimName":"pvc1"}}]}}`),
PatchData: `{"spec":{"volumes":[{"$retainKeys":["name","persistentVolumeClaim"],"name":"vol1","persistentVolumeClaim":{"claimName":"pvc1"}}]}}`,
},
},
},
Expand All @@ -1094,7 +1168,7 @@ func TestResourceModifiers_ApplyResourceModifierRules_StrategicMergePatch(t *tes
},
StrategicPatches: []StrategicMergePatch{
{
PatchData: []byte(`{"spec":{"$setElementOrder/ports":[{"port":8001},{"port":9000},{"port":8002}],"ports":[{"name":"fake","port":9000,"protocol":"TCP","targetPort":9000},{"$patch":"delete","port":8000}]}}`),
PatchData: `{"spec":{"$setElementOrder/ports":[{"port":8001},{"port":9000},{"port":8002}],"ports":[{"name":"fake","port":9000,"protocol":"TCP","targetPort":9000},{"$patch":"delete","port":8000}]}}`,
},
},
},
Expand Down Expand Up @@ -1151,7 +1225,7 @@ func TestResourceModifiers_ApplyResourceModifierRules_JSONMergePatch(t *testing.
},
MergePatches: []JSONMergePatch{
{
PatchData: []byte(`{"metadata":{"labels":{"a":"c"}}}`),
PatchData: `{"metadata":{"labels":{"a":"c"}}}`,
},
},
},
Expand All @@ -1174,9 +1248,9 @@ func TestResourceModifiers_ApplyResourceModifierRules_JSONMergePatch(t *testing.
},
MergePatches: []JSONMergePatch{
{
PatchData: []byte(`metadata:
PatchData: `metadata:
labels:
a: c`),
a: c`,
},
},
},
Expand All @@ -1199,7 +1273,7 @@ func TestResourceModifiers_ApplyResourceModifierRules_JSONMergePatch(t *testing.
},
MergePatches: []JSONMergePatch{
{
PatchData: []byte(`{"metadata":{"labels":{"a":null}}}`),
PatchData: `{"metadata":{"labels":{"a":null}}}`,
},
},
},
Expand All @@ -1222,7 +1296,7 @@ func TestResourceModifiers_ApplyResourceModifierRules_JSONMergePatch(t *testing.
},
MergePatches: []JSONMergePatch{
{
PatchData: []byte(`{"metadata":{"labels":{"a":"b"}}}`),
PatchData: `{"metadata":{"labels":{"a":"b"}}}`,
},
},
},
Expand All @@ -1245,7 +1319,7 @@ func TestResourceModifiers_ApplyResourceModifierRules_JSONMergePatch(t *testing.
},
MergePatches: []JSONMergePatch{
{
PatchData: []byte(`{"metadata":{"labels":{"a":null}}}`),
PatchData: `{"metadata":{"labels":{"a":null}}}`,
},
},
},
Expand Down Expand Up @@ -1298,7 +1372,7 @@ func TestResourceModifiers_wildcard_in_GroupResource(t *testing.T) {
},
MergePatches: []JSONMergePatch{
{
PatchData: []byte(`{"metadata":{"labels":{"a":"c"}}}`),
PatchData: `{"metadata":{"labels":{"a":"c"}}}`,
},
},
},
Expand All @@ -1321,7 +1395,7 @@ func TestResourceModifiers_wildcard_in_GroupResource(t *testing.T) {
},
MergePatches: []JSONMergePatch{
{
PatchData: []byte(`{"metadata":{"labels":{"a":"c"}}}`),
PatchData: `{"metadata":{"labels":{"a":"c"}}}`,
},
},
},
Expand Down Expand Up @@ -1380,7 +1454,7 @@ func TestResourceModifiers_conditional_patches(t *testing.T) {
},
MergePatches: []JSONMergePatch{
{
PatchData: []byte(`{"metadata":{"labels":{"a":"c"}}}`),
PatchData: `{"metadata":{"labels":{"a":"c"}}}`,
},
},
},
Expand Down Expand Up @@ -1409,7 +1483,7 @@ func TestResourceModifiers_conditional_patches(t *testing.T) {
},
MergePatches: []JSONMergePatch{
{
PatchData: []byte(`{"metadata":{"labels":{"a":"c"}}}`),
PatchData: `{"metadata":{"labels":{"a":"c"}}}`,
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func TestResourceModifiers_Validate(t *testing.T) {
},
MergePatches: []JSONMergePatch{
{
PatchData: []byte(`{"metadata":{"labels":{"a":null}}}`),
PatchData: `{"metadata":{"labels":{"a":null}}}`,
},
},
},
Expand Down
5 changes: 2 additions & 3 deletions internal/resourcemodifiers/strategic_merge_patch.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package resourcemodifiers

import (
"encoding/json"
"fmt"
"net/http"

Expand All @@ -18,7 +17,7 @@ import (
)

type StrategicMergePatch struct {
PatchData json.RawMessage `json:"patchData,omitempty"`
PatchData string `json:"patchData,omitempty"`
}

type StrategicMergePatcher struct {
Expand All @@ -36,7 +35,7 @@ func (p *StrategicMergePatcher) Patch(u *unstructured.Unstructured, _ logrus.Fie
origin := u.DeepCopy()
updated := u.DeepCopy()
for _, patch := range p.patches {
patchBytes, err := yaml.YAMLToJSON(patch.PatchData)
patchBytes, err := yaml.YAMLToJSON([]byte(patch.PatchData))
if err != nil {
return nil, fmt.Errorf("error in converting YAML to JSON %s", err)
}
Expand Down
Loading

0 comments on commit d1f5219

Please sign in to comment.