Merge branch 'main' of https://github.com/grafana/grafana into kristina/static-transform-refIds
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
+93
@@ -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: {}
|
||||
+138
@@ -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: {}
|
||||
+71
@@ -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: {}
|
||||
+104
@@ -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: {}
|
||||
@@ -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,
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
+1
-1
@@ -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"
|
||||
+99
@@ -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)
|
||||
}
|
||||
+1
-13
@@ -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{
|
||||
+99
@@ -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)
|
||||
}
|
||||
+99
@@ -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)
|
||||
}
|
||||
+1
-13
@@ -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{
|
||||
+99
@@ -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)
|
||||
}
|
||||
+1
-13
@@ -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{
|
||||
+92
-92
@@ -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)
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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=
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>" >}}
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}>;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
-1
@@ -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
-1
@@ -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
-1
@@ -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
-1
@@ -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
-1
@@ -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
Reference in New Issue
Block a user