Skip to content
This repository was archived by the owner on Aug 28, 2025. It is now read-only.

Commit 018293c

Browse files
authored
(feat) Add patch_json mutation (DXPFRAME-1489) (#3)
* Add new mutation for patch_json and patchItem method that sends a patch-json request * cleanup commented code * Fix error messages * Move creation of patch argument field config into a separate function * change patch_json to patch and add a type argument * throw error if patch-type is invalid * Change patch type names * fix error message
1 parent 60894cd commit 018293c

File tree

4 files changed

+113
-7
lines changed

4 files changed

+113
-7
lines changed

gateway/gateway.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,12 @@ func New(ctx context.Context, conf Config) (graphql.Schema, error) {
437437
Args: resolver.getChangeArguments(inputFields["spec"].Type),
438438
Resolve: resolver.updateItem(crd, typeInformation),
439439
})
440+
441+
mutationGroupType.AddFieldConfig("patch"+capitalizedSingular, &graphql.Field{
442+
Type: crdType,
443+
Args: resolver.getPatchArguments(),
444+
Resolve: resolver.patchItem(crd, typeInformation),
445+
})
440446
}
441447

442448
subscriptions[group+typeInformation.Name+capitalizedSingular] = &graphql.Field{

gateway/resolver.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"k8s.io/apimachinery/pkg/labels"
2121
"k8s.io/apimachinery/pkg/runtime"
2222
"k8s.io/apimachinery/pkg/runtime/schema"
23+
"k8s.io/apimachinery/pkg/types"
2324
"k8s.io/apimachinery/pkg/watch"
2425
"sigs.k8s.io/controller-runtime/pkg/client"
2526
)
@@ -121,6 +122,23 @@ func (r *resolver) getChangeArguments(input graphql.Input) graphql.FieldConfigAr
121122
}
122123
}
123124

