From c6a7312b57e789fcb4d0d42ff2823da9274319a6 Mon Sep 17 00:00:00 2001 From: Mihaly Gyongyosi Date: Wed, 14 Jan 2026 11:28:48 +0100 Subject: [PATCH] Add codegen + add setup for unistore --- apps/iam/go.mod | 7 +++- apps/iam/go.sum | 12 +++--- apps/iam/kinds/teambinding.cue | 4 ++ apps/iam/pkg/apis/iam/v0alpha1/register.go | 16 +++++++ .../iam/v0alpha1/teambinding_schema_gen.go | 26 +++++++++++- apps/iam/pkg/apis/iam_manifest.go | 4 ++ pkg/registry/apis/iam/register.go | 4 +- pkg/registry/apis/iam/teambinding/fields.go | 42 +++++++++++++++++++ 8 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 pkg/registry/apis/iam/teambinding/fields.go diff --git a/apps/iam/go.mod b/apps/iam/go.mod index e35a733d350..6f86b8537e4 100644 --- a/apps/iam/go.mod +++ b/apps/iam/go.mod @@ -46,6 +46,8 @@ replace github.com/grafana/grafana/apps/annotation => ../annotation replace github.com/grafana/grafana/apps/collections => ../collections +replace github.com/grafana/grafana/pkg/semconv => ../../pkg/semconv + replace github.com/prometheus/alertmanager => github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604 require ( @@ -94,7 +96,7 @@ require ( github.com/Masterminds/sprig/v3 v3.3.0 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect - github.com/ProtonMail/go-crypto v1.1.6 // indirect + github.com/ProtonMail/go-crypto v1.3.0 // indirect github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f // indirect github.com/Yiling-J/theine-go v0.6.2 // indirect github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect @@ -235,8 +237,9 @@ require ( github.com/grafana/grafana/apps/secret v0.0.0 // indirect github.com/grafana/grafana/pkg/aggregator v0.0.0 // indirect github.com/grafana/grafana/pkg/apiserver v0.0.0 // indirect + github.com/grafana/grafana/pkg/plugins v0.0.0-20260113153209-1d3f09d5193a // indirect github.com/grafana/grafana/pkg/promlib v0.0.8 // indirect - github.com/grafana/grafana/pkg/semconv v0.0.0-20250804150913-990f1c69ecc2 // indirect + github.com/grafana/grafana/pkg/semconv v0.0.0 // indirect github.com/grafana/otel-profiling-go v0.5.1 // indirect github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect diff --git a/apps/iam/go.sum b/apps/iam/go.sum index 063696e3d5a..a01581ad3e0 100644 --- a/apps/iam/go.sum +++ b/apps/iam/go.sum @@ -122,8 +122,8 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1/go.mod h1:8cl44BDmi+ github.com/Azure/azure-storage-blob-go v0.15.0 h1:rXtgp8tN1p29GvpGgfJetavIG0V7OgcSXPpwp3tx6qk= github.com/Azure/azure-storage-blob-go v0.15.0/go.mod h1:vbjsVbX0dlxnRc4FFMPsS9BsJWPcne7GB7onqlPvz58= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -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/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= @@ -186,8 +186,8 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= -github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= +github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= github.com/RoaringBitmap/roaring v1.9.3 h1:t4EbC5qQwnisr5PrP9nt0IRhRTb9gMUgQF4t4S2OByM= github.com/RoaringBitmap/roaring v1.9.3/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90= github.com/RoaringBitmap/roaring/v2 v2.4.5 h1:uGrrMreGjvAtTBobc0g5IrW1D5ldxDQYe2JW2gggRdg= @@ -871,10 +871,10 @@ github.com/grafana/grafana/apps/example v0.0.0-20251027162426-edef69fdc82b h1:6B github.com/grafana/grafana/apps/example v0.0.0-20251027162426-edef69fdc82b/go.mod h1:6+wASOCN8LWt6FJ8dc0oODUBIEY5XHaE6ABi8g0mR+k= github.com/grafana/grafana/apps/quotas v0.0.0-20251209183543-1013d74f13f2 h1:rDPMdshj3QMvpXn+wK4T8awF9n2sd8i4YRiGqX2xTvg= github.com/grafana/grafana/apps/quotas v0.0.0-20251209183543-1013d74f13f2/go.mod h1:M7bV60iRB61y0ISPG1HX/oNLZtlh0ZF22rUYwNkAKjo= +github.com/grafana/grafana/pkg/plugins v0.0.0-20260113153209-1d3f09d5193a h1:UmIA+Amg0Kgm56vSyqCUQQ5MBD4svQ+smCzIbAXYzyo= +github.com/grafana/grafana/pkg/plugins v0.0.0-20260113153209-1d3f09d5193a/go.mod h1:b9WxBFbMdf6pDxy90WRFHMyBl1/o8xY86SqnLLLN/yQ= github.com/grafana/grafana/pkg/promlib v0.0.8 h1:VUWsqttdf0wMI4j9OX9oNrykguQpZcruudDAFpJJVw0= github.com/grafana/grafana/pkg/promlib v0.0.8/go.mod h1:U1ezG/MGaEPoThqsr3lymMPN5yIPdVTJnDZ+wcXT+ao= -github.com/grafana/grafana/pkg/semconv v0.0.0-20250804150913-990f1c69ecc2 h1:A65jWgLk4Re28gIuZcpC0aTh71JZ0ey89hKGE9h543s= -github.com/grafana/grafana/pkg/semconv v0.0.0-20250804150913-990f1c69ecc2/go.mod h1:2HRzUK/xQEYc+8d5If/XSusMcaYq9IptnBSHACiQcOQ= github.com/grafana/jsonparser v0.0.0-20240425183733-ea80629e1a32 h1:NznuPwItog+rwdVg8hAuGKP29ndRSzJAwhxKldkP8oQ= github.com/grafana/jsonparser v0.0.0-20240425183733-ea80629e1a32/go.mod h1:796sq+UcONnSlzA3RtlBZ+b/hrerkZXiEmO8oMjyRwY= github.com/grafana/loki/pkg/push v0.0.0-20250823105456-332df2b20000 h1:/5LKSYgLmAhwA4m6iGUD4w1YkydEWWjazn9qxCFT8W0= diff --git a/apps/iam/kinds/teambinding.cue b/apps/iam/kinds/teambinding.cue index 60870b58853..f2027e7cb26 100644 --- a/apps/iam/kinds/teambinding.cue +++ b/apps/iam/kinds/teambinding.cue @@ -17,4 +17,8 @@ teambindingv0alpha1: teambindingKind & { schema: { spec: v0alpha1.TeamBindingSpec } + SelectableFields: [ + "spec.teamRef.name", + "spec.subject.name", + ], } diff --git a/apps/iam/pkg/apis/iam/v0alpha1/register.go b/apps/iam/pkg/apis/iam/v0alpha1/register.go index 05dbc30e684..f024c611f73 100644 --- a/apps/iam/pkg/apis/iam/v0alpha1/register.go +++ b/apps/iam/pkg/apis/iam/v0alpha1/register.go @@ -334,6 +334,22 @@ func AddAuthNKnownTypes(scheme *runtime.Scheme) error { &metav1.PartialObjectMetadata{}, &metav1.PartialObjectMetadataList{}, ) + + // Enable field selectors for TeamBinding + err := scheme.AddFieldLabelConversionFunc( + TeamBindingResourceInfo.GroupVersionKind(), + func(label, value string) (string, string, error) { + switch label { + case "metadata.name", "metadata.namespace", "spec.teamRef.name", "spec.subject.name": + return label, value, nil + default: + return "", "", fmt.Errorf("field label not supported for TeamBinding: %s", label) + } + }, + ) + if err != nil { + return err + } return nil } diff --git a/apps/iam/pkg/apis/iam/v0alpha1/teambinding_schema_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_schema_gen.go index d089b966e9b..4fcbd298be3 100644 --- a/apps/iam/pkg/apis/iam/v0alpha1/teambinding_schema_gen.go +++ b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_schema_gen.go @@ -5,13 +5,37 @@ package v0alpha1 import ( + "errors" + "github.com/grafana/grafana-app-sdk/resource" ) // schema is unexported to prevent accidental overwrites var ( schemaTeamBinding = resource.NewSimpleSchema("iam.grafana.app", "v0alpha1", NewTeamBinding(), &TeamBindingList{}, resource.WithKind("TeamBinding"), - resource.WithPlural("teambindings"), resource.WithScope(resource.NamespacedScope)) + resource.WithPlural("teambindings"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{resource.SelectableField{ + FieldSelector: "spec.teamRef.name", + FieldValueFunc: func(o resource.Object) (string, error) { + cast, ok := o.(*TeamBinding) + if !ok { + return "", errors.New("provided object must be of type *TeamBinding") + } + + return cast.Spec.TeamRef.Name, nil + }, + }, + resource.SelectableField{ + FieldSelector: "spec.subject.name", + FieldValueFunc: func(o resource.Object) (string, error) { + cast, ok := o.(*TeamBinding) + if !ok { + return "", errors.New("provided object must be of type *TeamBinding") + } + + return cast.Spec.Subject.Name, nil + }, + }, + })) kindTeamBinding = resource.Kind{ Schema: schemaTeamBinding, Codecs: map[resource.KindEncoding]resource.Codec{ diff --git a/apps/iam/pkg/apis/iam_manifest.go b/apps/iam/pkg/apis/iam_manifest.go index 664c12226de..e2e33bb6b61 100644 --- a/apps/iam/pkg/apis/iam_manifest.go +++ b/apps/iam/pkg/apis/iam_manifest.go @@ -147,6 +147,10 @@ var appManifestData = app.ManifestData{ Plural: "TeamBindings", Scope: "Namespaced", Conversion: false, + SelectableFields: []string{ + "spec.teamRef.name", + "spec.subject.name", + }, }, { diff --git a/pkg/registry/apis/iam/register.go b/pkg/registry/apis/iam/register.go index 7f42d620987..635fc831326 100644 --- a/pkg/registry/apis/iam/register.go +++ b/pkg/registry/apis/iam/register.go @@ -357,7 +357,9 @@ func (b *IdentityAccessManagementAPIBuilder) UpdateTeamsAPIGroup(opts builder.AP func (b *IdentityAccessManagementAPIBuilder) UpdateTeamBindingsAPIGroup(opts builder.APIGroupOptions, storage map[string]rest.Storage, enableZanzanaSync bool) error { teamBindingResource := iamv0.TeamBindingResourceInfo - teamBindingUniStore, err := grafanaregistry.NewRegistryStore(opts.Scheme, teamBindingResource, opts.OptsGetter) + teamBindingUniStore, err := grafanaregistry.NewRegistryStoreWithSelectableFields(opts.Scheme, teamBindingResource, opts.OptsGetter, grafanaregistry.SelectableFieldsOptions{ + GetAttrs: teambinding.GetAttrs, + }) if err != nil { return err } diff --git a/pkg/registry/apis/iam/teambinding/fields.go b/pkg/registry/apis/iam/teambinding/fields.go new file mode 100644 index 00000000000..90888971d3e --- /dev/null +++ b/pkg/registry/apis/iam/teambinding/fields.go @@ -0,0 +1,42 @@ +package teambinding + +import ( + "errors" + + genv0alpha1 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1" + iamv0alpha1 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/registry/generic" +) + +// GetTeamBindingSelectableFields returns a field set that can be used for field selectors. +func GetTeamBindingSelectableFields(obj *iamv0alpha1.TeamBinding) fields.Set { + objectMetaFields := generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true) + + // Using the generated schema to get selectable fields dynamically + schema := genv0alpha1.TeamBindingSchema() + specificFields := fields.Set{} + + for _, selectableField := range schema.SelectableFields() { + val, err := selectableField.FieldValueFunc(obj) + if err != nil { + val = "" + } + specificFields[selectableField.FieldSelector] = val + } + + return generic.MergeFieldsSets(objectMetaFields, specificFields) +} + +// GetAttrs returns labels and fields of a TeamBinding object. +// This is used by the storage layer for filtering. +func GetAttrs(o runtime.Object) (labels.Set, fields.Set, error) { + tb, ok := o.(*iamv0alpha1.TeamBinding) + if !ok { + return nil, nil, errors.New("provided object must be of type *TeamBinding") + } + + return labels.Set(tb.Labels), GetTeamBindingSelectableFields(tb), nil +}