Skip to content

Commit de0c744

Browse files
KRA-453 - bug fixing (#26)
* fix: bump unstructured-runtime version * fix: added handling of empty response body in Update function * fix: return error on unexpecded nil body * test: added unit tests for empty body case * fix: fixing typo in comment * fix: Fail when only GET verb is defined in rest definition (#20) --------- Co-authored-by: Leonardo Vicentini <[email protected]>
1 parent cec3ad7 commit de0c744

File tree

7 files changed

+185
-77
lines changed

7 files changed

+185
-77
lines changed

go.mod

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
module github.com/krateoplatformops/rest-dynamic-controller
22

3-
go 1.24.0
3+
go 1.24.2
44

55
require (
66
github.com/gobuffalo/flect v1.0.3
77
github.com/krateoplatformops/snowplow v0.0.0-20250311104630-6e215130151f
8-
github.com/krateoplatformops/unstructured-runtime v0.1.2
8+
github.com/krateoplatformops/unstructured-runtime v0.1.5
99
github.com/pb33f/libopenapi v0.21.8
1010
github.com/rs/zerolog v1.34.0
1111
github.com/stretchr/testify v1.10.0
12-
k8s.io/api v0.32.3
13-
k8s.io/apimachinery v0.32.3
14-
k8s.io/client-go v0.32.3
12+
k8s.io/api v0.33.0
13+
k8s.io/apimachinery v0.33.0
14+
k8s.io/client-go v0.33.0
1515
sigs.k8s.io/controller-runtime v0.20.0
1616
sigs.k8s.io/e2e-framework v0.6.0
1717
)
@@ -33,15 +33,14 @@ require (
3333
github.com/go-openapi/jsonreference v0.21.0 // indirect
3434
github.com/go-openapi/swag v0.23.0 // indirect
3535
github.com/gogo/protobuf v1.3.2 // indirect
36-
github.com/golang/protobuf v1.5.4 // indirect
37-
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
38-
github.com/google/go-cmp v0.6.0 // indirect
39-
github.com/google/gofuzz v1.2.0 // indirect
36+
github.com/google/gnostic-models v0.6.9 // indirect
37+
github.com/google/go-cmp v0.7.0 // indirect
4038
github.com/google/uuid v1.6.0 // indirect
41-
github.com/gorilla/websocket v1.5.1 // indirect
39+
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
4240
github.com/inconshreveable/mousetrap v1.1.0 // indirect
4341
github.com/josharian/intern v1.0.0 // indirect
4442
github.com/json-iterator/go v1.1.12 // indirect
43+
github.com/krateoplatformops/plumbing v0.4.0 // indirect
4544
github.com/mailru/easyjson v0.7.7 // indirect
4645
github.com/mattn/go-colorable v0.1.13 // indirect
4746
github.com/mattn/go-isatty v0.0.20 // indirect
@@ -76,19 +75,20 @@ require (
7675
golang.org/x/text v0.24.0 // indirect
7776
golang.org/x/time v0.11.0 // indirect
7877
golang.org/x/tools v0.26.0 // indirect
79-
google.golang.org/protobuf v1.35.1 // indirect
78+
google.golang.org/protobuf v1.36.5 // indirect
8079
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
8180
gopkg.in/inf.v0 v0.9.1 // indirect
8281
gopkg.in/yaml.v2 v2.4.0 // indirect
8382
gopkg.in/yaml.v3 v3.0.1 // indirect
8483
k8s.io/apiextensions-apiserver v0.32.0 // indirect
85-
k8s.io/component-base v0.32.1 // indirect
84+
k8s.io/component-base v0.32.3 // indirect
8685
k8s.io/klog/v2 v2.130.1 // indirect
87-
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
86+
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
8887
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
8988
sigs.k8s.io/controller-tools v0.16.5 // indirect
9089
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
91-
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
90+
sigs.k8s.io/randfill v1.0.0 // indirect
91+
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
9292
sigs.k8s.io/yaml v1.4.0 // indirect
9393
)
9494

go.sum

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,18 @@ github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnD
4343
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
4444
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
4545
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
46-
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
47-
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
48-
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU=
49-
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M=
46+
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
47+
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
5048
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
51-
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
52-
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
49+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
50+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
5351
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
54-
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
55-
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
5652
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
5753
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
5854
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
5955
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
60-
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
61-
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
56+
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
57+
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
6258
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
6359
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
6460
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -73,10 +69,12 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
7369
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
7470
github.com/krateoplatformops/libopenapi v0.21.8 h1:KKZxXBqkXoWv+/+bVLQiiRZXxHY1Zz+0Yd+ht+ArqWE=
7571
github.com/krateoplatformops/libopenapi v0.21.8/go.mod h1:Gc8oQkjr2InxwumK0zOBtKN9gIlv9L2VmSVIUk2YxcU=
72+
github.com/krateoplatformops/plumbing v0.4.0 h1:XIW3Y9LzaVMBJvbLVoloreAmjmFh4SPp65V264hd+3c=
73+
github.com/krateoplatformops/plumbing v0.4.0/go.mod h1:yzWtJEhG4hKqgci311GaauoJJ5HJBbZdbbZ23bYDUsE=
7674
github.com/krateoplatformops/snowplow v0.0.0-20250311104630-6e215130151f h1:Kw7J+0uCHPlWmcXeSvstQJDqwMwJ5WgETkHj4Z+UEjI=
7775
github.com/krateoplatformops/snowplow v0.0.0-20250311104630-6e215130151f/go.mod h1:C9UtLN04vcF+Hj79scByTjmwWvIQvAc7i8Dk3N+f6PA=
78-
github.com/krateoplatformops/unstructured-runtime v0.1.2 h1:SofN3JXGbyAIgfXWOFJOtQAg4CnePyoM0eD8KZa66iQ=
79-
github.com/krateoplatformops/unstructured-runtime v0.1.2/go.mod h1:B2QCsbn9XvgSdIj+Q4JMDYt7juHskkJ5ItGg3qBmJFo=
76+
github.com/krateoplatformops/unstructured-runtime v0.1.5 h1:HemxmcNFZO3UaJDMWopytw5+Vx8YLgLrzOoZrrvMfPI=
77+
github.com/krateoplatformops/unstructured-runtime v0.1.5/go.mod h1:jzptgwcrWB3UtusLKkH4eVDelmF57B37cKoFVzdZvQg=
8078
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
8179
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
8280
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
@@ -117,8 +115,8 @@ github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G
117115
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
118116
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
119117
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
120-
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
121-
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
118+
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
119+
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
122120
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
123121
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
124122
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
@@ -132,6 +130,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
132130
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
133131
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
134132
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
133+
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
134+
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
135135
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
136136
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
137137
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
@@ -204,8 +204,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
204204
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
205205
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
206206
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
207-
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
208-
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
207+
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
208+
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
209209
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
210210
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
211211
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -220,20 +220,20 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
220220
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
221221
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
222222
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
223-
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
224-
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
223+
k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=
224+
k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=
225225
k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0=
226226
k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw=
227-
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
228-
k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
229-
k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=
230-
k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY=
231-
k8s.io/component-base v0.32.1 h1:/5IfJ0dHIKBWysGV0yKTFfacZ5yNV1sulPh3ilJjRZk=
232-
k8s.io/component-base v0.32.1/go.mod h1:j1iMMHi/sqAHeG5z+O9BFNCF698a1u0186zkjMZQ28w=
227+
k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
228+
k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
229+
k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98=
230+
k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg=
231+
k8s.io/component-base v0.32.3 h1:98WJvvMs3QZ2LYHBzvltFSeJjEx7t5+8s71P7M74u8k=
232+
k8s.io/component-base v0.32.3/go.mod h1:LWi9cR+yPAv7cu2X9rZanTiFKB2kHA+JjmhkKjCZRpI=
233233
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
234234
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
235-
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
236-
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
235+
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
236+
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
237237
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
238238
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
239239
sigs.k8s.io/controller-runtime v0.20.0 h1:jjkMo29xEXH+02Md9qaVXfEIaMESSpy3TBWPrsfQkQs=
@@ -244,7 +244,10 @@ sigs.k8s.io/e2e-framework v0.6.0 h1:p7hFzHnLKO7eNsWGI2AbC1Mo2IYxidg49BiT4njxkrM=
244244
sigs.k8s.io/e2e-framework v0.6.0/go.mod h1:IREnCHnKgRCioLRmNi0hxSJ1kJ+aAdjEKK/gokcZu4k=
245245
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
246246
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
247-
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA=
248-
sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
247+
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
248+
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
249+
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
250+
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=
251+
sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
249252
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
250253
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

internal/client/restclient.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,39 @@ func (u *UnstructuredClient) Call(ctx context.Context, cli *http.Client, path st
9999
}
100100
}
101101

102+
// Read the response body as we need to check its content length
103+
// Just checking if resp.Body is nil does not work, as it can be non-nil with a zero-length body.
104+
bodyBytes, err := io.ReadAll(resp.Body)
105+
if err != nil {
106+
return nil, fmt.Errorf("failed to read response body: %w", err)
107+
}
108+
109+
defer resp.Body.Close()
110+
111+
// Re-wrap body otherwise it will be closed
112+
resp.Body = io.NopCloser(bytes.NewReader(bodyBytes))
113+
114+
// Allow empty body only 204 No Content and 304 Not Modified responses
115+
statusAllowsEmpty := resp.StatusCode == http.StatusNoContent || resp.StatusCode == http.StatusNotModified
116+
117+
// E.g. 200 but with no content, or 201 Created with no content (error case)
118+
if len(bodyBytes) == 0 && !statusAllowsEmpty {
119+
return nil, fmt.Errorf("response body is empty for unexpected status code %d", resp.StatusCode)
120+
}
121+
122+
// For status codes that allow empty bodies (e.g., 204, 304), return nil directly, without going through handleResponse
123+
if len(bodyBytes) == 0 && statusAllowsEmpty {
124+
return nil, nil
125+
}
126+
102127
err = handleResponse(resp.Body, &response)
103128
if err != nil {
104129
return nil, fmt.Errorf("error handling response: %w", err)
105130
}
106131

107132
val, ok := response.(map[string]interface{})
108133
if !ok {
109-
return nil, nil
134+
return nil, fmt.Errorf("unexpected response type: %T", response)
110135
}
111136
return &val, nil
112137
}

internal/client/restclient_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ func createTestClient(t *testing.T) *UnstructuredClient {
3333
}
3434
}
3535

