diff --git a/go.mod b/go.mod index 1d3e672..7eb9f99 100644 --- a/go.mod +++ b/go.mod @@ -1,22 +1,23 @@ module github.com/ironcore-dev/cloud-provider-ironcore -go 1.25.0 +go 1.25.1 require ( - github.com/ironcore-dev/controller-utils v0.11.0 - github.com/ironcore-dev/ironcore v0.3.0 + github.com/ironcore-dev/controller-utils v0.12.0 + github.com/ironcore-dev/ironcore v0.4.1 github.com/onsi/ginkgo/v2 v2.29.0 github.com/onsi/gomega v1.41.0 github.com/pkg/errors v0.9.1 github.com/spf13/pflag v1.0.10 - k8s.io/api v0.34.1 - k8s.io/apimachinery v0.34.1 - k8s.io/client-go v0.34.1 - k8s.io/cloud-provider v0.32.3 - k8s.io/component-base v0.34.1 - k8s.io/controller-manager v0.32.3 + k8s.io/api v0.35.3 + k8s.io/apimachinery v0.35.3 + k8s.io/client-go v0.35.3 + k8s.io/cloud-provider v0.35.3 + k8s.io/component-base v0.35.3 + k8s.io/controller-manager v0.35.3 k8s.io/klog/v2 v2.130.1 - sigs.k8s.io/controller-runtime v0.22.3 + k8s.io/utils v0.0.0-20260108192941-914a6e750570 + sigs.k8s.io/controller-runtime v0.23.3 sigs.k8s.io/yaml v1.6.0 ) @@ -81,9 +82,9 @@ require ( github.com/spf13/cobra v1.10.2 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect github.com/x448/float16 v0.8.4 // indirect - go.etcd.io/etcd/api/v3 v3.6.4 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.6.4 // indirect - go.etcd.io/etcd/client/v3 v3.6.4 // indirect + go.etcd.io/etcd/api/v3 v3.6.5 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.6.5 // indirect + go.etcd.io/etcd/client/v3 v3.6.5 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect @@ -103,30 +104,29 @@ require ( golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect golang.org/x/mod v0.35.0 // indirect golang.org/x/net v0.53.0 // indirect - golang.org/x/oauth2 v0.34.0 // indirect - golang.org/x/sync v0.20.0 // indirect - golang.org/x/sys v0.43.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sync v0.21.0 // indirect + golang.org/x/sys v0.46.0 // indirect golang.org/x/term v0.42.0 // indirect golang.org/x/text v0.36.0 // indirect golang.org/x/time v0.14.0 // indirect golang.org/x/tools v0.44.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect - google.golang.org/grpc v1.79.3 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect + google.golang.org/grpc v1.81.1 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect - k8s.io/apiextensions-apiserver v0.34.1 // indirect - k8s.io/apiserver v0.34.1 // indirect - k8s.io/component-helpers v0.32.3 // indirect - k8s.io/kms v0.34.1 // indirect - k8s.io/kube-aggregator v0.34.1 // indirect - k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect - k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect + k8s.io/apiextensions-apiserver v0.35.3 // indirect + k8s.io/apiserver v0.35.3 // indirect + k8s.io/component-helpers v0.35.3 // indirect + k8s.io/kms v0.35.3 // indirect + k8s.io/kube-aggregator v0.35.3 // indirect + k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.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/v6 v6.3.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 // indirect ) diff --git a/go.sum b/go.sum index ed64b93..df64157 100644 --- a/go.sum +++ b/go.sum @@ -122,10 +122,10 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLW github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/ironcore-dev/controller-utils v0.11.0 h1:vQhZgPxxFwmSi+fSlPEuwCmI5sOP7QwjX97DL4jew/c= -github.com/ironcore-dev/controller-utils v0.11.0/go.mod h1:kPIgIjGNMA5zUlwH04rCdDbYnvvDtd79z3Rgav1Yrpg= -github.com/ironcore-dev/ironcore v0.3.0 h1:l/q9xprt5iNG0HaySFDCGLX19tco/MNUMGc0+11Od8o= -github.com/ironcore-dev/ironcore v0.3.0/go.mod h1:qM1oGh2FcNmdyWPhrSbz+PQMt72aqMO62UgAyfWCa+c= +github.com/ironcore-dev/controller-utils v0.12.0 h1:0OBUzV+Zkh6K+2h4LtqAjWru19/5d3ucuUK5qMzt1rs= +github.com/ironcore-dev/controller-utils v0.12.0/go.mod h1:LHSeOLcIbPIkSiryKpZ30E/zDSWHTnkZD4w69+kPdMw= +github.com/ironcore-dev/ironcore v0.4.1 h1:nuFDomg0Lt292ILd8xzCufz+PS6RQHex3aEE0BhJawI= +github.com/ironcore-dev/ironcore v0.4.1/go.mod h1:Gdznl3R0oD858qVMeVhTuQoADKMsVEuYKccFlJWQ0dI= github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE= @@ -214,18 +214,18 @@ github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chq github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.4.2 h1:IrUHp260R8c+zYx/Tm8QZr04CX+qWS5PGfPdevhdm1I= -go.etcd.io/bbolt v1.4.2/go.mod h1:Is8rSHO/b4f3XigBC0lL0+4FwAQv3HXEEIgFMuKHceM= -go.etcd.io/etcd/api/v3 v3.6.4 h1:7F6N7toCKcV72QmoUKa23yYLiiljMrT4xCeBL9BmXdo= -go.etcd.io/etcd/api/v3 v3.6.4/go.mod h1:eFhhvfR8Px1P6SEuLT600v+vrhdDTdcfMzmnxVXXSbk= -go.etcd.io/etcd/client/pkg/v3 v3.6.4 h1:9HBYrjppeOfFjBjaMTRxT3R7xT0GLK8EJMVC4xg6ok0= -go.etcd.io/etcd/client/pkg/v3 v3.6.4/go.mod h1:sbdzr2cl3HzVmxNw//PH7aLGVtY4QySjQFuaCgcRFAI= -go.etcd.io/etcd/client/v3 v3.6.4 h1:YOMrCfMhRzY8NgtzUsHl8hC2EBSnuqbR3dh84Uryl7A= -go.etcd.io/etcd/client/v3 v3.6.4/go.mod h1:jaNNHCyg2FdALyKWnd7hxZXZxZANb0+KGY+YQaEMISo= -go.etcd.io/etcd/pkg/v3 v3.6.4 h1:fy8bmXIec1Q35/jRZ0KOes8vuFxbvdN0aAFqmEfJZWA= -go.etcd.io/etcd/pkg/v3 v3.6.4/go.mod h1:kKcYWP8gHuBRcteyv6MXWSN0+bVMnfgqiHueIZnKMtE= -go.etcd.io/etcd/server/v3 v3.6.4 h1:LsCA7CzjVt+8WGrdsnh6RhC0XqCsLkBly3ve5rTxMAU= -go.etcd.io/etcd/server/v3 v3.6.4/go.mod h1:aYCL/h43yiONOv0QIR82kH/2xZ7m+IWYjzRmyQfnCAg= +go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo= +go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= +go.etcd.io/etcd/api/v3 v3.6.5 h1:pMMc42276sgR1j1raO/Qv3QI9Af/AuyQUW6CBAWuntA= +go.etcd.io/etcd/api/v3 v3.6.5/go.mod h1:ob0/oWA/UQQlT1BmaEkWQzI0sJ1M0Et0mMpaABxguOQ= +go.etcd.io/etcd/client/pkg/v3 v3.6.5 h1:Duz9fAzIZFhYWgRjp/FgNq2gO1jId9Yae/rLn3RrBP8= +go.etcd.io/etcd/client/pkg/v3 v3.6.5/go.mod h1:8Wx3eGRPiy0qOFMZT/hfvdos+DjEaPxdIDiCDUv/FQk= +go.etcd.io/etcd/client/v3 v3.6.5 h1:yRwZNFBx/35VKHTcLDeO7XVLbCBFbPi+XV4OC3QJf2U= +go.etcd.io/etcd/client/v3 v3.6.5/go.mod h1:ZqwG/7TAFZ0BJ0jXRPoJjKQJtbFo/9NIY8uoFFKcCyo= +go.etcd.io/etcd/pkg/v3 v3.6.5 h1:byxWB4AqIKI4SBmquZUG1WGtvMfMaorXFoCcFbVeoxM= +go.etcd.io/etcd/pkg/v3 v3.6.5/go.mod h1:uqrXrzmMIJDEy5j00bCqhVLzR5jEJIwDp5wTlLwPGOU= +go.etcd.io/etcd/server/v3 v3.6.5 h1:4RbUb1Bd4y1WkBHmuF+cZII83JNQMuNXzyjwigQ06y0= +go.etcd.io/etcd/server/v3 v3.6.5/go.mod h1:PLuhyVXz8WWRhzXDsl3A3zv/+aK9e4A9lpQkqawIaH0= go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ= go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= @@ -279,19 +279,19 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= -golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= -golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -312,14 +312,14 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0= gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= -google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= -google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 h1:tu/dtnW1o3wfaxCOjSLn5IRX4YDcJrtlpzYkhHhGaC4= +google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171/go.mod h1:M5krXqk4GhBKvB596udGL3UyjL4I1+cTbK0orROM9ng= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ= +google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -334,43 +334,43 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYs gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM= -k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk= -k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJbII2CI= -k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc= -k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= -k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= -k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA= -k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0= -k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= -k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= -k8s.io/cloud-provider v0.32.3 h1:WC7KhWrqXsU4b0E4tjS+nBectGiJbr1wuc1TpWXvtZM= -k8s.io/cloud-provider v0.32.3/go.mod h1:/fwBfgRPuh16n8vLHT+PPT+Bc4LAEaJYj38opO2wsYY= -k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A= -k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0= -k8s.io/component-helpers v0.32.3 h1:9veHpOGTPLluqU4hAu5IPOwkOIZiGAJUhHndfVc5FT4= -k8s.io/component-helpers v0.32.3/go.mod h1:utTBXk8lhkJewBKNuNf32Xl3KT/0VV19DmiXU/SV4Ao= -k8s.io/controller-manager v0.32.3 h1:jBxZnQ24k6IMeWLyxWZmpa3QVS7ww+osAIzaUY/jqyc= -k8s.io/controller-manager v0.32.3/go.mod h1:out1L3DZjE/p7JG0MoMMIaQGWIkt3c+pKaswqSHgKsI= +k8s.io/api v0.35.3 h1:pA2fiBc6+N9PDf7SAiluKGEBuScsTzd2uYBkA5RzNWQ= +k8s.io/api v0.35.3/go.mod h1:9Y9tkBcFwKNq2sxwZTQh1Njh9qHl81D0As56tu42GA4= +k8s.io/apiextensions-apiserver v0.35.3 h1:2fQUhEO7P17sijylbdwt0nBdXP0TvHrHj0KeqHD8FiU= +k8s.io/apiextensions-apiserver v0.35.3/go.mod h1:tK4Kz58ykRpwAEkXUb634HD1ZAegEElktz/B3jgETd8= +k8s.io/apimachinery v0.35.3 h1:MeaUwQCV3tjKP4bcwWGgZ/cp/vpsRnQzqO6J6tJyoF8= +k8s.io/apimachinery v0.35.3/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= +k8s.io/apiserver v0.35.3 h1:D2eIcfJ05hEAEewoSDg+05e0aSRwx8Y4Agvd/wiomUI= +k8s.io/apiserver v0.35.3/go.mod h1:JI0n9bHYzSgIxgIrfe21dbduJ9NHzKJ6RchcsmIKWKY= +k8s.io/client-go v0.35.3 h1:s1lZbpN4uI6IxeTM2cpdtrwHcSOBML1ODNTCCfsP1pg= +k8s.io/client-go v0.35.3/go.mod h1:RzoXkc0mzpWIDvBrRnD+VlfXP+lRzqQjCmKtiwZ8Q9c= +k8s.io/cloud-provider v0.35.3 h1:8gmlIXd9LHhDOXfv0fqsM9KIgVbgl3fwtNI2lDL0qWE= +k8s.io/cloud-provider v0.35.3/go.mod h1:bHkYmoCLBoyDkx8r8usg0sOo6PIzYrM5qYuDxCyuUxw= +k8s.io/component-base v0.35.3 h1:mbKbzoIMy7JDWS/wqZobYW1JDVRn/RKRaoMQHP9c4P0= +k8s.io/component-base v0.35.3/go.mod h1:IZ8LEG30kPN4Et5NeC7vjNv5aU73ku5MS15iZyvyMYk= +k8s.io/component-helpers v0.35.3 h1:Rl2p3wNMC0YU21rziLkWXavr7MwkB5Td3lNZ/+gYGm8= +k8s.io/component-helpers v0.35.3/go.mod h1:8BkyfcBA6XsCtFYxDB+mCfZqM6P39Aco12AKigNn0C8= +k8s.io/controller-manager v0.35.3 h1:BlX95jtN41/vCwuTsmfzR9UpqweX7KDWdwm/mRHez/o= +k8s.io/controller-manager v0.35.3/go.mod h1:OaG4bXsMfN5zpqowtdyfoRX20LrfwUh6V0zmpF7hw30= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kms v0.34.1 h1:iCFOvewDPzWM9fMTfyIPO+4MeuZ0tcZbugxLNSHFG4w= -k8s.io/kms v0.34.1/go.mod h1:s1CFkLG7w9eaTYvctOxosx88fl4spqmixnNpys0JAtM= -k8s.io/kube-aggregator v0.34.1 h1:WNLV0dVNoFKmuyvdWLd92iDSyD/TSTjqwaPj0U9XAEU= -k8s.io/kube-aggregator v0.34.1/go.mod h1:RU8j+5ERfp0h+gIvWtxRPfsa5nK7rboDm8RST8BJfYQ= -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/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kms v0.35.3 h1:jaxr/7dNqcztGldnfCEZg8DegEOnHV6cfoBC2ACMWEg= +k8s.io/kms v0.35.3/go.mod h1:VT+4ekZAdrZDMgShK37vvlyHUVhwI9t/9tvh0AyCWmQ= +k8s.io/kube-aggregator v0.35.3 h1:erIo8Dfapd0Fg44XAbgCNioJMtr3Z5mI/G1PSpj9B7Q= +k8s.io/kube-aggregator v0.35.3/go.mod h1:lOLyWTEuiKT2kS/Wkj0foq+P+Xt4gs/xkrhz2r33lAQ= +k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4 h1:HhDfevmPS+OalTjQRKbTHppRIz01AWi8s45TMXStgYY= +k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= +k8s.io/utils v0.0.0-20260108192941-914a6e750570 h1:JT4W8lsdrGENg9W+YwwdLJxklIuKWdRm+BC+xt33FOY= +k8s.io/utils v0.0.0-20260108192941-914a6e750570/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0 h1:qPrZsv1cwQiFeieFlRqT627fVZ+tyfou/+S5S0H5ua0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/controller-runtime v0.22.3 h1:I7mfqz/a/WdmDCEnXmSPm8/b/yRTy6JsKKENTijTq8Y= -sigs.k8s.io/controller-runtime v0.22.3/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8= +sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80= +sigs.k8s.io/controller-runtime v0.23.3/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= 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/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/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 h1:2WOzJpHUBVrrkDjU4KBT8n5LDcj824eX0I5UKcgeRUs= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/pkg/cloudprovider/ironcore/load_balancer.go b/pkg/cloudprovider/ironcore/load_balancer.go index ad3393c..7e9f17b 100644 --- a/pkg/cloudprovider/ironcore/load_balancer.go +++ b/pkg/cloudprovider/ironcore/load_balancer.go @@ -17,12 +17,14 @@ import ( servicehelper "k8s.io/cloud-provider/service/helpers" "k8s.io/klog/v2" + ipamv1alpha1ac "github.com/ironcore-dev/ironcore/client-go/applyconfigurations/ipam/v1alpha1" + networkingv1alpha1ac "github.com/ironcore-dev/ironcore/client-go/applyconfigurations/networking/v1alpha1" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - commonv1alpha1 "github.com/ironcore-dev/ironcore/api/common/v1alpha1" + metav1ac "k8s.io/client-go/applyconfigurations/meta/v1" + + "github.com/ironcore-dev/ironcore/api/common/v1alpha1" computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1" - ipamv1alpha1 "github.com/ironcore-dev/ironcore/api/ipam/v1alpha1" networkingv1alpha1 "github.com/ironcore-dev/ironcore/api/networking/v1alpha1" ) @@ -104,110 +106,54 @@ func (o *ironcoreLoadBalancer) GetLoadBalancerName(ctx context.Context, clusterN func (o *ironcoreLoadBalancer) EnsureLoadBalancer(ctx context.Context, clusterName string, service *v1.Service, nodes []*v1.Node) (*v1.LoadBalancerStatus, error) { klog.V(2).InfoS("EnsureLoadBalancer for Service", "Cluster", clusterName, "Service", client.ObjectKeyFromObject(service)) - // decide load balancer type based on service annotation for internal load balancer - var desiredLoadBalancerType networkingv1alpha1.LoadBalancerType - if value, ok := service.Annotations[InternalLoadBalancerAnnotation]; ok && value == "true" { - desiredLoadBalancerType = networkingv1alpha1.LoadBalancerTypeInternal - } else { - desiredLoadBalancerType = networkingv1alpha1.LoadBalancerTypePublic - } + desiredLoadBalancerType := o.getDesiredLoadBalancerType(service) loadBalancerName, err := o.getLoadBalancerName(ctx, clusterName, service) if err != nil { return nil, fmt.Errorf("failed to get LoadBalancer name for Service %s: %w", client.ObjectKeyFromObject(service), err) } - // get existing load balancer type - existingLoadBalancer := &networkingv1alpha1.LoadBalancer{} - var existingLoadBalancerType networkingv1alpha1.LoadBalancerType - if err := o.ironcoreClient.Get(ctx, client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancerName}, existingLoadBalancer); err == nil { - existingLoadBalancerType = existingLoadBalancer.Spec.Type - if existingLoadBalancerType != desiredLoadBalancerType { - if err = o.EnsureLoadBalancerDeleted(ctx, clusterName, service); err != nil { - return nil, fmt.Errorf("failed deleting existing loadbalancer %s: %w", loadBalancerName, err) - } - } + existingLoadBalancerType, err := o.ensureLoadBalancerType(ctx, clusterName, service, loadBalancerName, desiredLoadBalancerType) + if err != nil { + return nil, err } - klog.V(2).InfoS("Getting LoadBalancer ports from Service", "Service", client.ObjectKeyFromObject(service)) - var lbPorts []networkingv1alpha1.LoadBalancerPort - for _, svcPort := range service.Spec.Ports { - protocol := svcPort.Protocol - lbPorts = append(lbPorts, networkingv1alpha1.LoadBalancerPort{ - Protocol: &protocol, - Port: svcPort.Port, - }) + loadBalancerApplyConfig, err := o.buildLoadBalancerApplyConfig(clusterName, service, loadBalancerName, desiredLoadBalancerType) + if err != nil { + return nil, err } - loadBalancer := &networkingv1alpha1.LoadBalancer{ - TypeMeta: metav1.TypeMeta{ - Kind: "LoadBalancer", - APIVersion: networkingv1alpha1.SchemeGroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: loadBalancerName, - Namespace: o.ironcoreNamespace, - Annotations: map[string]string{ - AnnotationKeyClusterName: clusterName, - AnnotationKeyServiceName: service.Name, - AnnotationKeyServiceNamespace: service.Namespace, - AnnotationKeyServiceUID: string(service.UID), - }, - }, - Spec: networkingv1alpha1.LoadBalancerSpec{ - Type: desiredLoadBalancerType, - IPFamilies: service.Spec.IPFamilies, - NetworkRef: v1.LocalObjectReference{ - Name: o.cloudConfig.NetworkName, - }, - Ports: lbPorts, - }, - } + klog.V(2).InfoS("Applying LoadBalancer for Service", "LoadBalancer", client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancerName}, "Service", client.ObjectKeyFromObject(service)) - // if load balancer type is Internal then update IPSource with valid prefix template - if desiredLoadBalancerType == networkingv1alpha1.LoadBalancerTypeInternal { - if o.cloudConfig.PrefixName == "" { - return nil, fmt.Errorf("prefixName is not defined in config") - } - loadBalancer.Spec.IPs = []networkingv1alpha1.IPSource{ - { - Ephemeral: &networkingv1alpha1.EphemeralPrefixSource{ - PrefixTemplate: &ipamv1alpha1.PrefixTemplateSpec{ - Spec: ipamv1alpha1.PrefixSpec{ - // TODO: for now we only support IPv4 until Gardener has support for IPv6 based Shoots - IPFamily: v1.IPv4Protocol, - ParentRef: &v1.LocalObjectReference{ - Name: o.cloudConfig.PrefixName, - }, - }, - }, - }, - }, - } - } - // If useNicSelector is set to true then add NetworkInterfaceSelector to loadbalancer.SPec - if o.useNicSelector { - loadBalancer.Spec.NetworkInterfaceSelector = &metav1.LabelSelector{ - MatchLabels: map[string]string{ - LabelKeyClusterName: clusterName, - }, - } + if err := o.ironcoreClient.Apply(ctx, loadBalancerApplyConfig, client.FieldOwner(loadBalancerFieldOwner), client.ForceOwnership); err != nil { + return nil, fmt.Errorf("failed to apply LoadBalancer %s for Service %s: %w", client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancerName}, client.ObjectKeyFromObject(service), err) } - klog.V(2).InfoS("Applying LoadBalancer for Service", "LoadBalancer", client.ObjectKeyFromObject(loadBalancer), "Service", client.ObjectKeyFromObject(service)) - if err := o.ironcoreClient.Patch(ctx, loadBalancer, client.Apply, loadBalancerFieldOwner, client.ForceOwnership); err != nil { - return nil, fmt.Errorf("failed to apply LoadBalancer %s for Service %s: %w", client.ObjectKeyFromObject(loadBalancer), client.ObjectKeyFromObject(service), err) - } - klog.V(2).InfoS("Applied LoadBalancer for Service", "LoadBalancer", client.ObjectKeyFromObject(loadBalancer), "Service", client.ObjectKeyFromObject(service)) + klog.V(2).InfoS("Applied LoadBalancer for Service", "LoadBalancer", client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancerName}, "Service", client.ObjectKeyFromObject(service)) // if useNicSelector is set to false then cloudProvider has to create the loadbalancerRouting // if useNicSelector is set to true then Ironcore will take care of creating the loadbalancerRouting if !o.useNicSelector { - klog.V(2).InfoS("Applying LoadBalancerRouting for LoadBalancer", "LoadBalancer", client.ObjectKeyFromObject(loadBalancer)) - if err := o.applyLoadBalancerRoutingForLoadBalancer(ctx, loadBalancer, nodes); err != nil { + loadBalancerToRoute := &networkingv1alpha1.LoadBalancer{} + loadBalancerKey := client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancerName} + if err := o.ironcoreClient.Get(ctx, loadBalancerKey, loadBalancerToRoute); err != nil { + return nil, fmt.Errorf("failed to get LoadBalancer %s for routing: %w", loadBalancerKey, err) + } + + klog.V(2).InfoS("Applying LoadBalancerRouting for LoadBalancer", "LoadBalancer", client.ObjectKeyFromObject(loadBalancerToRoute)) + + if err := o.applyLoadBalancerRoutingForLoadBalancer(ctx, loadBalancerToRoute, nodes); err != nil { return nil, err } - klog.V(2).InfoS("Applied LoadBalancerRouting for LoadBalancer", "LoadBalancer", client.ObjectKeyFromObject(loadBalancer)) + + klog.V(2).InfoS("Applied LoadBalancerRouting for LoadBalancer", "LoadBalancer", client.ObjectKeyFromObject(loadBalancerToRoute)) + } + + loadBalancer := &networkingv1alpha1.LoadBalancer{ + ObjectMeta: metav1.ObjectMeta{ + Name: loadBalancerName, + Namespace: o.ironcoreNamespace, + }, } lbStatus, err := waitLoadBalancerActive(ctx, o.ironcoreClient, existingLoadBalancerType, service, loadBalancer) @@ -217,6 +163,104 @@ func (o *ironcoreLoadBalancer) EnsureLoadBalancer(ctx context.Context, clusterNa return &lbStatus, nil } +func (o *ironcoreLoadBalancer) getDesiredLoadBalancerType(service *v1.Service) networkingv1alpha1.LoadBalancerType { + if value, ok := service.Annotations[InternalLoadBalancerAnnotation]; ok && value == "true" { + return networkingv1alpha1.LoadBalancerTypeInternal + } + + return networkingv1alpha1.LoadBalancerTypePublic +} + +func (o *ironcoreLoadBalancer) ensureLoadBalancerType(ctx context.Context, clusterName string, service *v1.Service, loadBalancerName string, + desiredType networkingv1alpha1.LoadBalancerType, +) (networkingv1alpha1.LoadBalancerType, error) { + existingLoadBalancer := &networkingv1alpha1.LoadBalancer{} + + if err := o.ironcoreClient.Get(ctx, client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancerName}, existingLoadBalancer); err != nil { + if apierrors.IsNotFound(err) { + return "", nil + } + + return "", err + } + + existingType := existingLoadBalancer.Spec.Type + + if existingType != desiredType { + if err := o.EnsureLoadBalancerDeleted(ctx, clusterName, service); err != nil { + return "", fmt.Errorf("failed deleting existing loadbalancer %s: %w", loadBalancerName, err) + } + } + + return existingType, nil +} + +func (o *ironcoreLoadBalancer) buildLoadBalancerApplyConfig(clusterName string, service *v1.Service, loadBalancerName string, + loadBalancerType networkingv1alpha1.LoadBalancerType, +) (*networkingv1alpha1ac.LoadBalancerApplyConfiguration, error) { + lbPorts := make([]*networkingv1alpha1ac.LoadBalancerPortApplyConfiguration, 0, len(service.Spec.Ports)) + + for _, svcPort := range service.Spec.Ports { + protocol := svcPort.Protocol + + lbPorts = append(lbPorts, networkingv1alpha1ac.LoadBalancerPort(). + WithProtocol(protocol). + WithPort(svcPort.Port), + ) + } + + spec := networkingv1alpha1ac.LoadBalancerSpec(). + WithType(loadBalancerType). + WithIPFamilies(service.Spec.IPFamilies...). + WithNetworkRef(v1.LocalObjectReference{Name: o.cloudConfig.NetworkName}). + WithPorts(lbPorts...) + + if loadBalancerType == networkingv1alpha1.LoadBalancerTypeInternal { + if o.cloudConfig.PrefixName == "" { + return nil, fmt.Errorf("prefixName is not defined in config") + } + + spec.WithIPs( + networkingv1alpha1ac.IPSource(). + WithEphemeral( + networkingv1alpha1ac.EphemeralPrefixSource(). + WithPrefixTemplate( + ipamv1alpha1ac.PrefixTemplateSpec(). + WithSpec( + ipamv1alpha1ac.PrefixSpec(). + // TODO: for now we only support IPv4 until Gardener has support for IPv6 based Shoots + WithIPFamily(v1.IPv4Protocol). + WithParentRef( + v1.LocalObjectReference{ + Name: o.cloudConfig.PrefixName, + }), + ), + ), + ), + ) + } + + if o.useNicSelector { + spec.WithNetworkInterfaceSelector( + metav1ac.LabelSelector(). + WithMatchLabels(map[string]string{ + LabelKeyClusterName: clusterName, + }), + ) + } + + return networkingv1alpha1ac.LoadBalancer( + loadBalancerName, + o.ironcoreNamespace, + ). + WithAnnotations(map[string]string{ + AnnotationKeyClusterName: clusterName, + AnnotationKeyServiceName: service.Name, + AnnotationKeyServiceNamespace: service.Namespace, + AnnotationKeyServiceUID: string(service.UID), + }). + WithSpec(spec), nil +} func waitLoadBalancerActive(ctx context.Context, ironcoreClient client.Client, existingLoadBalancerType networkingv1alpha1.LoadBalancerType, service *v1.Service, loadBalancer *networkingv1alpha1.LoadBalancer) (v1.LoadBalancerStatus, error) { klog.V(2).InfoS("Waiting for LoadBalancer instance to become ready", "LoadBalancer", client.ObjectKeyFromObject(loadBalancer)) @@ -253,43 +297,74 @@ func waitLoadBalancerActive(ctx context.Context, ironcoreClient client.Client, e } func (o *ironcoreLoadBalancer) applyLoadBalancerRoutingForLoadBalancer(ctx context.Context, loadBalancer *networkingv1alpha1.LoadBalancer, nodes []*v1.Node) error { - loadBalacerDestinations, err := o.getLoadBalancerDestinationsForNodes(ctx, nodes, loadBalancer.Spec.NetworkRef.Name) + loadBalancerDestinations, err := o.getLoadBalancerDestinationsForNodes(ctx, nodes, loadBalancer.Spec.NetworkRef.Name) if err != nil { return fmt.Errorf("failed to get NetworkInterfaces for Nodes: %w", err) } network := &networkingv1alpha1.Network{} - networkKey := client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancer.Spec.NetworkRef.Name} + networkKey := client.ObjectKey{ + Namespace: o.ironcoreNamespace, + Name: loadBalancer.Spec.NetworkRef.Name, + } + if err := o.ironcoreClient.Get(ctx, networkKey, network); err != nil { return fmt.Errorf("failed to get Network %s: %w", o.cloudConfig.NetworkName, err) } - loadBalancerRouting := &networkingv1alpha1.LoadBalancerRouting{ - TypeMeta: metav1.TypeMeta{ - Kind: "LoadBalancerRouting", - APIVersion: networkingv1alpha1.SchemeGroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: loadBalancer.Name, - Namespace: o.ironcoreNamespace, - }, - NetworkRef: commonv1alpha1.LocalUIDReference{ - Name: network.Name, - UID: network.UID, - }, - Destinations: loadBalacerDestinations, - } + loadBalancerRoutingApplyConfig := o.buildLoadBalancerRoutingApplyConfig(loadBalancer, network, loadBalancerDestinations) - if err := controllerutil.SetOwnerReference(loadBalancer, loadBalancerRouting, o.ironcoreClient.Scheme()); err != nil { - return fmt.Errorf("failed to set owner reference for load balancer routing %s: %w", client.ObjectKeyFromObject(loadBalancerRouting), err) + if err := o.ironcoreClient.Apply(ctx, loadBalancerRoutingApplyConfig, client.FieldOwner(loadBalancerFieldOwner), client.ForceOwnership); err != nil { + return fmt.Errorf("failed to apply LoadBalancerRouting %s for LoadBalancer %s: %w", client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancer.Name}, client.ObjectKeyFromObject(loadBalancer), err) } - if err := o.ironcoreClient.Patch(ctx, loadBalancerRouting, client.Apply, loadBalancerFieldOwner, client.ForceOwnership); err != nil { - return fmt.Errorf("failed to apply LoadBalancerRouting %s for LoadBalancer %s: %w", client.ObjectKeyFromObject(loadBalancerRouting), client.ObjectKeyFromObject(loadBalancer), err) - } return nil } +func (o *ironcoreLoadBalancer) buildLoadBalancerRoutingApplyConfig( + loadBalancer *networkingv1alpha1.LoadBalancer, + network *networkingv1alpha1.Network, + destinations []networkingv1alpha1.LoadBalancerDestination, +) *networkingv1alpha1ac.LoadBalancerRoutingApplyConfiguration { + destinationApplyConfigs := make([]*networkingv1alpha1ac.LoadBalancerDestinationApplyConfiguration, 0, len(destinations)) + + for _, destination := range destinations { + targetRef := networkingv1alpha1ac.LoadBalancerTargetRef(). + WithName(destination.TargetRef.Name). + WithUID(destination.TargetRef.UID) + if destination.TargetRef.ProviderID != "" { + targetRef = targetRef.WithProviderID(destination.TargetRef.ProviderID) + } + + destinationApplyConfigs = append( + destinationApplyConfigs, + networkingv1alpha1ac.LoadBalancerDestination(). + WithIP(destination.IP). + WithTargetRef(targetRef), + ) + } + + return networkingv1alpha1ac.LoadBalancerRouting( + loadBalancer.Name, + o.ironcoreNamespace, + ). + WithOwnerReferences( + metav1ac.OwnerReference(). + WithAPIVersion(networkingv1alpha1.SchemeGroupVersion.String()). + WithKind("LoadBalancer"). + WithName(loadBalancer.Name). + WithUID(loadBalancer.UID). + WithController(true). + WithBlockOwnerDeletion(true), + ). + WithNetworkRef( + v1alpha1.LocalUIDReference{ + Name: network.Name, + UID: network.UID, + }). + WithDestinations(destinationApplyConfigs...) +} + func (o *ironcoreLoadBalancer) getLoadBalancerDestinationsForNodes(ctx context.Context, nodes []*v1.Node, networkName string) ([]networkingv1alpha1.LoadBalancerDestination, error) { var loadbalancerDestinations []networkingv1alpha1.LoadBalancerDestination for _, node := range nodes { diff --git a/pkg/cloudprovider/ironcore/load_balancer_test.go b/pkg/cloudprovider/ironcore/load_balancer_test.go index d6ceee2..b1252d7 100644 --- a/pkg/cloudprovider/ironcore/load_balancer_test.go +++ b/pkg/cloudprovider/ironcore/load_balancer_test.go @@ -13,6 +13,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" cloudprovider "k8s.io/cloud-provider" + "k8s.io/utils/ptr" . "sigs.k8s.io/controller-runtime/pkg/envtest/komega" commonv1alpha1 "github.com/ironcore-dev/ironcore/api/common/v1alpha1" @@ -161,10 +162,12 @@ var _ = Describe("LoadBalancer", func() { } Eventually(Object(lbRouting)).Should(SatisfyAll( HaveField("ObjectMeta.OwnerReferences", ContainElement(metav1.OwnerReference{ - APIVersion: "networking.ironcore.dev/v1alpha1", - Kind: "LoadBalancer", - Name: loadBalancer.Name, - UID: loadBalancer.UID, + APIVersion: "networking.ironcore.dev/v1alpha1", + Kind: "LoadBalancer", + Name: loadBalancer.Name, + UID: loadBalancer.UID, + Controller: ptr.To(true), + BlockOwnerDeletion: ptr.To(true), })), HaveField("Destinations", ContainElements([]networkingv1alpha1.LoadBalancerDestination{ { @@ -334,10 +337,12 @@ var _ = Describe("LoadBalancer", func() { } Eventually(Object(lbRouting)).Should(SatisfyAll( HaveField("ObjectMeta.OwnerReferences", ContainElement(metav1.OwnerReference{ - APIVersion: "networking.ironcore.dev/v1alpha1", - Kind: "LoadBalancer", - Name: loadBalancer.Name, - UID: loadBalancer.UID, + APIVersion: "networking.ironcore.dev/v1alpha1", + Kind: "LoadBalancer", + Name: loadBalancer.Name, + UID: loadBalancer.UID, + Controller: ptr.To(true), + BlockOwnerDeletion: ptr.To(true), })), HaveField("Destinations", ContainElements([]networkingv1alpha1.LoadBalancerDestination{ { @@ -599,10 +604,12 @@ var _ = Describe("LoadBalancer", func() { } Eventually(Object(lbRouting)).Should(SatisfyAll( HaveField("ObjectMeta.OwnerReferences", ContainElement(metav1.OwnerReference{ - APIVersion: "networking.ironcore.dev/v1alpha1", - Kind: "LoadBalancer", - Name: loadBalancer.Name, - UID: loadBalancer.UID, + APIVersion: "networking.ironcore.dev/v1alpha1", + Kind: "LoadBalancer", + Name: loadBalancer.Name, + UID: loadBalancer.UID, + Controller: ptr.To(true), + BlockOwnerDeletion: ptr.To(true), })), // networkInterfaceFoo will not be listed in destinations, because network "foo" used by // networkInterfaceFoo does not exist @@ -866,10 +873,12 @@ var _ = Describe("LoadBalancer", func() { } Eventually(Object(lbRouting)).Should(SatisfyAll( HaveField("ObjectMeta.OwnerReferences", ContainElement(metav1.OwnerReference{ - APIVersion: "networking.ironcore.dev/v1alpha1", - Kind: "LoadBalancer", - Name: loadBalancer.Name, - UID: loadBalancer.UID, + APIVersion: "networking.ironcore.dev/v1alpha1", + Kind: "LoadBalancer", + Name: loadBalancer.Name, + UID: loadBalancer.UID, + Controller: ptr.To(true), + BlockOwnerDeletion: ptr.To(true), })), HaveField("Destinations", ContainElements([]networkingv1alpha1.LoadBalancerDestination{ { @@ -916,10 +925,12 @@ var _ = Describe("LoadBalancer", func() { Expect(lbProvider.UpdateLoadBalancer(ctx, clusterName, service, []*corev1.Node{node, node2})).NotTo(HaveOccurred()) Eventually(Object(lbRouting)).Should(SatisfyAll( HaveField("ObjectMeta.OwnerReferences", ContainElement(metav1.OwnerReference{ - APIVersion: "networking.ironcore.dev/v1alpha1", - Kind: "LoadBalancer", - Name: loadBalancer.Name, - UID: loadBalancer.UID, + APIVersion: "networking.ironcore.dev/v1alpha1", + Kind: "LoadBalancer", + Name: loadBalancer.Name, + UID: loadBalancer.UID, + Controller: ptr.To(true), + BlockOwnerDeletion: ptr.To(true), })), HaveField("Destinations", ContainElements([]networkingv1alpha1.LoadBalancerDestination{ { diff --git a/pkg/cloudprovider/ironcore/suite_test.go b/pkg/cloudprovider/ironcore/suite_test.go index d1ce46e..769c4b6 100644 --- a/pkg/cloudprovider/ironcore/suite_test.go +++ b/pkg/cloudprovider/ironcore/suite_test.go @@ -80,7 +80,7 @@ var _ = BeforeSuite(func() { // Note that you must have the required binaries setup under the bin directory to perform // the tests directly. When we run make test it will be setup and used automatically. BinaryAssetsDirectory: filepath.Join("..", "..", "..", "bin", "k8s", - fmt.Sprintf("1.34.0-%s-%s", runtime.GOOS, runtime.GOARCH)), + fmt.Sprintf("1.35.0-%s-%s", runtime.GOOS, runtime.GOARCH)), } testEnvExt = &envtestext.EnvironmentExtensions{ APIServiceDirectoryPaths: []string{