125+
func (r *resolver) getPatchArguments() graphql.FieldConfigArgument {
126+
return graphql.FieldConfigArgument{
127+
"type": &graphql.ArgumentConfig{
128+
Type: graphql.NewNonNull(graphql.String),
129+
Description: "The JSON patch type, it can be json-patch, merge-patch, strategic-merge-patch",
130+
},
131+
"payload": &graphql.ArgumentConfig{
132+
Type: graphql.NewNonNull(graphql.String),
133+
Description: "The JSON patch to apply to the object",
134+
},
135+
"metadata": &graphql.ArgumentConfig{
136+
Type: graphql.NewNonNull(metadataInput),
137+
Description: "Metadata including name and namespace of the object you want to patch",
138+
},
139+
}
140+
}
141+
124142
func (r *resolver) getItem(crd apiextensionsv1.CustomResourceDefinition, typeInformation apiextensionsv1.CustomResourceDefinitionVersion) func(p graphql.ResolveParams) (interface{}, error) {
125143
logger := slog.With(slog.String("operation", "get"), slog.String("kind", crd.Spec.Names.Kind), slog.String("version", typeInformation.Name))
126144
return func(p graphql.ResolveParams) (interface{}, error) {
@@ -284,6 +302,74 @@ func (r *resolver) updateItem(crd apiextensionsv1.CustomResourceDefinition, type
284302
}
285303
}
286304

305+
func (r *resolver) patchItem(crd apiextensionsv1.CustomResourceDefinition, typeInformation apiextensionsv1.CustomResourceDefinitionVersion) func(p graphql.ResolveParams) (interface{}, error) {
306+
logger := slog.With(slog.String("operation", "patch-json"), slog.String("kind", crd.Spec.Names.Kind), slog.String("version", typeInformation.Name))
307+
return func(p graphql.ResolveParams) (interface{}, error) {
308+
ctx, span := otel.Tracer("").Start(p.Context, "Patch", trace.WithAttributes(attribute.String("kind", crd.Spec.Names.Kind)))
309+
defer span.End()
310+
311+
var metadatInput MetadatInput
312+
if err := mapstructure.Decode(p.Args["metadata"], &metadatInput); err != nil {
313+
logger.Error("unable to decode metadata input", "error", err)
314+
return nil, err
315+
}
316+
317+
logger = logger.With(slog.Group("metadata", slog.String("name", metadatInput.Name), slog.String("namespace", metadatInput.Namespace)))
318+
319+
us := &unstructured.Unstructured{}
320+
us.SetGroupVersionKind(schema.GroupVersionKind{
321+
Group: crd.Spec.Group,
322+
Version: typeInformation.Name,
323+
Kind: crd.Spec.Names.Kind,
324+
})
325+
326+
us.SetNamespace(metadatInput.Namespace)
327+
us.SetName(metadatInput.Name)
328+
329+
err := r.conf.Client.Get(ctx, client.ObjectKey{Namespace: us.GetNamespace(), Name: us.GetName()}, us)
330+
if err != nil {
331+
logger.Error("unable to get object", slog.Any("error", err))
332+
return nil, err
333+
}
334+
335+
payload, ok := p.Args["payload"].(string)
336+
if !ok {
337+
logger.Error("unable to parse payload field")
338+
return nil, errors.New("unable to parse payload field")
339+
}
340+
341+
patchTypeArg, ok := p.Args["type"].(string)
342+
if !ok {
343+
logger.Error("unable to parse patch type field")
344+
return nil, errors.New("unable to parse patch type field")
345+
}
346+
347+
var patchType types.PatchType
348+
switch patchTypeArg {
349+
case "json-patch":
350+
patchType = types.JSONPatchType
351+
case "merge-patch":
352+
patchType = types.MergePatchType
353+
case "strategic-merge-patch":
354+
patchType = types.StrategicMergePatchType
355+
default:
356+
logger.Error("invalid patch type, patch type can be json-patch, merge-patch or strategic-merge-patch")
357+
return nil, errors.New("invalid patch type, patch type can be json-patch, merge-patch or strategic-merge-patch")
358+
}
359+
360+
patch := client.RawPatch(patchType, []byte(payload))
361+
362+
err = r.conf.Client.Patch(ctx, us, patch, &client.PatchOptions{})
363+
364+
if err != nil {
365+
logger.Error("unable to patch object", slog.Any("error", err))
366+
return nil, err
367+
}
368+
369+
return us.Object, nil
370+
}
371+
}
372+
287373
func (r *resolver) subscribeItem(crd apiextensionsv1.CustomResourceDefinition, typeInformation apiextensionsv1.CustomResourceDefinitionVersion) func(p graphql.ResolveParams) (interface{}, error) {
288374
logger := slog.With(slog.String("operation", "subribeItem"), slog.String("kind", crd.Spec.Names.Kind), slog.String("version", typeInformation.Name))
289375
return func(p graphql.ResolveParams) (interface{}, error) {

go.mod

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ require (
99
github.com/graphql-go/handler v0.2.3
1010
github.com/mitchellh/mapstructure v1.5.0
1111
github.com/spf13/cobra v1.8.1
12-
github.tools.sap/automaticd/automaticd/operators/jenx v0.0.0-20240726034443-228245d73830
12+
github.tools.sap/automaticd/automaticd/operators/jenx v0.0.0-20240821081458-cc06fd10fa7b
1313
github.tools.sap/automaticd/automaticd/operators/jira v0.0.0-20240513130407-09009e9c881c
1414
go.opentelemetry.io/otel v1.28.0
1515
go.opentelemetry.io/otel/trace v1.28.0
1616
golang.org/x/text v0.16.0
1717
k8s.io/api v0.30.3
18-
k8s.io/apiextensions-apiserver v0.30.2
18+
k8s.io/apiextensions-apiserver v0.30.3
1919
k8s.io/apimachinery v0.30.3
2020
k8s.io/client-go v0.30.3
2121
sigs.k8s.io/controller-runtime v0.18.4
@@ -61,15 +61,15 @@ require (
6161
go.opentelemetry.io/otel/metric v1.28.0 // indirect
6262
go.opentelemetry.io/otel/sdk v1.28.0 // indirect
6363
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
64-
golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect
64+
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
6565
golang.org/x/net v0.27.0 // indirect
66-
golang.org/x/oauth2 v0.21.0 // indirect
66+
golang.org/x/oauth2 v0.22.0 // indirect
6767
golang.org/x/sys v0.22.0 // indirect
6868
golang.org/x/term v0.22.0 // indirect
69-
golang.org/x/time v0.5.0 // indirect
69+
golang.org/x/time v0.6.0 // indirect
7070
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
71-
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect
72-
google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b // indirect
71+
google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f // indirect
72+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf // indirect
7373
google.golang.org/grpc v1.65.0 // indirect
7474
google.golang.org/protobuf v1.34.2 // indirect
7575
gopkg.in/inf.v0 v0.9.1 // indirect

go.sum

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
118118
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
119119
github.tools.sap/automaticd/automaticd/operators/jenx v0.0.0-20240726034443-228245d73830 h1:n2WvnV+unVVtxd6HOUPNKbhBu7tpGcQkF3Mu1wlrfMw=
120120
github.tools.sap/automaticd/automaticd/operators/jenx v0.0.0-20240726034443-228245d73830/go.mod h1:ZBkRAGjLGbV2R+xiBmYvClQTHUA7othEk55xOnskF9I=
121+
github.tools.sap/automaticd/automaticd/operators/jenx v0.0.0-20240821081458-cc06fd10fa7b h1:stDMPZcmccI+Xll5msHZq+/VdYSrv3nxBkTgCI9FouU=
122+
github.tools.sap/automaticd/automaticd/operators/jenx v0.0.0-20240821081458-cc06fd10fa7b/go.mod h1:WFRQVJemTPET441A8VQ1aPYe7hOXO13GlMsr+v7V928=
121123
github.tools.sap/automaticd/automaticd/operators/jira v0.0.0-20240513130407-09009e9c881c h1:Z7FreYuCUpV2y6WXhOtH2Lv3cf49WxsPKQaztfmwLsQ=
122124
github.tools.sap/automaticd/automaticd/operators/jira v0.0.0-20240513130407-09009e9c881c/go.mod h1:QeBIjruI/DXst/ZooNavxL1bVqY2FVOYlCK8iMUk4V4=
123125
github.tools.sap/automaticd/automaticd/shared v0.41.1 h1:f5CXih9C+ZIF6bGlNNWYBzXweWV16+wKl9JXVAkKJqA=
@@ -147,6 +149,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
147149
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
148150
golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w=
149151
golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
152+
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
153+
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
150154
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
151155
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
152156
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -157,6 +161,8 @@ golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
157161
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
158162
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
159163
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
164+
golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA=
165+
golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
160166
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
161167
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
162168
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -173,6 +179,8 @@ golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
173179
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
174180
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
175181
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
182+
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
183+
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
176184
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
177185
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
178186
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@@ -187,8 +195,12 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw
187195
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
188196
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0=
189197
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw=
198+
google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f h1:b1Ln/PG8orm0SsBbHZWke8dDp2lrCD4jSmfglFpTZbk=
199+
google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:AHT0dDg3SoMOgZGnZk29b5xTbPHMoEC8qthmBLJCpys=
190200
google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b h1:04+jVzTs2XBnOZcPsLnmrTGqltqJbZQ1Ey26hjYdQQ0=
191201
google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
202+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf h1:liao9UHurZLtiEwBgT9LMOnKYsHze6eA6w1KQCMVN2Q=
203+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
192204
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
193205
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
194206
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
@@ -207,6 +219,8 @@ k8s.io/api v0.30.3 h1:ImHwK9DCsPA9uoU3rVh4QHAHHK5dTSv1nxJUapx8hoQ=
207219
k8s.io/api v0.30.3/go.mod h1:GPc8jlzoe5JG3pb0KJCSLX5oAFIW3/qNJITlDj8BH04=
208220
k8s.io/apiextensions-apiserver v0.30.2 h1:l7Eue2t6QiLHErfn2vwK4KgF4NeDgjQkCXtEbOocKIE=
209221
k8s.io/apiextensions-apiserver v0.30.2/go.mod h1:lsJFLYyK40iguuinsb3nt+Sj6CmodSI4ACDLep1rgjw=
222+
k8s.io/apiextensions-apiserver v0.30.3 h1:oChu5li2vsZHx2IvnGP3ah8Nj3KyqG3kRSaKmijhB9U=
223+
k8s.io/apiextensions-apiserver v0.30.3/go.mod h1:uhXxYDkMAvl6CJw4lrDN4CPbONkF3+XL9cacCT44kV4=
210224
k8s.io/apimachinery v0.30.3 h1:q1laaWCmrszyQuSQCfNB8cFgCuDAoPszKY4ucAjDwHc=
211225
k8s.io/apimachinery v0.30.3/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
212226
k8s.io/client-go v0.30.3 h1:bHrJu3xQZNXIi8/MoxYtZBBWQQXwy16zqJwloXXfD3k=

0 commit comments

Comments
 (0)