@@ -18,9 +18,12 @@ package client_test
18
18
19
19
import (
20
20
"context"
21
+ "encoding/json"
21
22
"fmt"
22
23
"sync/atomic"
23
24
25
+ "k8s.io/apimachinery/pkg/types"
26
+
24
27
. "github.com/onsi/ginkgo"
25
28
. "github.com/onsi/gomega"
26
29
appsv1 "k8s.io/api/apps/v1"
@@ -62,6 +65,7 @@ var _ = Describe("Client", func() {
62
65
var count uint64 = 0
63
66
var replicaCount int32 = 2
64
67
var ns = "default"
68
+ var mergePatch []byte
65
69
66
70
BeforeEach (func (done Done ) {
67
71
atomic .AddUint64 (& count , 1 )
@@ -88,6 +92,15 @@ var _ = Describe("Client", func() {
88
92
Spec : corev1.NodeSpec {},
89
93
}
90
94
scheme = kscheme .Scheme
95
+ var err error
96
+ mergePatch , err = json .Marshal (map [string ]interface {}{
97
+ "metadata" : map [string ]interface {}{
98
+ "annotations" : map [string ]interface {}{
99
+ "foo" : "bar" ,
100
+ },
101
+ },
102
+ })
103
+ Expect (err ).NotTo (HaveOccurred ())
91
104
92
105
close (done )
93
106
}, serverSideTimeoutSeconds )
@@ -964,6 +977,174 @@ var _ = Describe("Client", func() {
964
977
})
965
978
})
966
979
980
+ Describe ("Patch" , func () {
981
+ Context ("with structured objects" , func () {
982
+ It ("should patch an existing object from a go struct" , func (done Done ) {
983
+ cl , err := client .New (cfg , client.Options {})
984
+ Expect (err ).NotTo (HaveOccurred ())
985
+ Expect (cl ).NotTo (BeNil ())
986
+
987
+ By ("initially creating a Deployment" )
988
+ dep , err := clientset .AppsV1 ().Deployments (ns ).Create (dep )
989
+ Expect (err ).NotTo (HaveOccurred ())
990
+
991
+ By ("patching the Deployment" )
992
+ err = cl .Patch (context .TODO (), dep , client .ConstantPatch (types .MergePatchType , mergePatch ))
993
+ Expect (err ).NotTo (HaveOccurred ())
994
+
995
+ By ("validating patched Deployment has new annotation" )
996
+ actual , err := clientset .AppsV1 ().Deployments (ns ).Get (dep .Name , metav1.GetOptions {})
997
+ Expect (err ).NotTo (HaveOccurred ())
998
+ Expect (actual ).NotTo (BeNil ())
999
+ Expect (actual .Annotations ["foo" ]).To (Equal ("bar" ))
1000
+
1001
+ close (done )
1002
+ })
1003
+
1004
+ It ("should patch an existing object non-namespace object from a go struct" , func (done Done ) {
1005
+ cl , err := client .New (cfg , client.Options {})
1006
+ Expect (err ).NotTo (HaveOccurred ())
1007
+ Expect (cl ).NotTo (BeNil ())
1008
+
1009
+ By ("initially creating a Node" )
1010
+ node , err := clientset .CoreV1 ().Nodes ().Create (node )
1011
+ Expect (err ).NotTo (HaveOccurred ())
1012
+
1013
+ By ("patching the Node" )
1014
+ nodeName := node .Name
1015
+ err = cl .Patch (context .TODO (), node , client .ConstantPatch (types .MergePatchType , mergePatch ))
1016
+ Expect (err ).NotTo (HaveOccurred ())
1017
+
1018
+ By ("validating the Node no longer exists" )
1019
+ actual , err := clientset .CoreV1 ().Nodes ().Get (nodeName , metav1.GetOptions {})
1020
+ Expect (err ).NotTo (HaveOccurred ())
1021
+ Expect (actual ).NotTo (BeNil ())
1022
+ Expect (actual .Annotations ["foo" ]).To (Equal ("bar" ))
1023
+
1024
+ close (done )
1025
+ })
1026
+
1027
+ It ("should fail if the object does not exists" , func (done Done ) {
1028
+ cl , err := client .New (cfg , client.Options {})
1029
+ Expect (err ).NotTo (HaveOccurred ())
1030
+ Expect (cl ).NotTo (BeNil ())
1031
+
1032
+ By ("Patching node before it is ever created" )
1033
+ err = cl .Patch (context .TODO (), node , client .ConstantPatch (types .MergePatchType , mergePatch ))
1034
+ Expect (err ).To (HaveOccurred ())
1035
+
1036
+ close (done )
1037
+ })
1038
+
1039
+ PIt ("should fail if the object doesn't have meta" , func () {
1040
+
1041
+ })
1042
+
1043
+ It ("should fail if the object cannot be mapped to a GVK" , func (done Done ) {
1044
+ By ("creating client with empty Scheme" )
1045
+ emptyScheme := runtime .NewScheme ()
1046
+ cl , err := client .New (cfg , client.Options {Scheme : emptyScheme })
1047
+ Expect (err ).NotTo (HaveOccurred ())
1048
+ Expect (cl ).NotTo (BeNil ())
1049
+
1050
+ By ("initially creating a Deployment" )
1051
+ dep , err := clientset .AppsV1 ().Deployments (ns ).Create (dep )
1052
+ Expect (err ).NotTo (HaveOccurred ())
1053
+
1054
+ By ("patching the Deployment fails" )
1055
+ err = cl .Patch (context .TODO (), dep , client .ConstantPatch (types .MergePatchType , mergePatch ))
1056
+ Expect (err ).To (HaveOccurred ())
1057
+ Expect (err .Error ()).To (ContainSubstring ("no kind is registered for the type" ))
1058
+
1059
+ close (done )
1060
+ })
1061
+
1062
+ PIt ("should fail if the GVK cannot be mapped to a Resource" , func () {
1063
+
1064
+ })
1065
+ })
1066
+ Context ("with unstructured objects" , func () {
1067
+ It ("should patch an existing object from a go struct" , func (done Done ) {
1068
+ cl , err := client .New (cfg , client.Options {})
1069
+ Expect (err ).NotTo (HaveOccurred ())
1070
+ Expect (cl ).NotTo (BeNil ())
1071
+
1072
+ By ("initially creating a Deployment" )
1073
+ dep , err := clientset .AppsV1 ().Deployments (ns ).Create (dep )
1074
+ Expect (err ).NotTo (HaveOccurred ())
1075
+
1076
+ By ("patching the Deployment" )
1077
+ depName := dep .Name
1078
+ u := & unstructured.Unstructured {}
1079
+ scheme .Convert (dep , u , nil )
1080
+ u .SetGroupVersionKind (schema.GroupVersionKind {
1081
+ Group : "apps" ,
1082
+ Kind : "Deployment" ,
1083
+ Version : "v1" ,
1084
+ })
1085
+ err = cl .Patch (context .TODO (), u , client .ConstantPatch (types .MergePatchType , mergePatch ))
1086
+ Expect (err ).NotTo (HaveOccurred ())
1087
+
1088
+ By ("validating patched Deployment has new annotation" )
1089
+ actual , err := clientset .AppsV1 ().Deployments (ns ).Get (depName , metav1.GetOptions {})
1090
+ Expect (err ).NotTo (HaveOccurred ())
1091
+ Expect (actual ).NotTo (BeNil ())
1092
+ Expect (actual .Annotations ["foo" ]).To (Equal ("bar" ))
1093
+
1094
+ close (done )
1095
+ })
1096
+
1097
+ It ("should patch an existing object non-namespace object from a go struct" , func (done Done ) {
1098
+ cl , err := client .New (cfg , client.Options {})
1099
+ Expect (err ).NotTo (HaveOccurred ())
1100
+ Expect (cl ).NotTo (BeNil ())
1101
+
1102
+ By ("initially creating a Node" )
1103
+ node , err := clientset .CoreV1 ().Nodes ().Create (node )
1104
+ Expect (err ).NotTo (HaveOccurred ())
1105
+
1106
+ By ("patching the Node" )
1107
+ nodeName := node .Name
1108
+ u := & unstructured.Unstructured {}
1109
+ scheme .Convert (node , u , nil )
1110
+ u .SetGroupVersionKind (schema.GroupVersionKind {
1111
+ Group : "" ,
1112
+ Kind : "Node" ,
1113
+ Version : "v1" ,
1114
+ })
1115
+ err = cl .Patch (context .TODO (), u , client .ConstantPatch (types .MergePatchType , mergePatch ))
1116
+ Expect (err ).NotTo (HaveOccurred ())
1117
+
1118
+ By ("validating pathed Node has new annotation" )
1119
+ actual , err := clientset .CoreV1 ().Nodes ().Get (nodeName , metav1.GetOptions {})
1120
+ Expect (err ).NotTo (HaveOccurred ())
1121
+ Expect (actual ).NotTo (BeNil ())
1122
+ Expect (actual .Annotations ["foo" ]).To (Equal ("bar" ))
1123
+
1124
+ close (done )
1125
+ })
1126
+
1127
+ It ("should fail if the object does not exist" , func (done Done ) {
1128
+ cl , err := client .New (cfg , client.Options {})
1129
+ Expect (err ).NotTo (HaveOccurred ())
1130
+ Expect (cl ).NotTo (BeNil ())
1131
+
1132
+ By ("Patching node before it is ever created" )
1133
+ u := & unstructured.Unstructured {}
1134
+ scheme .Convert (node , u , nil )
1135
+ u .SetGroupVersionKind (schema.GroupVersionKind {
1136
+ Group : "" ,
1137
+ Kind : "Node" ,
1138
+ Version : "v1" ,
1139
+ })
1140
+ err = cl .Patch (context .TODO (), node , client .ConstantPatch (types .MergePatchType , mergePatch ))
1141
+ Expect (err ).To (HaveOccurred ())
1142
+
1143
+ close (done )
1144
+ })
1145
+ })
1146
+ })
1147
+
967
1148
Describe ("Get" , func () {
968
1149
Context ("with structured objects" , func () {
969
1150
It ("should fetch an existing object for a go struct" , func (done Done ) {
@@ -1984,6 +2165,46 @@ var _ = Describe("DelegatingReader", func() {
1984
2165
})
1985
2166
})
1986
2167
2168
+ var _ = Describe ("Patch" , func () {
2169
+ Describe ("CreateMergePatch" , func () {
2170
+ var cm * corev1.ConfigMap
2171
+
2172
+ BeforeEach (func () {
2173
+ cm = & corev1.ConfigMap {
2174
+ ObjectMeta : metav1.ObjectMeta {
2175
+ Namespace : metav1 .NamespaceDefault ,
2176
+ Name : "cm" ,
2177
+ },
2178
+ }
2179
+ })
2180
+
2181
+ It ("creates a merge patch with the modifications applied during the mutation" , func () {
2182
+ const (
2183
+ annotationKey = "test"
2184
+ annotationValue = "foo"
2185
+ )
2186
+
2187
+ By ("creating a merge patch" )
2188
+ patch := client .MergeFrom (cm .DeepCopy ())
2189
+
2190
+ By ("returning a patch with type MergePatch" )
2191
+ Expect (patch .Type ()).To (Equal (types .MergePatchType ))
2192
+
2193
+ By ("retrieving modifying the config map" )
2194
+ metav1 .SetMetaDataAnnotation (& cm .ObjectMeta , annotationKey , annotationValue )
2195
+
2196
+ By ("computing the patch data" )
2197
+ data , err := patch .Data (cm )
2198
+
2199
+ By ("returning no error" )
2200
+ Expect (err ).NotTo (HaveOccurred ())
2201
+
2202
+ By ("returning a patch with data only containing the annotation change" )
2203
+ Expect (data ).To (Equal ([]byte (fmt .Sprintf (`{"metadata":{"annotations":{"%s":"%s"}}}` , annotationKey , annotationValue ))))
2204
+ })
2205
+ })
2206
+ })
2207
+
1987
2208
type fakeReader struct {
1988
2209
Called int
1989
2210
}
0 commit comments