IAM: Add teams/{id}/groups as a custom endpoint to Teams API (#114228)

* Add teams/{id}/groups as a custom endpoint

* TeamGroupsHandler OSS and Ent registration

* Update OpenAPI spec

* Add indexer tests for external group mapping

* Remove noopsearch

* Remove unnecessary interface declaration, fixes

* Chores

* fmt

* Rename constant

* Align the rest to the changes of main

* Update workspace

* Add missing file
This commit is contained in:
Misi
2025-11-25 14:19:57 +01:00
committed by GitHub
parent 9091ac6f5c
commit 93ec32dd6a
27 changed files with 732 additions and 79 deletions
+4 -4
View File
@@ -14,16 +14,12 @@ replace github.com/grafana/grafana/apps/provisioning => ../provisioning
replace github.com/grafana/grafana/apps/advisor => ../advisor
replace github.com/grafana/grafana/apps/annotation => ../annotation
replace github.com/grafana/grafana/apps/alerting/alertenrichment => ../alerting/alertenrichment
replace github.com/grafana/grafana/apps/alerting/notifications => ../alerting/notifications
replace github.com/grafana/grafana/apps/alerting/rules => ../alerting/rules
replace github.com/grafana/grafana/apps/collections => ../collections
replace github.com/grafana/grafana/apps/correlations => ../correlations
replace github.com/grafana/grafana/apps/investigations => ../investigations
@@ -46,6 +42,10 @@ replace github.com/grafana/grafana/pkg/apiserver => ../../pkg/apiserver
replace github.com/grafana/grafana/pkg/aggregator => ../../pkg/aggregator
replace github.com/grafana/grafana/apps/annotation => ../annotation
replace github.com/grafana/grafana/apps/collections => ../collections
replace github.com/prometheus/alertmanager => github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604
require (
+14
View File
@@ -18,4 +18,18 @@ teamv0alpha1: teamKind & {
schema: {
spec: v0alpha1.TeamSpec
}
routes: {
"/groups": {
"GET": {
response: {
#ExternalGroupMapping: {
name: string
externalGroup: string
}
items: [...#ExternalGroupMapping]
}
responseMetadata: objectMeta: false
}
}
}
}
@@ -321,6 +321,7 @@ func AddAuthNKnownTypes(scheme *runtime.Scheme) error {
&TeamBindingList{},
&ExternalGroupMapping{},
&ExternalGroupMappingList{},
&GetGroups{},
// For now these are registered in pkg/apis/iam/v0alpha1/register.go
// &UserTeamList{},
// &ServiceAccountTokenList{},
+24
View File
@@ -2,6 +2,9 @@ package v0alpha1
import (
"context"
"encoding/json"
"fmt"
"net/http"
"github.com/grafana/grafana-app-sdk/resource"
)
@@ -78,3 +81,24 @@ func (c *TeamClient) Patch(ctx context.Context, identifier resource.Identifier,
func (c *TeamClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error {
return c.client.Delete(ctx, identifier, opts)
}
type GetGroupsRequest struct {
Headers http.Header
}
func (c *TeamClient) GetGroups(ctx context.Context, identifier resource.Identifier, request GetGroupsRequest) (*GetGroups, error) {
resp, err := c.client.SubresourceRequest(ctx, identifier, resource.CustomRouteRequestOptions{
Path: "/groups",
Verb: "GET",
Headers: request.Headers,
})
if err != nil {
return nil, err
}
cast := GetGroups{}
err = json.Unmarshal(resp, &cast)
if err != nil {
return nil, fmt.Errorf("unable to unmarshal response bytes into GetGroups: %w", err)
}
return &cast, nil
}
@@ -0,0 +1,26 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
// +k8s:openapi-gen=true
type VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping struct {
Name string `json:"name"`
ExternalGroup string `json:"externalGroup"`
}
// NewVersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping creates a new VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping object.
func NewVersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping() *VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping {
return &VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping{}
}
// +k8s:openapi-gen=true
type GetGroupsBody struct {
Items []VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping `json:"items"`
}
// NewGetGroupsBody creates a new GetGroupsBody object.
func NewGetGroupsBody() *GetGroupsBody {
return &GetGroupsBody{
Items: []VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping{},
}
}
@@ -0,0 +1,37 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
import (
"github.com/grafana/grafana-app-sdk/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
// +k8s:openapi-gen=true
type GetGroups struct {
metav1.TypeMeta `json:",inline"`
GetGroupsBody `json:",inline"`
}
func NewGetGroups() *GetGroups {
return &GetGroups{}
}
func (t *GetGroupsBody) DeepCopyInto(dst *GetGroupsBody) {
_ = resource.CopyObjectInto(dst, t)
}
func (o *GetGroups) DeepCopyObject() runtime.Object {
dst := NewGetGroups()
o.DeepCopyInto(dst)
return dst
}
func (o *GetGroups) DeepCopyInto(dst *GetGroups) {
dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
dst.TypeMeta.Kind = o.TypeMeta.Kind
o.GetGroupsBody.DeepCopyInto(&dst.GetGroupsBody)
}
var _ runtime.Object = NewGetGroups()
+165 -65
View File
@@ -12,71 +12,74 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.CoreRole": schema_pkg_apis_iam_v0alpha1_CoreRole(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.CoreRoleList": schema_pkg_apis_iam_v0alpha1_CoreRoleList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.CoreRoleSpec": schema_pkg_apis_iam_v0alpha1_CoreRoleSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.CoreRoleStatus": schema_pkg_apis_iam_v0alpha1_CoreRoleStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.CoreRolespecPermission": schema_pkg_apis_iam_v0alpha1_CoreRolespecPermission(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.CoreRolestatusOperatorState": schema_pkg_apis_iam_v0alpha1_CoreRolestatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ExternalGroupMapping": schema_pkg_apis_iam_v0alpha1_ExternalGroupMapping(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ExternalGroupMappingList": schema_pkg_apis_iam_v0alpha1_ExternalGroupMappingList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ExternalGroupMappingSpec": schema_pkg_apis_iam_v0alpha1_ExternalGroupMappingSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ExternalGroupMappingTeamRef": schema_pkg_apis_iam_v0alpha1_ExternalGroupMappingTeamRef(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRole": schema_pkg_apis_iam_v0alpha1_GlobalRole(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBinding": schema_pkg_apis_iam_v0alpha1_GlobalRoleBinding(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBindingList": schema_pkg_apis_iam_v0alpha1_GlobalRoleBindingList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBindingSpec": schema_pkg_apis_iam_v0alpha1_GlobalRoleBindingSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBindingStatus": schema_pkg_apis_iam_v0alpha1_GlobalRoleBindingStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBindingspecRoleRef": schema_pkg_apis_iam_v0alpha1_GlobalRoleBindingspecRoleRef(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBindingspecSubject": schema_pkg_apis_iam_v0alpha1_GlobalRoleBindingspecSubject(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBindingstatusOperatorState": schema_pkg_apis_iam_v0alpha1_GlobalRoleBindingstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleList": schema_pkg_apis_iam_v0alpha1_GlobalRoleList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleSpec": schema_pkg_apis_iam_v0alpha1_GlobalRoleSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleStatus": schema_pkg_apis_iam_v0alpha1_GlobalRoleStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRolespecPermission": schema_pkg_apis_iam_v0alpha1_GlobalRolespecPermission(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRolestatusOperatorState": schema_pkg_apis_iam_v0alpha1_GlobalRolestatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ResourcePermission": schema_pkg_apis_iam_v0alpha1_ResourcePermission(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ResourcePermissionList": schema_pkg_apis_iam_v0alpha1_ResourcePermissionList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ResourcePermissionSpec": schema_pkg_apis_iam_v0alpha1_ResourcePermissionSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ResourcePermissionStatus": schema_pkg_apis_iam_v0alpha1_ResourcePermissionStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ResourcePermissionspecPermission": schema_pkg_apis_iam_v0alpha1_ResourcePermissionspecPermission(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ResourcePermissionspecResource": schema_pkg_apis_iam_v0alpha1_ResourcePermissionspecResource(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ResourcePermissionstatusOperatorState": schema_pkg_apis_iam_v0alpha1_ResourcePermissionstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.Role": schema_pkg_apis_iam_v0alpha1_Role(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleBinding": schema_pkg_apis_iam_v0alpha1_RoleBinding(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleBindingList": schema_pkg_apis_iam_v0alpha1_RoleBindingList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleBindingSpec": schema_pkg_apis_iam_v0alpha1_RoleBindingSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleBindingStatus": schema_pkg_apis_iam_v0alpha1_RoleBindingStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleBindingspecRoleRef": schema_pkg_apis_iam_v0alpha1_RoleBindingspecRoleRef(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleBindingspecSubject": schema_pkg_apis_iam_v0alpha1_RoleBindingspecSubject(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleBindingstatusOperatorState": schema_pkg_apis_iam_v0alpha1_RoleBindingstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleList": schema_pkg_apis_iam_v0alpha1_RoleList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleSpec": schema_pkg_apis_iam_v0alpha1_RoleSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleStatus": schema_pkg_apis_iam_v0alpha1_RoleStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RolespecPermission": schema_pkg_apis_iam_v0alpha1_RolespecPermission(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RolestatusOperatorState": schema_pkg_apis_iam_v0alpha1_RolestatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccount": schema_pkg_apis_iam_v0alpha1_ServiceAccount(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountList": schema_pkg_apis_iam_v0alpha1_ServiceAccountList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountSpec": schema_pkg_apis_iam_v0alpha1_ServiceAccountSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountStatus": schema_pkg_apis_iam_v0alpha1_ServiceAccountStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountstatusOperatorState": schema_pkg_apis_iam_v0alpha1_ServiceAccountstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.Team": schema_pkg_apis_iam_v0alpha1_Team(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBinding": schema_pkg_apis_iam_v0alpha1_TeamBinding(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingList": schema_pkg_apis_iam_v0alpha1_TeamBindingList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingSpec": schema_pkg_apis_iam_v0alpha1_TeamBindingSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingStatus": schema_pkg_apis_iam_v0alpha1_TeamBindingStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingTeamRef": schema_pkg_apis_iam_v0alpha1_TeamBindingTeamRef(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingspecSubject": schema_pkg_apis_iam_v0alpha1_TeamBindingspecSubject(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingstatusOperatorState": schema_pkg_apis_iam_v0alpha1_TeamBindingstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamList": schema_pkg_apis_iam_v0alpha1_TeamList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamSpec": schema_pkg_apis_iam_v0alpha1_TeamSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamStatus": schema_pkg_apis_iam_v0alpha1_TeamStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamstatusOperatorState": schema_pkg_apis_iam_v0alpha1_TeamstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.User": schema_pkg_apis_iam_v0alpha1_User(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserList": schema_pkg_apis_iam_v0alpha1_UserList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserSpec": schema_pkg_apis_iam_v0alpha1_UserSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserStatus": schema_pkg_apis_iam_v0alpha1_UserStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserstatusOperatorState": schema_pkg_apis_iam_v0alpha1_UserstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.CoreRole": schema_pkg_apis_iam_v0alpha1_CoreRole(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.CoreRoleList": schema_pkg_apis_iam_v0alpha1_CoreRoleList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.CoreRoleSpec": schema_pkg_apis_iam_v0alpha1_CoreRoleSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.CoreRoleStatus": schema_pkg_apis_iam_v0alpha1_CoreRoleStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.CoreRolespecPermission": schema_pkg_apis_iam_v0alpha1_CoreRolespecPermission(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.CoreRolestatusOperatorState": schema_pkg_apis_iam_v0alpha1_CoreRolestatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ExternalGroupMapping": schema_pkg_apis_iam_v0alpha1_ExternalGroupMapping(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ExternalGroupMappingList": schema_pkg_apis_iam_v0alpha1_ExternalGroupMappingList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ExternalGroupMappingSpec": schema_pkg_apis_iam_v0alpha1_ExternalGroupMappingSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ExternalGroupMappingTeamRef": schema_pkg_apis_iam_v0alpha1_ExternalGroupMappingTeamRef(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GetGroups": schema_pkg_apis_iam_v0alpha1_GetGroups(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GetGroupsBody": schema_pkg_apis_iam_v0alpha1_GetGroupsBody(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRole": schema_pkg_apis_iam_v0alpha1_GlobalRole(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBinding": schema_pkg_apis_iam_v0alpha1_GlobalRoleBinding(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBindingList": schema_pkg_apis_iam_v0alpha1_GlobalRoleBindingList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBindingSpec": schema_pkg_apis_iam_v0alpha1_GlobalRoleBindingSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBindingStatus": schema_pkg_apis_iam_v0alpha1_GlobalRoleBindingStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBindingspecRoleRef": schema_pkg_apis_iam_v0alpha1_GlobalRoleBindingspecRoleRef(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBindingspecSubject": schema_pkg_apis_iam_v0alpha1_GlobalRoleBindingspecSubject(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBindingstatusOperatorState": schema_pkg_apis_iam_v0alpha1_GlobalRoleBindingstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleList": schema_pkg_apis_iam_v0alpha1_GlobalRoleList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleSpec": schema_pkg_apis_iam_v0alpha1_GlobalRoleSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleStatus": schema_pkg_apis_iam_v0alpha1_GlobalRoleStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRolespecPermission": schema_pkg_apis_iam_v0alpha1_GlobalRolespecPermission(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRolestatusOperatorState": schema_pkg_apis_iam_v0alpha1_GlobalRolestatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ResourcePermission": schema_pkg_apis_iam_v0alpha1_ResourcePermission(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ResourcePermissionList": schema_pkg_apis_iam_v0alpha1_ResourcePermissionList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ResourcePermissionSpec": schema_pkg_apis_iam_v0alpha1_ResourcePermissionSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ResourcePermissionStatus": schema_pkg_apis_iam_v0alpha1_ResourcePermissionStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ResourcePermissionspecPermission": schema_pkg_apis_iam_v0alpha1_ResourcePermissionspecPermission(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ResourcePermissionspecResource": schema_pkg_apis_iam_v0alpha1_ResourcePermissionspecResource(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ResourcePermissionstatusOperatorState": schema_pkg_apis_iam_v0alpha1_ResourcePermissionstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.Role": schema_pkg_apis_iam_v0alpha1_Role(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleBinding": schema_pkg_apis_iam_v0alpha1_RoleBinding(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleBindingList": schema_pkg_apis_iam_v0alpha1_RoleBindingList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleBindingSpec": schema_pkg_apis_iam_v0alpha1_RoleBindingSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleBindingStatus": schema_pkg_apis_iam_v0alpha1_RoleBindingStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleBindingspecRoleRef": schema_pkg_apis_iam_v0alpha1_RoleBindingspecRoleRef(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleBindingspecSubject": schema_pkg_apis_iam_v0alpha1_RoleBindingspecSubject(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleBindingstatusOperatorState": schema_pkg_apis_iam_v0alpha1_RoleBindingstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleList": schema_pkg_apis_iam_v0alpha1_RoleList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleSpec": schema_pkg_apis_iam_v0alpha1_RoleSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleStatus": schema_pkg_apis_iam_v0alpha1_RoleStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RolespecPermission": schema_pkg_apis_iam_v0alpha1_RolespecPermission(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RolestatusOperatorState": schema_pkg_apis_iam_v0alpha1_RolestatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccount": schema_pkg_apis_iam_v0alpha1_ServiceAccount(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountList": schema_pkg_apis_iam_v0alpha1_ServiceAccountList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountSpec": schema_pkg_apis_iam_v0alpha1_ServiceAccountSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountStatus": schema_pkg_apis_iam_v0alpha1_ServiceAccountStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountstatusOperatorState": schema_pkg_apis_iam_v0alpha1_ServiceAccountstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.Team": schema_pkg_apis_iam_v0alpha1_Team(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBinding": schema_pkg_apis_iam_v0alpha1_TeamBinding(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingList": schema_pkg_apis_iam_v0alpha1_TeamBindingList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingSpec": schema_pkg_apis_iam_v0alpha1_TeamBindingSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingStatus": schema_pkg_apis_iam_v0alpha1_TeamBindingStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingTeamRef": schema_pkg_apis_iam_v0alpha1_TeamBindingTeamRef(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingspecSubject": schema_pkg_apis_iam_v0alpha1_TeamBindingspecSubject(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingstatusOperatorState": schema_pkg_apis_iam_v0alpha1_TeamBindingstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamList": schema_pkg_apis_iam_v0alpha1_TeamList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamSpec": schema_pkg_apis_iam_v0alpha1_TeamSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamStatus": schema_pkg_apis_iam_v0alpha1_TeamStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamstatusOperatorState": schema_pkg_apis_iam_v0alpha1_TeamstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.User": schema_pkg_apis_iam_v0alpha1_User(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserList": schema_pkg_apis_iam_v0alpha1_UserList(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserSpec": schema_pkg_apis_iam_v0alpha1_UserSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserStatus": schema_pkg_apis_iam_v0alpha1_UserStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserstatusOperatorState": schema_pkg_apis_iam_v0alpha1_UserstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping": schema_pkg_apis_iam_v0alpha1_VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping(ref),
}
}
@@ -491,6 +494,76 @@ func schema_pkg_apis_iam_v0alpha1_ExternalGroupMappingTeamRef(ref common.Referen
}
}
func schema_pkg_apis_iam_v0alpha1_GetGroups(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
"items": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping"),
},
},
},
},
},
},
Required: []string{"items"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping"},
}
}
func schema_pkg_apis_iam_v0alpha1_GetGroupsBody(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"items": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping"),
},
},
},
},
},
},
Required: []string{"items"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping"},
}
}
func schema_pkg_apis_iam_v0alpha1_GlobalRole(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -2856,3 +2929,30 @@ func schema_pkg_apis_iam_v0alpha1_UserstatusOperatorState(ref common.ReferenceCa
},
}
}
func schema_pkg_apis_iam_v0alpha1_VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"name": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"externalGroup": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"name", "externalGroup"},
},
},
}
}
+55 -1
View File
@@ -81,6 +81,58 @@ var appManifestData = app.ManifestData{
Plural: "Teams",
Scope: "Namespaced",
Conversion: false,
Routes: map[string]spec3.PathProps{
"/groups": {
Get: &spec3.Operation{
OperationProps: spec3.OperationProps{
OperationId: "getGroups",
Responses: &spec3.Responses{
ResponsesProps: spec3.ResponsesProps{
Default: &spec3.Response{
ResponseProps: spec3.ResponseProps{
Description: "Default OK response",
Content: map[string]*spec3.MediaType{
"application/json": {
MediaTypeProps: spec3.MediaTypeProps{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"apiVersion": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
},
},
"items": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
},
},
"kind": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
},
},
},
Required: []string{
"items",
"apiVersion",
"kind",
},
}},
}},
},
},
},
}},
},
},
},
},
},
{
@@ -142,7 +194,9 @@ func ManifestGoTypeAssociator(kind, version string) (goType resource.Kind, exist
return goType, exists
}
var customRouteToGoResponseType = map[string]any{}
var customRouteToGoResponseType = map[string]any{
"v0alpha1|Team|groups|GET": v0alpha1.GetGroups{},
}
// ManifestCustomRouteResponsesAssociator returns the associated response go type for a given kind, version, custom route path, and method, if one exists.
// kind may be empty for custom routes which are not kind subroutes. Leading slashes are removed from subroute paths.
@@ -561,6 +561,10 @@ const injectedRtkApi = api
}),
invalidatesTags: ['Team'],
}),
getTeamGroups: build.query<GetTeamGroupsApiResponse, GetTeamGroupsApiArg>({
query: (queryArg) => ({ url: `/teams/${queryArg.name}/groups` }),
providesTags: ['Team'],
}),
getTeamMembers: build.query<GetTeamMembersApiResponse, GetTeamMembersApiArg>({
query: (queryArg) => ({ url: `/teams/${queryArg.name}/members` }),
providesTags: ['Team'],
@@ -1461,6 +1465,11 @@ export type UpdateTeamApiArg = {
force?: boolean;
patch: Patch;
};
export type GetTeamGroupsApiResponse = /** status 200 OK */ GetGroups;
export type GetTeamGroupsApiArg = {
/** name of the GetGroups */
name: string;
};
export type GetTeamMembersApiResponse = /** status 200 OK */ TeamMemberList;
export type GetTeamMembersApiArg = {
/** name of the TeamMemberList */
@@ -1978,6 +1987,17 @@ export type TeamList = {
kind?: string;
metadata: ListMeta;
};
export type VersionsV0Alpha1Kinds7RoutesGroupsGetResponseExternalGroupMapping = {
externalGroup: string;
name: string;
};
export type GetGroups = {
/** APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources */
apiVersion?: string;
items: VersionsV0Alpha1Kinds7RoutesGroupsGetResponseExternalGroupMapping[];
/** Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds */
kind?: string;
};
export type TeamMember = {
/** AvatarURL is the url where we can get the avatar for identity */
avatarURL?: string;
@@ -2100,6 +2120,8 @@ export const {
useReplaceTeamMutation,
useDeleteTeamMutation,
useUpdateTeamMutation,
useGetTeamGroupsQuery,
useLazyGetTeamGroupsQuery,
useGetTeamMembersQuery,
useLazyGetTeamMembersQuery,
useListUserQuery,
@@ -6039,6 +6039,7 @@ export type TeamGroupDto = {
groupId?: string;
orgId?: number;
teamId?: number;
uid?: string;
};
export type TeamGroupMapping = {
groupId?: string;
@@ -0,0 +1,10 @@
package externalgroupmapping
import "k8s.io/apiserver/pkg/registry/rest"
type TeamGroupsHandler interface {
rest.Storage
rest.Scoper
rest.StorageMetadata
rest.Connecter
}
@@ -0,0 +1,58 @@
package externalgroupmapping
import (
"context"
"net/http"
iamv0alpha1 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest"
)
var _ TeamGroupsHandler = (*NoopTeamGroupsREST)(nil)
type NoopTeamGroupsREST struct{}
func ProvideNoopTeamGroupsREST() *NoopTeamGroupsREST {
return &NoopTeamGroupsREST{}
}
// Connect implements rest.Connecter.
func (n *NoopTeamGroupsREST) Connect(ctx context.Context, id string, options runtime.Object, r rest.Responder) (http.Handler, error) {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Error(w, "functionality not available", http.StatusForbidden)
}), nil
}
// New implements rest.Storage.
func (s *NoopTeamGroupsREST) New() runtime.Object {
return iamv0alpha1.NewGetGroups()
}
// Destroy implements rest.Storage.
func (s *NoopTeamGroupsREST) Destroy() {}
// NamespaceScoped implements rest.Scoper.
func (s *NoopTeamGroupsREST) NamespaceScoped() bool {
return true
}
// ProducesMIMETypes implements rest.StorageMetadata.
func (s *NoopTeamGroupsREST) ProducesMIMETypes(verb string) []string {
return []string{"application/json"}
}
// ProducesObject implements rest.StorageMetadata.
func (s *NoopTeamGroupsREST) ProducesObject(verb string) interface{} {
return s.New()
}
// NewConnectOptions implements rest.Connecter.
func (s *NoopTeamGroupsREST) NewConnectOptions() (runtime.Object, bool, string) {
return nil, false, ""
}
// ConnectMethods implements rest.Connecter.
func (s *NoopTeamGroupsREST) ConnectMethods() []string {
return []string{http.MethodGet}
}
+3
View File
@@ -7,6 +7,7 @@ import (
"github.com/grafana/authlib/types"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/registry/apis/iam/externalgroupmapping"
"github.com/grafana/grafana/pkg/registry/apis/iam/legacy"
"github.com/grafana/grafana/pkg/registry/apis/iam/serviceaccount"
"github.com/grafana/grafana/pkg/registry/apis/iam/sso"
@@ -80,6 +81,8 @@ type IdentityAccessManagementAPIBuilder struct {
unified resource.ResourceClient
userSearchClient resourcepb.ResourceIndexClient
teamGroupsHandler externalgroupmapping.TeamGroupsHandler
// non-k8s api route
display *user.LegacyDisplayREST
+5 -1
View File
@@ -65,6 +65,7 @@ func RegisterAPIService(
rolesStorage RoleStorageBackend,
roleBindingsStorage RoleBindingStorageBackend,
externalGroupMappingStorageBackend ExternalGroupMappingStorageBackend,
teamGroupsHandlerImpl externalgroupmapping.TeamGroupsHandler,
dual dualwrite.Service,
unified resource.ResourceClient,
userService legacyuser.Service,
@@ -90,6 +91,7 @@ func RegisterAPIService(
resourcePermissionsStorage: resourcepermission.ProvideStorageBackend(dbProvider),
roleBindingsStorage: roleBindingsStorage,
externalGroupMappingStorage: externalGroupMappingStorageBackend,
teamGroupsHandler: teamGroupsHandlerImpl,
sso: ssoService,
authorizer: authorizer,
legacyAccessClient: legacyAccessClient,
@@ -102,7 +104,8 @@ func RegisterAPIService(
features: features,
dual: dual,
unified: unified,
userSearchClient: resource.NewSearchClient(dualwrite.NewSearchAdapter(dual), iamv0.UserResourceInfo.GroupResource(), unified, user.NewUserLegacySearchClient(userService), features),
userSearchClient: resource.NewSearchClient(dualwrite.NewSearchAdapter(dual), iamv0.UserResourceInfo.GroupResource(),
unified, user.NewUserLegacySearchClient(userService), features),
}
apiregistration.RegisterAPI(builder)
@@ -216,6 +219,7 @@ func (b *IdentityAccessManagementAPIBuilder) UpdateAPIGroupInfo(apiGroupInfo *ge
}
storage[teamResource.StoragePath("members")] = team.NewLegacyTeamMemberREST(b.store)
storage[teamResource.StoragePath("groups")] = b.teamGroupsHandler
teamBindingResource := iamv0.TeamBindingResourceInfo
teamBindingUniStore, err := grafanaregistry.NewRegistryStore(opts.Scheme, teamBindingResource, opts.OptsGetter)
+4 -2
View File
@@ -20,6 +20,8 @@ const (
UserResourceGroup = "iam.grafana.com"
)
var _ resourcepb.ResourceIndexClient = (*UserLegacySearchClient)(nil)
// UserLegacySearchClient is a client for searching for users in the legacy search engine.
type UserLegacySearchClient struct {
resourcepb.ResourceIndexClient
@@ -129,9 +131,9 @@ func getColumns(fields []string) []*resourcepb.ResourceTableColumnDefinition {
for _, field := range fields {
switch field {
case "email":
columns = append(columns, builders.TableColumnDefinitions[builders.USER_EMAIL])
columns = append(columns, builders.UserTableColumnDefinitions[builders.USER_EMAIL])
case "login":
columns = append(columns, builders.TableColumnDefinitions[builders.USER_LOGIN])
columns = append(columns, builders.UserTableColumnDefinitions[builders.USER_LOGIN])
}
}
return columns
+4
View File
@@ -9,6 +9,7 @@ import (
"github.com/grafana/grafana/pkg/registry/apis/datasource"
"github.com/grafana/grafana/pkg/registry/apis/folders"
"github.com/grafana/grafana/pkg/registry/apis/iam"
"github.com/grafana/grafana/pkg/registry/apis/iam/externalgroupmapping"
"github.com/grafana/grafana/pkg/registry/apis/iam/noopstorage"
"github.com/grafana/grafana/pkg/registry/apis/ofrep"
"github.com/grafana/grafana/pkg/registry/apis/preferences"
@@ -30,6 +31,9 @@ var WireSetExts = wire.NewSet(
wire.Bind(new(iam.RoleStorageBackend), new(*noopstorage.StorageBackendImpl)),
wire.Bind(new(iam.RoleBindingStorageBackend), new(*noopstorage.StorageBackendImpl)),
wire.Bind(new(iam.ExternalGroupMappingStorageBackend), new(*noopstorage.StorageBackendImpl)),
externalgroupmapping.ProvideNoopTeamGroupsREST,
wire.Bind(new(externalgroupmapping.TeamGroupsHandler), new(*externalgroupmapping.NoopTeamGroupsREST)),
)
var provisioningExtras = wire.NewSet(
+5 -2
View File
@@ -55,6 +55,7 @@ import (
"github.com/grafana/grafana/pkg/registry/apis/datasource"
"github.com/grafana/grafana/pkg/registry/apis/folders"
"github.com/grafana/grafana/pkg/registry/apis/iam"
"github.com/grafana/grafana/pkg/registry/apis/iam/externalgroupmapping"
"github.com/grafana/grafana/pkg/registry/apis/iam/noopstorage"
"github.com/grafana/grafana/pkg/registry/apis/ofrep"
"github.com/grafana/grafana/pkg/registry/apis/preferences"
@@ -868,7 +869,8 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api
}
folderAPIBuilder := folders.RegisterAPIService(cfg, featureToggles, apiserverService, folderimplService, folderPermissionsService, accessControl, acimplService, accessClient, registerer, resourceClient, zanzanaClient)
storageBackendImpl := noopstorage.ProvideStorageBackend()
identityAccessManagementAPIBuilder, err := iam.RegisterAPIService(featureToggles, apiserverService, ssosettingsimplService, sqlStore, accessControl, accessClient, zanzanaClient, registerer, storageBackendImpl, storageBackendImpl, storageBackendImpl, storageBackendImpl, dualwriteService, resourceClient, userService)
noopTeamGroupsREST := externalgroupmapping.ProvideNoopTeamGroupsREST()
identityAccessManagementAPIBuilder, err := iam.RegisterAPIService(featureToggles, apiserverService, ssosettingsimplService, sqlStore, accessControl, accessClient, zanzanaClient, registerer, storageBackendImpl, storageBackendImpl, storageBackendImpl, storageBackendImpl, noopTeamGroupsREST, dualwriteService, resourceClient, userService)
if err != nil {
return nil, err
}
@@ -1517,7 +1519,8 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac
}
folderAPIBuilder := folders.RegisterAPIService(cfg, featureToggles, apiserverService, folderimplService, folderPermissionsService, accessControl, acimplService, accessClient, registerer, resourceClient, zanzanaClient)
storageBackendImpl := noopstorage.ProvideStorageBackend()
identityAccessManagementAPIBuilder, err := iam.RegisterAPIService(featureToggles, apiserverService, ssosettingsimplService, sqlStore, accessControl, accessClient, zanzanaClient, registerer, storageBackendImpl, storageBackendImpl, storageBackendImpl, storageBackendImpl, dualwriteService, resourceClient, userService)
noopTeamGroupsREST := externalgroupmapping.ProvideNoopTeamGroupsREST()
identityAccessManagementAPIBuilder, err := iam.RegisterAPIService(featureToggles, apiserverService, ssosettingsimplService, sqlStore, accessControl, accessClient, zanzanaClient, registerer, storageBackendImpl, storageBackendImpl, storageBackendImpl, storageBackendImpl, noopTeamGroupsREST, dualwriteService, resourceClient, userService)
if err != nil {
return nil, err
}
@@ -62,5 +62,10 @@ func All(sql db.DB, sprinkles DashboardStats) ([]resource.DocumentBuilderInfo, e
return nil, err
}
return []resource.DocumentBuilderInfo{dashboards, users}, nil
extGroupMappings, err := GetExternalGroupMappingBuilder()
if err != nil {
return nil, err
}
return []resource.DocumentBuilderInfo{dashboards, users, extGroupMappings}, nil
}
@@ -58,6 +58,18 @@ func TestUserDocumentBuilder(t *testing.T) {
})
}
func TestExternalGroupMappingDocumentBuilder(t *testing.T) {
info, err := GetExternalGroupMappingBuilder()
require.NoError(t, err)
doSnapshotTests(t, info.Builder, "external_group_mapping", &resourcepb.ResourceKey{
Namespace: "default",
Group: "iam.grafana.app",
Resource: "externalgroupmappings",
}, []string{
"mapping-with-team-and-group",
})
}
func TestDashboardDocumentBuilder(t *testing.T) {
key := &resourcepb.ResourceKey{
Namespace: "default",
@@ -0,0 +1,80 @@
package builders
import (
"bytes"
"context"
"encoding/json"
iamv0 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/grafana/grafana/pkg/storage/unified/resource"
"github.com/grafana/grafana/pkg/storage/unified/resourcepb"
)
const (
EXTERNAL_GROUP_MAPPING_TEAM = "team"
EXTERNAL_GROUP_MAPPING_EXTERNAL_GROUP = "external_group"
)
var ExternalGroupMappingTableColumnDefinitions = map[string]*resourcepb.ResourceTableColumnDefinition{
EXTERNAL_GROUP_MAPPING_TEAM: {
Name: EXTERNAL_GROUP_MAPPING_TEAM,
Type: resourcepb.ResourceTableColumnDefinition_STRING,
Description: "The team name associated with the external group mapping",
Properties: &resourcepb.ResourceTableColumnDefinition_Properties{
Filterable: true,
},
},
EXTERNAL_GROUP_MAPPING_EXTERNAL_GROUP: {
Name: EXTERNAL_GROUP_MAPPING_EXTERNAL_GROUP,
Type: resourcepb.ResourceTableColumnDefinition_STRING,
Description: "The external group name/id associated with the external group mapping",
Properties: &resourcepb.ResourceTableColumnDefinition_Properties{
Filterable: true,
},
},
}
func GetExternalGroupMappingBuilder() (resource.DocumentBuilderInfo, error) {
values := make([]*resourcepb.ResourceTableColumnDefinition, 0, len(ExternalGroupMappingTableColumnDefinitions))
for _, v := range ExternalGroupMappingTableColumnDefinitions {
values = append(values, v)
}
fields, err := resource.NewSearchableDocumentFields(values)
return resource.DocumentBuilderInfo{
GroupResource: iamv0.ExternalGroupMappingResourceInfo.GroupResource(),
Fields: fields,
Builder: new(extGroupMappingDocumentBuilder),
}, err
}
var _ resource.DocumentBuilder = new(extGroupMappingDocumentBuilder)
type extGroupMappingDocumentBuilder struct{}
// BuildDocument implements resource.DocumentBuilder.
func (u *extGroupMappingDocumentBuilder) BuildDocument(ctx context.Context, key *resourcepb.ResourceKey, rv int64, value []byte) (*resource.IndexableDocument, error) {
extGroupMapping := &iamv0.ExternalGroupMapping{}
err := json.NewDecoder(bytes.NewReader(value)).Decode(extGroupMapping)
if err != nil {
return nil, err
}
obj, err := utils.MetaAccessor(extGroupMapping)
if err != nil {
return nil, err
}
doc := resource.NewIndexableDocument(key, rv, obj)
doc.Fields = make(map[string]any)
if extGroupMapping.Spec.TeamRef.Name != "" {
doc.Fields[EXTERNAL_GROUP_MAPPING_TEAM] = extGroupMapping.Spec.TeamRef.Name
}
if extGroupMapping.Spec.ExternalGroupId != "" {
doc.Fields[EXTERNAL_GROUP_MAPPING_EXTERNAL_GROUP] = extGroupMapping.Spec.ExternalGroupId
}
return doc, nil
}
@@ -0,0 +1,17 @@
{
"key": {
"namespace": "default",
"group": "iam.grafana.app",
"resource": "externalgroupmappings",
"name": "mapping-with-team-and-group"
},
"name": "mapping-with-team-and-group",
"rv": 1234,
"fields": {
"team": "team1",
"external_group": "group1"
},
"title": "mapping-with-team-and-group",
"title_ngram": "mapping-with-team-and-group",
"title_phrase": "mapping-with-team-and-group"
}
@@ -0,0 +1,14 @@
{
"apiVersion": "iam.grafana.app/v0alpha1",
"kind": "ExternalGroupMapping",
"metadata": {
"name": "mapping-with-team-and-group",
"namespace": "default"
},
"spec": {
"teamRef": {
"name": "team1"
},
"externalGroupId": "group1"
}
}
+3 -3
View File
@@ -16,7 +16,7 @@ const (
USER_LOGIN = "login"
)
var TableColumnDefinitions = map[string]*resourcepb.ResourceTableColumnDefinition{
var UserTableColumnDefinitions = map[string]*resourcepb.ResourceTableColumnDefinition{
USER_EMAIL: {
Name: USER_EMAIL,
Type: resourcepb.ResourceTableColumnDefinition_STRING,
@@ -38,8 +38,8 @@ var TableColumnDefinitions = map[string]*resourcepb.ResourceTableColumnDefinitio
}
func GetUserBuilder() (resource.DocumentBuilderInfo, error) {
values := make([]*resourcepb.ResourceTableColumnDefinition, 0, len(TableColumnDefinitions))
for _, v := range TableColumnDefinitions {
values := make([]*resourcepb.ResourceTableColumnDefinition, 0, len(UserTableColumnDefinitions))
for _, v := range UserTableColumnDefinitions {
values = append(values, v)
}
fields, err := resource.NewSearchableDocumentFields(values)
@@ -4001,6 +4001,55 @@
}
]
},
"/apis/iam.grafana.app/v0alpha1/namespaces/{namespace}/teams/{name}/groups": {
"get": {
"tags": [
"Team"
],
"description": "connect GET requests to groups of Team",
"operationId": "getTeamGroups",
"responses": {
"200": {
"description": "OK",
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.GetGroups"
}
}
}
}
},
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "iam.grafana.app",
"version": "v0alpha1",
"kind": "GetGroups"
}
},
"parameters": [
{
"name": "name",
"in": "path",
"description": "name of the GetGroups",
"required": true,
"schema": {
"type": "string",
"uniqueItems": true
}
},
{
"name": "namespace",
"in": "path",
"description": "object name and auth scope, such as for teams and projects",
"required": true,
"schema": {
"type": "string",
"uniqueItems": true
}
}
]
},
"/apis/iam.grafana.app/v0alpha1/namespaces/{namespace}/teams/{name}/members": {
"get": {
"tags": [
@@ -5050,6 +5099,40 @@
}
}
},
"com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.GetGroups": {
"type": "object",
"required": [
"items"
],
"properties": {
"apiVersion": {
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
"type": "string"
},
"items": {
"type": "array",
"items": {
"default": {},
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping"
}
]
}
},
"kind": {
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
"type": "string"
}
},
"x-kubernetes-group-version-kind": [
{
"group": "iam.grafana.app",
"kind": "GetGroups",
"version": "v0alpha1"
}
]
},
"com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.ServiceAccount": {
"type": "object",
"required": [
@@ -5549,6 +5632,23 @@
}
}
},
"com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping": {
"type": "object",
"required": [
"name",
"externalGroup"
],
"properties": {
"externalGroup": {
"type": "string",
"default": ""
},
"name": {
"type": "string",
"default": ""
}
}
},
"com.github.grafana.grafana.pkg.apimachinery.apis.common.v0alpha1.Unstructured": {
"type": "object",
"additionalProperties": true,
@@ -6237,6 +6337,42 @@
}
}
},
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GetGroups": {
"type": "object",
"required": [
"items"
],
"properties": {
"apiVersion": {
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
"type": "string"
},
"items": {
"type": "array",
"items": {
"default": {}
}
},
"kind": {
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
"type": "string"
}
}
},
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GetGroupsBody": {
"type": "object",
"required": [
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"default": {}
}
}
}
},
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRole": {
"type": "object",
"required": [
@@ -7573,6 +7709,23 @@
}
}
},
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping": {
"type": "object",
"required": [
"name",
"externalGroup"
],
"properties": {
"externalGroup": {
"type": "string",
"default": ""
},
"name": {
"type": "string",
"default": ""
}
}
},
"io.k8s.apimachinery.pkg.apis.meta.v1.APIResource": {
"description": "APIResource specifies the name of a resource and whether it is namespaced.",
"type": "object",
+3
View File
@@ -7967,6 +7967,9 @@
"teamId": {
"type": "integer",
"format": "int64"
},
"uid": {
"type": "string"
}
}
},
+3
View File
@@ -22070,6 +22070,9 @@
"teamId": {
"type": "integer",
"format": "int64"
},
"uid": {
"type": "string"
}
}
},
+3
View File
@@ -11609,6 +11609,9 @@
"teamId": {
"format": "int64",
"type": "integer"
},
"uid": {
"type": "string"
}
},
"type": "object"