Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Check known required permissions for install before installing with the helm applier #1858

Open
wants to merge 57 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
4456b4c
permissions preflight: copy necessary kubernetes libs
joelanford Feb 25, 2025
8b72c7d
permissions preflight: kubernetes rbac code modifications
joelanford Feb 25, 2025
98c5724
permissions preflight: add preauth implementation
joelanford Feb 25, 2025
2b2f6be
permissions preflight: enable implementation behind feature gate
joelanford Feb 25, 2025
f6d2927
Rm k8s.io/kubernetes copypasta & import/replace
bentito Mar 5, 2025
be82601
Adds k8s.io/ lib maintainer tool
bentito Mar 6, 2025
f404264
Make debug a flag
bentito Mar 7, 2025
61815ad
Small fix, fixes err on kubernetes replace itself
bentito Mar 10, 2025
4369ce8
Changes to allow calling as make target
bentito Mar 10, 2025
aac71ae
Run go mod tidy post rebase
bentito Mar 10, 2025
ee0c590
From rebase - add PreAuthorizer to Helm struct
bentito Mar 10, 2025
96baece
Fixes to pass linter
bentito Mar 10, 2025
31cad4d
Add needed setups to preflightPerm unit tests
bentito Mar 11, 2025
3691ff8
Address review comments on rbac.go
bentito Mar 14, 2025
d1fd8a5
Add tests for authorization/rbac.go
trgeiger Mar 15, 2025
0b7b1bc
Move k8sMaintainer code to its own dir
bentito Mar 17, 2025
ea4fd22
Run k8smaintainer code post rebase
bentito Mar 18, 2025
6c105b9
Lint acceptable format for rbac_test.go
bentito Mar 18, 2025
a9df8bd
Add tests for authorization/rbac.go
trgeiger Mar 15, 2025
51e9e7f
Refactor inline feature gate check
bentito Mar 18, 2025
7c134b7
Change PreAuthorize() return value to []ScopedPolicyRules
trgeiger Mar 18, 2025
cbe69e8
Lint acceptable format for rbac_test.go (take 2)
bentito Mar 18, 2025
8999be6
Add fakeStorage dry run for escalationCheck
bentito Mar 19, 2025
a8ad905
Revert "Add fakeStorage dry run for escalationCheck"
bentito Mar 20, 2025
593e6e2
Run make tidy after rebase
bentito Mar 31, 2025
c079969
Rename template func to renderClientOnlyRelease
bentito Apr 1, 2025
59a4dfc
Updated comment on returns of PreAuthorize
bentito Apr 1, 2025
44a5e12
Remove repetition in rbac_test.go
trgeiger Apr 1, 2025
8184fc3
k8smaintainer stage repo version pin logic upgrade
bentito Apr 2, 2025
b1398cf
Simplify PreAuthorizer handling via feature gate
bentito Apr 2, 2025
7945556
Split pre-auth checks cluster-scoped & ns-scoped
bentito Apr 2, 2025
8283d9b
Handle missing rules from escalation errors
trgeiger Apr 2, 2025
000024f
Clean up escalation error parsing and fix tests
trgeiger Apr 2, 2025
d62d4a7
Make tidy after rebase
bentito Apr 3, 2025
b72b752
GCI the files so lint passes
bentito Apr 3, 2025
1cff41c
Use slices.SortFunc instead of sort.Slice
trgeiger Apr 3, 2025
3a1655f
Lift running pre-auth checks out of Helm Apply
bentito Apr 4, 2025
f0de7a1
Add centralized logging for feature gate status
bentito Apr 4, 2025
bebbf25
Err msg reads better
bentito Apr 7, 2025
913b004
Run make tidy after rebase
bentito Apr 7, 2025
b8a0150
No more magic numbers
bentito Apr 7, 2025
1301972
Sort components of missing rules lists
bentito Apr 8, 2025
aa4d94f
Streamline var usage
bentito Apr 8, 2025
352de66
Lift to escalationCheckerFor method
bentito Apr 8, 2025
7693d23
Fix lint prealloc err on allMissingPolicyRules
bentito Apr 8, 2025
ea89d7f
Prealloc missingRulesWithDeduplicatedVerbs
bentito Apr 8, 2025
937ae42
Tidy verb vars together with comment & issue link
bentito Apr 8, 2025
f9721fb
Add comments and protections on parsing err msg
bentito Apr 8, 2025
3a7c448
Improvements to k8smaintainer code
bentito Apr 9, 2025
3db9576
Linter fix for unused byte slice
bentito Apr 9, 2025
3b06759
New target now 'k8s-pin', take ENVVAR for k8s ver
bentito Apr 9, 2025
231bac9
Replace x/mod/semver w/ blang - more legible parse
bentito Apr 9, 2025
368033f
Move EXHELP for k8s-pin target
bentito Apr 9, 2025
5f4fd5a
Update README.md to account for changes
bentito Apr 9, 2025
54621a9
Improve permission regexp matching
trgeiger Apr 9, 2025
22c1144
Split permission & resolution error captures
bentito Apr 10, 2025
758e0a3
Merge remote-tracking branch 'origin/rbac-auth-k8s-replacer' into rba…
bentito Apr 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -16,6 +16,10 @@ run:
# Default timeout is 1m, up to give more room
timeout: 4m

