diff --git a/.golangci.yml b/.golangci.yml index 7201594..48453fb 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -28,7 +28,6 @@ output: path: stdout print-issued-lines: true print-linter-name: true - uniq-by-line: true sort-results: true # all available settings of specific linters @@ -154,6 +153,7 @@ linters: fast: false issues: + uniq-by-line: true # List of regexps of issue texts to exclude, empty list by default. # But independently from this option we use default exclude patterns, # it can be disabled by `exclude-use-default: false`. To list all diff --git a/docs/config.md b/docs/config.md index c26a814..e56c590 100644 --- a/docs/config.md +++ b/docs/config.md @@ -67,7 +67,7 @@ transformations: # Match nodes by nodeSelector nodeSelector: - matchExpressions: - - key: platform <- talos platfrom metadata variable case insensitive + - key: platform <- talos platform metadata variable case insensitive operator: In <- In, NotIn, Exists, DoesNotExist, Gt, Lt, Regexp values: <- array of string values - nocloud @@ -80,7 +80,7 @@ transformations: # Or condition for nodeSelector - matchExpressions: # And condition for matchExpressions - - key: platform <- talos platfrom metadata variable case insensitive + - key: platform <- talos platform metadata variable case insensitive operator: In <- In, NotIn, Exists, DoesNotExist, Gt, Lt, Regexp values: <- array of string values - metal @@ -94,7 +94,7 @@ transformations: values: - ^web-cloud-.+$ - # Add/replace annotations and labels for nodes that match the transformation + # Add/replace annotations, labels and taints for nodes that match the transformation annotations: # You can use the Go template to get the value of the platform metadata variable custom-annotation/instance-id: "id-{{ .InstanceID }}" @@ -105,7 +105,10 @@ transformations: # Add label to the node, in this case, we add well-known node role label node-role.kubernetes.io/web: "" # Set capacity-type spot/on-demand - node-role.kubernetes.io/capacity-type: "{{ if .Spot }}spot{{ else }}on-demand{{ end }}", + node-role.kubernetes.io/capacity-type: "{{ if .Spot }}spot{{ else }}on-demand{{ end }}" + taints: + # Add taint to the node + node.cloudprovider.kubernetes.io/storage-type: "ceph:NoSchedule" # Replace platform metadata variables for nodes that match the transformation platformMetadata: @@ -120,8 +123,8 @@ transformations: ### Transformations parameters -* `nodeSelector` - a list of node selector requirements by platfrom metadata variable. - * `matchExpressions` - a list of node selector requirements by platfrom metadata variable. +* `nodeSelector` - a list of node selector requirements by platform metadata variable. + * `matchExpressions` - a list of node selector requirements by platform metadata variable. * `key` - the key that the selector applies to, case `insensitive`. * `operator` - represents a key's relationship to a set of values. Supported operators are `In`, `NotIn`, `Exists`, `DoesNotExist`, `Gt`, `Lt`, `Regexp`. * `values` - an array of string values. @@ -134,6 +137,10 @@ transformations: * `key` - the key of the label. * `value` - the value of the label. You can use the [Go template](https://golang.org/pkg/text/template/) to get the value of the platform metadata variable. Variables are case `sensitive`. +* `taints` - a map of key-value pairs to add to each node that matches the transformation. + * `key` - the key of the taint. Can not be well-known taints name, like `node.kubernetes.io/unreachable`. + * `value` - the string in format ':', ''. Effect can be `NoExecute`, `NoSchedule`, `PreferNoSchedule`. + * `platformMetadata` - a map of key-value pairs to add to each node that matches the transformation. * `key` - the key of the platform metadata variable to replace. * `value` - the value of the platform metadata variable. You can use the [Go template](https://golang.org/pkg/text/template/) to get the value of the platform metadata variable. Variables are case `sensitive`. diff --git a/go.mod b/go.mod index 0a6ff0f..ce3de55 100644 --- a/go.mod +++ b/go.mod @@ -3,31 +3,31 @@ module github.com/siderolabs/talos-cloud-controller-manager go 1.23.4 require ( - github.com/cosi-project/runtime v0.9.0 + github.com/cosi-project/runtime v0.9.2 github.com/siderolabs/go-retry v0.3.3 github.com/siderolabs/net v0.4.0 - github.com/siderolabs/talos/pkg/machinery v1.9.1 - github.com/spf13/pflag v1.0.5 + github.com/siderolabs/talos/pkg/machinery v1.9.3 + github.com/spf13/pflag v1.0.6 github.com/stretchr/testify v1.10.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 - k8s.io/api v0.32.0 - k8s.io/apimachinery v0.32.0 - k8s.io/client-go v0.32.0 - k8s.io/cloud-provider v0.32.0 - k8s.io/component-base v0.32.0 - k8s.io/controller-manager v0.32.0 + k8s.io/api v0.32.1 + k8s.io/apimachinery v0.32.1 + k8s.io/client-go v0.32.1 + k8s.io/cloud-provider v0.32.1 + k8s.io/component-base v0.32.1 + k8s.io/controller-manager v0.32.1 k8s.io/klog/v2 v2.130.1 k8s.io/utils v0.0.0-20241210054802-24370beab758 ) require ( cel.dev/expr v0.18.0 // indirect - github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect - github.com/ProtonMail/go-crypto v1.1.3 // indirect + github.com/ProtonMail/go-crypto v1.1.5 // indirect github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f // indirect - github.com/ProtonMail/gopenpgp/v2 v2.8.1 // indirect + github.com/ProtonMail/gopenpgp/v2 v2.8.2 // indirect github.com/adrg/xdg v0.5.3 // indirect github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect @@ -61,7 +61,7 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -76,7 +76,7 @@ require ( github.com/mdlayher/genetlink v1.3.2 // indirect github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/socket v0.5.1 // indirect - github.com/moby/term v0.5.0 // indirect + github.com/moby/term v0.5.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect @@ -93,7 +93,7 @@ require ( github.com/siderolabs/crypto v0.5.1 // indirect github.com/siderolabs/gen v0.8.0 // indirect github.com/siderolabs/go-api-signature v0.3.6 // indirect - github.com/siderolabs/go-blockdevice/v2 v2.0.9 // indirect + github.com/siderolabs/go-blockdevice/v2 v2.0.13 // indirect github.com/siderolabs/go-pointer v1.0.0 // indirect github.com/siderolabs/protoenc v0.2.1 // indirect github.com/spf13/cobra v1.8.1 // indirect @@ -113,25 +113,25 @@ require ( go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.31.0 // indirect - golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect - golang.org/x/net v0.33.0 // indirect - golang.org/x/oauth2 v0.24.0 // indirect + golang.org/x/crypto v0.32.0 // indirect + golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/oauth2 v0.25.0 // indirect golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/term v0.27.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/term v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.8.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241216192217-9240e9c98484 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 // indirect - google.golang.org/grpc v1.69.0 // indirect - google.golang.org/protobuf v1.36.0 // indirect + golang.org/x/time v0.9.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/grpc v1.69.4 // indirect + google.golang.org/protobuf v1.36.3 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect - k8s.io/apiserver v0.32.0 // indirect - k8s.io/component-helpers v0.32.0 // indirect - k8s.io/kms v0.32.0 // indirect + k8s.io/apiserver v0.32.1 // indirect + k8s.io/component-helpers v0.32.1 // indirect + k8s.io/kms v0.32.1 // indirect k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.1 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect diff --git a/go.sum b/go.sum index 8176a00..0fcb79b 100644 --- a/go.sum +++ b/go.sum @@ -2,14 +2,16 @@ cel.dev/expr v0.18.0 h1:CJ6drgk+Hf96lkLikr4rFf19WrU0BOWEihyZnI2TAzo= cel.dev/expr v0.18.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk= -github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4= +github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k= github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw= -github.com/ProtonMail/gopenpgp/v2 v2.8.1 h1:WGE1THOhOnLurL0+N4BOlLkIhjEO7YVZgmpgyDHN56A= -github.com/ProtonMail/gopenpgp/v2 v2.8.1/go.mod h1:4PUgqGSQjd7HldUbAgMmC69+Gv6DO8NomCNi0y8+BTc= +github.com/ProtonMail/gopenpgp/v2 v2.8.2 h1:fe/XagfxkHRCr+cLFMcoF7XwaASRGSmK/fmcmK8yo6o= +github.com/ProtonMail/gopenpgp/v2 v2.8.2/go.mod h1:pPWZyRQWpQ7g8NWsdZmUynNZ1R09k4MdbSHvm+KooqM= github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= @@ -38,8 +40,8 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cosi-project/runtime v0.9.0 h1:xcyuK0zzNI6vUBNBJXtMg60vkvp9fRYV7LGJGSlKKFc= -github.com/cosi-project/runtime v0.9.0/go.mod h1:sNqLK/aBb8862xGS4HLAcwTloDuH0TeU3N1+qr3TmAs= +github.com/cosi-project/runtime v0.9.2 h1:l0kugKjZUFrmBFwkza2lt2vA1u8PBuWbrbB2HvPmkTs= +github.com/cosi-project/runtime v0.9.2/go.mod h1:dzAY2bdrPv0y39FyJOOURMkx3Ae7erMVoxX/N0OAZQU= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= @@ -109,8 +111,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92Bcuy github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -150,6 +152,8 @@ github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= +github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -191,8 +195,8 @@ github.com/siderolabs/gen v0.8.0 h1:Pj93+hexkk5hQ7izjJ6YXnEWc8vlzOmDwFz13/VzS7o= github.com/siderolabs/gen v0.8.0/go.mod h1:an3a2Y53O7kUjnnK8Bfu3gewtvnIOu5RTU6HalFtXQQ= github.com/siderolabs/go-api-signature v0.3.6 h1:wDIsXbpl7Oa/FXvxB6uz4VL9INA9fmr3EbmjEZYFJrU= github.com/siderolabs/go-api-signature v0.3.6/go.mod h1:hoH13AfunHflxbXfh+NoploqV13ZTDfQ1mQJWNVSW9U= -github.com/siderolabs/go-blockdevice/v2 v2.0.9 h1:OTo+ADN/3LT4XtI8p7Dz3hlh6DJABHwMAnOlK7MOtMk= -github.com/siderolabs/go-blockdevice/v2 v2.0.9/go.mod h1:74htzCV913UzaLZ4H+NBXkwWlYnBJIq5m/379ZEcu8w= +github.com/siderolabs/go-blockdevice/v2 v2.0.13 h1:N94eK+EFwnD+2kdNT38910Qlu+5+Z0WDODKbX7NXvPs= +github.com/siderolabs/go-blockdevice/v2 v2.0.13/go.mod h1:74htzCV913UzaLZ4H+NBXkwWlYnBJIq5m/379ZEcu8w= github.com/siderolabs/go-pointer v1.0.0 h1:6TshPKep2doDQJAAtHUuHWXbca8ZfyRySjSBT/4GsMU= github.com/siderolabs/go-pointer v1.0.0/go.mod h1:HTRFUNYa3R+k0FFKNv11zgkaCLzEkWVzoYZ433P3kHc= github.com/siderolabs/go-retry v0.3.3 h1:zKV+S1vumtO72E6sYsLlmIdV/G/GcYSBLiEx/c9oCEg= @@ -201,16 +205,17 @@ github.com/siderolabs/net v0.4.0 h1:1bOgVay/ijPkJz4qct98nHsiB/ysLQU0KLoBC4qLm7I= github.com/siderolabs/net v0.4.0/go.mod h1:/ibG+Hm9HU27agp5r9Q3eZicEfjquzNzQNux5uEk0kM= github.com/siderolabs/protoenc v0.2.1 h1:BqxEmeWQeMpNP3R6WrPqDatX8sM/r4t97OP8mFmg6GA= github.com/siderolabs/protoenc v0.2.1/go.mod h1:StTHxjet1g11GpNAWiATgc8K0HMKiFSEVVFOa/H0otc= -github.com/siderolabs/talos/pkg/machinery v1.9.1 h1:TWkvUSiLbJmtBXLKAfFgEBAQSJe3Q9iS+VoBz4lQEWE= -github.com/siderolabs/talos/pkg/machinery v1.9.1/go.mod h1:CnGp19ojbNQ6vU66mtfzNkde8It0CmBMQjytTUHXc3g= +github.com/siderolabs/talos/pkg/machinery v1.9.3 h1:P3fb4UsmF3UEV2CDf100L7fVW+CBL5Yk6sEDis7uZr4= +github.com/siderolabs/talos/pkg/machinery v1.9.3/go.mod h1:G4swVKn4vK3455ssgcPUrikPTypx6n+uaqv7GyBWXy4= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -281,10 +286,10 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo= -golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c h1:KL/ZBHXgKGVmuZBZ01Lt57yE5ws8ZPSkkihmEyq7FXc= +golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -296,10 +301,10 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= -golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= +golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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= @@ -317,13 +322,13 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -331,30 +336,30 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= -golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= -golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= +golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= +golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= -google.golang.org/genproto/googleapis/api v0.0.0-20241216192217-9240e9c98484 h1:ChAdCYNQFDk5fYvFZMywKLIijG7TC2m1C2CMEu11G3o= -google.golang.org/genproto/googleapis/api v0.0.0-20241216192217-9240e9c98484/go.mod h1:KRUmxRI4JmbpAm8gcZM4Jsffi859fo5LQjILwuqj9z8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 h1:Z7FRVJPSMaHQxD0uXU8WdgFh8PseLM8Q8NzhnpMrBhQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= -google.golang.org/grpc v1.69.0 h1:quSiOM1GJPmPH5XtU+BCoVXcDVJJAzNcoyfC2cCjGkI= -google.golang.org/grpc v1.69.0/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ= -google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= +google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= +google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -371,26 +376,26 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE= -k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0= -k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg= -k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/apiserver v0.32.0 h1:VJ89ZvQZ8p1sLeiWdRJpRD6oLozNZD2+qVSLi+ft5Qs= -k8s.io/apiserver v0.32.0/go.mod h1:HFh+dM1/BE/Hm4bS4nTXHVfN6Z6tFIZPi649n83b4Ag= -k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8= -k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8= -k8s.io/cloud-provider v0.32.0 h1:QXYJGmwME2q2rprymbmw2GroMChQYc/MWN6l/I4Kgp8= -k8s.io/cloud-provider v0.32.0/go.mod h1:cz3gVodkhgwi2ugj/JUPglIruLSdDaThxawuDyCHfr8= -k8s.io/component-base v0.32.0 h1:d6cWHZkCiiep41ObYQS6IcgzOUQUNpywm39KVYaUqzU= -k8s.io/component-base v0.32.0/go.mod h1:JLG2W5TUxUu5uDyKiH2R/7NnxJo1HlPoRIIbVLkK5eM= -k8s.io/component-helpers v0.32.0 h1:pQEEBmRt3pDJJX98cQvZshDgJFeKRM4YtYkMmfOlczw= -k8s.io/component-helpers v0.32.0/go.mod h1:9RuClQatbClcokXOcDWSzFKQm1huIf0FzQlPRpizlMc= -k8s.io/controller-manager v0.32.0 h1:tpQl1rvH4huFB6Avl1nhowZHtZoCNWqn6OYdZPl7Ybc= -k8s.io/controller-manager v0.32.0/go.mod h1:JRuYnYCkKj3NgBTy+KNQKIUm/lJRoDAvGbfdEmk9LhY= +k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc= +k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k= +k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs= +k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/apiserver v0.32.1 h1:oo0OozRos66WFq87Zc5tclUX2r0mymoVHRq8JmR7Aak= +k8s.io/apiserver v0.32.1/go.mod h1:UcB9tWjBY7aryeI5zAgzVJB/6k7E97bkr1RgqDz0jPw= +k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU= +k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg= +k8s.io/cloud-provider v0.32.1 h1:74rRhnfca3o4CsjjnIp/C3ARVuSmyNsxgWPtH0yc9Z0= +k8s.io/cloud-provider v0.32.1/go.mod h1:GECSanFT+EeZ/ToX3xlasjETzMUI+VFu92zHUDUsGHw= +k8s.io/component-base v0.32.1 h1:/5IfJ0dHIKBWysGV0yKTFfacZ5yNV1sulPh3ilJjRZk= +k8s.io/component-base v0.32.1/go.mod h1:j1iMMHi/sqAHeG5z+O9BFNCF698a1u0186zkjMZQ28w= +k8s.io/component-helpers v0.32.1 h1:TwdsSM1vW9GjnfX18lkrZbwE5G9psCIS2/rhenTDXd8= +k8s.io/component-helpers v0.32.1/go.mod h1:1JT1Ei3FD29yFQ18F3laj1WyvxYdHIhyxx6adKMFQXI= +k8s.io/controller-manager v0.32.1 h1:z3oQp1O5l0cSzM/MKf8V4olhJ9TmnELoJRPcV/v1s+Y= +k8s.io/controller-manager v0.32.1/go.mod h1:dVA1UZPbqHH4hEhrrnLvQ4d5qVQCklNB8GEzYV59v/4= 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.32.0 h1:jwOfunHIrcdYl5FRcA+uUKKtg6qiqoPCwmS2T3XTYL4= -k8s.io/kms v0.32.0/go.mod h1:Bk2evz/Yvk0oVrvm4MvZbgq8BD34Ksxs2SRHn4/UiOM= +k8s.io/kms v0.32.1 h1:TW6cswRI/fawoQRFGWLmEceO37rZXupdoRdmO019jCc= +k8s.io/kms v0.32.1/go.mod h1:Bk2evz/Yvk0oVrvm4MvZbgq8BD34Ksxs2SRHn4/UiOM= k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg= k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas= k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= diff --git a/hack/ccm-config.yaml b/hack/ccm-config.yaml index f7a6339..1cac970 100644 --- a/hack/ccm-config.yaml +++ b/hack/ccm-config.yaml @@ -3,7 +3,8 @@ global: # - 1.2.3.4 # - 4.3.2.1 transformations: - - nodeSelector: + - name: web + nodeSelector: - matchExpressions: - key: hostname operator: Regexp @@ -13,3 +14,5 @@ transformations: talos.dev/instance-id: "id-{{ .InstanceID }}" labels: node-role.kubernetes.io/web: "" + taints: + node.cloudprovider.kubernetes.io/storage-type: "NoSchedule" diff --git a/pkg/talos/helper.go b/pkg/talos/helper.go index f361a56..2598288 100644 --- a/pkg/talos/helper.go +++ b/pkg/talos/helper.go @@ -144,6 +144,42 @@ func syncNodeAnnotations(ctx context.Context, c *client, node *v1.Node, nodeAnno return nil } +func syncNodeTaints(_ context.Context, c *client, node *v1.Node, nodeTaints map[string]string) error { + taints := []*v1.Taint{} + + for k, v := range nodeTaints { + taint := v1.Taint{ + Key: k, + } + + value := strings.Split(v, ":") + if len(value) == 2 { + taint.Value = value[0] + taint.Effect = v1.TaintEffect(value[1]) + } else { + taint.Effect = v1.TaintEffect(value[0]) + } + + taints = append(taints, &taint) + } + + if err := cloudnodeutil.AddOrUpdateTaintOnNode(c.kclient, node.Name, taints...); err != nil { + return err + } + + return nil +} + +func taintExists(taints []v1.Taint, taintToFind *v1.Taint) bool { + for _, taint := range taints { + if taint.MatchTaint(taintToFind) { + return true + } + } + + return false +} + func setTalosNodeLabels(c *client, meta *runtime.PlatformMetadataSpec) map[string]string { if meta == nil { return make(map[string]string) diff --git a/pkg/talos/instances.go b/pkg/talos/instances.go index 72e2cd9..d8b368d 100644 --- a/pkg/talos/instances.go +++ b/pkg/talos/instances.go @@ -164,7 +164,7 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud addresses = append(addresses, v1.NodeAddress{Type: v1.NodeInternalDNS, Address: meta.Hostname}) } - if nodeSpec.Annotations != nil { + if len(nodeSpec.Annotations) > 0 { klog.V(4).InfoS("instances.InstanceMetadata() node has annotations", "node", klog.KRef("", node.Name), "annotations", nodeSpec.Annotations) if err := syncNodeAnnotations(ctx, i.c, node, nodeSpec.Annotations); err != nil { @@ -172,9 +172,19 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud } } + if len(nodeSpec.Taints) > 0 { + klog.V(4).InfoS("instances.InstanceMetadata() node has taints", "node", klog.KRef("", node.Name), "taints", nodeSpec.Taints) + + if taintExists(node.Spec.Taints, uninitializedTaint) { + if err := syncNodeTaints(ctx, i.c, node, nodeSpec.Taints); err != nil { + klog.ErrorS(err, "error updating taints for the node", "node", klog.KRef("", node.Name)) + } + } + } + nodeLabels := setTalosNodeLabels(i.c, meta) - if nodeSpec.Labels != nil { + if len(nodeSpec.Labels) > 0 { klog.V(4).InfoS("instances.InstanceMetadata() node has labels", "node", klog.KRef("", node.Name), "labels", nodeSpec.Labels) maps.Copy(nodeLabels, nodeSpec.Labels) diff --git a/pkg/transformer/transformer.go b/pkg/transformer/transformer.go index 7f6071e..a615560 100644 --- a/pkg/transformer/transformer.go +++ b/pkg/transformer/transformer.go @@ -12,7 +12,9 @@ import ( "github.com/siderolabs/talos-cloud-controller-manager/pkg/nodeselector" "github.com/siderolabs/talos/pkg/machinery/resources/runtime" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/validation" + cloudproviderapi "k8s.io/cloud-provider/api" ) // NodeTerm represents expressions and fields to transform node metadata. @@ -21,14 +23,16 @@ type NodeTerm struct { NodeSelector []nodeselector.NodeSelectorTerm `yaml:"nodeSelector,omitempty"` Annotations map[string]string `yaml:"annotations,omitempty"` Labels map[string]string `yaml:"labels,omitempty"` + Taints map[string]string `yaml:"taints,omitempty"` PlatformMetadata map[string]string `yaml:"platformMetadata,omitempty"` Features NodeFeaturesFlagSpec `yaml:"features,omitempty"` } -// NodeSpec represents the transformed node specifcations. +// NodeSpec represents the transformed node specifications. type NodeSpec struct { Annotations map[string]string Labels map[string]string + Taints map[string]string Features NodeFeaturesFlagSpec } @@ -47,6 +51,7 @@ func TransformNode(terms []NodeTerm, platformMetadata *runtime.PlatformMetadataS node := &NodeSpec{ Annotations: make(map[string]string), Labels: make(map[string]string), + Taints: make(map[string]string), } if len(terms) == 0 { @@ -66,7 +71,7 @@ func TransformNode(terms []NodeTerm, platformMetadata *runtime.PlatformMetadataS for k, v := range term.Annotations { t, err := executeTemplate(v, platformMetadata) if err != nil { - return nil, fmt.Errorf("failed to transformer annotation '%q': %w", k, err) + return nil, fmt.Errorf("failed to transformer annotation %q: %w", k, err) } if errs := validation.IsQualifiedName(k); len(errs) != 0 { @@ -81,7 +86,7 @@ func TransformNode(terms []NodeTerm, platformMetadata *runtime.PlatformMetadataS for k, v := range term.Labels { t, err := executeTemplate(v, platformMetadata) if err != nil { - return nil, fmt.Errorf("failed to transformer label '%s': %w", k, err) + return nil, fmt.Errorf("failed to transformer label %q: %w", k, err) } if errs := validation.IsQualifiedName(k); len(errs) != 0 { @@ -96,6 +101,25 @@ func TransformNode(terms []NodeTerm, platformMetadata *runtime.PlatformMetadataS } } + if term.Taints != nil { + for k, v := range term.Taints { + t, err := executeTemplate(v, platformMetadata) + if err != nil { + return nil, fmt.Errorf("failed to transformer label %q: %w", k, err) + } + + if errs := isQualifiedTaintName(k); len(errs) != 0 { + return nil, fmt.Errorf("invalid taint name %q: %v", k, errs) + } + + if errs := isValidTaintValue(t); len(errs) != 0 { + return nil, fmt.Errorf("invalid taint value %q: %v", v, errs) + } + + node.Taints[k] = v + } + } + if term.PlatformMetadata != nil { p := reflect.ValueOf(platformMetadata) ps := p.Elem() @@ -107,7 +131,7 @@ func TransformNode(terms []NodeTerm, platformMetadata *runtime.PlatformMetadataS t, err := executeTemplate(v, platformMetadata) if err != nil { - return nil, fmt.Errorf("failed to transformer platform metadata '%s': %w", k, err) + return nil, fmt.Errorf("failed to transformer platform metadata %q: %w", k, err) } f := ps.FieldByNameFunc(func(fieldName string) bool { @@ -189,3 +213,47 @@ func metadataFromStruct(in *runtime.PlatformMetadataSpec) map[string]string { return metadata } + +func isQualifiedTaintName(name string) []string { + var errs []string + + if strings.Contains(name, "kubernetes.io/") { + switch name { + case v1.TaintNodeNotReady, + v1.TaintNodeUnreachable, + v1.TaintNodeMemoryPressure, + v1.TaintNodeDiskPressure, + v1.TaintNodeNetworkUnavailable, + v1.TaintNodePIDPressure: + errs = append(errs, "taint in kubernetes namespace") + case cloudproviderapi.TaintExternalCloudProvider, + cloudproviderapi.TaintNodeShutdown: + errs = append(errs, "taint in cloud provider namespace") + } + } + + return errs +} + +func isValidTaintValue(value string) (errs []string) { + effects := strings.Split(value, ":") + effect := effects[0] + + if len(effects) > 2 { + errs = append(errs, "taint value is not valid") + + return errs + } + + if len(effects) == 2 { + effect = effects[1] + } + + switch effect { + case "NoSchedule", "PreferNoSchedule", "NoExecute": + default: + errs = append(errs, fmt.Sprintf("taint effect %q is not valid", effect)) + } + + return errs +} diff --git a/pkg/transformer/transformer_test.go b/pkg/transformer/transformer_test.go index e77ece1..ba730a9 100644 --- a/pkg/transformer/transformer_test.go +++ b/pkg/transformer/transformer_test.go @@ -29,6 +29,7 @@ func TestMatch(t *testing.T) { expected: &transformer.NodeSpec{ Annotations: map[string]string{}, Labels: map[string]string{}, + Taints: map[string]string{}, }, }, { @@ -50,6 +51,7 @@ func TestMatch(t *testing.T) { Labels: map[string]string{ "my-label-name": "my-value", }, + Taints: map[string]string{}, }, }, { @@ -76,6 +78,29 @@ func TestMatch(t *testing.T) { Labels: map[string]string{ "my-label-name": "my-value", }, + Taints: map[string]string{}, + }, + }, + { + name: "Transform taints", + terms: []transformer.NodeTerm{ + { + Name: "my-transformer", + Taints: map[string]string{ + "my-taint-name": "NoSchedule", + }, + }, + }, + metadata: runtime.PlatformMetadataSpec{ + Platform: "test-platform", + Hostname: "test-hostname", + }, + expected: &transformer.NodeSpec{ + Annotations: map[string]string{}, + Labels: map[string]string{}, + Taints: map[string]string{ + "my-taint-name": "NoSchedule", + }, }, }, { @@ -92,7 +117,7 @@ func TestMatch(t *testing.T) { Platform: "test-platform", Hostname: "test-hostname", }, - expectedError: fmt.Errorf("failed to transformer label 'label-template': failed to parse template \"my-value-{{ .Spot\": template: transformer:1: unclosed action"), + expectedError: fmt.Errorf("failed to transformer label \"label-template\": failed to parse template \"my-value-{{ .Spot\": template: transformer:1: unclosed action"), }, { name: "Transform annotations with template", @@ -113,6 +138,7 @@ func TestMatch(t *testing.T) { "annotation-template": "my-value-test-platform", }, Labels: map[string]string{}, + Taints: map[string]string{}, }, }, { @@ -134,6 +160,7 @@ func TestMatch(t *testing.T) { Labels: map[string]string{ "label-template": "my-value-false-a", }, + Taints: map[string]string{}, }, }, { @@ -159,6 +186,7 @@ func TestMatch(t *testing.T) { Labels: map[string]string{ "karpenter.sh/capacity-type": "spot", }, + Taints: map[string]string{}, }, expectedMeta: &runtime.PlatformMetadataSpec{ Platform: "test-platform", @@ -188,6 +216,7 @@ func TestMatch(t *testing.T) { expected: &transformer.NodeSpec{ Annotations: map[string]string{}, Labels: map[string]string{}, + Taints: map[string]string{}, }, expectedMeta: &runtime.PlatformMetadataSpec{ Platform: "test-platform", @@ -230,6 +259,7 @@ func TestMatch(t *testing.T) { Labels: map[string]string{ "karpenter.sh/capacity-type": "spot", }, + Taints: map[string]string{}, }, expectedMeta: &runtime.PlatformMetadataSpec{ Platform: "test-platform", @@ -253,6 +283,38 @@ func TestMatch(t *testing.T) { }, expectedError: fmt.Errorf("invalid label name \"-template\": [name part must consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]')]"), //nolint:lll }, + { + name: "Transform taint with bad name", + terms: []transformer.NodeTerm{ + { + Name: "my-transformer", + Taints: map[string]string{ + "node.kubernetes.io/pid-pressure": "my-value", + }, + }, + }, + metadata: runtime.PlatformMetadataSpec{ + Platform: "test-platform", + Hostname: "test-hostname", + }, + expectedError: fmt.Errorf("invalid taint name \"node.kubernetes.io/pid-pressure\": [taint in kubernetes namespace]"), //nolint:lll + }, + { + name: "Transform taint with bad value", + terms: []transformer.NodeTerm{ + { + Name: "my-transformer", + Taints: map[string]string{ + "node.cloudprovider.kubernetes.io/storage-type": "my-value:PleaseSchedule", + }, + }, + }, + metadata: runtime.PlatformMetadataSpec{ + Platform: "test-platform", + Hostname: "test-hostname", + }, + expectedError: fmt.Errorf("invalid taint value \"my-value:PleaseSchedule\": [taint effect \"PleaseSchedule\" is not valid]"), //nolint:lll + }, } { t.Run(tt.name, func(t *testing.T) { node, err := transformer.TransformNode(tt.terms, &tt.metadata)