Skip to content

Commit 543f099

Browse files
bentitojoelanfordtrgeigerperdasilva
authored
✨ Check known required permissions for install before installing with the helm applier (#1858)
* permissions preflight: copy necessary kubernetes libs Signed-off-by: Joe Lanford <[email protected]> * permissions preflight: kubernetes rbac code modifications Signed-off-by: Joe Lanford <[email protected]> * permissions preflight: add preauth implementation Signed-off-by: Joe Lanford <[email protected]> * permissions preflight: enable implementation behind feature gate Signed-off-by: Joe Lanford <[email protected]> * Rm k8s.io/kubernetes copypasta & import/replace This is the manual version. Needed to change rbac.go a bit to allow for v1.32.2 code changes, but basically as-was Signed-off-by: Brett Tofel <[email protected]> * Adds k8s.io/ lib maintainer tool go.mod made in the current form the tool generates Signed-off-by: Brett Tofel <[email protected]> * Make debug a flag Signed-off-by: Brett Tofel <[email protected]> * Small fix, fixes err on kubernetes replace itself Signed-off-by: Brett Tofel <[email protected]> * Changes to allow calling as make target Signed-off-by: Brett Tofel <[email protected]> * Run go mod tidy post rebase Signed-off-by: Brett Tofel <[email protected]> * From rebase - add PreAuthorizer to Helm struct Signed-off-by: Brett Tofel <[email protected]> * Fixes to pass linter Signed-off-by: Brett Tofel <[email protected]> * Add needed setups to preflightPerm unit tests Signed-off-by: Brett Tofel <[email protected]> * Address review comments on rbac.go rbac_test.go likely coming soon Signed-off-by: Brett Tofel <[email protected]> * Add tests for authorization/rbac.go Signed-off-by: Tayler Geiger <[email protected]> * Move k8sMaintainer code to its own dir Signed-off-by: Brett Tofel <[email protected]> * Run k8smaintainer code post rebase Signed-off-by: Brett Tofel <[email protected]> * Lint acceptable format for rbac_test.go Signed-off-by: Brett Tofel <[email protected]> * Add tests for authorization/rbac.go Signed-off-by: Tayler Geiger <[email protected]> * Refactor inline feature gate check Signed-off-by: Brett Tofel <[email protected]> * Change PreAuthorize() return value to []ScopedPolicyRules Use []ScopedPolicyRules struct for first return value in PreAuthorize() to avoid issues with random iteration order in previous map return value. Signed-off-by: Tayler Geiger <[email protected]> * Lint acceptable format for rbac_test.go (take 2) Signed-off-by: Brett Tofel <[email protected]> * Add fakeStorage dry run for escalationCheck Signed-off-by: Brett Tofel <[email protected]> * Revert "Add fakeStorage dry run for escalationCheck" This reverts commit 2681194. * Rename template func to renderClientOnlyRelease Signed-off-by: Brett Tofel <[email protected]> * Updated comment on returns of PreAuthorize Signed-off-by: Brett Tofel <[email protected]> * Remove repetition in rbac_test.go Signed-off-by: Tayler Geiger <[email protected]> * k8smaintainer stage repo version pin logic upgrade Signed-off-by: Brett Tofel <[email protected]> * Simplify PreAuthorizer handling via feature gate Signed-off-by: Brett Tofel <[email protected]> * Split pre-auth checks cluster-scoped & ns-scoped Signed-off-by: Brett Tofel <[email protected]> * Handle missing rules from escalation errors Also sort final missing rules by namespace Signed-off-by: Tayler Geiger <[email protected]> * Clean up escalation error parsing and fix tests Pass in the clusterextension to PreAuthorize instead of the user.Info since we need the extension to create the clusterextension/finalizer Signed-off-by: Tayler Geiger <[email protected]> * Make tidy after rebase Signed-off-by: Brett Tofel <[email protected]> * GCI the files so lint passes Signed-off-by: Brett Tofel <[email protected]> * Use slices.SortFunc instead of sort.Slice Signed-off-by: Tayler Geiger <[email protected]> * Lift running pre-auth checks out of Helm Apply Signed-off-by: Brett Tofel <[email protected]> * Add centralized logging for feature gate status Signed-off-by: Brett Tofel <[email protected]> * Err msg reads better Co-authored-by: Per Goncalves da Silva <[email protected]> * Run make tidy after rebase Signed-off-by: Brett Tofel <[email protected]> * No more magic numbers Signed-off-by: Brett Tofel <[email protected]> * Sort components of missing rules lists Signed-off-by: Brett Tofel <[email protected]> * Streamline var usage * Lift to escalationCheckerFor method Signed-off-by: Brett Tofel <[email protected]> * Fix lint prealloc err on allMissingPolicyRules Signed-off-by: Brett Tofel <[email protected]> * Prealloc missingRulesWithDeduplicatedVerbs * Tidy verb vars together with comment & issue link Signed-off-by: Brett Tofel <[email protected]> * Add comments and protections on parsing err msg Signed-off-by: Brett Tofel <[email protected]> * Improvements to k8smaintainer code Signed-off-by: Brett Tofel <[email protected]> * Linter fix for unused byte slice Signed-off-by: Brett Tofel <[email protected]> * New target now 'k8s-pin', take ENVVAR for k8s ver Also separate the target from make tiday and some code cleanup. Signed-off-by: Brett Tofel <[email protected]> * Replace x/mod/semver w/ blang - more legible parse Signed-off-by: Brett Tofel <[email protected]> * Move EXHELP for k8s-pin target Signed-off-by: Brett Tofel <[email protected]> * Update README.md to account for changes Signed-off-by: Brett Tofel <[email protected]> * Split permission & resolution error captures Signed-off-by: Brett Tofel <[email protected]> * Improve permission regexp matching Now handles multiple values in any of APIGroups, Resources, or Verbs. Adds small utility function for trimming and splitting those values into a string slice. Signed-off-by: Tayler Geiger <[email protected]> * Run make k8s-pin post-rebase Signed-off-by: Brett Tofel <[email protected]> * Add tests to verify kubernetes API errors vs regex Signed-off-by: Brett Tofel <[email protected]> * permissions preflight: refactoring escalation error parser Signed-off-by: Joe Lanford <[email protected]> * permission preflight: emit error when encountering unknown policy rule field Signed-off-by: Joe Lanford <[email protected]> * permissions preflight: fixup escalation error parser and tests Signed-off-by: Joe Lanford <[email protected]> * permissions preflight: add kubernetes compatibility tests, other small fixups Signed-off-by: Joe Lanford <[email protected]> * preflight permissions: removing clusterextensions/finalizer patch requirement The clusterextensions/finalizer requirement comes from the desire to support clusters where OwnerReferencesPermissionEnforcement plugin is enabled. This plugin requires "update", but not "patch" for the clusterextensions/finalizers permission. See: https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement Signed-off-by: Joe Lanford <[email protected]> * Addressing latest round of PR feedback Signed-off-by: Tayler Geiger <[email protected]> * Fix linting errors Signed-off-by: Brett Tofel <[email protected]> * SingleOwnNSInstallSupport feature gate reset Signed-off-by: Brett Tofel <[email protected]> * Fix feature gate logging unhashable hash problem Signed-off-by: Tayler Geiger <[email protected]> * Remove duplicate test case Signed-off-by: Tayler Geiger <[email protected]> --------- Signed-off-by: Joe Lanford <[email protected]> Signed-off-by: Brett Tofel <[email protected]> Signed-off-by: Tayler Geiger <[email protected]> Co-authored-by: Joe Lanford <[email protected]> Co-authored-by: Tayler Geiger <[email protected]> Co-authored-by: Per Goncalves da Silva <[email protected]>
1 parent 2092ee9 commit 543f099

File tree

14 files changed

+1985
-38
lines changed

14 files changed

+1985
-38
lines changed

Makefile

+8-5
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,13 @@ custom-linter-build: #EXHELP Build custom linter
120120
lint-custom: custom-linter-build #EXHELP Call custom linter for the project
121121
go vet -tags=$(GO_BUILD_TAGS) -vettool=./bin/custom-linter ./...
122122

123-
.PHONY: tidy
124-
tidy: #HELP Update dependencies.
125-
# Force tidy to use the version already in go.mod
126-
$(Q)go mod tidy -go=$(GOLANG_VERSION)
123+
.PHONY: k8s-pin
124+
k8s-pin: #EXHELP Pin k8s staging modules based on k8s.io/kubernetes version (in go.mod or from K8S_IO_K8S_VERSION env var) and run go mod tidy.
125+
K8S_IO_K8S_VERSION='$(K8S_IO_K8S_VERSION)' go run hack/tools/k8smaintainer/main.go
126+
127+
.PHONY: tidy #HELP Run go mod tidy.
128+
tidy:
129+
go mod tidy
127130

128131
.PHONY: manifests
129132
KUSTOMIZE_CATD_CRDS_DIR := config/base/catalogd/crd/bases
@@ -151,7 +154,7 @@ generate: $(CONTROLLER_GEN) #EXHELP Generate code containing DeepCopy, DeepCopyI
151154
$(CONTROLLER_GEN) --load-build-tags=$(GO_BUILD_TAGS) object:headerFile="hack/boilerplate.go.txt" paths="./..."
152155

153156
.PHONY: verify
154-
verify: tidy fmt generate manifests crd-ref-docs generate-test-data #HELP Verify all generated code is up-to-date.
157+
verify: k8s-pin fmt generate manifests crd-ref-docs generate-test-data #HELP Verify all generated code is up-to-date. Runs k8s-pin instead of just tidy.
155158
git diff --exit-code
156159

157160
# Renders registry+v1 bundles in test/convert

cmd/operator-controller/main.go

+19-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/containers/image/v5/types"
3232
"github.com/spf13/cobra"
3333
corev1 "k8s.io/api/core/v1"
34+
rbacv1 "k8s.io/api/rbac/v1"
3435
apiextensionsv1client "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
3536
"k8s.io/apimachinery/pkg/fields"
3637
k8slabels "k8s.io/apimachinery/pkg/labels"
@@ -56,6 +57,7 @@ import (
5657
"github.com/operator-framework/operator-controller/internal/operator-controller/action"
5758
"github.com/operator-framework/operator-controller/internal/operator-controller/applier"
5859
"github.com/operator-framework/operator-controller/internal/operator-controller/authentication"
60+
"github.com/operator-framework/operator-controller/internal/operator-controller/authorization"
5961
"github.com/operator-framework/operator-controller/internal/operator-controller/catalogmetadata/cache"
6062
catalogclient "github.com/operator-framework/operator-controller/internal/operator-controller/catalogmetadata/client"
6163
"github.com/operator-framework/operator-controller/internal/operator-controller/contentmanager"
@@ -178,6 +180,9 @@ func validateMetricsFlags() error {
178180
func run() error {
179181
setupLog.Info("starting up the controller", "version info", version.String())
180182

183+
// log feature gate status after parsing flags and setting up logger
184+
features.LogFeatureGateStates(setupLog, features.OperatorControllerFeatureGate)
185+
181186
authFilePath := filepath.Join(os.TempDir(), fmt.Sprintf("%s-%s.json", authFilePrefix, apimachineryrand.String(8)))
182187
var globalPullSecretKey *k8stypes.NamespacedName
183188
if cfg.globalPullSecret != "" {
@@ -197,8 +202,12 @@ func run() error {
197202
setupLog.Info("set up manager")
198203
cacheOptions := crcache.Options{
199204
ByObject: map[client.Object]crcache.ByObject{
200-
&ocv1.ClusterExtension{}: {Label: k8slabels.Everything()},
201-
&ocv1.ClusterCatalog{}: {Label: k8slabels.Everything()},
205+
&ocv1.ClusterExtension{}: {Label: k8slabels.Everything()},
206+
&ocv1.ClusterCatalog{}: {Label: k8slabels.Everything()},
207+
&rbacv1.ClusterRole{}: {Label: k8slabels.Everything()},
208+
&rbacv1.ClusterRoleBinding{}: {Label: k8slabels.Everything()},
209+
&rbacv1.Role{}: {Namespaces: map[string]crcache.Config{}, Label: k8slabels.Everything()},
210+
&rbacv1.RoleBinding{}: {Namespaces: map[string]crcache.Config{}, Label: k8slabels.Everything()},
202211
},
203212
DefaultNamespaces: map[string]crcache.Config{
204213
cfg.systemNamespace: {LabelSelector: k8slabels.Everything()},
@@ -403,10 +412,18 @@ func run() error {
403412
crdupgradesafety.NewPreflight(aeClient.CustomResourceDefinitions()),
404413
}
405414

415+
// determine if PreAuthorizer should be enabled based on feature gate
416+
var preAuth authorization.PreAuthorizer
417+
if features.OperatorControllerFeatureGate.Enabled(features.PreflightPermissions) {
418+
preAuth = authorization.NewRBACPreAuthorizer(mgr.GetClient())
419+
}
420+
421+
// now initialize the helmApplier, assigning the potentially nil preAuth
406422
helmApplier := &applier.Helm{
407423
ActionClientGetter: acg,
408424
Preflights: preflights,
409425
BundleToHelmChartFn: convert.RegistryV1ToHelmChart,
426+
PreAuthorizer: preAuth,
410427
}
411428

412429
cm := contentmanager.NewManager(clientRestConfigMapper, mgr.GetConfig(), mgr.GetRESTMapper())

codecov.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ coverage:
88
paths:
99
- "api/"
1010
- "cmd/"
11-
- "internal/"
11+
- "internal/"
12+

config/base/operator-controller/rbac/role.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ rules:
4747
verbs:
4848
- patch
4949
- update
50+
- apiGroups:
51+
- rbac.authorization.k8s.io
52+
resources:
53+
- clusterrolebindings
54+
- clusterroles
55+
- rolebindings
56+
- roles
57+
verbs:
58+
- list
59+
- watch
5060
---
5161
apiVersion: rbac.authorization.k8s.io/v1
5262
kind: Role

go.mod

+70-4
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,30 @@ require (
2424
github.com/spf13/cobra v1.9.1
2525
github.com/stretchr/testify v1.10.0
2626
golang.org/x/exp v0.0.0-20250228200357-dead58393ab7
27+
golang.org/x/mod v0.24.0
2728
golang.org/x/sync v0.13.0
2829
golang.org/x/tools v0.32.0
2930
gopkg.in/yaml.v2 v2.4.0
3031
helm.sh/helm/v3 v3.17.3
3132
k8s.io/api v0.32.3
32-
k8s.io/apiextensions-apiserver v0.32.2
33+
k8s.io/apiextensions-apiserver v0.32.3
3334
k8s.io/apimachinery v0.32.3
3435
k8s.io/apiserver v0.32.3
3536
k8s.io/cli-runtime v0.32.3
3637
k8s.io/client-go v0.32.3
3738
k8s.io/component-base v0.32.3
3839
k8s.io/klog/v2 v2.130.1
40+
k8s.io/kubernetes v1.32.3
3941
k8s.io/utils v0.0.0-20241210054802-24370beab758
4042
sigs.k8s.io/controller-runtime v0.20.2
4143
sigs.k8s.io/yaml v1.4.0
4244
)
4345

46+
require (
47+
k8s.io/component-helpers v0.32.3 // indirect
48+
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
49+
)
50+
4451
require (
4552
cel.dev/expr v0.19.0 // indirect
4653
dario.cat/mergo v1.0.1 // indirect
@@ -215,7 +222,6 @@ require (
215222
go.opentelemetry.io/otel/trace v1.33.0 // indirect
216223
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
217224
golang.org/x/crypto v0.37.0 // indirect
218-
golang.org/x/mod v0.24.0 // indirect
219225
golang.org/x/net v0.39.0 // indirect
220226
golang.org/x/oauth2 v0.27.0 // indirect
221227
golang.org/x/sys v0.32.0 // indirect
@@ -232,12 +238,72 @@ require (
232238
gopkg.in/inf.v0 v0.9.1 // indirect
233239
gopkg.in/warnings.v0 v0.1.2 // indirect
234240
gopkg.in/yaml.v3 v3.0.1 // indirect
235-
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect
236-
k8s.io/kubectl v0.32.2 // indirect
241+
k8s.io/controller-manager v0.32.3 // indirect
242+
k8s.io/kubectl v0.32.3 // indirect
237243
oras.land/oras-go v1.2.5 // indirect
238244
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 // indirect
239245
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
240246
sigs.k8s.io/kustomize/api v0.18.0 // indirect
241247
sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect
242248
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
243249
)
250+
251+
replace k8s.io/api => k8s.io/api v0.32.3
252+
253+
replace k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.32.3
254+
255+
replace k8s.io/apimachinery => k8s.io/apimachinery v0.32.3
256+
257+
replace k8s.io/apiserver => k8s.io/apiserver v0.32.3
258+
259+
replace k8s.io/cli-runtime => k8s.io/cli-runtime v0.32.3
260+
261+
replace k8s.io/client-go => k8s.io/client-go v0.32.3
262+
263+
replace k8s.io/cloud-provider => k8s.io/cloud-provider v0.32.3
264+
265+
replace k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.32.3
266+
267+
replace k8s.io/code-generator => k8s.io/code-generator v0.32.3
268+
269+
replace k8s.io/component-base => k8s.io/component-base v0.32.3
270+
271+
replace k8s.io/component-helpers => k8s.io/component-helpers v0.32.3
272+
273+
replace k8s.io/controller-manager => k8s.io/controller-manager v0.32.3
274+
275+
replace k8s.io/cri-api => k8s.io/cri-api v0.32.3
276+
277+
replace k8s.io/cri-client => k8s.io/cri-client v0.32.3
278+
279+
replace k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.32.3
280+
281+
replace k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.32.3
282+
283+
replace k8s.io/endpointslice => k8s.io/endpointslice v0.32.3
284+
285+
replace k8s.io/externaljwt => k8s.io/externaljwt v0.32.3
286+
287+
replace k8s.io/kms => k8s.io/kms v0.32.3
288+
289+
replace k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.32.3
290+
291+
replace k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.32.3
292+
293+
replace k8s.io/kube-proxy => k8s.io/kube-proxy v0.32.3
294+
295+
replace k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.32.3
296+
297+
replace k8s.io/kubectl => k8s.io/kubectl v0.32.3
298+
299+
replace k8s.io/kubelet => k8s.io/kubelet v0.32.3
300+
301+
replace k8s.io/kubernetes => k8s.io/kubernetes v1.32.3
302+
303+
replace k8s.io/metrics => k8s.io/metrics v0.32.3
304+
305+
replace k8s.io/mount-utils => k8s.io/mount-utils v0.32.3
306+
307+
replace k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.32.3
308+
309+
replace k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.32.3

go.sum

+12-6
Original file line numberDiff line numberDiff line change
@@ -771,8 +771,8 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
771771
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
772772
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
773773
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
774-
k8s.io/apiextensions-apiserver v0.32.2 h1:2YMk285jWMk2188V2AERy5yDwBYrjgWYggscghPCvV4=
775-
k8s.io/apiextensions-apiserver v0.32.2/go.mod h1:GPwf8sph7YlJT3H6aKUWtd0E+oyShk/YHWQHf/OOgCA=
774+
k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY=
775+
k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss=
776776
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
777777
k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
778778
k8s.io/apiserver v0.32.3 h1:kOw2KBuHOA+wetX1MkmrxgBr648ksz653j26ESuWNY8=
@@ -783,12 +783,18 @@ k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=
783783
k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY=
784784
k8s.io/component-base v0.32.3 h1:98WJvvMs3QZ2LYHBzvltFSeJjEx7t5+8s71P7M74u8k=
785785
k8s.io/component-base v0.32.3/go.mod h1:LWi9cR+yPAv7cu2X9rZanTiFKB2kHA+JjmhkKjCZRpI=
786+
k8s.io/component-helpers v0.32.3 h1:9veHpOGTPLluqU4hAu5IPOwkOIZiGAJUhHndfVc5FT4=
787+
k8s.io/component-helpers v0.32.3/go.mod h1:utTBXk8lhkJewBKNuNf32Xl3KT/0VV19DmiXU/SV4Ao=
788+
k8s.io/controller-manager v0.32.3 h1:jBxZnQ24k6IMeWLyxWZmpa3QVS7ww+osAIzaUY/jqyc=
789+
k8s.io/controller-manager v0.32.3/go.mod h1:out1L3DZjE/p7JG0MoMMIaQGWIkt3c+pKaswqSHgKsI=
786790
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
787791
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
788-
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg=
789-
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas=
790-
k8s.io/kubectl v0.32.2 h1:TAkag6+XfSBgkqK9I7ZvwtF0WVtUAvK8ZqTt+5zi1Us=
791-
k8s.io/kubectl v0.32.2/go.mod h1:+h/NQFSPxiDZYX/WZaWw9fwYezGLISP0ud8nQKg+3g8=
792+
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
793+
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
794+
k8s.io/kubectl v0.32.3 h1:VMi584rbboso+yjfv0d8uBHwwxbC438LKq+dXd5tOAI=
795+
k8s.io/kubectl v0.32.3/go.mod h1:6Euv2aso5GKzo/UVMacV6C7miuyevpfI91SvBvV9Zdg=
796+
k8s.io/kubernetes v1.32.3 h1:2A58BlNME8NwsMawmnM6InYo3Jf35Nw5G79q46kXwoA=
797+
k8s.io/kubernetes v1.32.3/go.mod h1:GvhiBeolvSRzBpFlgM0z/Bbu3Oxs9w3P6XfEgYaMi8k=
792798
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
793799
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
794800
oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo=

hack/tools/k8smaintainer/README.md

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Kubernetes Staging Module Version Synchronization Tool
2+
3+
## Purpose
4+
This tool ensures that if `k8s.io/kubernetes` changes version in your `go.mod`, all related staging modules (e.g., `k8s.io/api`, `k8s.io/apimachinery`) are automatically pinned to the corresponding published version. Recent improvements include an environment variable override and refined logic for version resolution.
5+
6+
## How It Works
7+
8+
1. **Parsing and Filtering:**
9+
- Reads and parses your `go.mod` file.
10+
- Removes existing `replace` directives for `k8s.io/` modules to avoid stale mappings.
11+
12+
2. **Determine Kubernetes Version:**
13+
- **Environment Variable Override:**
14+
If the environment variable `K8S_IO_K8S_VERSION` is set, its value is validated (using semver standards) and used as the target version for `k8s.io/kubernetes`. The tool then runs `go get k8s.io/kubernetes@<version>` to update the dependency.
15+
- **Default Behavior:**
16+
If `K8S_IO_K8S_VERSION` is not set, the tool reads the version of `k8s.io/kubernetes` from the `go.mod` file.
17+
18+
3. **Compute the Target Staging Version:**
19+
- Converts a Kubernetes version in the form `v1.xx.yy` into the staging version format `v0.xx.yy`.
20+
- If the target staging version is unavailable, the tool attempts to fall back to the previous patch version.
21+
22+
4. **Updating Module Replace Directives:**
23+
- Retrieves the full dependency graph using `go list -m -json all`.
24+
- Identifies relevant `k8s.io/*` modules (skipping the main module and version-suffixed modules).
25+
- Removes outdated `replace` directives (ignoring local path replacements).
26+
- Adds new `replace` directives to pin modules—including `k8s.io/kubernetes`—to the computed staging version.
27+
28+
5. **Finalizing Changes:**
29+
- Writes the updated `go.mod` file.
30+
- Runs `go mod tidy` to clean up dependencies.
31+
- Executes `go mod download k8s.io/kubernetes` to update `go.sum`.
32+
- Logs any issues, such as modules remaining at an untagged version (`v0.0.0`), which may indicate upstream tagging problems.
33+
34+
## Environment Variables
35+
36+
- **K8S_IO_K8S_VERSION (optional):**
37+
When set, this environment variable overrides the Kubernetes version found in `go.mod`. The tool validates this semver string, updates the dependency using `go get`, and processes modules accordingly.
38+
39+
## Additional Notes
40+
41+
- The tool ensures consistency across all `k8s.io/*` modules, even if they are not explicitly listed in `go.mod`.
42+
- If a suitable staging version is not found, a warning is logged and the closest valid version is used.
43+
- All operations are logged, which helps in troubleshooting and verifying the process.

0 commit comments

Comments
 (0)