36+
func TestPathValidation(t *testing.T) {
37+
client := createTestClient(t)
38+
39+
// This should get errors because the path does not exist in the OpenAPI document
40+
_, err := client.Call(context.Background(), &http.Client{}, "/api/nonexistent", &RequestConfiguration{Method: "GET"})
41+
assert.Error(t, err)
42+
}
43+
3644
func TestCallWithRecorder(t *testing.T) {
3745
tests := []struct {
3846
name string
@@ -200,6 +208,53 @@ func TestCallWithRecorder(t *testing.T) {
200208
expected: map[string]interface{}{"message": "override success"},
201209
expectedURL: "http://override.example.com/api/override",
202210
},
211+
{
212+
name: "error with empty body and 200 status code",
213+
handler: func(w http.ResponseWriter, r *http.Request) {
214+
assert.Equal(t, "GET", r.Method)
215+
w.WriteHeader(http.StatusOK) // 200 OK
216+
// No body written, this should cause an error since 200 expects content
217+
},
218+
path: "/api/test/{id}",
219+
opts: &RequestConfiguration{
220+
Method: "GET",
221+
Parameters: map[string]string{
222+
"id": "123",
223+
},
224+
},
225+
expectedError: "response body is empty for unexpected status code 200",
226+
},
227+
{
228+
name: "error with empty body and 201 status code",
229+
handler: func(w http.ResponseWriter, r *http.Request) {
230+
assert.Equal(t, "POST", r.Method)
231+
w.WriteHeader(http.StatusCreated) // 201 Created
232+
// No body written, this should cause an error since 201 expects content
233+
},
234+
path: "/api/test",
235+
opts: &RequestConfiguration{
236+
Method: "POST",
237+
Body: map[string]interface{}{"name": "test"},
238+
},
239+
expectedError: "response body is empty for unexpected status code 201",
240+
},
241+
{
242+
name: "success with empty body and 204 status code",
243+
handler: func(w http.ResponseWriter, r *http.Request) {
244+
assert.Equal(t, "PUT", r.Method)
245+
w.WriteHeader(http.StatusNoContent) // 204 No Content
246+
// No body written
247+
},
248+
path: "/api/test/{id}",
249+
opts: &RequestConfiguration{
250+
Method: "PUT",
251+
Parameters: map[string]string{
252+
"id": "123",
253+
},
254+
Body: map[string]interface{}{"name": "test"},
255+
},
256+
expected: nil, // 204 should return nil
257+
},
203258
}
204259

205260
for _, tt := range tests {
@@ -239,6 +294,12 @@ func TestCallWithRecorder(t *testing.T) {
239294

240295
require.NoError(t, err)
241296

297+
// We expect nil for 204 and 304 responses and no error
298+
if tt.expected == nil {
299+
assert.Nil(t, result)
300+
return
301+
}
302+
242303
if result == nil {
243304
assert.Nil(t, tt.expected)
244305
return

internal/client/testdata/openapi.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,27 @@ paths:
3131
type: string
3232
'404':
3333
description: Not found
34+
put:
35+
summary: Update test data
36+
operationId: updateTest
37+
parameters:
38+
- name: id
39+
in: path
40+
required: true
41+
schema:
42+
type: string
43+
requestBody:
44+
required: true
45+
content:
46+
application/json:
47+
schema:
48+
type: object
49+
properties:
50+
name:
51+
type: string
52+
responses:
53+
'204':
54+
description: No content
3455
/api/test:
3556
get:
3657
summary: Get test data

0 commit comments

Comments
 (0)