Schema: Covering service accounts Core Kind (#62091)

* Adding service accounts schema

Co-authored-by: Eric Leijonmarck <eric.leijonmarck@gmail.com>

* Change metadata field

Co-authored-by: Eric Leijonmarck <eric.leijonmarck@gmail.com>

* Merging the two DTOs into one schema

Co-authored-by: Eric Leijonmarck <eric.leijonmarck@gmail.com>

* Eric dedup things

Co-authored-by: Eric Leijonmarck <eric.leijonmarck@gmail.com>

* Add optional to teams/created/updated

Co-authored-by: Eric Leijonmarck <eric.leijonmarck@gmail.com>

* Lower case the OrgId

Co-authored-by: Eric Leijonmarck <eric.leijonmarck@gmail.com>

Co-authored-by: Eric Leijonmarck <eric.leijonmarck@gmail.com>
This commit is contained in:
Gabriel MABILLE
2023-01-25 18:07:00 +01:00
committed by GitHub
parent 3c073b00ec
commit f99523048a
9 changed files with 377 additions and 17 deletions

View File

@@ -0,0 +1,38 @@
---
keywords:
- grafana
- schema
title: Serviceaccount kind
---
> Both documentation generation and kinds schemas are in active development and subject to change without prior notice.
# Serviceaccount kind
## Maturity: merged
## Version: 0.0
## Properties
| Property | Type | Required | Description |
|-----------------|--------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------|
| `avatarUrl` | string | **Yes** | AvatarUrl is the service account's avatar URL. It allows the frontend to display a picture in front<br/>of the service account. |
| `id` | integer | **Yes** | ID is the unique identifier of the service account in the database. |
| `isDisabled` | boolean | **Yes** | IsDisabled indicates if the service account is disabled. |
| `login` | string | **Yes** | Login of the service account. |
| `name` | string | **Yes** | Name of the service account. |
| `orgId` | integer | **Yes** | OrgId is the ID of an organisation the service account belongs to. |
| `role` | string | **Yes** | OrgRole is a Grafana Organization Role which can be 'Viewer', 'Editor', 'Admin'. Possible values are: `Admin`, `Editor`, `Viewer`. |
| `tokens` | integer | **Yes** | Tokens is the number of active tokens for the service account.<br/>Tokens are used to authenticate the service account against Grafana. |
| `accessControl` | [object](#accesscontrol) | No | AccessControl metadata associated with a given resource. |
| `created` | integer | No | Created indicates when the service account was created. |
| `teams` | string[] | No | Teams is a list of teams the service account belongs to. |
| `updated` | integer | No | Updated indicates when the service account was updated. |
## accessControl
AccessControl metadata associated with a given resource.
| Property | Type | Required | Description |
|----------|------|----------|-------------|

View File

@@ -0,0 +1,46 @@
package kind
name: "Serviceaccount"
maturity: "merged"
lineage: seqs: [
{
schemas: [
// v0.0
{
// ID is the unique identifier of the service account in the database.
id: int64 @grafanamaturity(ToMetadata="sys")
// OrgId is the ID of an organisation the service account belongs to.
orgId: int64 @grafanamaturity(ToMetadata="sys")
// Name of the service account.
name: string
// Login of the service account.
login: string
// IsDisabled indicates if the service account is disabled.
isDisabled: bool
// Role is the Grafana organization role of the service account which can be 'Viewer', 'Editor', 'Admin'.
role: #OrgRole @grafanamaturity(ToMetadata="kind")
// Tokens is the number of active tokens for the service account.
// Tokens are used to authenticate the service account against Grafana.
tokens: int64 @grafanamaturity(ToMetadata="kind")
// AvatarUrl is the service account's avatar URL. It allows the frontend to display a picture in front
// of the service account.
avatarUrl: string @grafanamaturity(ToMetadata="kind")
// AccessControl metadata associated with a given resource.
accessControl?: {
[string]: bool @grafanamaturity(ToMetadata="sys")
}
// Teams is a list of teams the service account belongs to.
teams?: [...string] @grafanamaturity(ToMetadata="sys")
// Created indicates when the service account was created.
created?: int64 @grafanamaturity(ToMetadata="sys")
// Updated indicates when the service account was updated.
updated?: int64 @grafanamaturity(ToMetadata="sys")
// OrgRole is a Grafana Organization Role which can be 'Viewer', 'Editor', 'Admin'.
#OrgRole: "Admin" | "Editor" | "Viewer" @cuetsy(kind="type")
},
]
},
]

View File

@@ -95,6 +95,15 @@ export type {
// Raw generated enums and default consts from playlist kind.
export { defaultPlaylist } from './raw/playlist/x/playlist_types.gen';
// Raw generated types from Serviceaccount kind.
export type {
Serviceaccount,
OrgRole
} from './raw/serviceaccount/x/serviceaccount_types.gen';
// Raw generated enums and default consts from serviceaccount kind.
export { defaultServiceaccount } from './raw/serviceaccount/x/serviceaccount_types.gen';
// Raw generated types from Team kind.
export type { Team } from './raw/team/x/team_types.gen';

View File

@@ -0,0 +1,71 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
//
// Generated by:
// kinds/gen.go
// Using jennies:
// TSTypesJenny
// LatestMajorsOrXJenny
//
// Run 'make gen-cue' from repository root to regenerate.
/**
* OrgRole is a Grafana Organization Role which can be 'Viewer', 'Editor', 'Admin'.
*/
export type OrgRole = ('Admin' | 'Editor' | 'Viewer');
export interface Serviceaccount {
/**
* AccessControl metadata associated with a given resource.
*/
accessControl?: Record<string, boolean>;
/**
* AvatarUrl is the service account's avatar URL. It allows the frontend to display a picture in front
* of the service account.
*/
avatarUrl: string;
/**
* Created indicates when the service account was created.
*/
created?: number;
/**
* ID is the unique identifier of the service account in the database.
*/
id: number;
/**
* IsDisabled indicates if the service account is disabled.
*/
isDisabled: boolean;
/**
* Login of the service account.
*/
login: string;
/**
* Name of the service account.
*/
name: string;
/**
* OrgId is the ID of an organisation the service account belongs to.
*/
orgId: number;
/**
* Role is the Grafana organization role of the service account which can be 'Viewer', 'Editor', 'Admin'.
*/
role: OrgRole;
/**
* Teams is a list of teams the service account belongs to.
*/
teams?: Array<string>;
/**
* Tokens is the number of active tokens for the service account.
* Tokens are used to authenticate the service account against Grafana.
*/
tokens: number;
/**
* Updated indicates when the service account was updated.
*/
updated?: number;
}
export const defaultServiceaccount: Partial<Serviceaccount> = {
teams: [],
};

View File

@@ -0,0 +1,113 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
//
// Generated by:
// kinds/gen.go
// Using jennies:
// CoreKindJenny
//
// Run 'make gen-cue' from repository root to regenerate.
package serviceaccount
import (
"github.com/grafana/grafana/pkg/kindsys"
"github.com/grafana/thema"
"github.com/grafana/thema/vmux"
)
// rootrel is the relative path from the grafana repository root to the
// directory containing the .cue files in which this kind is declared. Necessary
// for runtime errors related to the declaration and/or lineage to provide
// a real path to the correct .cue file.
const rootrel string = "kinds/serviceaccount"
// TODO standard generated docs
type Kind struct {
lin thema.ConvergentLineage[*Serviceaccount]
jcodec vmux.Codec
valmux vmux.ValueMux[*Serviceaccount]
decl kindsys.Decl[kindsys.CoreProperties]
}
// type guard
var _ kindsys.Core = &Kind{}
// TODO standard generated docs
func NewKind(rt *thema.Runtime, opts ...thema.BindOption) (*Kind, error) {
decl, err := kindsys.LoadCoreKind(rootrel, rt.Context(), nil)
if err != nil {
return nil, err
}
k := &Kind{
decl: decl,
}
lin, err := decl.Some().BindKindLineage(rt, opts...)
if err != nil {
return nil, err
}
// Get the thema.Schema that the meta says is in the current version (which
// codegen ensures is always the latest)
cursch := thema.SchemaP(lin, k.decl.Properties.CurrentVersion)
tsch, err := thema.BindType[*Serviceaccount](cursch, &Serviceaccount{})
if err != nil {
// Should be unreachable, modulo bugs in the Thema->Go code generator
return nil, err
}
k.jcodec = vmux.NewJSONCodec("serviceaccount.json")
k.lin = tsch.ConvergentLineage()
k.valmux = vmux.NewValueMux(k.lin.TypedSchema(), k.jcodec)
return k, nil
}
// TODO standard generated docs
func (k *Kind) Name() string {
return "serviceaccount"
}
// TODO standard generated docs
func (k *Kind) MachineName() string {
return "serviceaccount"
}
// TODO standard generated docs
func (k *Kind) Lineage() thema.Lineage {
return k.lin
}
// TODO standard generated docs
func (k *Kind) ConvergentLineage() thema.ConvergentLineage[*Serviceaccount] {
return k.lin
}
// JSONValueMux is a version multiplexer that maps a []byte containing JSON data
// at any schematized dashboard version to an instance of Serviceaccount.
//
// Validation and translation errors emitted from this func will identify the
// input bytes as "dashboard.json".
//
// This is a thin wrapper around Thema's [vmux.ValueMux].
func (k *Kind) JSONValueMux(b []byte) (*Serviceaccount, thema.TranslationLacunas, error) {
return k.valmux(b)
}
// TODO standard generated docs
func (k *Kind) Maturity() kindsys.Maturity {
return k.decl.Properties.Maturity
}
// Decl returns the [kindsys.Decl] containing both CUE and Go representations of the
// serviceaccount declaration in .cue files.
func (k *Kind) Decl() kindsys.Decl[kindsys.CoreProperties] {
return k.decl
}
// Props returns a [kindsys.SomeKindProps], with underlying type [kindsys.CoreProperties],
// representing the static properties declared in the serviceaccount kind.
//
// This method is identical to calling Decl().Props. It is provided to satisfy [kindsys.Interface].
func (k *Kind) Props() kindsys.SomeKindProperties {
return k.decl.Properties
}

View File

@@ -0,0 +1,64 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
//
// Generated by:
// kinds/gen.go
// Using jennies:
// GoTypesJenny
// LatestJenny
//
// Run 'make gen-cue' from repository root to regenerate.
package serviceaccount
// Defines values for OrgRole.
const (
OrgRoleAdmin OrgRole = "Admin"
OrgRoleEditor OrgRole = "Editor"
OrgRoleViewer OrgRole = "Viewer"
)
// OrgRole is a Grafana Organization Role which can be 'Viewer', 'Editor', 'Admin'.
type OrgRole string
// Serviceaccount defines model for serviceaccount.
type Serviceaccount struct {
// AccessControl metadata associated with a given resource.
AccessControl map[string]bool `json:"accessControl,omitempty"`
// AvatarUrl is the service account's avatar URL. It allows the frontend to display a picture in front
// of the service account.
AvatarUrl string `json:"avatarUrl"`
// Created indicates when the service account was created.
Created *int64 `json:"created,omitempty"`
// ID is the unique identifier of the service account in the database.
Id int64 `json:"id"`
// IsDisabled indicates if the service account is disabled.
IsDisabled bool `json:"isDisabled"`
// Login of the service account.
Login string `json:"login"`
// Name of the service account.
Name string `json:"name"`
// OrgId is the ID of an organisation the service account belongs to.
OrgId int64 `json:"orgId"`
// OrgRole is a Grafana Organization Role which can be 'Viewer', 'Editor', 'Admin'.
Role OrgRole `json:"role"`
// Teams is a list of teams the service account belongs to.
Teams *[]string `json:"teams,omitempty"`
// Tokens is the number of active tokens for the service account.
// Tokens are used to authenticate the service account against Grafana.
Tokens int64 `json:"tokens"`
// Updated indicates when the service account was updated.
Updated *int64 `json:"updated,omitempty"`
}

View File

@@ -71,7 +71,7 @@ var plannedCoreKinds = []string{
"Folder",
"DataSource",
"APIKey",
"ServiceAccount",
"Serviceaccount",
"Thumb",
"Query",
"QueryHistory",

View File

@@ -1299,24 +1299,29 @@
},
"serviceaccount": {
"category": "core",
"codeowners": [],
"codeowners": [
"grafana/grafana-as-code",
"grafana/grafana-bi-squad",
"grafana/plugins-platform-frontend",
"grafana/user-essentials"
],
"currentVersion": [
0,
0
],
"grafanaMaturityCount": 0,
"grafanaMaturityCount": 9,
"lineageIsGroup": false,
"links": {
"docs": "n/a",
"go": "n/a",
"schema": "n/a",
"ts": "n/a"
"docs": "https://grafana.com/docs/grafana/next/developers/kinds/core/serviceaccount/schema-reference",
"go": "https://github.com/grafana/grafana/tree/main/pkg/kinds/serviceaccount",
"schema": "https://github.com/grafana/grafana/tree/main/kinds/serviceaccount/serviceaccount_kind.cue",
"ts": "https://github.com/grafana/grafana/tree/main/packages/grafana-schema/src/raw/serviceaccount/x/serviceaccount_types.gen.ts"
},
"machineName": "serviceaccount",
"maturity": "planned",
"name": "ServiceAccount",
"maturity": "merged",
"name": "Serviceaccount",
"pluralMachineName": "serviceaccounts",
"pluralName": "ServiceAccounts"
"pluralName": "Serviceaccounts"
},
"statpanelcfg": {
"category": "composable",
@@ -1772,9 +1777,10 @@
"items": [
"alertgroupspanelcfg",
"playlist",
"serviceaccount",
"team"
],
"count": 3
"count": 4
},
"planned": {
"name": "planned",
@@ -1826,7 +1832,6 @@
"prometheusdatasourcecfg",
"query",
"queryhistory",
"serviceaccount",
"tableoldpanelcfg",
"tempodataquery",
"tempodatasourcecfg",
@@ -1840,7 +1845,7 @@
"zipkindataquery",
"zipkindatasourcecfg"
],
"count": 60
"count": 59
},
"stable": {
"name": "stable",

View File

@@ -14,6 +14,7 @@ import (
"github.com/grafana/grafana/pkg/kinds/dashboard"
"github.com/grafana/grafana/pkg/kinds/playlist"
"github.com/grafana/grafana/pkg/kinds/serviceaccount"
"github.com/grafana/grafana/pkg/kinds/team"
"github.com/grafana/grafana/pkg/kindsys"
"github.com/grafana/thema"
@@ -30,16 +31,18 @@ import (
// Prefer All*() methods when performing operations generically across all kinds.
// For example, a validation HTTP middleware for any kind-schematized object type.
type Base struct {
all []kindsys.Core
dashboard *dashboard.Kind
playlist *playlist.Kind
team *team.Kind
all []kindsys.Core
dashboard *dashboard.Kind
playlist *playlist.Kind
serviceaccount *serviceaccount.Kind
team *team.Kind
}
// type guards
var (
_ kindsys.Core = &dashboard.Kind{}
_ kindsys.Core = &playlist.Kind{}
_ kindsys.Core = &serviceaccount.Kind{}
_ kindsys.Core = &team.Kind{}
)
@@ -53,6 +56,11 @@ func (b *Base) Playlist() *playlist.Kind {
return b.playlist
}
// Serviceaccount returns the [kindsys.Interface] implementation for the serviceaccount kind.
func (b *Base) Serviceaccount() *serviceaccount.Kind {
return b.serviceaccount
}
// Team returns the [kindsys.Interface] implementation for the team kind.
func (b *Base) Team() *team.Kind {
return b.team
@@ -74,6 +82,12 @@ func doNewBase(rt *thema.Runtime) *Base {
}
reg.all = append(reg.all, reg.playlist)
reg.serviceaccount, err = serviceaccount.NewKind(rt)
if err != nil {
panic(fmt.Sprintf("error while initializing the serviceaccount Kind: %s", err))
}
reg.all = append(reg.all, reg.serviceaccount)
reg.team, err = team.NewKind(rt)
if err != nil {
panic(fmt.Sprintf("error while initializing the team Kind: %s", err))