Skip to content
Open
21 changes: 17 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ go 1.25.7

replace github.com/yudai/gojsondiff v1.0.0 => github.com/Kong/gojsondiff v1.3.0

replace (
k8s.io/api => k8s.io/api v0.33.1
k8s.io/apimachinery => k8s.io/apimachinery v0.33.1
k8s.io/client-go => k8s.io/client-go v0.33.1
k8s.io/code-generator => k8s.io/code-generator v0.33.1
k8s.io/kubectl => k8s.io/kubectl v0.33.1
)

require (
dario.cat/mergo v1.0.2
github.com/Kong/gojsondiff v1.3.2
Expand All @@ -20,8 +28,8 @@ require (
github.com/hashicorp/go-memdb v1.3.5
github.com/hashicorp/go-retryablehttp v0.7.8
github.com/hexops/gotextdiff v1.0.3
github.com/kong/deck v1.56.0
github.com/kong/go-kong v0.72.1
github.com/kong/deck v1.55.1
github.com/kong/go-kong v0.72.1-0.20260313025716-eb4629dd857b
github.com/samber/lo v1.52.0
github.com/shirou/gopsutil/v3 v3.24.5
github.com/ssgelm/cookiejarparser v1.0.1
Expand Down Expand Up @@ -127,16 +135,20 @@ require (
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/mod v0.29.0 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.31.0 // indirect
golang.org/x/tools v0.38.0 // indirect
google.golang.org/protobuf v1.36.8 // indirect
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.35.1 // indirect
k8s.io/api v0.35.2 // indirect
k8s.io/apiextensions-apiserver v0.33.1 // indirect
k8s.io/apimachinery v0.35.1 // indirect
k8s.io/apimachinery v0.35.2 // indirect
k8s.io/client-go v0.35.2 // indirect
k8s.io/component-helpers v0.35.2 // indirect
k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
Expand All @@ -145,5 +157,6 @@ require (
sigs.k8s.io/gateway-api v1.3.0 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
)
53 changes: 28 additions & 25 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/
github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE=
github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4=
github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
Expand Down Expand Up @@ -221,12 +218,12 @@ github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuOb
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kong/deck v1.56.0 h1:HpVpODc3Ct0X+3GnZZlcuTK2zwxAioNK8IlVjX0XbU0=
github.com/kong/deck v1.56.0/go.mod h1:0qVMay6jN0fc8hlpKcS+ggiLCnXwbMH1gBXg87ueRB4=
github.com/kong/deck v1.55.1 h1:p7Mg6ruIsrpOWPigvKOv8GdPznnTy7/CYryTlnIm4W8=
github.com/kong/deck v1.55.1/go.mod h1:wTzQPElIoKgBheytGTyzY+wlHAWd72hUDFDeUmOa2V4=
github.com/kong/go-apiops v0.2.2 h1:Owdcl/PxTdtciqyZKgPScVhTKHgY2b8dGIC1Bms8NpI=
github.com/kong/go-apiops v0.2.2/go.mod h1:yPwbl3P2eQinVGAEA0d3legaYmzPJ+WtJf9fSeGF4b8=
github.com/kong/go-kong v0.72.1 h1:rQ69f3Wd0Fvc3JANkavo34vePqR4uZG/YQ2y5U7d2Po=
github.com/kong/go-kong v0.72.1/go.mod h1:J0vGB3wsZ2i99zly1zTRe3v7rOKpkhQZRwbcTFP76qM=
github.com/kong/go-kong v0.72.1-0.20260313025716-eb4629dd857b h1:OmGL1ujx54UH6Jqth/RGR6vSc2jZBPkabIrX7EpczLU=
github.com/kong/go-kong v0.72.1-0.20260313025716-eb4629dd857b/go.mod h1:J0vGB3wsZ2i99zly1zTRe3v7rOKpkhQZRwbcTFP76qM=
github.com/kong/go-slugify v1.0.0 h1:vCFAyf2sdoSlBtLcrmDWUFn0ohlpKiKvQfXZkO5vSKY=
github.com/kong/go-slugify v1.0.0/go.mod h1:dbR2h3J2QKXQ1k0aww6cN7o4cIcwlWflr6RKRdcoaiw=
github.com/kong/kubernetes-configuration v1.4.2 h1:/OafLbl2NucvgQV7Xf/uneIgjxmPPUeE92BrssfVAQY=
Expand Down Expand Up @@ -296,15 +293,15 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns=
github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
Expand Down Expand Up @@ -339,8 +336,8 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
Expand Down Expand Up @@ -544,8 +541,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
golang.org/x/tools/go/expect v0.1.0-deprecated h1:jY2C5HGYR5lqex3gEniOQL0r7Dq5+VGVgY1nudX5lXY=
golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down Expand Up @@ -587,28 +584,30 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.35.1 h1:0PO/1FhlK/EQNVK5+txc4FuhQibV25VLSdLMmGpDE/Q=
k8s.io/api v0.35.1/go.mod h1:28uR9xlXWml9eT0uaGo6y71xK86JBELShLy4wR1XtxM=
k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
k8s.io/apiextensions-apiserver v0.33.1 h1:N7ccbSlRN6I2QBcXevB73PixX2dQNIW0ZRuguEE91zI=
k8s.io/apiextensions-apiserver v0.33.1/go.mod h1:uNQ52z1A1Gu75QSa+pFK5bcXc4hq7lpOXbweZgi4dqA=
k8s.io/apimachinery v0.35.1 h1:yxO6gV555P1YV0SANtnTjXYfiivaTPvCTKX6w6qdDsU=
k8s.io/apimachinery v0.35.1/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns=
k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/cli-runtime v0.31.0 h1:V2Q1gj1u3/WfhD475HBQrIYsoryg/LrhhK4RwpN+DhA=
k8s.io/cli-runtime v0.31.0/go.mod h1:vg3H94wsubuvWfSmStDbekvbla5vFGC+zLWqcf+bGDw=
k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM=
k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA=
k8s.io/code-generator v0.35.1 h1:yLKR2la7Z9cWT5qmk67ayx8xXLM4RRKQMnC8YPvTWRI=
k8s.io/code-generator v0.35.1/go.mod h1:F2Fhm7aA69tC/VkMXLDokdovltXEF026Tb9yfQXQWKg=
k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
k8s.io/client-go v0.33.1/go.mod h1:JAsUrl1ArO7uRVFWfcj6kOomSlCv+JpvIsp6usAGefA=
k8s.io/code-generator v0.33.1 h1:ZLzIRdMsh3Myfnx9BaooX6iQry29UJjVfVG+BuS+UMw=
k8s.io/code-generator v0.33.1/go.mod h1:HUKT7Ubp6bOgIbbaPIs9lpd2Q02uqkMCMx9/GjDrWpY=
k8s.io/component-base v0.33.1 h1:EoJ0xA+wr77T+G8p6T3l4efT2oNwbqBVKR71E0tBIaI=
k8s.io/component-base v0.33.1/go.mod h1:guT/w/6piyPfTgq7gfvgetyXMIh10zuXA6cRRm3rDuY=
k8s.io/component-helpers v0.35.2 h1:7Ea4CDgHnyOGrl3ZhD8e46SdTyf1itTONnreJ2Q52UM=
k8s.io/component-helpers v0.35.2/go.mod h1:ybIoc8i92FG7xJFrBcEMzB8ul1wlZgfF0I4Z9w0V6VQ=
k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b h1:gMplByicHV/TJBizHd9aVEsTYoJBnnUAT5MHlTkbjhQ=
k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b/go.mod h1:CgujABENc3KuTrcsdpGmrrASjtQsWCT7R99mEV4U/fM=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
k8s.io/kubectl v0.31.0 h1:kANwAAPVY02r4U4jARP/C+Q1sssCcN/1p9Nk+7BQKVg=
k8s.io/kubectl v0.31.0/go.mod h1:pB47hhFypGsaHAPjlwrNbvhXgmuAr01ZBvAIIUaI8d4=
k8s.io/kubectl v0.33.1 h1:OJUXa6FV5bap6iRy345ezEjU9dTLxqv1zFTVqmeHb6A=
k8s.io/kubectl v0.33.1/go.mod h1:Z07pGqXoP4NgITlPRrnmiM3qnoo1QrK1zjw85Aiz8J0=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU=
Expand All @@ -623,9 +622,13 @@ sigs.k8s.io/kustomize/api v0.17.3 h1:6GCuHSsxq7fN5yhF2XrC+AAr8gxQwhexgHflOAD/JJU
sigs.k8s.io/kustomize/api v0.17.3/go.mod h1:TuDH4mdx7jTfK61SQ/j1QZM/QWR+5rmEiNjvYlhzFhc=
sigs.k8s.io/kustomize/kyaml v0.17.2 h1:+AzvoJUY0kq4QAhH/ydPHHMRLijtUKiyVyh7fOSshr0=
sigs.k8s.io/kustomize/kyaml v0.17.2/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U=
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=
sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco=
sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
2 changes: 2 additions & 0 deletions pkg/diff/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,8 @@ func (sc *Syncer) init() error {

types.DegraphqlRoute,

types.GraphqlRateLimitingCostDecoration,

types.Partial,

types.Key, types.KeySet,
Expand Down
2 changes: 2 additions & 0 deletions pkg/diff/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ L3 +---------------------------> Service <---+ +-> Route |
L4 +----------> Document <---------+ +-> Plugins / <---------+
FilterChains
CustomEntities - DegraphqlRoute
- GraphqlRateLimitingCostDecoration
*/

// dependencyOrder defines the order in which entities will be synced by decK.
Expand Down Expand Up @@ -69,6 +70,7 @@ var dependencyOrder = [][]types.EntityType{
types.FilterChain,
types.Document,
types.DegraphqlRoute,
types.GraphqlRateLimitingCostDecoration,
},
}

Expand Down
33 changes: 23 additions & 10 deletions pkg/dump/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -644,19 +644,22 @@ func getProxyConfiguration(ctx context.Context, group *errgroup.Group,
}

if !skipCustomEntities && len(config.CustomEntityTypes) > 0 {
// Get custom entities with types given in config.CustomEntityTypes.
// Register all entity types first (sequentially) to avoid data race on the registry map.
// The registry is not thread-safe, so we must complete all registrations before
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were using a mutex for that. What was the issue here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So basically, mutex only protected the Register() (write) operation, but not the subsequent Lookup() (read) that happens inside GetAllCustomEntitiesWithType.

I have got race conditions on one test where we were adding multiple decorations simultaneously, there i have faced this issue and then added this fix.

// starting concurrent fetch operations that call Lookup().
for _, entityType := range config.CustomEntityTypes {
if err := tryRegisterEntityType(client, custom.Type(entityType)); err != nil {
group.Go(func() error {
return fmt.Errorf("custom entity %s: %w", entityType, err)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of this goroutine?

Copy link
Contributor Author

@shivaygupta-dotcom shivaygupta-dotcom Mar 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function getProxyConfiguration doesn't return an error directly - it uses errgroup.Group to collect errors from concurrent operations.

})
continue
}
}

customEntityLock := sync.Mutex{}
for _, entityType := range config.CustomEntityTypes {
t := entityType
group.Go(func() error {
// Register entity type.
// Because client writes an unprotected map to register entity types, we need to use mutex to protect it.
customEntityLock.Lock()
err := tryRegisterEntityType(client, custom.Type(t))
customEntityLock.Unlock()
if err != nil {
return fmt.Errorf("custom entity %s: %w", t, err)
}
// Fetch all entities with the given type.
entities, err := GetAllCustomEntitiesWithType(ctx, client, t)
if err != nil {
Expand All @@ -676,9 +679,19 @@ func tryRegisterEntityType(client *kong.Client, typ custom.Type) error {
if client.Lookup(typ) != nil {
return nil
}

// Determine the CRUD path based on entity type
crudPath := "/" + string(typ)

// Special case: Kong exposes this API at /graphql-rate-limiting-advanced/costs,
// not at /graphql_ratelimiting_cost_decorations (the entity type name).
if typ == "graphql_ratelimiting_cost_decorations" {
crudPath = "/graphql-rate-limiting-advanced/costs"
}

return client.Register(typ, &custom.EntityCRUDDefinition{
Name: typ,
CRUDPath: "/" + string(typ),
CRUDPath: crudPath,
PrimaryKey: "id",
})
}
Expand Down
119 changes: 118 additions & 1 deletion pkg/file/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -2135,7 +2135,8 @@ func (b *stateBuilder) customEntities() {
}

supportedCustomEntities := map[string]bool{
degraphqlRoutesType: true,
degraphqlRoutesType: true,
graphqlRateLimitingCostDecorationsType: true,
}

var customEntities []FCustomEntity
Expand All @@ -2156,6 +2157,8 @@ func (b *stateBuilder) ingestCustomEntities(customEntities []FCustomEntity) {
switch *e.Type {
case degraphqlRoutesType:
b.ingestDeGraphqlRoute(e)
case graphqlRateLimitingCostDecorationsType:
b.ingestGraphqlRateLimitingCostDecoration(e)
}
}
}
Expand Down Expand Up @@ -2258,6 +2261,120 @@ func (b *stateBuilder) copyToDegraphqlRoute(fcEntity FCustomEntity) (DegraphqlRo
return degraphqlRoute, nil
}

func (b *stateBuilder) ingestGraphqlRateLimitingCostDecoration(entity FCustomEntity) {
decoration, err := b.copyToGraphqlRateLimitingCostDecoration(entity)
if err != nil {
b.err = err
return
}

if utils.Empty(decoration.ID) {
// Try to find existing by TypePath
d, err := b.currentState.GraphqlRateLimitingCostDecorations.GetByTypePath(*decoration.TypePath)
if errors.Is(err, state.ErrNotFound) {
decoration.ID = uuid()
} else if err != nil {
b.err = err
return
} else {
decoration.ID = kong.String(*d.ID)
}
} else {
decoration.ID = kong.String(*decoration.ID)
}

b.rawState.GraphqlRateLimitingCostDecorations = append(
b.rawState.GraphqlRateLimitingCostDecorations,
&decoration.GraphqlRateLimitingCostDecoration,
)
}

func (b *stateBuilder) copyToGraphqlRateLimitingCostDecoration(
fcEntity FCustomEntity,
) (GraphqlRateLimitingCostDecoration, error) {
decoration := GraphqlRateLimitingCostDecoration{}

if fcEntity.ID != nil {
decoration.ID = fcEntity.ID
}

if fcEntity.Fields == nil {
return GraphqlRateLimitingCostDecoration{},
fmt.Errorf("fields are required for graphql_ratelimiting_cost_decorations")
}

if fcEntity.Fields["id"] != nil {
if id, ok := fcEntity.Fields["id"].(*string); ok {
decoration.ID = id
} else if id, ok := fcEntity.Fields["id"].(string); ok {
decoration.ID = kong.String(id)
}
}

if fcEntity.Fields["type_path"] != nil {
if tp, ok := fcEntity.Fields["type_path"].(*string); ok {
decoration.TypePath = tp
} else if tp, ok := fcEntity.Fields["type_path"].(string); ok {
decoration.TypePath = kong.String(tp)
}
}

if fcEntity.Fields["add_constant"] != nil {
if ac, ok := fcEntity.Fields["add_constant"].(*float64); ok {
decoration.AddConstant = ac
} else if ac, ok := fcEntity.Fields["add_constant"].(float64); ok {
decoration.AddConstant = kong.Float64(ac)
}
}

if fcEntity.Fields["mul_constant"] != nil {
if mc, ok := fcEntity.Fields["mul_constant"].(*float64); ok {
decoration.MulConstant = mc
} else if mc, ok := fcEntity.Fields["mul_constant"].(float64); ok {
decoration.MulConstant = kong.Float64(mc)
}
}

if fcEntity.Fields["add_arguments"] != nil {
if args, ok := fcEntity.Fields["add_arguments"].([]*string); ok {
decoration.AddArguments = args
} else if args, ok := fcEntity.Fields["add_arguments"].([]interface{}); ok {
addArgs := make([]*string, len(args))
for i, arg := range args {
if argStr, ok := arg.(string); ok {
addArgs[i] = kong.String(argStr)
} else if argPtr, ok := arg.(*string); ok {
addArgs[i] = argPtr
}
}
decoration.AddArguments = addArgs
}
}

if fcEntity.Fields["mul_arguments"] != nil {
if args, ok := fcEntity.Fields["mul_arguments"].([]*string); ok {
decoration.MulArguments = args
} else if args, ok := fcEntity.Fields["mul_arguments"].([]interface{}); ok {
mulArgs := make([]*string, len(args))
for i, arg := range args {
if argStr, ok := arg.(string); ok {
mulArgs[i] = kong.String(argStr)
} else if argPtr, ok := arg.(*string); ok {
mulArgs[i] = argPtr
}
}
decoration.MulArguments = mulArgs
}
}

if decoration.TypePath == nil {
return GraphqlRateLimitingCostDecoration{},
fmt.Errorf("type_path is required for graphql_ratelimiting_cost_decorations")
}

return decoration, nil
}

func defaulter(
ctx context.Context, client *kong.Client, fileContent *Content, disableDynamicDefaults, isKonnect bool,
) (*utils.Defaulter, error) {
Expand Down
Loading
Loading