Merge branch 'main' of https://github.com/grafana/grafana into kristina/static-transform-refIds

This commit is contained in:
Kristina Durivage
2025-09-23 14:36:10 -05:00
254 changed files with 11786 additions and 2587 deletions
+2
View File
@@ -310,6 +310,7 @@
/devenv/docker/blocks/webdav/ @grafana/alerting-backend
/devenv/docker/buildcontainer/ @bergquist
/devenv/docker/compose_header.yml @grafana/grafana-backend-services-squad
/devenv/docker/compose_volume_section.yml @grafana/grafana-backend-services-squad
/devenv/docker/debtest/ @bergquist
/devenv/docker/ha-test-unified-alerting/ @grafana/alerting-backend
/devenv/docker/ha_test/ @grafana/grafana-backend-services-squad
@@ -926,6 +927,7 @@ playwright.storybook.config.ts @grafana/grafana-frontend-platform
/public/app/features/inspector/ @grafana/dashboards-squad
/public/app/features/logs/ @grafana/observability-logs
/public/app/features/live/ @grafana/dashboards-squad
/public/app/features/stars/ @grafana/grafana-search-navigate-organise
/public/app/features/apiserver/ @grafana/grafana-app-platform-squad
/public/app/features/manage-dashboards/ @grafana/dashboards-squad
/public/app/features/migrate-to-cloud @grafana/grafana-operator-experience-squad
+1 -1
View File
@@ -123,7 +123,7 @@ jobs:
echo "No changes in generated Go files"
else
if [[ "${{ github.event.pull_request.head.repo.fork }}" == "false" ]]; then
echo "> !!! Please link Enterprise and run 'make gen-go', then commit the changes to both repositories."
echo "> !!! Please synchronize the grafana OSS and grafana enterprise code bases as defined in the enterprise readme, then run 'make gen-go' in the OSS folder and commit the changes to both repositories."
else
echo "> !!! Please run 'make gen-go' and commit the changes."
fi
-2
View File
@@ -135,7 +135,6 @@ jobs:
tag-nightly:
name: Tag nightly release
runs-on: github-hosted-ubuntu-x64-small
needs: publish
if: inputs.version_type == 'nightly'
steps:
@@ -146,4 +145,3 @@ jobs:
# TODO: tag the given release with nightly
+1 -2
View File
@@ -5,5 +5,4 @@ generate: do-generate ## Run Grafana App SDK code generation
.PHONY: do-generate
do-generate: install-app-sdk update-app-sdk
## --defencoding=none and noschemasinmanifest are needed to avoid infinite loop while generating recursive models (see routingtree.cue)
@$(APP_SDK_BIN) generate --grouping=group --gogenpath=./pkg/apis --defencoding=none --postprocess --noschemasinmanifest --useoldmanifestkinds
@$(APP_SDK_BIN) generate --grouping=group --gogenpath=./pkg/apis --defencoding=yaml --postprocess
@@ -0,0 +1,432 @@
apiVersion: apps.grafana.com/v1alpha2
kind: AppManifest
metadata:
name: alerting-notifications
spec:
appName: alerting-notifications
group: notifications.alerting.grafana.app
versions:
- kinds:
- conversion: false
kind: Receiver
plural: Receivers
schemas:
Integration:
additionalProperties: false
properties:
disableResolveMessage:
type: boolean
secureFields:
additionalProperties:
type: boolean
type: object
settings:
additionalProperties:
additionalProperties: {}
type: object
type: object
type:
type: string
uid:
type: string
version:
type: string
required:
- type
- version
- settings
type: object
OperatorState:
additionalProperties: false
properties:
descriptiveState:
description: descriptiveState is an optional more descriptive state
field which has no requirements on format
type: string
details:
additionalProperties:
additionalProperties: {}
type: object
description: details contains any extra information that is operator-specific
type: object
lastEvaluation:
description: lastEvaluation is the ResourceVersion last evaluated
type: string
state:
description: |-
state describes the state of the lastEvaluation.
It is limited to three possible states for machine evaluation.
enum:
- success
- in_progress
- failed
type: string
required:
- lastEvaluation
- state
type: object
Receiver:
properties:
spec:
$ref: '#/components/schemas/spec'
status:
$ref: '#/components/schemas/status'
required:
- spec
spec:
additionalProperties: false
properties:
integrations:
items:
$ref: '#/components/schemas/Integration'
type: array
title:
type: string
required:
- title
- integrations
type: object
status:
additionalProperties: false
properties:
additionalFields:
additionalProperties:
additionalProperties: {}
type: object
description: additionalFields is reserved for future use
type: object
operatorStates:
additionalProperties:
$ref: '#/components/schemas/OperatorState'
description: |-
operatorStates is a map of operator ID to operator state evaluations.
Any operator which consumes this kind SHOULD add its state evaluation information to this field.
type: object
type: object
scope: Namespaced
- conversion: false
kind: RoutingTree
plural: RoutingTrees
schemas:
Matcher:
additionalProperties: false
properties:
label:
type: string
type:
enum:
- =
- '!='
- =~
- '!~'
type: string
value:
type: string
required:
- type
- label
- value
type: object
OperatorState:
additionalProperties: false
properties:
descriptiveState:
description: descriptiveState is an optional more descriptive state
field which has no requirements on format
type: string
details:
additionalProperties:
additionalProperties: {}
type: object
description: details contains any extra information that is operator-specific
type: object
lastEvaluation:
description: lastEvaluation is the ResourceVersion last evaluated
type: string
state:
description: |-
state describes the state of the lastEvaluation.
It is limited to three possible states for machine evaluation.
enum:
- success
- in_progress
- failed
type: string
required:
- lastEvaluation
- state
type: object
Route:
additionalProperties: false
properties:
active_time_intervals:
items:
type: string
type: array
continue:
type: boolean
group_by:
items:
type: string
type: array
group_interval:
type: string
group_wait:
type: string
matchers:
items:
$ref: '#/components/schemas/Matcher'
type: array
mute_time_intervals:
items:
type: string
type: array
receiver:
type: string
repeat_interval:
type: string
routes:
items:
$ref: '#/components/schemas/Route'
type: array
required:
- continue
type: object
RouteDefaults:
additionalProperties: false
properties:
group_by:
items:
type: string
type: array
group_interval:
type: string
group_wait:
type: string
receiver:
type: string
repeat_interval:
type: string
required:
- receiver
type: object
RoutingTree:
properties:
spec:
$ref: '#/components/schemas/spec'
status:
$ref: '#/components/schemas/status'
required:
- spec
spec:
additionalProperties: false
properties:
defaults:
$ref: '#/components/schemas/RouteDefaults'
routes:
items:
$ref: '#/components/schemas/Route'
type: array
required:
- defaults
- routes
type: object
status:
additionalProperties: false
properties:
additionalFields:
additionalProperties:
additionalProperties: {}
type: object
description: additionalFields is reserved for future use
type: object
operatorStates:
additionalProperties:
$ref: '#/components/schemas/OperatorState'
description: |-
operatorStates is a map of operator ID to operator state evaluations.
Any operator which consumes this kind SHOULD add its state evaluation information to this field.
type: object
type: object
scope: Namespaced
- conversion: false
kind: TemplateGroup
plural: TemplateGroups
schemas:
OperatorState:
additionalProperties: false
properties:
descriptiveState:
description: descriptiveState is an optional more descriptive state
field which has no requirements on format
type: string
details:
additionalProperties:
additionalProperties: {}
type: object
description: details contains any extra information that is operator-specific
type: object
lastEvaluation:
description: lastEvaluation is the ResourceVersion last evaluated
type: string
state:
description: |-
state describes the state of the lastEvaluation.
It is limited to three possible states for machine evaluation.
enum:
- success
- in_progress
- failed
type: string
required:
- lastEvaluation
- state
type: object
TemplateGroup:
properties:
spec:
$ref: '#/components/schemas/spec'
status:
$ref: '#/components/schemas/status'
required:
- spec
spec:
additionalProperties: false
properties:
content:
type: string
title:
type: string
required:
- title
- content
type: object
status:
additionalProperties: false
properties:
additionalFields:
additionalProperties:
additionalProperties: {}
type: object
description: additionalFields is reserved for future use
type: object
operatorStates:
additionalProperties:
$ref: '#/components/schemas/OperatorState'
description: |-
operatorStates is a map of operator ID to operator state evaluations.
Any operator which consumes this kind SHOULD add its state evaluation information to this field.
type: object
type: object
scope: Namespaced
- conversion: false
kind: TimeInterval
plural: TimeIntervals
schemas:
Interval:
additionalProperties: false
properties:
days_of_month:
items:
type: string
type: array
location:
type: string
months:
items:
type: string
type: array
times:
items:
$ref: '#/components/schemas/TimeRange'
type: array
weekdays:
items:
type: string
type: array
years:
items:
type: string
type: array
type: object
OperatorState:
additionalProperties: false
properties:
descriptiveState:
description: descriptiveState is an optional more descriptive state
field which has no requirements on format
type: string
details:
additionalProperties:
additionalProperties: {}
type: object
description: details contains any extra information that is operator-specific
type: object
lastEvaluation:
description: lastEvaluation is the ResourceVersion last evaluated
type: string
state:
description: |-
state describes the state of the lastEvaluation.
It is limited to three possible states for machine evaluation.
enum:
- success
- in_progress
- failed
type: string
required:
- lastEvaluation
- state
type: object
TimeInterval:
properties:
spec:
$ref: '#/components/schemas/spec'
status:
$ref: '#/components/schemas/status'
required:
- spec
TimeRange:
additionalProperties: false
properties:
end_time:
type: string
start_time:
type: string
required:
- start_time
- end_time
type: object
spec:
additionalProperties: false
properties:
name:
type: string
time_intervals:
items:
$ref: '#/components/schemas/Interval'
type: array
required:
- name
- time_intervals
type: object
status:
additionalProperties: false
properties:
additionalFields:
additionalProperties:
additionalProperties: {}
type: object
description: additionalFields is reserved for future use
type: object
operatorStates:
additionalProperties:
$ref: '#/components/schemas/OperatorState'
description: |-
operatorStates is a map of operator ID to operator state evaluations.
Any operator which consumes this kind SHOULD add its state evaluation information to this field.
type: object
type: object
scope: Namespaced
name: v0alpha1
served: true
@@ -0,0 +1,93 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: receivers.notifications.alerting.grafana.app
spec:
group: notifications.alerting.grafana.app
names:
kind: Receiver
plural: receivers
scope: Namespaced
versions:
- name: v0alpha1
schema:
openAPIV3Schema:
properties:
spec:
properties:
integrations:
items:
properties:
disableResolveMessage:
type: boolean
secureFields:
additionalProperties:
type: boolean
type: object
settings:
type: object
x-kubernetes-preserve-unknown-fields: true
type:
type: string
uid:
type: string
version:
type: string
required:
- type
- version
- settings
type: object
type: array
title:
type: string
required:
- title
- integrations
type: object
status:
properties:
additionalFields:
description: additionalFields is reserved for future use
type: object
x-kubernetes-preserve-unknown-fields: true
operatorStates:
additionalProperties:
properties:
descriptiveState:
description: descriptiveState is an optional more descriptive
state field which has no requirements on format
type: string
details:
description: details contains any extra information that is
operator-specific
type: object
x-kubernetes-preserve-unknown-fields: true
lastEvaluation:
description: lastEvaluation is the ResourceVersion last evaluated
type: string
state:
description: |-
state describes the state of the lastEvaluation.
It is limited to three possible states for machine evaluation.
enum:
- success
- in_progress
- failed
type: string
required:
- lastEvaluation
- state
type: object
description: |-
operatorStates is a map of operator ID to operator state evaluations.
Any operator which consumes this kind SHOULD add its state evaluation information to this field.
type: object
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
@@ -0,0 +1,138 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: routingtrees.notifications.alerting.grafana.app
spec:
group: notifications.alerting.grafana.app
names:
kind: RoutingTree
plural: routingtrees
scope: Namespaced
versions:
- name: v0alpha1
schema:
openAPIV3Schema:
properties:
spec:
properties:
defaults:
properties:
group_by:
items:
type: string
type: array
group_interval:
type: string
group_wait:
type: string
receiver:
type: string
repeat_interval:
type: string
required:
- receiver
type: object
routes:
items:
properties:
active_time_intervals:
items:
type: string
type: array
continue:
type: boolean
group_by:
items:
type: string
type: array
group_interval:
type: string
group_wait:
type: string
matchers:
items:
properties:
label:
type: string
type:
enum:
- =
- '!='
- =~
- '!~'
type: string
value:
type: string
required:
- type
- label
- value
type: object
type: array
mute_time_intervals:
items:
type: string
type: array
receiver:
type: string
repeat_interval:
type: string
routes:
items:
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
required:
- continue
type: object
type: array
required:
- defaults
- routes
type: object
status:
properties:
additionalFields:
description: additionalFields is reserved for future use
type: object
x-kubernetes-preserve-unknown-fields: true
operatorStates:
additionalProperties:
properties:
descriptiveState:
description: descriptiveState is an optional more descriptive
state field which has no requirements on format
type: string
details:
description: details contains any extra information that is
operator-specific
type: object
x-kubernetes-preserve-unknown-fields: true
lastEvaluation:
description: lastEvaluation is the ResourceVersion last evaluated
type: string
state:
description: |-
state describes the state of the lastEvaluation.
It is limited to three possible states for machine evaluation.
enum:
- success
- in_progress
- failed
type: string
required:
- lastEvaluation
- state
type: object
description: |-
operatorStates is a map of operator ID to operator state evaluations.
Any operator which consumes this kind SHOULD add its state evaluation information to this field.
type: object
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
@@ -0,0 +1,71 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: templategroups.notifications.alerting.grafana.app
spec:
group: notifications.alerting.grafana.app
names:
kind: TemplateGroup
plural: templategroups
scope: Namespaced
versions:
- name: v0alpha1
schema:
openAPIV3Schema:
properties:
spec:
properties:
content:
type: string
title:
type: string
required:
- title
- content
type: object
status:
properties:
additionalFields:
description: additionalFields is reserved for future use
type: object
x-kubernetes-preserve-unknown-fields: true
operatorStates:
additionalProperties:
properties:
descriptiveState:
description: descriptiveState is an optional more descriptive
state field which has no requirements on format
type: string
details:
description: details contains any extra information that is
operator-specific
type: object
x-kubernetes-preserve-unknown-fields: true
lastEvaluation:
description: lastEvaluation is the ResourceVersion last evaluated
type: string
state:
description: |-
state describes the state of the lastEvaluation.
It is limited to three possible states for machine evaluation.
enum:
- success
- in_progress
- failed
type: string
required:
- lastEvaluation
- state
type: object
description: |-
operatorStates is a map of operator ID to operator state evaluations.
Any operator which consumes this kind SHOULD add its state evaluation information to this field.
type: object
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
@@ -0,0 +1,104 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: timeintervals.notifications.alerting.grafana.app
spec:
group: notifications.alerting.grafana.app
names:
kind: TimeInterval
plural: timeintervals
scope: Namespaced
versions:
- name: v0alpha1
schema:
openAPIV3Schema:
properties:
spec:
properties:
name:
type: string
time_intervals:
items:
properties:
days_of_month:
items:
type: string
type: array
location:
type: string
months:
items:
type: string
type: array
times:
items:
properties:
end_time:
type: string
start_time:
type: string
required:
- start_time
- end_time
type: object
type: array
weekdays:
items:
type: string
type: array
years:
items:
type: string
type: array
type: object
type: array
required:
- name
- time_intervals
type: object
status:
properties:
additionalFields:
description: additionalFields is reserved for future use
type: object
x-kubernetes-preserve-unknown-fields: true
operatorStates:
additionalProperties:
properties:
descriptiveState:
description: descriptiveState is an optional more descriptive
state field which has no requirements on format
type: string
details:
description: details contains any extra information that is
operator-specific
type: object
x-kubernetes-preserve-unknown-fields: true
lastEvaluation:
description: lastEvaluation is the ResourceVersion last evaluated
type: string
state:
description: |-
state describes the state of the lastEvaluation.
It is limited to three possible states for machine evaluation.
enum:
- success
- in_progress
- failed
type: string
required:
- lastEvaluation
- state
type: object
description: |-
operatorStates is a map of operator ID to operator state evaluations.
Any operator which consumes this kind SHOULD add its state evaluation information to this field.
type: object
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
+15 -7
View File
@@ -1,12 +1,20 @@
package kinds
manifest: {
appName: "alerting"
appName: "alerting-notifications"
groupOverride: "notifications.alerting.grafana.app"
kinds: [
receiver,
routeTree,
templateGroup,
timeInterval,
]
versions: {
"v0alpha1": {
codegen: {
ts: {enabled: false}
go: {enabled: true}
}
kinds: [
receiverv0alpha1,
routeTreev0alpha1,
templatev0alpha1,
timeIntervalv0alpha1,
]
}
}
}
+10 -19
View File
@@ -4,25 +4,16 @@ import (
"github.com/grafana/grafana/apps/alerting/notifications/kinds/v0alpha1"
)
receiver: {
receiverKind: {
kind: "Receiver"
apiResource: {
groupOverride: "notifications.alerting.grafana.app"
}
pluralName: "Receivers"
current: "v0alpha1"
versions: {
"v0alpha1": {
codegen: {
ts: {enabled: false}
go: {enabled: true}
}
schema: {
spec: v0alpha1.ReceiverSpec
}
selectableFields: [
"spec.title",
]
}
}
}
receiverv0alpha1: receiverKind & {
schema: {
spec: v0alpha1.ReceiverSpec
}
// selectableFields: [ // TODO revisit when custom field selectors are supported
// "spec.title",
// ]
}
@@ -3,23 +3,13 @@ package kinds
import (
"github.com/grafana/grafana/apps/alerting/notifications/kinds/v0alpha1"
)
routeTree: {
routingTreeKind: {
kind: "RoutingTree"
apiResource: {
groupOverride: "notifications.alerting.grafana.app"
}
pluralName: "RoutingTrees"
current: "v0alpha1"
versions: {
"v0alpha1": {
codegen: {
ts: {enabled: false}
go: {enabled: true}
}
schema: {
spec: v0alpha1.RouteTreeSpec
}
}
}
routeTreev0alpha1: routingTreeKind & {
schema: {
spec: v0alpha1.RouteTreeSpec
}
}
+10 -19
View File
@@ -4,25 +4,16 @@ import (
"github.com/grafana/grafana/apps/alerting/notifications/kinds/v0alpha1"
)
templateGroup: {
templateKind: {
kind: "TemplateGroup"
apiResource: {
groupOverride: "notifications.alerting.grafana.app"
}
pluralName: "TemplateGroups"
current: "v0alpha1"
versions: {
"v0alpha1": {
codegen: {
ts: {enabled: false}
go: {enabled: true}
}
schema: {
spec: v0alpha1.TemplateGroupSpec
}
selectableFields: [
"spec.title",
]
}
}
}
templatev0alpha1: templateKind & {
schema: {
spec: v0alpha1.TemplateGroupSpec
}
// selectableFields: [ // TODO revisit when custom field selectors are supported
// "spec.title",
// ]
}
@@ -3,26 +3,16 @@ package kinds
import (
"github.com/grafana/grafana/apps/alerting/notifications/kinds/v0alpha1"
)
timeInterval: {
timeIntervalKind: {
kind: "TimeInterval"
apiResource: {
groupOverride: "notifications.alerting.grafana.app"
}
pluralName: "TimeIntervals"
current: "v0alpha1"
versions: {
"v0alpha1": {
codegen: {
ts: {enabled: false}
go: {enabled: true}
}
schema: {
spec: v0alpha1.TimeIntervalSpec
}
selectableFields: [
"spec.name",
]
}
}
}
timeIntervalv0alpha1: timeIntervalKind & {
schema: {
spec: v0alpha1.TimeIntervalSpec
}
// selectableFields: [ // TODO revisit when custom field selectors are supported
// "spec.name",
// ]
}
@@ -1,100 +0,0 @@
//
// This file is generated by grafana-app-sdk
// DO NOT EDIT
//
package apis
import (
"fmt"
"strings"
"github.com/grafana/grafana-app-sdk/app"
"github.com/grafana/grafana-app-sdk/resource"
v0alpha1 "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
)
var appManifestData = app.ManifestData{
AppName: "alerting",
Group: "notifications.alerting.grafana.app",
Versions: []app.ManifestVersion{
{
Name: "v0alpha1",
Served: true,
Kinds: []app.ManifestVersionKind{
{
Kind: "Receiver",
Plural: "Receivers",
Scope: "Namespaced",
Conversion: false,
SelectableFields: []string{
"spec.title",
},
},
{
Kind: "RoutingTree",
Plural: "RoutingTrees",
Scope: "Namespaced",
Conversion: false,
},
{
Kind: "TemplateGroup",
Plural: "TemplateGroups",
Scope: "Namespaced",
Conversion: false,
SelectableFields: []string{
"spec.title",
},
},
{
Kind: "TimeInterval",
Plural: "TimeIntervals",
Scope: "Namespaced",
Conversion: false,
SelectableFields: []string{
"spec.name",
},
},
},
},
},
}
func LocalManifest() app.Manifest {
return app.NewEmbeddedManifest(appManifestData)
}
func RemoteManifest() app.Manifest {
return app.NewAPIServerManifest("alerting")
}
var kindVersionToGoType = map[string]resource.Kind{
"Receiver/v0alpha1": v0alpha1.ReceiverKind(),
"RoutingTree/v0alpha1": v0alpha1.RoutingTreeKind(),
"TemplateGroup/v0alpha1": v0alpha1.TemplateGroupKind(),
"TimeInterval/v0alpha1": v0alpha1.TimeIntervalKind(),
}
// ManifestGoTypeAssociator returns the associated resource.Kind instance for a given Kind and Version, if one exists.
// If there is no association for the provided Kind and Version, exists will return false.
func ManifestGoTypeAssociator(kind, version string) (goType resource.Kind, exists bool) {
goType, exists = kindVersionToGoType[fmt.Sprintf("%s/%s", kind, version)]
return goType, exists
}
var customRouteToGoResponseType = map[string]any{}
// 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.
// If there is no association for the provided kind, version, custom route path, and method, exists will return false.
func ManifestCustomRouteResponsesAssociator(kind, version, path, verb string) (goType any, exists bool) {
if len(path) > 0 && path[0] == '/' {
path = path[1:]
}
goType, exists = customRouteToGoResponseType[fmt.Sprintf("%s|%s|%s|%s", version, kind, path, strings.ToUpper(verb))]
return goType, exists
}
@@ -7,7 +7,7 @@ import (
"strings"
"time"
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1"
)
var UTCLocation = "UTC"
@@ -0,0 +1,99 @@
package v0alpha1
import (
"context"
"github.com/grafana/grafana-app-sdk/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type ReceiverClient struct {
client *resource.TypedClient[*Receiver, *ReceiverList]
}
func NewReceiverClient(client resource.Client) *ReceiverClient {
return &ReceiverClient{
client: resource.NewTypedClient[*Receiver, *ReceiverList](client, ReceiverKind()),
}
}
func NewReceiverClientFromGenerator(generator resource.ClientGenerator) (*ReceiverClient, error) {
c, err := generator.ClientFor(ReceiverKind())
if err != nil {
return nil, err
}
return NewReceiverClient(c), nil
}
func (c *ReceiverClient) Get(ctx context.Context, identifier resource.Identifier) (*Receiver, error) {
return c.client.Get(ctx, identifier)
}
func (c *ReceiverClient) List(ctx context.Context, namespace string, opts resource.ListOptions) (*ReceiverList, error) {
return c.client.List(ctx, namespace, opts)
}
func (c *ReceiverClient) ListAll(ctx context.Context, namespace string, opts resource.ListOptions) (*ReceiverList, error) {
resp, err := c.client.List(ctx, namespace, resource.ListOptions{
ResourceVersion: opts.ResourceVersion,
Limit: opts.Limit,
LabelFilters: opts.LabelFilters,
FieldSelectors: opts.FieldSelectors,
})
if err != nil {
return nil, err
}
for resp.GetContinue() != "" {
page, err := c.client.List(ctx, namespace, resource.ListOptions{
Continue: resp.GetContinue(),
ResourceVersion: opts.ResourceVersion,
Limit: opts.Limit,
LabelFilters: opts.LabelFilters,
FieldSelectors: opts.FieldSelectors,
})
if err != nil {
return nil, err
}
resp.SetContinue(page.GetContinue())
resp.SetResourceVersion(page.GetResourceVersion())
resp.SetItems(append(resp.GetItems(), page.GetItems()...))
}
return resp, nil
}
func (c *ReceiverClient) Create(ctx context.Context, obj *Receiver, opts resource.CreateOptions) (*Receiver, error) {
// Make sure apiVersion and kind are set
obj.APIVersion = GroupVersion.Identifier()
obj.Kind = ReceiverKind().Kind()
return c.client.Create(ctx, obj, opts)
}
func (c *ReceiverClient) Update(ctx context.Context, obj *Receiver, opts resource.UpdateOptions) (*Receiver, error) {
return c.client.Update(ctx, obj, opts)
}
func (c *ReceiverClient) Patch(ctx context.Context, identifier resource.Identifier, req resource.PatchRequest, opts resource.PatchOptions) (*Receiver, error) {
return c.client.Patch(ctx, identifier, req, opts)
}
func (c *ReceiverClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus ReceiverStatus, opts resource.UpdateOptions) (*Receiver, error) {
return c.client.Update(ctx, &Receiver{
TypeMeta: metav1.TypeMeta{
Kind: ReceiverKind().Kind(),
APIVersion: GroupVersion.Identifier(),
},
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: opts.ResourceVersion,
Namespace: identifier.Namespace,
Name: identifier.Name,
},
Status: newStatus,
}, resource.UpdateOptions{
Subresource: "status",
ResourceVersion: opts.ResourceVersion,
})
}
func (c *ReceiverClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error {
return c.client.Delete(ctx, identifier, opts)
}
@@ -5,25 +5,13 @@
package v0alpha1
import (
"fmt"
"github.com/grafana/grafana-app-sdk/resource"
)
// schema is unexported to prevent accidental overwrites
var (
schemaReceiver = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &Receiver{}, &ReceiverList{}, resource.WithKind("Receiver"),
resource.WithPlural("receivers"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{{
FieldSelector: "spec.title",
FieldValueFunc: func(o resource.Object) (string, error) {
cast, ok := o.(*Receiver)
if !ok {
return "", fmt.Errorf("provided object must be of type *Receiver")
}
return cast.Spec.Title, nil
},
},
}))
resource.WithPlural("receivers"), resource.WithScope(resource.NamespacedScope))
kindReceiver = resource.Kind{
Schema: schemaReceiver,
Codecs: map[resource.KindEncoding]resource.Codec{
@@ -0,0 +1,99 @@
package v0alpha1
import (
"context"
"github.com/grafana/grafana-app-sdk/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type RoutingTreeClient struct {
client *resource.TypedClient[*RoutingTree, *RoutingTreeList]
}
func NewRoutingTreeClient(client resource.Client) *RoutingTreeClient {
return &RoutingTreeClient{
client: resource.NewTypedClient[*RoutingTree, *RoutingTreeList](client, RoutingTreeKind()),
}
}
func NewRoutingTreeClientFromGenerator(generator resource.ClientGenerator) (*RoutingTreeClient, error) {
c, err := generator.ClientFor(RoutingTreeKind())
if err != nil {
return nil, err
}
return NewRoutingTreeClient(c), nil
}
func (c *RoutingTreeClient) Get(ctx context.Context, identifier resource.Identifier) (*RoutingTree, error) {
return c.client.Get(ctx, identifier)
}
func (c *RoutingTreeClient) List(ctx context.Context, namespace string, opts resource.ListOptions) (*RoutingTreeList, error) {
return c.client.List(ctx, namespace, opts)
}
func (c *RoutingTreeClient) ListAll(ctx context.Context, namespace string, opts resource.ListOptions) (*RoutingTreeList, error) {
resp, err := c.client.List(ctx, namespace, resource.ListOptions{
ResourceVersion: opts.ResourceVersion,
Limit: opts.Limit,
LabelFilters: opts.LabelFilters,
FieldSelectors: opts.FieldSelectors,
})
if err != nil {
return nil, err
}
for resp.GetContinue() != "" {
page, err := c.client.List(ctx, namespace, resource.ListOptions{
Continue: resp.GetContinue(),
ResourceVersion: opts.ResourceVersion,
Limit: opts.Limit,
LabelFilters: opts.LabelFilters,
FieldSelectors: opts.FieldSelectors,
})
if err != nil {
return nil, err
}
resp.SetContinue(page.GetContinue())
resp.SetResourceVersion(page.GetResourceVersion())
resp.SetItems(append(resp.GetItems(), page.GetItems()...))
}
return resp, nil
}
func (c *RoutingTreeClient) Create(ctx context.Context, obj *RoutingTree, opts resource.CreateOptions) (*RoutingTree, error) {
// Make sure apiVersion and kind are set
obj.APIVersion = GroupVersion.Identifier()
obj.Kind = RoutingTreeKind().Kind()
return c.client.Create(ctx, obj, opts)
}
func (c *RoutingTreeClient) Update(ctx context.Context, obj *RoutingTree, opts resource.UpdateOptions) (*RoutingTree, error) {
return c.client.Update(ctx, obj, opts)
}
func (c *RoutingTreeClient) Patch(ctx context.Context, identifier resource.Identifier, req resource.PatchRequest, opts resource.PatchOptions) (*RoutingTree, error) {
return c.client.Patch(ctx, identifier, req, opts)
}
func (c *RoutingTreeClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus RoutingTreeStatus, opts resource.UpdateOptions) (*RoutingTree, error) {
return c.client.Update(ctx, &RoutingTree{
TypeMeta: metav1.TypeMeta{
Kind: RoutingTreeKind().Kind(),
APIVersion: GroupVersion.Identifier(),
},
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: opts.ResourceVersion,
Namespace: identifier.Namespace,
Name: identifier.Name,
},
Status: newStatus,
}, resource.UpdateOptions{
Subresource: "status",
ResourceVersion: opts.ResourceVersion,
})
}
func (c *RoutingTreeClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error {
return c.client.Delete(ctx, identifier, opts)
}
@@ -0,0 +1,99 @@
package v0alpha1
import (
"context"
"github.com/grafana/grafana-app-sdk/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type TemplateGroupClient struct {
client *resource.TypedClient[*TemplateGroup, *TemplateGroupList]
}
func NewTemplateGroupClient(client resource.Client) *TemplateGroupClient {
return &TemplateGroupClient{
client: resource.NewTypedClient[*TemplateGroup, *TemplateGroupList](client, TemplateGroupKind()),
}
}
func NewTemplateGroupClientFromGenerator(generator resource.ClientGenerator) (*TemplateGroupClient, error) {
c, err := generator.ClientFor(TemplateGroupKind())
if err != nil {
return nil, err
}
return NewTemplateGroupClient(c), nil
}
func (c *TemplateGroupClient) Get(ctx context.Context, identifier resource.Identifier) (*TemplateGroup, error) {
return c.client.Get(ctx, identifier)
}
func (c *TemplateGroupClient) List(ctx context.Context, namespace string, opts resource.ListOptions) (*TemplateGroupList, error) {
return c.client.List(ctx, namespace, opts)
}
func (c *TemplateGroupClient) ListAll(ctx context.Context, namespace string, opts resource.ListOptions) (*TemplateGroupList, error) {
resp, err := c.client.List(ctx, namespace, resource.ListOptions{
ResourceVersion: opts.ResourceVersion,
Limit: opts.Limit,
LabelFilters: opts.LabelFilters,
FieldSelectors: opts.FieldSelectors,
})
if err != nil {
return nil, err
}
for resp.GetContinue() != "" {
page, err := c.client.List(ctx, namespace, resource.ListOptions{
Continue: resp.GetContinue(),
ResourceVersion: opts.ResourceVersion,
Limit: opts.Limit,
LabelFilters: opts.LabelFilters,
FieldSelectors: opts.FieldSelectors,
})
if err != nil {
return nil, err
}
resp.SetContinue(page.GetContinue())
resp.SetResourceVersion(page.GetResourceVersion())
resp.SetItems(append(resp.GetItems(), page.GetItems()...))
}
return resp, nil
}
func (c *TemplateGroupClient) Create(ctx context.Context, obj *TemplateGroup, opts resource.CreateOptions) (*TemplateGroup, error) {
// Make sure apiVersion and kind are set
obj.APIVersion = GroupVersion.Identifier()
obj.Kind = TemplateGroupKind().Kind()
return c.client.Create(ctx, obj, opts)
}
func (c *TemplateGroupClient) Update(ctx context.Context, obj *TemplateGroup, opts resource.UpdateOptions) (*TemplateGroup, error) {
return c.client.Update(ctx, obj, opts)
}
func (c *TemplateGroupClient) Patch(ctx context.Context, identifier resource.Identifier, req resource.PatchRequest, opts resource.PatchOptions) (*TemplateGroup, error) {
return c.client.Patch(ctx, identifier, req, opts)
}
func (c *TemplateGroupClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus TemplateGroupStatus, opts resource.UpdateOptions) (*TemplateGroup, error) {
return c.client.Update(ctx, &TemplateGroup{
TypeMeta: metav1.TypeMeta{
Kind: TemplateGroupKind().Kind(),
APIVersion: GroupVersion.Identifier(),
},
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: opts.ResourceVersion,
Namespace: identifier.Namespace,
Name: identifier.Name,
},
Status: newStatus,
}, resource.UpdateOptions{
Subresource: "status",
ResourceVersion: opts.ResourceVersion,
})
}
func (c *TemplateGroupClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error {
return c.client.Delete(ctx, identifier, opts)
}
@@ -5,25 +5,13 @@
package v0alpha1
import (
"fmt"
"github.com/grafana/grafana-app-sdk/resource"
)
// schema is unexported to prevent accidental overwrites
var (
schemaTemplateGroup = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &TemplateGroup{}, &TemplateGroupList{}, resource.WithKind("TemplateGroup"),
resource.WithPlural("templategroups"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{{
FieldSelector: "spec.title",
FieldValueFunc: func(o resource.Object) (string, error) {
cast, ok := o.(*TemplateGroup)
if !ok {
return "", fmt.Errorf("provided object must be of type *TemplateGroup")
}
return cast.Spec.Title, nil
},
},
}))
resource.WithPlural("templategroups"), resource.WithScope(resource.NamespacedScope))
kindTemplateGroup = resource.Kind{
Schema: schemaTemplateGroup,
Codecs: map[resource.KindEncoding]resource.Codec{
@@ -0,0 +1,99 @@
package v0alpha1
import (
"context"
"github.com/grafana/grafana-app-sdk/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type TimeIntervalClient struct {
client *resource.TypedClient[*TimeInterval, *TimeIntervalList]
}
func NewTimeIntervalClient(client resource.Client) *TimeIntervalClient {
return &TimeIntervalClient{
client: resource.NewTypedClient[*TimeInterval, *TimeIntervalList](client, TimeIntervalKind()),
}
}
func NewTimeIntervalClientFromGenerator(generator resource.ClientGenerator) (*TimeIntervalClient, error) {
c, err := generator.ClientFor(TimeIntervalKind())
if err != nil {
return nil, err
}
return NewTimeIntervalClient(c), nil
}
func (c *TimeIntervalClient) Get(ctx context.Context, identifier resource.Identifier) (*TimeInterval, error) {
return c.client.Get(ctx, identifier)
}
func (c *TimeIntervalClient) List(ctx context.Context, namespace string, opts resource.ListOptions) (*TimeIntervalList, error) {
return c.client.List(ctx, namespace, opts)
}
func (c *TimeIntervalClient) ListAll(ctx context.Context, namespace string, opts resource.ListOptions) (*TimeIntervalList, error) {
resp, err := c.client.List(ctx, namespace, resource.ListOptions{
ResourceVersion: opts.ResourceVersion,
Limit: opts.Limit,
LabelFilters: opts.LabelFilters,
FieldSelectors: opts.FieldSelectors,
})
if err != nil {
return nil, err
}
for resp.GetContinue() != "" {
page, err := c.client.List(ctx, namespace, resource.ListOptions{
Continue: resp.GetContinue(),
ResourceVersion: opts.ResourceVersion,
Limit: opts.Limit,
LabelFilters: opts.LabelFilters,
FieldSelectors: opts.FieldSelectors,
})
if err != nil {
return nil, err
}
resp.SetContinue(page.GetContinue())
resp.SetResourceVersion(page.GetResourceVersion())
resp.SetItems(append(resp.GetItems(), page.GetItems()...))
}
return resp, nil
}
func (c *TimeIntervalClient) Create(ctx context.Context, obj *TimeInterval, opts resource.CreateOptions) (*TimeInterval, error) {
// Make sure apiVersion and kind are set
obj.APIVersion = GroupVersion.Identifier()
obj.Kind = TimeIntervalKind().Kind()
return c.client.Create(ctx, obj, opts)
}
func (c *TimeIntervalClient) Update(ctx context.Context, obj *TimeInterval, opts resource.UpdateOptions) (*TimeInterval, error) {
return c.client.Update(ctx, obj, opts)
}
func (c *TimeIntervalClient) Patch(ctx context.Context, identifier resource.Identifier, req resource.PatchRequest, opts resource.PatchOptions) (*TimeInterval, error) {
return c.client.Patch(ctx, identifier, req, opts)
}
func (c *TimeIntervalClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus TimeIntervalStatus, opts resource.UpdateOptions) (*TimeInterval, error) {
return c.client.Update(ctx, &TimeInterval{
TypeMeta: metav1.TypeMeta{
Kind: TimeIntervalKind().Kind(),
APIVersion: GroupVersion.Identifier(),
},
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: opts.ResourceVersion,
Namespace: identifier.Namespace,
Name: identifier.Name,
},
Status: newStatus,
}, resource.UpdateOptions{
Subresource: "status",
ResourceVersion: opts.ResourceVersion,
})
}
func (c *TimeIntervalClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error {
return c.client.Delete(ctx, identifier, opts)
}
@@ -5,25 +5,13 @@
package v0alpha1
import (
"fmt"
"github.com/grafana/grafana-app-sdk/resource"
)
// schema is unexported to prevent accidental overwrites
var (
schemaTimeInterval = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &TimeInterval{}, &TimeIntervalList{}, resource.WithKind("TimeInterval"),
resource.WithPlural("timeintervals"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{{
FieldSelector: "spec.name",
FieldValueFunc: func(o resource.Object) (string, error) {
cast, ok := o.(*TimeInterval)
if !ok {
return "", fmt.Errorf("provided object must be of type *TimeInterval")
}
return cast.Spec.Name, nil
},
},
}))
resource.WithPlural("timeintervals"), resource.WithScope(resource.NamespacedScope))
kindTimeInterval = resource.Kind{
Schema: schemaTimeInterval,
Codecs: map[resource.KindEncoding]resource.Codec{
@@ -12,36 +12,36 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.Receiver": schema_pkg_apis_alerting_v0alpha1_Receiver(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.ReceiverIntegration": schema_pkg_apis_alerting_v0alpha1_ReceiverIntegration(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.ReceiverList": schema_pkg_apis_alerting_v0alpha1_ReceiverList(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.ReceiverSpec": schema_pkg_apis_alerting_v0alpha1_ReceiverSpec(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.ReceiverStatus": schema_pkg_apis_alerting_v0alpha1_ReceiverStatus(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.ReceiverstatusOperatorState": schema_pkg_apis_alerting_v0alpha1_ReceiverstatusOperatorState(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTree": schema_pkg_apis_alerting_v0alpha1_RoutingTree(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeList": schema_pkg_apis_alerting_v0alpha1_RoutingTreeList(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeMatcher": schema_pkg_apis_alerting_v0alpha1_RoutingTreeMatcher(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeRoute": schema_pkg_apis_alerting_v0alpha1_RoutingTreeRoute(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeRouteDefaults": schema_pkg_apis_alerting_v0alpha1_RoutingTreeRouteDefaults(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeSpec": schema_pkg_apis_alerting_v0alpha1_RoutingTreeSpec(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeStatus": schema_pkg_apis_alerting_v0alpha1_RoutingTreeStatus(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreestatusOperatorState": schema_pkg_apis_alerting_v0alpha1_RoutingTreestatusOperatorState(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TemplateGroup": schema_pkg_apis_alerting_v0alpha1_TemplateGroup(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TemplateGroupList": schema_pkg_apis_alerting_v0alpha1_TemplateGroupList(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TemplateGroupSpec": schema_pkg_apis_alerting_v0alpha1_TemplateGroupSpec(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TemplateGroupStatus": schema_pkg_apis_alerting_v0alpha1_TemplateGroupStatus(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TemplateGroupstatusOperatorState": schema_pkg_apis_alerting_v0alpha1_TemplateGroupstatusOperatorState(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeInterval": schema_pkg_apis_alerting_v0alpha1_TimeInterval(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalInterval": schema_pkg_apis_alerting_v0alpha1_TimeIntervalInterval(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalList": schema_pkg_apis_alerting_v0alpha1_TimeIntervalList(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalSpec": schema_pkg_apis_alerting_v0alpha1_TimeIntervalSpec(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalStatus": schema_pkg_apis_alerting_v0alpha1_TimeIntervalStatus(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalTimeRange": schema_pkg_apis_alerting_v0alpha1_TimeIntervalTimeRange(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalstatusOperatorState": schema_pkg_apis_alerting_v0alpha1_TimeIntervalstatusOperatorState(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.Receiver": schema_pkg_apis_alertingnotifications_v0alpha1_Receiver(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.ReceiverIntegration": schema_pkg_apis_alertingnotifications_v0alpha1_ReceiverIntegration(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.ReceiverList": schema_pkg_apis_alertingnotifications_v0alpha1_ReceiverList(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.ReceiverSpec": schema_pkg_apis_alertingnotifications_v0alpha1_ReceiverSpec(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.ReceiverStatus": schema_pkg_apis_alertingnotifications_v0alpha1_ReceiverStatus(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.ReceiverstatusOperatorState": schema_pkg_apis_alertingnotifications_v0alpha1_ReceiverstatusOperatorState(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTree": schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTree(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeList": schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTreeList(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeMatcher": schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTreeMatcher(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeRoute": schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTreeRoute(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeRouteDefaults": schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTreeRouteDefaults(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeSpec": schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTreeSpec(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeStatus": schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTreeStatus(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreestatusOperatorState": schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTreestatusOperatorState(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TemplateGroup": schema_pkg_apis_alertingnotifications_v0alpha1_TemplateGroup(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TemplateGroupList": schema_pkg_apis_alertingnotifications_v0alpha1_TemplateGroupList(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TemplateGroupSpec": schema_pkg_apis_alertingnotifications_v0alpha1_TemplateGroupSpec(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TemplateGroupStatus": schema_pkg_apis_alertingnotifications_v0alpha1_TemplateGroupStatus(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TemplateGroupstatusOperatorState": schema_pkg_apis_alertingnotifications_v0alpha1_TemplateGroupstatusOperatorState(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeInterval": schema_pkg_apis_alertingnotifications_v0alpha1_TimeInterval(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalInterval": schema_pkg_apis_alertingnotifications_v0alpha1_TimeIntervalInterval(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalList": schema_pkg_apis_alertingnotifications_v0alpha1_TimeIntervalList(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalSpec": schema_pkg_apis_alertingnotifications_v0alpha1_TimeIntervalSpec(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalStatus": schema_pkg_apis_alertingnotifications_v0alpha1_TimeIntervalStatus(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalTimeRange": schema_pkg_apis_alertingnotifications_v0alpha1_TimeIntervalTimeRange(ref),
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalstatusOperatorState": schema_pkg_apis_alertingnotifications_v0alpha1_TimeIntervalstatusOperatorState(ref),
}
}
func schema_pkg_apis_alerting_v0alpha1_Receiver(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_Receiver(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -71,13 +71,13 @@ func schema_pkg_apis_alerting_v0alpha1_Receiver(ref common.ReferenceCallback) co
SchemaProps: spec.SchemaProps{
Description: "Spec is the spec of the Receiver",
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.ReceiverSpec"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.ReceiverSpec"),
},
},
"status": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.ReceiverStatus"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.ReceiverStatus"),
},
},
},
@@ -85,11 +85,11 @@ func schema_pkg_apis_alerting_v0alpha1_Receiver(ref common.ReferenceCallback) co
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.ReceiverSpec", "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.ReceiverStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.ReceiverSpec", "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.ReceiverStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
}
}
func schema_pkg_apis_alerting_v0alpha1_ReceiverIntegration(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_ReceiverIntegration(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -157,7 +157,7 @@ func schema_pkg_apis_alerting_v0alpha1_ReceiverIntegration(ref common.ReferenceC
}
}
func schema_pkg_apis_alerting_v0alpha1_ReceiverList(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_ReceiverList(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -190,7 +190,7 @@ func schema_pkg_apis_alerting_v0alpha1_ReceiverList(ref common.ReferenceCallback
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.Receiver"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.Receiver"),
},
},
},
@@ -201,11 +201,11 @@ func schema_pkg_apis_alerting_v0alpha1_ReceiverList(ref common.ReferenceCallback
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.Receiver", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.Receiver", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
}
}
func schema_pkg_apis_alerting_v0alpha1_ReceiverSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_ReceiverSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -225,7 +225,7 @@ func schema_pkg_apis_alerting_v0alpha1_ReceiverSpec(ref common.ReferenceCallback
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.ReceiverIntegration"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.ReceiverIntegration"),
},
},
},
@@ -236,11 +236,11 @@ func schema_pkg_apis_alerting_v0alpha1_ReceiverSpec(ref common.ReferenceCallback
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.ReceiverIntegration"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.ReceiverIntegration"},
}
}
func schema_pkg_apis_alerting_v0alpha1_ReceiverStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_ReceiverStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -255,7 +255,7 @@ func schema_pkg_apis_alerting_v0alpha1_ReceiverStatus(ref common.ReferenceCallba
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.ReceiverstatusOperatorState"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.ReceiverstatusOperatorState"),
},
},
},
@@ -280,11 +280,11 @@ func schema_pkg_apis_alerting_v0alpha1_ReceiverStatus(ref common.ReferenceCallba
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.ReceiverstatusOperatorState"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.ReceiverstatusOperatorState"},
}
}
func schema_pkg_apis_alerting_v0alpha1_ReceiverstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_ReceiverstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -335,7 +335,7 @@ func schema_pkg_apis_alerting_v0alpha1_ReceiverstatusOperatorState(ref common.Re
}
}
func schema_pkg_apis_alerting_v0alpha1_RoutingTree(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTree(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -365,13 +365,13 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTree(ref common.ReferenceCallback)
SchemaProps: spec.SchemaProps{
Description: "Spec is the spec of the RoutingTree",
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeSpec"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeSpec"),
},
},
"status": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeStatus"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeStatus"),
},
},
},
@@ -379,11 +379,11 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTree(ref common.ReferenceCallback)
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeSpec", "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeSpec", "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
}
}
func schema_pkg_apis_alerting_v0alpha1_RoutingTreeList(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTreeList(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -416,7 +416,7 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTreeList(ref common.ReferenceCallb
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTree"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTree"),
},
},
},
@@ -427,11 +427,11 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTreeList(ref common.ReferenceCallb
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTree", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTree", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
}
}
func schema_pkg_apis_alerting_v0alpha1_RoutingTreeMatcher(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTreeMatcher(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -465,7 +465,7 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTreeMatcher(ref common.ReferenceCa
}
}
func schema_pkg_apis_alerting_v0alpha1_RoutingTreeRoute(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTreeRoute(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -484,7 +484,7 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTreeRoute(ref common.ReferenceCall
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeMatcher"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeMatcher"),
},
},
},
@@ -546,7 +546,7 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTreeRoute(ref common.ReferenceCall
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeRoute"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeRoute"),
},
},
},
@@ -575,11 +575,11 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTreeRoute(ref common.ReferenceCall
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeMatcher", "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeRoute"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeMatcher", "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeRoute"},
}
}
func schema_pkg_apis_alerting_v0alpha1_RoutingTreeRouteDefaults(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTreeRouteDefaults(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -631,7 +631,7 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTreeRouteDefaults(ref common.Refer
}
}
func schema_pkg_apis_alerting_v0alpha1_RoutingTreeSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTreeSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -640,7 +640,7 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTreeSpec(ref common.ReferenceCallb
"defaults": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeRouteDefaults"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeRouteDefaults"),
},
},
"routes": {
@@ -650,7 +650,7 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTreeSpec(ref common.ReferenceCallb
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeRoute"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeRoute"),
},
},
},
@@ -661,11 +661,11 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTreeSpec(ref common.ReferenceCallb
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeRoute", "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreeRouteDefaults"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeRoute", "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreeRouteDefaults"},
}
}
func schema_pkg_apis_alerting_v0alpha1_RoutingTreeStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTreeStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -680,7 +680,7 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTreeStatus(ref common.ReferenceCal
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreestatusOperatorState"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreestatusOperatorState"),
},
},
},
@@ -705,11 +705,11 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTreeStatus(ref common.ReferenceCal
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.RoutingTreestatusOperatorState"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.RoutingTreestatusOperatorState"},
}
}
func schema_pkg_apis_alerting_v0alpha1_RoutingTreestatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_RoutingTreestatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -760,7 +760,7 @@ func schema_pkg_apis_alerting_v0alpha1_RoutingTreestatusOperatorState(ref common
}
}
func schema_pkg_apis_alerting_v0alpha1_TemplateGroup(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_TemplateGroup(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -790,13 +790,13 @@ func schema_pkg_apis_alerting_v0alpha1_TemplateGroup(ref common.ReferenceCallbac
SchemaProps: spec.SchemaProps{
Description: "Spec is the spec of the TemplateGroup",
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TemplateGroupSpec"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TemplateGroupSpec"),
},
},
"status": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TemplateGroupStatus"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TemplateGroupStatus"),
},
},
},
@@ -804,11 +804,11 @@ func schema_pkg_apis_alerting_v0alpha1_TemplateGroup(ref common.ReferenceCallbac
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TemplateGroupSpec", "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TemplateGroupStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TemplateGroupSpec", "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TemplateGroupStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
}
}
func schema_pkg_apis_alerting_v0alpha1_TemplateGroupList(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_TemplateGroupList(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -841,7 +841,7 @@ func schema_pkg_apis_alerting_v0alpha1_TemplateGroupList(ref common.ReferenceCal
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TemplateGroup"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TemplateGroup"),
},
},
},
@@ -852,11 +852,11 @@ func schema_pkg_apis_alerting_v0alpha1_TemplateGroupList(ref common.ReferenceCal
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TemplateGroup", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TemplateGroup", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
}
}
func schema_pkg_apis_alerting_v0alpha1_TemplateGroupSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_TemplateGroupSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -883,7 +883,7 @@ func schema_pkg_apis_alerting_v0alpha1_TemplateGroupSpec(ref common.ReferenceCal
}
}
func schema_pkg_apis_alerting_v0alpha1_TemplateGroupStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_TemplateGroupStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -898,7 +898,7 @@ func schema_pkg_apis_alerting_v0alpha1_TemplateGroupStatus(ref common.ReferenceC
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TemplateGroupstatusOperatorState"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TemplateGroupstatusOperatorState"),
},
},
},
@@ -923,11 +923,11 @@ func schema_pkg_apis_alerting_v0alpha1_TemplateGroupStatus(ref common.ReferenceC
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TemplateGroupstatusOperatorState"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TemplateGroupstatusOperatorState"},
}
}
func schema_pkg_apis_alerting_v0alpha1_TemplateGroupstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_TemplateGroupstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -978,7 +978,7 @@ func schema_pkg_apis_alerting_v0alpha1_TemplateGroupstatusOperatorState(ref comm
}
}
func schema_pkg_apis_alerting_v0alpha1_TimeInterval(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_TimeInterval(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -1008,13 +1008,13 @@ func schema_pkg_apis_alerting_v0alpha1_TimeInterval(ref common.ReferenceCallback
SchemaProps: spec.SchemaProps{
Description: "Spec is the spec of the TimeInterval",
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalSpec"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalSpec"),
},
},
"status": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalStatus"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalStatus"),
},
},
},
@@ -1022,11 +1022,11 @@ func schema_pkg_apis_alerting_v0alpha1_TimeInterval(ref common.ReferenceCallback
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalSpec", "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalSpec", "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
}
}
func schema_pkg_apis_alerting_v0alpha1_TimeIntervalInterval(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_TimeIntervalInterval(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -1039,7 +1039,7 @@ func schema_pkg_apis_alerting_v0alpha1_TimeIntervalInterval(ref common.Reference
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalTimeRange"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalTimeRange"),
},
},
},
@@ -1111,11 +1111,11 @@ func schema_pkg_apis_alerting_v0alpha1_TimeIntervalInterval(ref common.Reference
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalTimeRange"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalTimeRange"},
}
}
func schema_pkg_apis_alerting_v0alpha1_TimeIntervalList(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_TimeIntervalList(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -1148,7 +1148,7 @@ func schema_pkg_apis_alerting_v0alpha1_TimeIntervalList(ref common.ReferenceCall
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeInterval"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeInterval"),
},
},
},
@@ -1159,11 +1159,11 @@ func schema_pkg_apis_alerting_v0alpha1_TimeIntervalList(ref common.ReferenceCall
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeInterval", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeInterval", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
}
}
func schema_pkg_apis_alerting_v0alpha1_TimeIntervalSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_TimeIntervalSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -1183,7 +1183,7 @@ func schema_pkg_apis_alerting_v0alpha1_TimeIntervalSpec(ref common.ReferenceCall
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalInterval"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalInterval"),
},
},
},
@@ -1194,11 +1194,11 @@ func schema_pkg_apis_alerting_v0alpha1_TimeIntervalSpec(ref common.ReferenceCall
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalInterval"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalInterval"},
}
}
func schema_pkg_apis_alerting_v0alpha1_TimeIntervalStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_TimeIntervalStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -1213,7 +1213,7 @@ func schema_pkg_apis_alerting_v0alpha1_TimeIntervalStatus(ref common.ReferenceCa
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalstatusOperatorState"),
Ref: ref("github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalstatusOperatorState"),
},
},
},
@@ -1238,11 +1238,11 @@ func schema_pkg_apis_alerting_v0alpha1_TimeIntervalStatus(ref common.ReferenceCa
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1.TimeIntervalstatusOperatorState"},
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1.TimeIntervalstatusOperatorState"},
}
}
func schema_pkg_apis_alerting_v0alpha1_TimeIntervalTimeRange(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_TimeIntervalTimeRange(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -1269,7 +1269,7 @@ func schema_pkg_apis_alerting_v0alpha1_TimeIntervalTimeRange(ref common.Referenc
}
}
func schema_pkg_apis_alerting_v0alpha1_TimeIntervalstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_alertingnotifications_v0alpha1_TimeIntervalstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -0,0 +1,157 @@
//
// This file is generated by grafana-app-sdk
// DO NOT EDIT
//
package apis
import (
"encoding/json"
"fmt"
"strings"
"github.com/grafana/grafana-app-sdk/app"
"github.com/grafana/grafana-app-sdk/resource"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kube-openapi/pkg/spec3"
v0alpha1 "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1"
)
var (
rawSchemaReceiverv0alpha1 = []byte(`{"Integration":{"additionalProperties":false,"properties":{"disableResolveMessage":{"type":"boolean"},"secureFields":{"additionalProperties":{"type":"boolean"},"type":"object"},"settings":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"type":{"type":"string"},"uid":{"type":"string"},"version":{"type":"string"}},"required":["type","version","settings"],"type":"object"},"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"Receiver":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"spec":{"additionalProperties":false,"properties":{"integrations":{"items":{"$ref":"#/components/schemas/Integration"},"type":"array"},"title":{"type":"string"}},"required":["title","integrations"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
versionSchemaReceiverv0alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaReceiverv0alpha1, &versionSchemaReceiverv0alpha1)
rawSchemaRoutingTreev0alpha1 = []byte(`{"Matcher":{"additionalProperties":false,"properties":{"label":{"type":"string"},"type":{"enum":["=","!=","=~","!~"],"type":"string"},"value":{"type":"string"}},"required":["type","label","value"],"type":"object"},"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"Route":{"additionalProperties":false,"properties":{"active_time_intervals":{"items":{"type":"string"},"type":"array"},"continue":{"type":"boolean"},"group_by":{"items":{"type":"string"},"type":"array"},"group_interval":{"type":"string"},"group_wait":{"type":"string"},"matchers":{"items":{"$ref":"#/components/schemas/Matcher"},"type":"array"},"mute_time_intervals":{"items":{"type":"string"},"type":"array"},"receiver":{"type":"string"},"repeat_interval":{"type":"string"},"routes":{"items":{"$ref":"#/components/schemas/Route"},"type":"array"}},"required":["continue"],"type":"object"},"RouteDefaults":{"additionalProperties":false,"properties":{"group_by":{"items":{"type":"string"},"type":"array"},"group_interval":{"type":"string"},"group_wait":{"type":"string"},"receiver":{"type":"string"},"repeat_interval":{"type":"string"}},"required":["receiver"],"type":"object"},"RoutingTree":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"spec":{"additionalProperties":false,"properties":{"defaults":{"$ref":"#/components/schemas/RouteDefaults"},"routes":{"items":{"$ref":"#/components/schemas/Route"},"type":"array"}},"required":["defaults","routes"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
versionSchemaRoutingTreev0alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaRoutingTreev0alpha1, &versionSchemaRoutingTreev0alpha1)
rawSchemaTemplateGroupv0alpha1 = []byte(`{"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"TemplateGroup":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"spec":{"additionalProperties":false,"properties":{"content":{"type":"string"},"title":{"type":"string"}},"required":["title","content"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
versionSchemaTemplateGroupv0alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaTemplateGroupv0alpha1, &versionSchemaTemplateGroupv0alpha1)
rawSchemaTimeIntervalv0alpha1 = []byte(`{"Interval":{"additionalProperties":false,"properties":{"days_of_month":{"items":{"type":"string"},"type":"array"},"location":{"type":"string"},"months":{"items":{"type":"string"},"type":"array"},"times":{"items":{"$ref":"#/components/schemas/TimeRange"},"type":"array"},"weekdays":{"items":{"type":"string"},"type":"array"},"years":{"items":{"type":"string"},"type":"array"}},"type":"object"},"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"TimeInterval":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"TimeRange":{"additionalProperties":false,"properties":{"end_time":{"type":"string"},"start_time":{"type":"string"}},"required":["start_time","end_time"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"name":{"type":"string"},"time_intervals":{"items":{"$ref":"#/components/schemas/Interval"},"type":"array"}},"required":["name","time_intervals"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
versionSchemaTimeIntervalv0alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaTimeIntervalv0alpha1, &versionSchemaTimeIntervalv0alpha1)
)
var appManifestData = app.ManifestData{
AppName: "alerting-notifications",
Group: "notifications.alerting.grafana.app",
Versions: []app.ManifestVersion{
{
Name: "v0alpha1",
Served: true,
Kinds: []app.ManifestVersionKind{
{
Kind: "Receiver",
Plural: "Receivers",
Scope: "Namespaced",
Conversion: false,
Schema: &versionSchemaReceiverv0alpha1,
},
{
Kind: "RoutingTree",
Plural: "RoutingTrees",
Scope: "Namespaced",
Conversion: false,
Schema: &versionSchemaRoutingTreev0alpha1,
},
{
Kind: "TemplateGroup",
Plural: "TemplateGroups",
Scope: "Namespaced",
Conversion: false,
Schema: &versionSchemaTemplateGroupv0alpha1,
},
{
Kind: "TimeInterval",
Plural: "TimeIntervals",
Scope: "Namespaced",
Conversion: false,
Schema: &versionSchemaTimeIntervalv0alpha1,
},
},
Routes: app.ManifestVersionRoutes{
Namespaced: map[string]spec3.PathProps{},
Cluster: map[string]spec3.PathProps{},
},
},
},
}
func LocalManifest() app.Manifest {
return app.NewEmbeddedManifest(appManifestData)
}
func RemoteManifest() app.Manifest {
return app.NewAPIServerManifest("alerting-notifications")
}
var kindVersionToGoType = map[string]resource.Kind{
"Receiver/v0alpha1": v0alpha1.ReceiverKind(),
"RoutingTree/v0alpha1": v0alpha1.RoutingTreeKind(),
"TemplateGroup/v0alpha1": v0alpha1.TemplateGroupKind(),
"TimeInterval/v0alpha1": v0alpha1.TimeIntervalKind(),
}
// ManifestGoTypeAssociator returns the associated resource.Kind instance for a given Kind and Version, if one exists.
// If there is no association for the provided Kind and Version, exists will return false.
func ManifestGoTypeAssociator(kind, version string) (goType resource.Kind, exists bool) {
goType, exists = kindVersionToGoType[fmt.Sprintf("%s/%s", kind, version)]
return goType, exists
}
var customRouteToGoResponseType = map[string]any{}
// 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.
// If there is no association for the provided kind, version, custom route path, and method, exists will return false.
// Resource routes (those without a kind) should prefix their route with "<namespace>/" if the route is namespaced (otherwise the route is assumed to be cluster-scope)
func ManifestCustomRouteResponsesAssociator(kind, version, path, verb string) (goType any, exists bool) {
if len(path) > 0 && path[0] == '/' {
path = path[1:]
}
goType, exists = customRouteToGoResponseType[fmt.Sprintf("%s|%s|%s|%s", version, kind, path, strings.ToUpper(verb))]
return goType, exists
}
var customRouteToGoParamsType = map[string]runtime.Object{}
func ManifestCustomRouteQueryAssociator(kind, version, path, verb string) (goType runtime.Object, exists bool) {
if len(path) > 0 && path[0] == '/' {
path = path[1:]
}
goType, exists = customRouteToGoParamsType[fmt.Sprintf("%s|%s|%s|%s", version, kind, path, strings.ToUpper(verb))]
return goType, exists
}
var customRouteToGoRequestBodyType = map[string]any{}
func ManifestCustomRouteRequestBodyAssociator(kind, version, path, verb string) (goType any, exists bool) {
if len(path) > 0 && path[0] == '/' {
path = path[1:]
}
goType, exists = customRouteToGoRequestBodyType[fmt.Sprintf("%s|%s|%s|%s", version, kind, path, strings.ToUpper(verb))]
return goType, exists
}
type GoTypeAssociator struct{}
func NewGoTypeAssociator() *GoTypeAssociator {
return &GoTypeAssociator{}
}
func (g *GoTypeAssociator) KindToGoType(kind, version string) (goType resource.Kind, exists bool) {
return ManifestGoTypeAssociator(kind, version)
}
func (g *GoTypeAssociator) CustomRouteReturnGoType(kind, version, path, verb string) (goType any, exists bool) {
return ManifestCustomRouteResponsesAssociator(kind, version, path, verb)
}
func (g *GoTypeAssociator) CustomRouteQueryGoType(kind, version, path, verb string) (goType runtime.Object, exists bool) {
return ManifestCustomRouteQueryAssociator(kind, version, path, verb)
}
func (g *GoTypeAssociator) CustomRouteRequestBodyGoType(kind, version, path, verb string) (goType any, exists bool) {
return ManifestCustomRouteRequestBodyAssociator(kind, version, path, verb)
}
+1 -1
View File
@@ -4,7 +4,7 @@ import (
sdkResource "github.com/grafana/grafana-app-sdk/resource"
"k8s.io/apimachinery/pkg/runtime/schema"
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1"
)
func GetKinds() map[schema.GroupVersion][]sdkResource.Kind {
+1 -1
View File
@@ -200,7 +200,7 @@ require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/google/wire v0.6.0 // indirect
github.com/google/wire v0.7.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.14.2 // indirect
github.com/gorilla/mux v1.8.1 // indirect
+2 -37
View File
@@ -694,12 +694,11 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI=
github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA=
github.com/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4=
github.com/google/wire v0.7.0/go.mod h1:n6YbUQD9cPKTnHXEBN2DXlOp/mVADhVErcMFb0v3J18=
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
@@ -1333,7 +1332,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM=
@@ -1469,12 +1467,9 @@ golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1518,10 +1513,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1578,11 +1569,6 @@ golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1621,10 +1607,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1717,24 +1699,15 @@ golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8=
golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1746,10 +1719,6 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1818,10 +1787,6 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
golang.org/x/tools/godoc v0.1.0-deprecated h1:o+aZ1BOj6Hsx/GBdJO/s815sqftjSnrZZwyYTHODvtk=
+28
View File
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
shopt -s nullglob # Enable nullglob
blocks_dir=docker/blocks
docker_dir=docker
template_dir=templates
@@ -8,6 +10,8 @@ grafana_config_file=conf.tmp
grafana_config=config
compose_header_file=docker/compose_header.yml
compose_volume_section_file=docker/compose_volume_section.yml
compose_volume_section_create_flag=docker_volume_create_true
compose_file=docker-compose.yaml
env_file=.env
@@ -60,3 +64,27 @@ for dir in $@; do
fi
done
volume_files=$($blocks_dir/**/$compose_volume_section_create_flag)
if [[ ${#volume_files[@]} -ne 0 ]]; then
echo "Adding volume section to $compose_file"
cat $compose_volume_section_file >> $compose_file
echo "" >> $compose_file
for dir in $@; do
current_dir=$blocks_dir/$dir
if [ ! -d "$current_dir" ]; then
echo "$current_dir is not a directory"
exit 1
fi
if [ -f $current_dir/$compose_volume_section_create_flag ]; then
echo "Adding volume for $current_dir to $compose_file"
echo " $dir-data-volume:" >> $compose_file
echo "" >> $compose_file
fi
done
cat $compose_file
fi
+1
View File
@@ -0,0 +1 @@
volumes:
@@ -0,0 +1,20 @@
---
description: Guide for upgrading to Grafana v12.2
keywords:
- grafana
- configuration
- documentation
- upgrade
- '12.2'
title: Upgrade to Grafana v12.2
menuTitle: Upgrade to v12.2
weight: 498
---
# Upgrade to Grafana v12.2
{{< docs/shared lookup="upgrade/intro_2.md" source="grafana" version="<GRAFANA_VERSION>" >}}
{{< docs/shared lookup="back-up/back-up-grafana.md" source="grafana" version="<GRAFANA_VERSION>" leveloffset="+1" >}}
{{< docs/shared lookup="upgrade/upgrade-common-tasks.md" source="grafana" version="<GRAFANA_VERSION>" >}}
+1
View File
@@ -192,6 +192,7 @@ For a complete list of every change, with links to pull requests and related iss
## Grafana 12
- [What's new in 12.2](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/whatsnew/whats-new-in-v12-2)
- [What's new in 12.1](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/whatsnew/whats-new-in-v12-1)
- [What's new in 12.0](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/whatsnew/whats-new-in-v12-0)
@@ -0,0 +1,72 @@
---
description: Feature and improvement highlights for Grafana v12.2
keywords:
- grafana
- new
- documentation
- '12.2'
- release notes
labels:
products:
- cloud
- enterprise
- oss
title: What's new in Grafana v12.2
posts:
- title: SQL expressions
items:
- whats-new/2025-09-05-sql-expressions.md
- title: Dashboards and visualizations
items:
- whats-new/2025-08-22-new-table-visualization-is-generally-available.md
- whats-new/2025-08-27-generate-tooltips-from-table-fields.md
- whats-new/2025-08-27-improved-footer-for-table-visualization.md
- whats-new/2025-07-17-disable-tooltips-in-canvas-visualizations.md
- whats-new/2025-07-14-static-options-for-query-variable.md
- whats-new/2025-07-24-dynamic-connection-direction-in-canvas.md
- whats-new/2025-08-04-canvas-pan-zoom-improvements.md
- whats-new/2025-09-01-actions-authentication-via-infinity-datasource.md
- whats-new/2025-09-02-enhanced-ad-hoc-filter-support.md
- whats-new/2025-09-02-new-dashboard-apis-now-enabled-by-default.md
- title: Reporting
items:
- whats-new/2025-05-27-new-and-improved-reporting.md
- title: Data sources
items:
- whats-new/2025-08-12-jenkins-enterprise-data-source-for-grafana.md
- whats-new/2025-07-16-google-sheets-data-source-now-supports-template-variables.md
- whats-new/2025-09-04-azure-monitor-resource-picker-filtering-and-recent-resources.md
- title: Explore
items:
- whats-new/2025-07-08-saved-queries-in-dashboards-and-explore.md
- title: Logs Drilldown
items:
- whats-new/2025-08-29-json-log-line-viewer-in-logs-drilldown-is-now-generally-available.md
- title: Metrics Drilldown
items:
- whats-new/2025-08-07-grafana-metrics-drilldown-entry-point-from-alerting-rule.md
- title: Plugins
items:
- whats-new/2025-09-11-translate-your-plugin.md
- title: Authentication and authorization
items:
- whats-new/2025-09-10-scim-configuration-ui.md
whats_new_grafana_version: 12.2
weight: -51
---
# What’s new in Grafana v12.2
Welcome to Grafana 12.2! This release focuses on making it easier to gain insights from your data.
We're excited to announce several features are now GA. Enhanced ad hoc filtering transforms your dashboards into true command centers, allowing you to slice and dice datasets on the fly. The redesigned table visualization offers improved performance and visual aids for quick pattern and anomaly identification, helping you make faster decisions. The Logs Drilldown JSON viewer makes intimidating log structures organized and explorable. Metrics Drilldown now integrates with alert creation in Grafana, so you can explore Prometheus data with intuitive point-and-click interactions, find the right visualization, and easily use its query in your alert rule.
We're also collecting feedback on some new public preview features. AI-powered SQL expressions eliminate the barrier between questions and answers by generating SQL queries from natural language and providing instant explanations for existing queries. Our enhanced Canvas Pan and Zoom experience lets you design complex dashboards exactly as you envision them.
Keep reading to learn more about everything 12.2 has in store.
{{< youtube id=-7A_tePidEM >}}
For even more detail about all the changes in this release, refer to the [changelog](https://github.com/grafana/grafana/blob/main/CHANGELOG.md). For the specific steps we recommend when you upgrade to v12.2, check out our [Upgrade Guide](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/upgrade-guide/upgrade-v12.2/).
{{< docs/whats-new >}}
@@ -134,8 +134,8 @@ test.describe(
expect.soft(await timePickerButton.textContent()).toContain('2024-01-01 08:30:00 to 2024-01-01 08:40:00');
const forwardBtn = page.locator('button[aria-label="Move time range forwards"]');
const backwardBtn = page.locator('button[aria-label="Move time range backwards"]');
const forwardBtn = page.locator('button[aria-label*="Move"][aria-label*="forward"]');
const backwardBtn = page.locator('button[aria-label*="Move"][aria-label*="backward"]');
await forwardBtn.click();
@@ -169,12 +169,15 @@ test.describe(
await searchScopes(page, scopeSearchOne, [secondLevelScopes[0]]);
await expect.soft(scopeTreeCheckboxes).toHaveCount(1);
expect.soft(await scopeTreeCheckboxes.first().locator('../..').textContent()).toBe(scopeSearchOne);
// Check grandparent title, to make sure we get what we want
expect.soft(await scopeTreeCheckboxes.first().locator('../../..').textContent()).toBe(scopeSearchOne);
await searchScopes(page, scopeSearchTwo, [secondLevelScopes[1]]);
await expect.soft(scopeTreeCheckboxes).toHaveCount(1);
expect.soft(await scopeTreeCheckboxes.first().locator('../..').textContent()).toBe(scopeSearchTwo);
// Check grandparent title, to make sure we get what we want
expect.soft(await scopeTreeCheckboxes.first().locator('../../..').textContent()).toBe(scopeSearchTwo);
});
});
}
@@ -3,13 +3,14 @@ import { test, expect } from '@grafana/plugin-e2e';
import pluginJson from '../plugin.json';
import testApp3pluginJson from '../plugins/grafana-extensionexample3-app/plugin.json';
import { testIds } from '../testIds';
import { selectors } from '@grafana/e2e-selectors';
test.describe('grafana-extensionstest-app', { tag: ['@plugins'] }, () => {
test('should extend the actions menu with a link to a-app plugin', async ({ page }) => {
await page.goto(`/a/${pluginJson.id}/added-links`);
const section = await page.getByTestId(testIds.addedLinksPage.section1);
await section.getByTestId(testIds.actions.button).click();
await page.getByTestId(testIds.container).getByText('Go to A').click();
await page.getByTestId(selectors.components.Portal.container).getByText('Go to A').click();
await page.getByTestId(testIds.modal.open).click();
await expect(page.getByTestId(testIds.appA.container)).toBeVisible();
});
@@ -18,7 +19,7 @@ test.describe('grafana-extensionstest-app', { tag: ['@plugins'] }, () => {
await page.goto(`/a/${pluginJson.id}/added-links`);
const section = await page.getByTestId(testIds.addedLinksPage.section1);
await section.getByTestId(testIds.actions.button).click();
await page.getByTestId(testIds.container).getByText('Open from B').click();
await page.getByTestId(selectors.components.Portal.container).getByText('Open from B').click();
await expect(page.getByTestId(testIds.appB.modal)).toBeVisible();
});
@@ -26,7 +27,7 @@ test.describe('grafana-extensionstest-app', { tag: ['@plugins'] }, () => {
await page.goto(`/a/${pluginJson.id}/added-links`);
const section = await page.getByTestId(testIds.addedLinksPage.section1);
await section.getByTestId(testIds.actions.button).click();
await page.getByTestId(testIds.container).getByText('Basic link').click();
await page.getByTestId(selectors.components.Portal.container).getByText('Basic link').click();
await page.getByTestId(testIds.modal.open).click();
await expect(page.getByTestId(testIds.appA.container)).toBeVisible();
});
+6 -4
View File
@@ -262,13 +262,15 @@ export async function getScopeLeafName(page: Page, nth: number): Promise<string>
}
export async function getScopeLeafTitle(page: Page, nth: number): Promise<string> {
const locator = page.getByTestId(/^scopes-tree-.*-(checkbox|radio)/).nth(nth);
const scopeTitle = await locator.locator('../..').textContent();
const leafLocator = page.getByTestId(/^scopes-tree-.*-(checkbox|radio)/).nth(nth);
// Find the closest ancestor element that has the main tree item test id
const titleLocator = leafLocator.locator(
'xpath=ancestor::*[@data-testid][starts-with(@data-testid, "scopes-tree-") and not(contains(@data-testid, "-checkbox")) and not(contains(@data-testid, "-radio")) and not(contains(@data-testid, "-expand"))]'
);
const scopeTitle = await titleLocator.textContent();
if (!scopeTitle) {
throw new Error('There are no scopes in the selector');
}
return scopeTitle;
}
@@ -85,5 +85,63 @@ test.describe(
expectedRange = 'Time range selected: 2024-06-05 10:04:00 to 2024-06-05 10:05:00'; // 1 min back
await expect(timePickerButton).toHaveAttribute('aria-label', expectedRange);
});
test('ctrl+o should toggle shared crosshair', async ({ page, selectors }) => {
// Navigate to a new dashboard
await page.goto('/dashboard/new?orgId=1');
// Wait for dashboard to load
await page.waitForLoadState('networkidle');
// Wait for dashboard to be fully initialized by checking for dashboard content
await page
.locator('[data-testid*="dashboard"]')
.or(page.locator('text=Start your new dashboard'))
.first()
.waitFor({ state: 'visible' });
// Test the keyboard shortcut first in the main dashboard view
const currentUrl = page.url();
const modKey = process.platform === 'darwin' ? 'Meta' : 'Control';
// Test that mod+o works in the main dashboard (should not trigger file dialog)
console.log('Testing mod+o in main dashboard view...');
await page.keyboard.press(`${modKey}+o`);
expect(page.url()).toBe(currentUrl); // Should not navigate away
// Now open settings to check if the state actually changed
await page.keyboard.press('d');
await page.keyboard.press('s');
// Wait for settings page to load by checking for the General tab or settings content
await page
.locator('text=General')
.or(page.locator('[data-testid*="dashboard-settings"]'))
.waitFor({ state: 'visible' });
// Wait for Panel options section to be visible and scroll to it
const panelOptionsSection = page.locator('text=Panel options');
await panelOptionsSection.waitFor({ state: 'visible' });
await panelOptionsSection.scrollIntoViewIfNeeded();
// Wait for radio buttons to be visible
await page
.locator('[role="radiogroup"]')
.last()
.locator('input[type="radio"]')
.first()
.waitFor({ state: 'visible' });
// Check current state - after one mod+o press, it should be crosshair (1)
await expect(page.locator('[role="radiogroup"]').last().locator('input[type="radio"]').nth(1)).toBeChecked(); // Shared crosshair
// Test second press in the main dashboard view (should go to tooltip)
await page.keyboard.press(`${modKey}+o`);
await expect(page.locator('[role="radiogroup"]').last().locator('input[type="radio"]').nth(2)).toBeChecked(); // Shared tooltip
// Test third press in the main dashboard view (should go back to default)
await page.keyboard.press(`${modKey}+o`);
await expect(page.locator('[role="radiogroup"]').last().locator('input[type="radio"]').nth(0)).toBeChecked(); // Default
});
}
);
-5
View File
@@ -1809,11 +1809,6 @@
"count": 1
}
},
"public/app/features/alerting/unified/rule-list/StateView.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/alerting/unified/types/alerting.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 5
+1 -1
View File
@@ -82,7 +82,7 @@ require (
github.com/google/go-github/v70 v70.0.0 // indirect; @grafana/grafana-git-ui-sync-team
github.com/google/go-querystring v1.1.0 // indirect; @grafana/oss-big-tent
github.com/google/uuid v1.6.0 // @grafana/grafana-backend-group
github.com/google/wire v0.6.0 // @grafana/grafana-backend-group
github.com/google/wire v0.7.0 // @grafana/grafana-backend-group
github.com/googleapis/gax-go/v2 v2.14.2 // @grafana/grafana-backend-group
github.com/gorilla/mux v1.8.1 // @grafana/grafana-backend-group
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // @grafana/grafana-app-platform-squad
+2 -5
View File
@@ -1528,7 +1528,6 @@ github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkj
github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -1538,8 +1537,8 @@ github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI=
github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA=
github.com/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4=
github.com/google/wire v0.7.0/go.mod h1:n6YbUQD9cPKTnHXEBN2DXlOp/mVADhVErcMFb0v3J18=
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
@@ -2785,7 +2784,6 @@ golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
@@ -3204,7 +3202,6 @@ golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
+2 -2
View File
@@ -1055,6 +1055,7 @@ github.com/grafana/dskit v0.0.0-20250818234656-8ff9c6532e85/go.mod h1:kImsvJ1xnm
github.com/grafana/go-gelf/v2 v2.0.1 h1:BOChP0h/jLeD+7F9mL7tq10xVkDG15he3T1zHuQaWak=
github.com/grafana/go-gelf/v2 v2.0.1/go.mod h1:lexHie0xzYGwCgiRGcvZ723bSNyNI8ZRD4s0CLobh90=
github.com/grafana/gomemcache v0.0.0-20250228145437-da7b95fd2ac1/go.mod h1:j/s0jkda4UXTemDs7Pgw/vMT06alWc42CHisvYac0qw=
github.com/grafana/gomemcache v0.0.0-20250828162811-a96f6acee2fe/go.mod h1:j/s0jkda4UXTemDs7Pgw/vMT06alWc42CHisvYac0qw=
github.com/grafana/grafana-app-sdk v0.40.1/go.mod h1:4P8h7VB6KcDjX9bAoBQc6IP8iNylxe6bSXLR9gA39gM=
github.com/grafana/grafana-app-sdk v0.41.0 h1:SYHN3U7B1myRKY3UZZDkFsue9TDmAOap0UrQVTqtYBU=
github.com/grafana/grafana-app-sdk v0.41.0/go.mod h1:Wg/3vEZfok1hhIWiHaaJm+FwkosfO98o8KbeLFEnZpY=
@@ -1068,8 +1069,6 @@ github.com/grafana/grafana-app-sdk/logging v0.43.1/go.mod h1:0xrjKSGY5z+NLGuGsXQ
github.com/grafana/grafana-app-sdk/logging v0.43.2/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grafana/grafana-app-sdk/plugin v0.41.0 h1:ShUvGpAVzM3UxcsfwS6l/lwW4ytDeTbCQXf8w2P8Yp8=
github.com/grafana/grafana-app-sdk/plugin v0.41.0/go.mod h1:YIhimVfAqtOp3kdhxOanaSZjypVKh/bYxf9wfFfhDm0=
github.com/grafana/grafana-app-sdk/plugin v0.45.0 h1:rK4FL5h7SqGBDeUdrUjHVGnwgN6w8deQAKx8gJ27Iew=
github.com/grafana/grafana-app-sdk/plugin v0.45.0/go.mod h1:fZ6lWVMWr0EpkmyocxZ7MTTc9x6b2jYM93+gjlMgVD4=
github.com/grafana/grafana-aws-sdk v0.38.2 h1:TzQD0OpWsNjtldi5G5TLDlBRk8OyDf+B5ujcoAu4Dp0=
github.com/grafana/grafana-aws-sdk v0.38.2/go.mod h1:j3vi+cXYHEFqjhBGrI6/lw1TNM+dl0Y3f0cSnDOPy+s=
github.com/grafana/grafana-aws-sdk v1.0.2 h1:98eBuHYFmgvH0xO9kKf4RBsEsgQRp8EOA/9yhDIpkss=
@@ -2034,6 +2033,7 @@ golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
golang.org/x/tools v0.24.1/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
+2 -2
View File
@@ -286,8 +286,8 @@
"@grafana/plugin-ui": "^0.10.10",
"@grafana/prometheus": "workspace:*",
"@grafana/runtime": "workspace:*",
"@grafana/scenes": "6.35.3",
"@grafana/scenes-react": "6.35.3",
"@grafana/scenes": "6.38.0",
"@grafana/scenes-react": "6.38.0",
"@grafana/schema": "workspace:*",
"@grafana/sql": "workspace:*",
"@grafana/ui": "workspace:*",
@@ -1249,6 +1249,7 @@ export type ReceiverIntegration = {
};
type: string;
uid?: string;
version: string;
};
export type ReceiverSpec = {
integrations: ReceiverIntegration[];
@@ -47,10 +47,12 @@ export const GenericIntegrationFactory = Factory.define<Integration>(() => ({
settings: {
foo: 'bar',
},
version: 'v1', // Add version field
}));
export const EmailIntegrationFactory = Factory.define<Integration>(() => ({
type: 'email',
version: 'v1',
settings: {
addresses: faker.internet.email(),
},
@@ -58,6 +60,7 @@ export const EmailIntegrationFactory = Factory.define<Integration>(() => ({
export const SlackIntegrationFactory = Factory.define<Integration>(() => ({
type: 'slack',
version: 'v1',
settings: {
mentionChannel: '#alerts',
},
@@ -70,5 +73,6 @@ export const ContactPointMetadataAnnotationsFactory = Factory.define<ContactPoin
'grafana.com/access/canReadSecrets': 'true',
'grafana.com/inUse/routes': '1',
'grafana.com/inUse/rules': '1',
'grafana.com/canUse': 'true',
...AlertingEntityMetadataAnnotationsFactory.build(),
}));
@@ -17,6 +17,7 @@ type EmailIntegration = OverrideProperties<
GenericIntegration,
{
type: 'email';
version: 'v1';
settings: {
singleEmail?: boolean;
addresses: string;
@@ -32,6 +33,7 @@ type SlackIntegration = OverrideProperties<
GenericIntegration,
{
type: 'slack';
version: 'v1';
settings: {
endpointUrl?: string;
url?: string;
@@ -56,6 +58,7 @@ type OnCallIntegration = OverrideProperties<
GenericIntegration,
{
type: 'OnCall';
version: 'v1';
settings: {
url: string;
httpMethod?: 'POST' | 'PUT';
@@ -98,6 +101,7 @@ export type AlertingEntityMetadataAnnotations = Partial<{
'grafana.com/access/canAdmin': 'true' | 'false';
'grafana.com/access/canDelete': 'true' | 'false';
'grafana.com/access/canWrite': 'true' | 'false';
'grafana.com/canUse': 'true' | 'false';
// used for provisioning to identify what system created the entity
'grafana.com/provenance': string;
}>;
+1 -1
View File
@@ -16,7 +16,7 @@ export const palette = {
darkBorder2: '#64646b',
// Dashboard bg / layer 0 (light theme)
gray90: '#f4f5f5',
gray90: '#fbfbfb',
// Card bg / layer 1
gray100: '#f4f5f5',
// divider line
@@ -111,6 +111,10 @@ export interface FeatureToggles {
*/
influxdbBackendMigration?: boolean;
/**
* populate star status from apiserver
*/
starsFromAPIServer?: boolean;
/**
* Enable streaming JSON parser for InfluxDB datasource InfluxQL query language
*/
influxqlStreamingParser?: boolean;
@@ -5,7 +5,7 @@ import * as React from 'react';
import { GrafanaTheme2, ThemeRichColor } from '@grafana/data';
import { useTheme2 } from '../../themes/ThemeContext';
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
import { getButtonFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
import { IconName, IconSize, IconType } from '../../types/icon';
import { ComponentSize } from '../../types/size';
import { getPropertiesForButtonSize } from '../Forms/commonStyles';
@@ -234,7 +234,7 @@ export const getButtonStyles = (props: StyleProps) => {
const { height, padding, fontSize } = getPropertiesForButtonSize(size, theme);
const variantStyles = getPropertiesForVariant(theme, variant, fill);
const disabledStyles = getPropertiesForDisabled(theme, variant, fill);
const focusStyle = getFocusStyles(theme);
const focusStyle = getButtonFocusStyles(theme);
const paddingMinusBorder = theme.spacing.gridSize * padding - 1;
return {
@@ -263,6 +263,12 @@ export const getButtonStyles = (props: StyleProps) => {
...variantStyles,
':disabled': disabledStyles,
'&[disabled]': disabledStyles,
[theme.transitions.handleMotion('no-preference', 'reduce')]: {
transition: theme.transitions.create(['background-color', 'border-color', 'color'], {
duration: theme.transitions.duration.short,
}),
},
}),
disabled: css(disabledStyles, {
'&:hover': css(disabledStyles),
@@ -290,12 +296,18 @@ export const getButtonStyles = (props: StyleProps) => {
};
};
function getButtonVariantStyles(theme: GrafanaTheme2, color: ThemeRichColor, fill: ButtonFill) {
export function getActiveButtonStyles(color: ThemeRichColor, fill: ButtonFill) {
return {
background: fill === 'solid' ? color.main : 'transparent',
};
}
export function getButtonVariantStyles(theme: GrafanaTheme2, color: ThemeRichColor, fill: ButtonFill) {
let outlineBorderColor = color.border;
let borderColor = 'transparent';
let hoverBorderColor = 'transparent';
// Secondary button has some special rules as we lack theem color token to
// Secondary button has some special rules as we lack the color token to
// specify border color for normal button vs border color for outline button
if (color.name === 'secondary') {
borderColor = color.border;
@@ -308,15 +320,16 @@ function getButtonVariantStyles(theme: GrafanaTheme2, color: ThemeRichColor, fil
background: 'transparent',
color: color.text,
border: `1px solid ${outlineBorderColor}`,
transition: theme.transitions.create(['background-color', 'border-color', 'color'], {
duration: theme.transitions.duration.short,
}),
'&:hover': {
'&:hover, &:focus': {
background: color.transparent,
borderColor: theme.colors.emphasize(outlineBorderColor, 0.25),
color: color.text,
},
'&:active': {
...getActiveButtonStyles(color, fill),
},
};
}
@@ -325,18 +338,15 @@ function getButtonVariantStyles(theme: GrafanaTheme2, color: ThemeRichColor, fil
background: 'transparent',
color: color.text,
border: '1px solid transparent',
transition: theme.transitions.create(['background-color', 'color'], {
duration: theme.transitions.duration.short,
}),
'&:focus': {
outline: 'none',
textDecoration: 'none',
},
'&:hover': {
'&:hover, &:focus': {
background: color.transparent,
textDecoration: 'none',
outline: 'none',
},
'&:active': {
...getActiveButtonStyles(color, fill),
},
};
}
@@ -345,9 +355,6 @@ function getButtonVariantStyles(theme: GrafanaTheme2, color: ThemeRichColor, fil
background: color.main,
color: color.contrastText,
border: `1px solid ${borderColor}`,
transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], {
duration: theme.transitions.duration.short,
}),
'&:hover': {
background: color.shade,
@@ -355,6 +362,15 @@ function getButtonVariantStyles(theme: GrafanaTheme2, color: ThemeRichColor, fil
boxShadow: theme.shadows.z1,
borderColor: hoverBorderColor,
},
'&:focus': {
background: color.shade,
color: color.contrastText,
},
'&:active': {
...getActiveButtonStyles(color, fill),
},
};
}
@@ -364,6 +380,7 @@ function getPropertiesForDisabled(theme: GrafanaTheme2, variant: ButtonVariant,
boxShadow: 'none',
color: theme.colors.text.disabled,
transition: 'none',
background: theme.colors.action.disabledBackground,
};
if (fill === 'text') {
@@ -55,6 +55,8 @@ export interface TimeRangePickerProps {
onChangeFiscalYearStartMonth?: (month: number) => void;
onMoveBackward: () => void;
onMoveForward: () => void;
moveForwardTooltip?: string;
moveBackwardTooltip?: string;
onZoom: () => void;
onError?: (error?: string) => void;
history?: TimeRange[];
@@ -78,6 +80,8 @@ export function TimeRangePicker(props: TimeRangePickerProps) {
value,
onMoveBackward,
onMoveForward,
moveForwardTooltip,
moveBackwardTooltip,
onZoom,
onError,
timeZone,
@@ -150,11 +154,14 @@ export function TimeRangePicker(props: TimeRangePickerProps) {
return (
<ButtonGroup className={styles.container}>
<ToolbarButton
aria-label={t('time-picker.range-picker.backwards-time-aria-label', 'Move time range backwards')}
variant={variant}
onClick={onMoveBackward}
icon="angle-left"
icon="angle-double-left"
type="button"
iconSize="xl"
tooltip={
moveBackwardTooltip ?? t('time-picker.range-picker.backwards-time-aria-label', 'Move time range backwards')
}
narrow
/>
@@ -207,12 +214,15 @@ export function TimeRangePicker(props: TimeRangePickerProps) {
{timeSyncButton}
<ToolbarButton
aria-label={t('time-picker.range-picker.forwards-time-aria-label', 'Move time range forwards')}
onClick={onMoveForward}
icon="angle-right"
narrow
icon="angle-double-right"
type="button"
variant={variant}
iconSize="xl"
tooltip={
moveForwardTooltip ?? t('time-picker.range-picker.forwards-time-aria-label', 'Move time range forwards')
}
narrow
/>
<Tooltip content={ZoomOutTooltip} placement="bottom">
@@ -1,17 +1,15 @@
import { css } from '@emotion/css';
import { autoUpdate, offset, useClick, useDismiss, useFloating, useInteractions } from '@floating-ui/react';
import { FocusScope } from '@react-aria/focus';
import { memo, HTMLAttributes, useState } from 'react';
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
import { SelectableValue } from '@grafana/data';
import { useStyles2 } from '../../themes/ThemeContext';
import { getPositioningMiddleware } from '../../utils/floating';
import { Menu } from '../Menu/Menu';
import { MenuItem } from '../Menu/MenuItem';
import { ScrollContainer } from '../ScrollContainer/ScrollContainer';
import { ToolbarButton, ToolbarButtonVariant } from '../ToolbarButton/ToolbarButton';
import { PopoverContent } from '../Tooltip/types';
import { Dropdown } from './Dropdown';
export interface Props<T> extends HTMLAttributes<HTMLButtonElement> {
className?: string;
options: Array<SelectableValue<T>>;
@@ -29,70 +27,34 @@ export interface Props<T> extends HTMLAttributes<HTMLButtonElement> {
*/
const ButtonSelectComponent = <T,>(props: Props<T>) => {
const { className, options, value, onChange, narrow, variant, ...restProps } = props;
const styles = useStyles2(getStyles);
const [isOpen, setIsOpen] = useState(false);
const placement = 'bottom-end';
// the order of middleware is important!
const middleware = [offset(0), ...getPositioningMiddleware(placement)];
const { context, refs, floatingStyles } = useFloating({
open: isOpen,
placement,
onOpenChange: setIsOpen,
middleware,
whileElementsMounted: autoUpdate,
});
const click = useClick(context);
const dismiss = useDismiss(context);
const { getReferenceProps, getFloatingProps } = useInteractions([dismiss, click]);
const onChangeInternal = (item: SelectableValue<T>) => {
onChange(item);
setIsOpen(false);
};
const renderMenu = () => (
<Menu tabIndex={-1} onClose={() => setIsOpen(false)}>
<ScrollContainer maxHeight="100vh">
{options.map((item) => (
<MenuItem
key={`${item.value}`}
label={item.label ?? String(item.value)}
onClick={() => onChange(item)}
active={item.value === value?.value}
ariaChecked={item.value === value?.value}
ariaLabel={item.ariaLabel || item.label}
disabled={item.isDisabled}
component={item.component}
role="menuitemradio"
/>
))}
</ScrollContainer>
</Menu>
);
return (
<div className={styles.wrapper}>
<ToolbarButton
className={className}
isOpen={isOpen}
narrow={narrow}
variant={variant}
ref={refs.setReference}
{...getReferenceProps()}
{...restProps}
>
<Dropdown overlay={renderMenu} placement="bottom-end">
<ToolbarButton className={className} isOpen={isOpen} narrow={narrow} variant={variant} {...restProps}>
{value?.label || (value?.value != null ? String(value?.value) : null)}
</ToolbarButton>
{isOpen && (
<div className={styles.menuWrapper} ref={refs.setFloating} {...getFloatingProps()} style={floatingStyles}>
<FocusScope contain autoFocus restoreFocus>
{/*
tabIndex=-1 is needed here to support highlighting text within the menu when using FocusScope
see https://github.com/adobe/react-spectrum/issues/1604#issuecomment-781574668
*/}
<Menu tabIndex={-1} onClose={() => setIsOpen(false)}>
{options.map((item) => (
<MenuItem
key={`${item.value}`}
label={item.label ?? String(item.value)}
onClick={() => onChangeInternal(item)}
active={item.value === value?.value}
ariaChecked={item.value === value?.value}
ariaLabel={item.ariaLabel || item.label}
disabled={item.isDisabled}
component={item.component}
role="menuitemradio"
/>
))}
</Menu>
</FocusScope>
</div>
)}
</div>
</Dropdown>
);
};
@@ -102,17 +64,3 @@ ButtonSelectComponent.displayName = 'ButtonSelect';
// see https://github.com/DefinitelyTyped/DefinitelyTyped/issues/37087#issuecomment-656596623
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
export const ButtonSelect = memo(ButtonSelectComponent) as typeof ButtonSelectComponent;
const getStyles = (theme: GrafanaTheme2) => {
return {
wrapper: css({
position: 'relative',
display: 'inline-flex',
}),
menuWrapper: css({
zIndex: theme.zIndex.dropdown,
maxHeight: '100vh',
overflow: 'auto',
}),
};
};
@@ -1,13 +1,13 @@
import { css, cx } from '@emotion/css';
import * as React from 'react';
import { GrafanaTheme2, colorManipulator, deprecationWarning } from '@grafana/data';
import { GrafanaTheme2, deprecationWarning } from '@grafana/data';
import { useStyles2 } from '../../themes/ThemeContext';
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
import { IconName, IconSize, IconType } from '../../types/icon';
import { ComponentSize } from '../../types/size';
import { IconRenderer } from '../Button/Button';
import { getActiveButtonStyles, IconRenderer } from '../Button/Button';
import { getSvgSize } from '../Icon/utils';
import { Tooltip } from '../Tooltip/Tooltip';
import { PopoverContent, TooltipPlacement } from '../Tooltip/types';
@@ -107,13 +107,17 @@ const getStyles = (theme: GrafanaTheme2, size: IconSize, variant: IconButtonVari
// overall size of the IconButton on hover
// theme.spacing.gridSize originates from 2*4px for padding and letting the IconSize generally decide on the hoverSize
const hoverSize = getSvgSize(size) + theme.spacing.gridSize;
const activeButtonStyle = getActiveButtonStyles(theme.colors.secondary, 'text');
let iconColor = theme.colors.text.primary;
let iconColor = theme.colors.primary.text;
let hoverColor = theme.colors.primary.transparent;
if (variant === 'primary') {
iconColor = theme.colors.primary.text;
if (variant === 'secondary') {
iconColor = theme.colors.secondary.text;
hoverColor = theme.colors.secondary.transparent;
} else if (variant === 'destructive') {
iconColor = theme.colors.error.text;
hoverColor = theme.colors.error.transparent;
}
return {
@@ -129,11 +133,21 @@ const getStyles = (theme: GrafanaTheme2, size: IconSize, variant: IconButtonVari
alignItems: 'center',
padding: 0,
color: iconColor,
borderRadius: theme.shape.radius.default,
'&:active': {
'&:before, &:hover:before': {
backgroundColor: activeButtonStyle.background,
},
},
'&[disabled], &:disabled': {
cursor: 'not-allowed',
color: theme.colors.action.disabledText,
opacity: 0.65,
'&:hover:before': {
backgroundColor: 'transparent',
},
},
'&:before': {
@@ -155,12 +169,9 @@ const getStyles = (theme: GrafanaTheme2, size: IconSize, variant: IconButtonVari
'&:focus:not(:focus-visible)': getMouseFocusStyles(theme),
'&:hover': {
'&:before': {
backgroundColor:
variant === 'secondary' ? theme.colors.action.hover : colorManipulator.alpha(iconColor, 0.12),
opacity: 1,
},
'&:hover:before': {
backgroundColor: hoverColor,
opacity: 1,
},
}),
icon: css({
@@ -8,7 +8,7 @@ import { selectors } from '@grafana/e2e-selectors';
import { useStyles2 } from '../../themes/ThemeContext';
import { getFocusStyles, getMouseFocusStyles, mediaUp } from '../../themes/mixins';
import { IconSize } from '../../types/icon';
import { getPropertiesForVariant } from '../Button/Button';
import { getActiveButtonStyles, getPropertiesForVariant } from '../Button/Button';
import { Icon } from '../Icon/Icon';
import { Tooltip } from '../Tooltip/Tooltip';
@@ -134,11 +134,15 @@ const getStyles = (theme: GrafanaTheme2) => {
color: theme.colors.text.primary,
background: theme.colors.secondary.main,
'&:hover': {
'&:hover, &:focus': {
color: theme.colors.text.primary,
background: theme.colors.secondary.shade,
border: `1px solid ${theme.colors.border.medium}`,
},
'&:active': {
...getActiveButtonStyles(theme.colors.secondary, 'solid'),
},
});
return {
@@ -155,7 +159,7 @@ const getStyles = (theme: GrafanaTheme2) => {
border: `1px solid ${theme.colors.secondary.border}`,
whiteSpace: 'nowrap',
[theme.transitions.handleMotion('no-preference', 'reduce')]: {
transition: theme.transitions.create(['background', 'box-shadow', 'border-color', 'color'], {
transition: theme.transitions.create(['background-color', 'border-color', 'color'], {
duration: theme.transitions.duration.short,
}),
},
@@ -189,10 +193,14 @@ const getStyles = (theme: GrafanaTheme2) => {
background: 'transparent',
border: `1px solid transparent`,
'&:hover': {
'&:hover, &:focus': {
color: theme.colors.text.primary,
background: theme.colors.action.hover,
},
'&:active': {
...getActiveButtonStyles(theme.colors.secondary, 'solid'),
},
}),
canvas: defaultOld,
active: cx(
+7
View File
@@ -72,6 +72,13 @@ export function getFocusStyles(theme: GrafanaTheme2) {
};
}
export function getButtonFocusStyles(theme: GrafanaTheme2) {
return {
...getFocusStyles(theme),
transitionProperty: undefined,
};
}
// max-width is set up based on .grafana-tooltip class that's used in dashboard
export const getTooltipContainerStyles = (theme: GrafanaTheme2) => ({
overflow: 'hidden',
+1 -1
View File
@@ -60,7 +60,7 @@ func (hs *HTTPServer) isDashboardStarredByUser(c *contextmodel.ReqContext, dashU
return false, err
}
query := star.IsStarredByUserQuery{UserID: userID, DashboardUID: dashUID}
query := star.IsStarredByUserQuery{UserID: userID, OrgID: c.OrgID, DashboardUID: dashUID}
return hs.starService.IsStarredByUser(c.Req.Context(), &query)
}
-2
View File
@@ -31,7 +31,6 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
"github.com/grafana/grafana/pkg/services/annotations/annotationstest"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/dashboards"
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
@@ -129,7 +128,6 @@ func newTestLive(t *testing.T, store db.DB) *live.GrafanaLive {
nil,
features, acimpl.ProvideAccessControl(features),
&dashboards.FakeDashboardService{},
annotationstest.NewFakeAnnotationsRepo(),
nil, nil)
require.NoError(t, err)
return gLive
@@ -684,7 +684,7 @@ func RunTestClusterScopedWatch(ctx context.Context, t *testing.T, store storage.
currentObjs := map[string]*example.Pod{}
for _, watchTest := range tt.watchTests {
out := &example.Pod{}
key := "pods/ns-1/" + watchTest.obj.Name
key := "pods/" + watchTest.obj.Name
err := store.GuaranteedUpdate(ctx, key, out, true, nil, storage.SimpleUpdate(
func(runtime.Object) (runtime.Object, error) {
obj := watchTest.obj.DeepCopy()
@@ -1607,15 +1607,15 @@ func clusterScopedNodeNameAttrFunc(obj runtime.Object) (labels.Set, fields.Set,
}
func basePod(podName string) *example.Pod {
return baseNamespacedPod(podName, "ns-1")
return baseNamespacedPod(podName, "")
}
func basePodUpdated(podName string) *example.Pod {
return baseNamespacedPodUpdated(podName, "ns-1")
return baseNamespacedPodUpdated(podName, "")
}
func basePodAssigned(podName, nodeName string) *example.Pod {
return baseNamespacedPodAssigned(podName, "ns-1", nodeName)
return baseNamespacedPodAssigned(podName, "", nodeName)
}
func baseNamespacedPod(podName, namespace string) *example.Pod {
+4 -3
View File
@@ -69,7 +69,7 @@ type provisioningControllerConfig struct {
// local_permitted_prefixes =
// [provisioning]
// repository_types =
func setupFromConfig(cfg *setting.Cfg) (controllerCfg *provisioningControllerConfig, err error) {
func setupFromConfig(cfg *setting.Cfg, registry prometheus.Registerer) (controllerCfg *provisioningControllerConfig, err error) {
if cfg == nil {
return nil, fmt.Errorf("no configuration available")
}
@@ -130,7 +130,7 @@ func setupFromConfig(cfg *setting.Cfg) (controllerCfg *provisioningControllerCon
return nil, fmt.Errorf("failed to setup decrypter: %w", err)
}
repoFactory, err := setupRepoFactory(cfg, decrypter, provisioningClient)
repoFactory, err := setupRepoFactory(cfg, decrypter, provisioningClient, registry)
if err != nil {
return nil, fmt.Errorf("failed to setup repository getter: %w", err)
}
@@ -220,6 +220,7 @@ func setupRepoFactory(
cfg *setting.Cfg,
decrypter repository.Decrypter,
provisioningClient *client.Clientset,
registry prometheus.Registerer,
) (repository.Factory, error) {
operatorSec := cfg.SectionWithEnvOverrides("operator")
provisioningSec := cfg.SectionWithEnvOverrides("provisioning")
@@ -246,7 +247,7 @@ func setupRepoFactory(
var webhook *webhooks.WebhookExtraBuilder
provisioningAppURL := operatorSec.Key("provisioning_server_public_url").String()
if provisioningAppURL != "" {
webhook = webhooks.ProvideWebhooks(provisioningAppURL)
webhook = webhooks.ProvideWebhooks(provisioningAppURL, registry)
}
extras = append(extras, github.Extra(
+43 -15
View File
@@ -10,8 +10,10 @@ import (
"time"
"github.com/grafana/grafana-app-sdk/logging"
"github.com/prometheus/client_golang/prometheus"
"k8s.io/client-go/tools/cache"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs"
"github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs/export"
"github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs/migrate"
@@ -33,7 +35,17 @@ func RunJobController(deps server.OperatorDependencies) error {
})).With("logger", "provisioning-job-controller")
logger.Info("Starting provisioning job controller")
controllerCfg, err := setupJobsControllerFromConfig(deps.Config)
tracingConfig, err := tracing.ProvideTracingConfig(deps.Config)
if err != nil {
return fmt.Errorf("failed to provide tracing config: %w", err)
}
tracer, err := tracing.ProvideService(tracingConfig)
if err != nil {
return fmt.Errorf("failed to provide tracing service: %w", err)
}
controllerCfg, err := setupJobsControllerFromConfig(deps.Config, deps.Registerer)
if err != nil {
return fmt.Errorf("failed to setup operator: %w", err)
}
@@ -94,12 +106,12 @@ func RunJobController(deps server.OperatorDependencies) error {
// }
jobHistoryWriter := jobs.NewAPIClientHistoryWriter(controllerCfg.provisioningClient.ProvisioningV0alpha1())
jobStore, err := jobs.NewJobStore(controllerCfg.provisioningClient.ProvisioningV0alpha1(), 30*time.Second)
jobStore, err := jobs.NewJobStore(controllerCfg.provisioningClient.ProvisioningV0alpha1(), 30*time.Second, deps.Registerer)
if err != nil {
return fmt.Errorf("create API client job store: %w", err)
}
workers, err := setupWorkers(controllerCfg)
workers, err := setupWorkers(controllerCfg, deps.Registerer, tracer)
if err != nil {
return fmt.Errorf("setup workers: %w", err)
}
@@ -111,15 +123,16 @@ func RunJobController(deps server.OperatorDependencies) error {
// This is basically our own JobQueue system
driver, err := jobs.NewConcurrentJobDriver(
3, // 3 drivers for now
20*time.Minute, // Max time for each job
time.Minute, // Cleanup jobs
30*time.Second, // Periodically look for new jobs
30*time.Second, // Lease renewal interval
controllerCfg.concurrentDrivers,
controllerCfg.maxJobTimeout,
controllerCfg.cleanupInterval,
controllerCfg.jobInterval,
controllerCfg.leaseRenewalInterval,
jobStore,
repoGetter,
jobHistoryWriter,
jobController.InsertNotifications(),
deps.Registerer,
workers...,
)
if err != nil {
@@ -148,11 +161,16 @@ func RunJobController(deps server.OperatorDependencies) error {
type jobsControllerConfig struct {
provisioningControllerConfig
historyExpiration time.Duration
historyExpiration time.Duration
maxJobTimeout time.Duration
cleanupInterval time.Duration
jobInterval time.Duration
leaseRenewalInterval time.Duration
concurrentDrivers int
}
func setupJobsControllerFromConfig(cfg *setting.Cfg) (*jobsControllerConfig, error) {
controllerCfg, err := setupFromConfig(cfg)
func setupJobsControllerFromConfig(cfg *setting.Cfg, registry prometheus.Registerer) (*jobsControllerConfig, error) {
controllerCfg, err := setupFromConfig(cfg, registry)
if err != nil {
return nil, err
}
@@ -160,10 +178,15 @@ func setupJobsControllerFromConfig(cfg *setting.Cfg) (*jobsControllerConfig, err
return &jobsControllerConfig{
provisioningControllerConfig: *controllerCfg,
historyExpiration: cfg.SectionWithEnvOverrides("operator").Key("history_expiration").MustDuration(0),
concurrentDrivers: cfg.SectionWithEnvOverrides("operator").Key("concurrent_drivers").MustInt(3),
maxJobTimeout: cfg.SectionWithEnvOverrides("operator").Key("max_job_timeout").MustDuration(20 * time.Minute),
cleanupInterval: cfg.SectionWithEnvOverrides("operator").Key("cleanup_interval").MustDuration(time.Minute),
jobInterval: cfg.SectionWithEnvOverrides("operator").Key("job_interval").MustDuration(30 * time.Second),
leaseRenewalInterval: cfg.SectionWithEnvOverrides("operator").Key("lease_renewal_interval").MustDuration(30 * time.Second),
}, nil
}
func setupWorkers(controllerCfg *jobsControllerConfig) ([]jobs.Worker, error) {
func setupWorkers(controllerCfg *jobsControllerConfig, registry prometheus.Registerer, tracer tracing.Tracer) ([]jobs.Worker, error) {
clients := controllerCfg.clients
parsers := resources.NewParserFactory(clients)
resourceLister := resources.NewResourceLister(controllerCfg.unified)
@@ -172,14 +195,18 @@ func setupWorkers(controllerCfg *jobsControllerConfig) ([]jobs.Worker, error) {
workers := make([]jobs.Worker, 0)
metrics := jobs.RegisterJobMetrics(registry)
// Sync
syncer := sync.NewSyncer(sync.Compare, sync.FullSync, sync.IncrementalSync)
syncer := sync.NewSyncer(sync.Compare, sync.FullSync, sync.IncrementalSync, tracer)
syncWorker := sync.NewSyncWorker(
clients,
repositoryResources,
nil, // HACK: we have updated the worker to check for nil
statusPatcher.Patch,
syncer,
metrics,
tracer,
)
workers = append(workers, syncWorker)
@@ -190,6 +217,7 @@ func setupWorkers(controllerCfg *jobsControllerConfig) ([]jobs.Worker, error) {
repositoryResources,
export.ExportAll,
stageIfPossible,
metrics,
)
workers = append(workers, exportWorker)
@@ -204,11 +232,11 @@ func setupWorkers(controllerCfg *jobsControllerConfig) ([]jobs.Worker, error) {
workers = append(workers, migrationWorker)
// Delete
deleteWorker := deletepkg.NewWorker(syncWorker, stageIfPossible, repositoryResources)
deleteWorker := deletepkg.NewWorker(syncWorker, stageIfPossible, repositoryResources, metrics)
workers = append(workers, deleteWorker)
// Move
moveWorker := move.NewWorker(syncWorker, stageIfPossible, repositoryResources)
moveWorker := move.NewWorker(syncWorker, stageIfPossible, repositoryResources, metrics)
workers = append(workers, moveWorker)
return workers, nil
+19 -5
View File
@@ -11,8 +11,10 @@ import (
"github.com/grafana/grafana-app-sdk/logging"
appcontroller "github.com/grafana/grafana/apps/provisioning/pkg/controller"
"github.com/prometheus/client_golang/prometheus"
"k8s.io/client-go/tools/cache"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/registry/apis/provisioning/controller"
"github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs"
"github.com/grafana/grafana/pkg/registry/apis/provisioning/resources"
@@ -28,11 +30,21 @@ func RunRepoController(deps server.OperatorDependencies) error {
})).With("logger", "provisioning-repo-controller")
logger.Info("Starting provisioning repo controller")
controllerCfg, err := getRepoControllerConfig(deps.Config)
controllerCfg, err := getRepoControllerConfig(deps.Config, deps.Registerer)
if err != nil {
return fmt.Errorf("failed to setup operator: %w", err)
}
tracingConfig, err := tracing.ProvideTracingConfig(deps.Config)
if err != nil {
return fmt.Errorf("failed to provide tracing config: %w", err)
}
tracer, err := tracing.ProvideService(tracingConfig)
if err != nil {
return fmt.Errorf("failed to provide tracing service: %w", err)
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -50,12 +62,12 @@ func RunRepoController(deps server.OperatorDependencies) error {
)
resourceLister := resources.NewResourceLister(controllerCfg.unified)
jobs, err := jobs.NewJobStore(controllerCfg.provisioningClient.ProvisioningV0alpha1(), 30*time.Second)
jobs, err := jobs.NewJobStore(controllerCfg.provisioningClient.ProvisioningV0alpha1(), 30*time.Second, deps.Registerer)
if err != nil {
return fmt.Errorf("create API client job store: %w", err)
}
statusPatcher := appcontroller.NewRepositoryStatusPatcher(controllerCfg.provisioningClient.ProvisioningV0alpha1())
healthChecker := controller.NewHealthChecker(statusPatcher)
healthChecker := controller.NewHealthChecker(statusPatcher, deps.Registerer)
repoInformer := informerFactory.Provisioning().V0alpha1().Repositories()
controller, err := controller.NewRepositoryController(
@@ -68,6 +80,8 @@ func RunRepoController(deps server.OperatorDependencies) error {
nil, // dualwrite -- standalone operator assumes it is backed by unified storage
healthChecker,
statusPatcher,
deps.Registerer,
tracer,
)
if err != nil {
return fmt.Errorf("failed to create repository controller: %w", err)
@@ -87,8 +101,8 @@ type repoControllerConfig struct {
workerCount int
}
func getRepoControllerConfig(cfg *setting.Cfg) (*repoControllerConfig, error) {
controllerCfg, err := setupFromConfig(cfg)
func getRepoControllerConfig(cfg *setting.Cfg, registry prometheus.Registerer) (*repoControllerConfig, error) {
controllerCfg, err := setupFromConfig(cfg, registry)
if err != nil {
return nil, err
}
+13 -9
View File
@@ -675,17 +675,21 @@ func (b *DashboardsAPIBuilder) GetAuthorizer() authorizer.Authorizer {
}
func (b *DashboardsAPIBuilder) verifyFolderAccessPermissions(ctx context.Context, user identity.Requester, folderIds ...string) error {
scopes := []string{}
for _, folderId := range folderIds {
scopes = append(scopes, dashboards.ScopeFoldersProvider.GetResourceScopeUID(folderId))
}
ok, err := b.accessControl.Evaluate(ctx, user, accesscontrol.EvalPermission(dashboards.ActionFoldersWrite, scopes...))
if err != nil {
return err
}
resp, err := b.folderClient.Get(ctx, folderId, user.GetOrgID(), metav1.GetOptions{}, "access")
if err != nil {
return dashboards.ErrFolderAccessDenied
}
var accessInfo folders.FolderAccessInfo
err = runtime.DefaultUnstructuredConverter.FromUnstructured(resp.Object, &accessInfo)
if err != nil {
b.log.Error("Failed to convert folder access response", "error", err)
return dashboards.ErrFolderAccessDenied
}
if !ok {
return dashboards.ErrFolderAccessDenied
if !accessInfo.CanEdit {
return dashboards.ErrFolderAccessDenied
}
}
return nil
+46 -64
View File
@@ -19,9 +19,7 @@ import (
"k8s.io/kube-openapi/pkg/spec3"
authlib "github.com/grafana/authlib/types"
"github.com/grafana/grafana-app-sdk/logging"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/apps/iam/pkg/reconcilers"
"github.com/grafana/grafana/pkg/apimachinery/identity"
@@ -49,21 +47,21 @@ var errNoResource = errors.New("resource name is required")
// This is used just so wire has something unique to return
type FolderAPIBuilder struct {
features featuremgmt.FeatureToggles
namespacer request.NamespaceMapper
features featuremgmt.FeatureToggles
namespacer request.NamespaceMapper
storage grafanarest.Storage
permissionStore reconcilers.PermissionStore
authorizer authorizer.Authorizer
accessClient authlib.AccessClient
parents parentsGetter
searcher resourcepb.ResourceIndexClient
permissionsOnCreate bool
// Legacy services -- these will not exist in the MT environment
folderSvc folder.LegacyService
folderPermissionsSvc accesscontrol.FolderPermissionsService
acService accesscontrol.Service
ac accesscontrol.AccessControl
storage grafanarest.Storage
permissionStore reconcilers.PermissionStore
authorizer authorizer.Authorizer
parents parentsGetter
searcher resourcepb.ResourceIndexClient
permissionsOnCreate bool
ignoreLegacy bool // skip legacy storage and only use unified storage
}
func RegisterAPIService(cfg *setting.Cfg,
@@ -85,6 +83,7 @@ func RegisterAPIService(cfg *setting.Cfg,
folderPermissionsSvc: folderPermissionsSvc,
acService: acService,
ac: accessControl,
accessClient: accessClient,
permissionsOnCreate: cfg.RBAC.PermissionsOnCreation("folder"),
authorizer: newLegacyAuthorizer(accessControl),
searcher: unified,
@@ -99,10 +98,10 @@ func NewAPIService(ac authlib.AccessClient, searcher resource.ResourceClient, fe
features: features,
authorizer: newMultiTenantAuthorizer(ac),
searcher: searcher,
ignoreLegacy: true,
permissionStore: reconcilers.NewZanzanaPermissionStore(zanzanaClient),
}
}
func (b *FolderAPIBuilder) GetGroupVersion() schema.GroupVersion {
return resourceInfo.GroupVersion()
}
@@ -142,77 +141,60 @@ func (b *FolderAPIBuilder) AllowedV0Alpha1Resources() []string {
}
func (b *FolderAPIBuilder) UpdateAPIGroupInfo(apiGroupInfo *genericapiserver.APIGroupInfo, opts builder.APIGroupOptions) error {
scheme := opts.Scheme
optsGetter := opts.OptsGetter
dualWriteBuilder := opts.DualWriteBuilder
storage := map[string]rest.Storage{}
if b.ignoreLegacy {
opts.StorageOptsRegister(resourceInfo.GroupResource(), apistore.StorageOptions{
EnableFolderSupport: true,
RequireDeprecatedInternalID: true})
store, err := grafanaregistry.NewRegistryStore(opts.Scheme, resourceInfo, opts.OptsGetter)
if err != nil {
return err
}
b.registerPermissionHooks(store)
storage[resourceInfo.StoragePath()] = store
apiGroupInfo.VersionedResourcesStorageMap[folders.VERSION] = storage
b.storage = storage[resourceInfo.StoragePath()].(grafanarest.Storage)
b.parents = newParentsGetter(store, folder.MaxNestedFolderDepth)
return nil
}
legacyStore := &legacyStorage{
service: b.folderSvc,
namespacer: b.namespacer,
tableConverter: resourceInfo.TableConverter(),
}
opts.StorageOptsRegister(resourceInfo.GroupResource(), apistore.StorageOptions{
EnableFolderSupport: true,
RequireDeprecatedInternalID: true})
folderStore := &folderStorage{
tableConverter: resourceInfo.TableConverter(),
folderPermissionsSvc: b.folderPermissionsSvc,
acService: b.acService,
permissionsOnCreate: b.permissionsOnCreate,
unified, err := grafanaregistry.NewRegistryStore(opts.Scheme, resourceInfo, opts.OptsGetter)
if err != nil {
return err
}
b.registerPermissionHooks(unified)
b.storage = unified
if optsGetter != nil && dualWriteBuilder != nil {
store, err := grafanaregistry.NewRegistryStore(scheme, resourceInfo, optsGetter)
if b.folderSvc != nil {
legacyStore := &legacyStorage{
service: b.folderSvc,
namespacer: b.namespacer,
tableConverter: resourceInfo.TableConverter(),
}
dw, err := opts.DualWriteBuilder(resourceInfo.GroupResource(), legacyStore, unified)
if err != nil {
return err
}
b.registerPermissionHooks(store)
dw, err := dualWriteBuilder(resourceInfo.GroupResource(), legacyStore, store)
if err != nil {
return err
b.storage = &folderStorage{
tableConverter: resourceInfo.TableConverter(),
folderPermissionsSvc: b.folderPermissionsSvc,
acService: b.acService,
permissionsOnCreate: b.permissionsOnCreate,
store: dw,
}
folderStore.store = dw
}
storage[resourceInfo.StoragePath()] = folderStore
b.parents = newParentsGetter(folderStore, folder.MaxNestedFolderDepth) // used for validation
storage := map[string]rest.Storage{}
storage[resourceInfo.StoragePath()] = b.storage
b.parents = newParentsGetter(b.storage, folder.MaxNestedFolderDepth) // used for validation
storage[resourceInfo.StoragePath("parents")] = &subParentsREST{
getter: folderStore,
getter: b.storage,
parents: b.parents,
}
storage[resourceInfo.StoragePath("counts")] = &subCountREST{searcher: b.searcher}
storage[resourceInfo.StoragePath("access")] = &subAccessREST{folderStore, b.ac}
storage[resourceInfo.StoragePath("counts")] = &subCountREST{
getter: b.storage,
searcher: b.searcher,
}
storage[resourceInfo.StoragePath("access")] = &subAccessREST{
getter: b.storage,
accessClient: b.accessClient,
}
// Adds a path to return children of a given folder
storage[resourceInfo.StoragePath("children")] = &subChildrenREST{
lister: storage[resourceInfo.StoragePath()].(rest.Lister),
getter: b.storage,
lister: b.storage,
}
apiGroupInfo.VersionedResourcesStorageMap[folders.VERSION] = storage
b.storage = storage[resourceInfo.StoragePath()].(grafanarest.Storage)
return nil
}
+62 -23
View File
@@ -8,22 +8,23 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
authlib "github.com/grafana/authlib/types"
foldersV1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
)
type subAccessREST struct {
getter rest.Getter
ac accesscontrol.AccessControl
getter rest.Getter
accessClient authlib.AccessClient
}
var _ = rest.Connecter(&subAccessREST{})
var _ = rest.StorageMetadata(&subAccessREST{})
func (r *subAccessREST) New() runtime.Object {
return &folders.FolderAccessInfo{}
return &foldersV1.FolderAccessInfo{}
}
func (r *subAccessREST) Destroy() {
@@ -38,7 +39,7 @@ func (r *subAccessREST) ProducesMIMETypes(verb string) []string {
}
func (r *subAccessREST) ProducesObject(verb string) interface{} {
return &folders.FolderAccessInfo{}
return &foldersV1.FolderAccessInfo{}
}
func (r *subAccessREST) NewConnectOptions() (runtime.Object, bool, string) {
@@ -46,29 +47,67 @@ func (r *subAccessREST) NewConnectOptions() (runtime.Object, bool, string) {
}
func (r *subAccessREST) Connect(ctx context.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
access, err := r.getAccessInfo(ctx, name)
if err != nil {
responder.Error(err)
} else {
responder.Object(200, access)
}
}), nil
}
func (r *subAccessREST) getAccessInfo(ctx context.Context, name string) (*foldersV1.FolderAccessInfo, error) {
ns, err := request.NamespaceInfoFrom(ctx, true)
if err != nil {
return nil, err
}
user, err := identity.GetRequester(ctx)
if err != nil {
return nil, err
}
// Must be able to get the resource
_, err = r.getter.Get(ctx, name, &v1.GetOptions{})
// Can view is managed here (and in the Authorizer)
f, err := r.getter.Get(ctx, name, &v1.GetOptions{})
if err != nil {
return nil, err
}
obj, err := utils.MetaAccessor(f)
if err != nil {
return nil, err
}
var tmp authlib.CheckResponse
check := func(verb string) bool {
if err != nil {
return false
}
tmp, err = r.accessClient.Check(ctx, user, authlib.CheckRequest{
Verb: verb,
Group: foldersV1.GROUP,
Resource: foldersV1.RESOURCE,
Namespace: ns.Value,
Name: name,
Folder: obj.GetFolder(),
})
return tmp.Allowed
}
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
access := &folders.FolderAccessInfo{}
canEditEvaluator := accesscontrol.EvalPermission(dashboards.ActionFoldersWrite, dashboards.ScopeFoldersProvider.GetResourceScopeUID(name))
access.CanEdit, _ = r.ac.Evaluate(ctx, user, canEditEvaluator)
access.CanSave = access.CanEdit
canAdminEvaluator := accesscontrol.EvalAll(
accesscontrol.EvalPermission(dashboards.ActionFoldersPermissionsRead, dashboards.ScopeFoldersProvider.GetResourceScopeUID(name)),
accesscontrol.EvalPermission(dashboards.ActionFoldersPermissionsWrite, dashboards.ScopeFoldersProvider.GetResourceScopeUID(name)),
)
access.CanAdmin, _ = r.ac.Evaluate(ctx, user, canAdminEvaluator)
canDeleteEvaluator := accesscontrol.EvalPermission(dashboards.ActionFoldersDelete, dashboards.ScopeFoldersProvider.GetResourceScopeUID(name))
access.CanDelete, _ = r.ac.Evaluate(ctx, user, canDeleteEvaluator)
responder.Object(http.StatusOK, access)
}), nil
rsp := &foldersV1.FolderAccessInfo{}
rsp.CanAdmin = check(utils.VerbSetPermissions)
if err != nil {
return nil, err
}
rsp.CanDelete = rsp.CanAdmin || check(utils.VerbDelete)
if err != nil {
return nil, err
}
rsp.CanEdit = rsp.CanAdmin || check(utils.VerbUpdate)
if err != nil {
return nil, err
}
rsp.CanSave = rsp.CanAdmin || check(utils.VerbCreate) // or the same as update?
if err != nil {
return nil, err
}
return rsp, nil
}
@@ -6,6 +6,7 @@ import (
"net/http"
"k8s.io/apimachinery/pkg/apis/meta/internalversion"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest"
@@ -15,6 +16,7 @@ import (
)
type subChildrenREST struct {
getter rest.Getter
lister rest.Lister
}
@@ -45,6 +47,10 @@ func (r *subChildrenREST) NewConnectOptions() (runtime.Object, bool, string) {
}
func (r *subChildrenREST) Connect(ctx context.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) {
if _, err := r.getter.Get(ctx, name, &v1.GetOptions{}); err != nil {
return nil, err
}
obj, err := r.lister.List(ctx, &internalversion.ListOptions{
Limit: 500,
// TODO, field selector
+5
View File
@@ -4,6 +4,7 @@ import (
"context"
"net/http"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest"
@@ -13,6 +14,7 @@ import (
)
type subCountREST struct {
getter rest.Getter
searcher resourcepb.ResourceIndexClient
}
@@ -45,6 +47,9 @@ func (r *subCountREST) NewConnectOptions() (runtime.Object, bool, string) {
}
func (r *subCountREST) Connect(ctx context.Context, name string, _ runtime.Object, responder rest.Responder) (http.Handler, error) {
if _, err := r.getter.Get(ctx, name, &v1.GetOptions{}); err != nil {
return nil, err
}
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
ns, err := request.NamespaceInfoFrom(ctx, true)
if err != nil {
-5
View File
@@ -8,7 +8,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/services/folder"
@@ -55,10 +54,6 @@ func (r *subParentsREST) Connect(ctx context.Context, name string, opts runtime.
}
obj, err := r.getter.Get(ctx, name, &metav1.GetOptions{})
if storage.IsNotFound(err) {
responder.Object(http.StatusNotFound, nil)
return
}
if err != nil {
responder.Error(err)
return
@@ -1,6 +1,6 @@
SELECT o.org_id, u.id, u.uid, u.login, u.email, u.name,
u.created, u.updated, u.is_service_account, u.is_disabled, u.is_admin,
u.email_verified, u.is_provisioned, u.last_seen_at
u.email_verified, u.is_provisioned, u.last_seen_at, o.role
FROM {{ .Ident .UserTable }} as u JOIN {{ .Ident .OrgUserTable }} as o ON u.id = o.user_id
WHERE o.org_id = {{ .Arg .Query.OrgID }} AND ( 1=2
{{ if .Query.UIDs }}
@@ -1,6 +1,6 @@
SELECT o.org_id, u.id, u.uid, u.login, u.email, u.name,
u.created, u.updated, u.is_service_account, u.is_disabled, u.is_admin,
u.email_verified, u.is_provisioned, u.last_seen_at
u.email_verified, u.is_provisioned, u.last_seen_at, o.role
FROM `grafana`.`user` as u JOIN `grafana`.`org_user` as o ON u.id = o.user_id
WHERE o.org_id = 2 AND ( 1=2
OR u.id IN (1, 2)
@@ -1,6 +1,6 @@
SELECT o.org_id, u.id, u.uid, u.login, u.email, u.name,
u.created, u.updated, u.is_service_account, u.is_disabled, u.is_admin,
u.email_verified, u.is_provisioned, u.last_seen_at
u.email_verified, u.is_provisioned, u.last_seen_at, o.role
FROM `grafana`.`user` as u JOIN `grafana`.`org_user` as o ON u.id = o.user_id
WHERE o.org_id = 2 AND ( 1=2
OR uid IN ('a', 'b')
@@ -1,6 +1,6 @@
SELECT o.org_id, u.id, u.uid, u.login, u.email, u.name,
u.created, u.updated, u.is_service_account, u.is_disabled, u.is_admin,
u.email_verified, u.is_provisioned, u.last_seen_at
u.email_verified, u.is_provisioned, u.last_seen_at, o.role
FROM `grafana`.`user` as u JOIN `grafana`.`org_user` as o ON u.id = o.user_id
WHERE o.org_id = 2 AND ( 1=2
OR uid IN ('a', 'b')
@@ -1,6 +1,6 @@
SELECT o.org_id, u.id, u.uid, u.login, u.email, u.name,
u.created, u.updated, u.is_service_account, u.is_disabled, u.is_admin,
u.email_verified, u.is_provisioned, u.last_seen_at
u.email_verified, u.is_provisioned, u.last_seen_at, o.role
FROM "grafana"."user" as u JOIN "grafana"."org_user" as o ON u.id = o.user_id
WHERE o.org_id = 2 AND ( 1=2
OR u.id IN (1, 2)
@@ -1,6 +1,6 @@
SELECT o.org_id, u.id, u.uid, u.login, u.email, u.name,
u.created, u.updated, u.is_service_account, u.is_disabled, u.is_admin,
u.email_verified, u.is_provisioned, u.last_seen_at
u.email_verified, u.is_provisioned, u.last_seen_at, o.role
FROM "grafana"."user" as u JOIN "grafana"."org_user" as o ON u.id = o.user_id
WHERE o.org_id = 2 AND ( 1=2
OR uid IN ('a', 'b')
@@ -1,6 +1,6 @@
SELECT o.org_id, u.id, u.uid, u.login, u.email, u.name,
u.created, u.updated, u.is_service_account, u.is_disabled, u.is_admin,
u.email_verified, u.is_provisioned, u.last_seen_at
u.email_verified, u.is_provisioned, u.last_seen_at, o.role
FROM "grafana"."user" as u JOIN "grafana"."org_user" as o ON u.id = o.user_id
WHERE o.org_id = 2 AND ( 1=2
OR uid IN ('a', 'b')

Some files were not shown because too many files have changed in this diff Show More