issues:
exclude-dirs:
- internal/operator-controller/authorization/internal/kubernetes

linters:
enable:
- asciicheck
13 changes: 8 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -120,10 +120,13 @@ custom-linter-build: #EXHELP Build custom linter
lint-custom: custom-linter-build #EXHELP Call custom linter for the project
go vet -tags=$(GO_BUILD_TAGS) -vettool=./bin/custom-linter ./...

.PHONY: tidy
tidy: #HELP Update dependencies.
# Force tidy to use the version already in go.mod
$(Q)go mod tidy -go=$(GOLANG_VERSION)
.PHONY: k8s-pin
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.
K8S_IO_K8S_VERSION='$(K8S_IO_K8S_VERSION)' go run hack/tools/k8smaintainer/main.go

.PHONY: tidy #HELP Run go mod tidy.
tidy:
go mod tidy

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

.PHONY: verify
verify: tidy fmt generate manifests crd-ref-docs generate-test-data #HELP Verify all generated code is up-to-date.
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.
git diff --exit-code

# Renders registry+v1 bundles in test/convert
21 changes: 19 additions & 2 deletions cmd/operator-controller/main.go
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
apiextensionsv1client "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
"k8s.io/apimachinery/pkg/fields"
k8slabels "k8s.io/apimachinery/pkg/labels"
@@ -58,6 +59,7 @@ import (
"github.com/operator-framework/operator-controller/internal/operator-controller/action"
"github.com/operator-framework/operator-controller/internal/operator-controller/applier"
"github.com/operator-framework/operator-controller/internal/operator-controller/authentication"
"github.com/operator-framework/operator-controller/internal/operator-controller/authorization"
"github.com/operator-framework/operator-controller/internal/operator-controller/catalogmetadata/cache"
catalogclient "github.com/operator-framework/operator-controller/internal/operator-controller/catalogmetadata/client"
"github.com/operator-framework/operator-controller/internal/operator-controller/contentmanager"
@@ -185,6 +187,9 @@ func run() error {

setupLog.Info("starting up the controller", "version info", version.String())

// log feature gate status after parsing flags and setting up logger
features.LogFeatureGateStates(setupLog, features.OperatorControllerFeatureGate)

authFilePath := filepath.Join(os.TempDir(), fmt.Sprintf("%s-%s.json", authFilePrefix, apimachineryrand.String(8)))
var globalPullSecretKey *k8stypes.NamespacedName
if cfg.globalPullSecret != "" {
@@ -204,8 +209,12 @@ func run() error {
setupLog.Info("set up manager")
cacheOptions := crcache.Options{
ByObject: map[client.Object]crcache.ByObject{
&ocv1.ClusterExtension{}: {Label: k8slabels.Everything()},
&ocv1.ClusterCatalog{}: {Label: k8slabels.Everything()},
&ocv1.ClusterExtension{}: {Label: k8slabels.Everything()},
&ocv1.ClusterCatalog{}: {Label: k8slabels.Everything()},
&rbacv1.ClusterRole{}: {Label: k8slabels.Everything()},
&rbacv1.ClusterRoleBinding{}: {Label: k8slabels.Everything()},
&rbacv1.Role{}: {Namespaces: map[string]crcache.Config{}, Label: k8slabels.Everything()},
&rbacv1.RoleBinding{}: {Namespaces: map[string]crcache.Config{}, Label: k8slabels.Everything()},
},
DefaultNamespaces: map[string]crcache.Config{
cfg.systemNamespace: {LabelSelector: k8slabels.Everything()},
@@ -410,10 +419,18 @@ func run() error {
crdupgradesafety.NewPreflight(aeClient.CustomResourceDefinitions()),
}

// determine if PreAuthorizer should be enabled based on feature gate
var preAuth authorization.PreAuthorizer
if features.OperatorControllerFeatureGate.Enabled(features.PreflightPermissions) {
preAuth = authorization.NewRBACPreAuthorizer(mgr.GetClient())
}

// now initialize the helmApplier, assigning the potentially nil preAuth
helmApplier := &applier.Helm{
ActionClientGetter: acg,
Preflights: preflights,
BundleToHelmChartFn: convert.RegistryV1ToHelmChart,
PreAuthorizer: preAuth,
}

cm := contentmanager.NewManager(clientRestConfigMapper, mgr.GetConfig(), mgr.GetRESTMapper())
5 changes: 4 additions & 1 deletion codecov.yml
Original file line number Diff line number Diff line change
@@ -8,4 +8,7 @@ coverage:
paths:
- "api/"
- "cmd/"
- "internal/"
- "internal/"

ignore:
- "internal/operator-controller/authorization/internal/kubernetes"
10 changes: 10 additions & 0 deletions config/base/operator-controller/rbac/role.yaml
Original file line number Diff line number Diff line change
@@ -47,6 +47,16 @@ rules:
verbs:
- patch
- update
- apiGroups:
- rbac.authorization.k8s.io
resources:
- clusterrolebindings
- clusterroles
- rolebindings
- roles
verbs:
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
86 changes: 75 additions & 11 deletions go.mod
Original file line number Diff line number Diff line change
@@ -25,23 +25,20 @@ require (
github.com/spf13/cobra v1.9.1
github.com/stretchr/testify v1.10.0
golang.org/x/exp v0.0.0-20250228200357-dead58393ab7
golang.org/x/sync v0.13.0
golang.org/x/mod v0.24.0
golang.org/x/sync v0.12.0
golang.org/x/tools v0.31.0
gopkg.in/yaml.v2 v2.4.0
helm.sh/helm/v3 v3.17.2
k8s.io/api v0.32.3
k8s.io/apiextensions-apiserver v0.32.2
k8s.io/apimachinery v0.32.3
k8s.io/apiserver v0.32.3
k8s.io/cli-runtime v0.32.3
k8s.io/client-go v0.32.3
k8s.io/component-base v0.32.3
k8s.io/klog/v2 v2.130.1
k8s.io/kubernetes v1.32.3
k8s.io/utils v0.0.0-20241210054802-24370beab758
sigs.k8s.io/controller-runtime v0.20.2
sigs.k8s.io/yaml v1.4.0
)

require k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect

require (
cel.dev/expr v0.18.0 // indirect
dario.cat/mergo v1.0.1 // indirect
@@ -214,7 +211,6 @@ require (
go.opentelemetry.io/otel/trace v1.33.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/mod v0.24.0 // indirect
golang.org/x/net v0.37.0 // indirect
golang.org/x/oauth2 v0.27.0 // indirect
golang.org/x/sys v0.31.0 // indirect
@@ -231,12 +227,80 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect
k8s.io/kubectl v0.32.2 // indirect
k8s.io/api v0.32.3
k8s.io/apiextensions-apiserver v0.32.3
k8s.io/apimachinery v0.32.3
k8s.io/apiserver v0.32.3
k8s.io/cli-runtime v0.32.3
k8s.io/client-go v0.32.3
k8s.io/component-base v0.32.3
k8s.io/component-helpers v0.32.3 // indirect
k8s.io/controller-manager v0.32.3 // indirect
k8s.io/kubectl v0.32.3 // indirect
oras.land/oras-go v1.2.5 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/kustomize/api v0.18.0 // indirect
sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
)

replace k8s.io/api => k8s.io/api v0.32.3

replace k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.32.3

replace k8s.io/apimachinery => k8s.io/apimachinery v0.32.3

replace k8s.io/apiserver => k8s.io/apiserver v0.32.3

replace k8s.io/cli-runtime => k8s.io/cli-runtime v0.32.3

replace k8s.io/client-go => k8s.io/client-go v0.32.3

replace k8s.io/cloud-provider => k8s.io/cloud-provider v0.32.3

replace k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.32.3

replace k8s.io/code-generator => k8s.io/code-generator v0.32.3

replace k8s.io/component-base => k8s.io/component-base v0.32.3

replace k8s.io/component-helpers => k8s.io/component-helpers v0.32.3

replace k8s.io/controller-manager => k8s.io/controller-manager v0.32.3

replace k8s.io/cri-api => k8s.io/cri-api v0.32.3

replace k8s.io/cri-client => k8s.io/cri-client v0.32.3

replace k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.32.3

replace k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.32.3

replace k8s.io/endpointslice => k8s.io/endpointslice v0.32.3

replace k8s.io/externaljwt => k8s.io/externaljwt v0.32.3

replace k8s.io/kms => k8s.io/kms v0.32.3

replace k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.32.3

replace k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.32.3

replace k8s.io/kube-proxy => k8s.io/kube-proxy v0.32.3

replace k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.32.3

replace k8s.io/kubectl => k8s.io/kubectl v0.32.3

replace k8s.io/kubelet => k8s.io/kubelet v0.32.3

replace k8s.io/kubernetes => k8s.io/kubernetes v1.32.3

replace k8s.io/metrics => k8s.io/metrics v0.32.3

replace k8s.io/mount-utils => k8s.io/mount-utils v0.32.3

replace k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.32.3

replace k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.32.3
22 changes: 14 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
@@ -646,8 +646,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -769,8 +769,8 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
k8s.io/apiextensions-apiserver v0.32.2 h1:2YMk285jWMk2188V2AERy5yDwBYrjgWYggscghPCvV4=
k8s.io/apiextensions-apiserver v0.32.2/go.mod h1:GPwf8sph7YlJT3H6aKUWtd0E+oyShk/YHWQHf/OOgCA=
k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY=
k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss=
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/apiserver v0.32.3 h1:kOw2KBuHOA+wetX1MkmrxgBr648ksz653j26ESuWNY8=
@@ -781,12 +781,18 @@ k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=
k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY=
k8s.io/component-base v0.32.3 h1:98WJvvMs3QZ2LYHBzvltFSeJjEx7t5+8s71P7M74u8k=
k8s.io/component-base v0.32.3/go.mod h1:LWi9cR+yPAv7cu2X9rZanTiFKB2kHA+JjmhkKjCZRpI=
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/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg=
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas=
k8s.io/kubectl v0.32.2 h1:TAkag6+XfSBgkqK9I7ZvwtF0WVtUAvK8ZqTt+5zi1Us=
k8s.io/kubectl v0.32.2/go.mod h1:+h/NQFSPxiDZYX/WZaWw9fwYezGLISP0ud8nQKg+3g8=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
k8s.io/kubectl v0.32.3 h1:VMi584rbboso+yjfv0d8uBHwwxbC438LKq+dXd5tOAI=
k8s.io/kubectl v0.32.3/go.mod h1:6Euv2aso5GKzo/UVMacV6C7miuyevpfI91SvBvV9Zdg=
k8s.io/kubernetes v1.32.3 h1:2A58BlNME8NwsMawmnM6InYo3Jf35Nw5G79q46kXwoA=
k8s.io/kubernetes v1.32.3/go.mod h1:GvhiBeolvSRzBpFlgM0z/Bbu3Oxs9w3P6XfEgYaMi8k=
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo=
43 changes: 43 additions & 0 deletions hack/tools/k8smaintainer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Kubernetes Staging Module Version Synchronization Tool

## Purpose
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.

## How It Works

1. **Parsing and Filtering:**
- Reads and parses your `go.mod` file.
- Removes existing `replace` directives for `k8s.io/` modules to avoid stale mappings.

2. **Determine Kubernetes Version:**
- **Environment Variable Override:**
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.
- **Default Behavior:**
If `K8S_IO_K8S_VERSION` is not set, the tool reads the version of `k8s.io/kubernetes` from the `go.mod` file.

3. **Compute the Target Staging Version:**
- Converts a Kubernetes version in the form `v1.xx.yy` into the staging version format `v0.xx.yy`.
- If the target staging version is unavailable, the tool attempts to fall back to the previous patch version.

4. **Updating Module Replace Directives:**
- Retrieves the full dependency graph using `go list -m -json all`.
- Identifies relevant `k8s.io/*` modules (skipping the main module and version-suffixed modules).
- Removes outdated `replace` directives (ignoring local path replacements).
- Adds new `replace` directives to pin modules—including `k8s.io/kubernetes`—to the computed staging version.

5. **Finalizing Changes:**
- Writes the updated `go.mod` file.
- Runs `go mod tidy` to clean up dependencies.
- Executes `go mod download k8s.io/kubernetes` to update `go.sum`.
- Logs any issues, such as modules remaining at an untagged version (`v0.0.0`), which may indicate upstream tagging problems.

## Environment Variables

- **K8S_IO_K8S_VERSION (optional):**
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.

## Additional Notes

- The tool ensures consistency across all `k8s.io/*` modules, even if they are not explicitly listed in `go.mod`.
- If a suitable staging version is not found, a warning is logged and the closest valid version is used.
- All operations are logged, which helps in troubleshooting and verifying the process.
Loading