K8s: Data Plane Aggregator (#91228)

This commit is contained in:
Todd Treece 2024-08-13 15:28:17 -04:00 committed by GitHub
parent 4ce82d3f14
commit 1b0e6b5c09
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
64 changed files with 5555 additions and 57 deletions

1
.github/CODEOWNERS vendored
View File

@ -106,6 +106,7 @@
/pkg/semconv/ @grafana/grafana-backend-group /pkg/semconv/ @grafana/grafana-backend-group
/pkg/server/ @grafana/grafana-backend-group /pkg/server/ @grafana/grafana-backend-group
/pkg/apiserver @grafana/grafana-app-platform-squad /pkg/apiserver @grafana/grafana-app-platform-squad
/pkg/aggregator @grafana/grafana-app-platform-squad
/pkg/apimachinery @grafana/grafana-app-platform-squad /pkg/apimachinery @grafana/grafana-app-platform-squad
/pkg/apimachinery/identity/ @grafana/identity-squad /pkg/apimachinery/identity/ @grafana/identity-squad
/pkg/apimachinery/errutil/ @grafana/grafana-backend-group /pkg/apimachinery/errutil/ @grafana/grafana-backend-group

View File

@ -98,6 +98,21 @@ files = [
"**/pkg/apimachinery/**/*" "**/pkg/apimachinery/**/*"
] ]
[linters-settings.depguard.rules.aggregator]
list-mode = "lax"
allow = [
"github.com/grafana/grafana/pkg/aggregator",
"github.com/grafana/grafana/pkg/semconv",
"github.com/grafana/grafana/pkg/apimachinery",
]
deny = [
{ pkg = "github.com/grafana/grafana/pkg", desc = "apimachinery is not allowed to import grafana core" }
]
files = [
"./pkg/aggregator/*",
"./pkg/aggregator/**/*"
]
[linters-settings.depguard.rules.promlib] [linters-settings.depguard.rules.promlib]
list-mode = "lax" # allow unless explicitely denied list-mode = "lax" # allow unless explicitely denied
deny = [ deny = [
@ -107,7 +122,6 @@ allow = [
"github.com/grafana/grafana/pkg/promlib" "github.com/grafana/grafana/pkg/promlib"
] ]
files = [ files = [
"**/pkg/promlib/*",
"**/pkg/promlib/**/*" "**/pkg/promlib/**/*"
] ]

View File

@ -5,6 +5,7 @@ go 1.22.4
use ( use (
. // skip:golangci-lint . // skip:golangci-lint
./pkg/aggregator
./pkg/apimachinery ./pkg/apimachinery
./pkg/apiserver ./pkg/apiserver
./pkg/build ./pkg/build

View File

@ -268,6 +268,8 @@ github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nC
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c h1:2zRrJWIt/f9c9HhNHAgrRgq0San5gRRUJTBXLkchal0= github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c h1:2zRrJWIt/f9c9HhNHAgrRgq0San5gRRUJTBXLkchal0=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y=
github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA=
github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=
github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0=
github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04= github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04=
@ -386,8 +388,6 @@ github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 h1:EcQR3gusLHN
github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws= github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws=
github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE= github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
github.com/google/cel-go v0.17.7 h1:6ebJFzu1xO2n7TLtN+UBqShGBhlD85bhvglh5DpcfqQ=
github.com/google/cel-go v0.17.7/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
github.com/google/go-jsonnet v0.18.0 h1:/6pTy6g+Jh1a1I2UMoAODkqELFiVIdOxbNwv0DDzoOg= github.com/google/go-jsonnet v0.18.0 h1:/6pTy6g+Jh1a1I2UMoAODkqELFiVIdOxbNwv0DDzoOg=
github.com/google/go-jsonnet v0.18.0/go.mod h1:C3fTzyVJDslXdiTqw/bTFk7vSGyCtH3MGRbDfvEwGd0= github.com/google/go-jsonnet v0.18.0/go.mod h1:C3fTzyVJDslXdiTqw/bTFk7vSGyCtH3MGRbDfvEwGd0=
github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9 h1:OF1IPgv+F4NmqmJ98KTjdN97Vs1JxDPB3vbmYzV2dpk= github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9 h1:OF1IPgv+F4NmqmJ98KTjdN97Vs1JxDPB3vbmYzV2dpk=
@ -407,7 +407,6 @@ github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/grafana/authlib/claims v0.0.0-20240809095826-8eb5495c0b2a/go.mod h1:r+F8H6awwjNQt/KPZ2GNwjk8TvsJ7/gxzkXN26GlL/A=
github.com/grafana/gomemcache v0.0.0-20240229205252-cd6a66d6fb56/go.mod h1:PGk3RjYHpxMM8HFPhKKo+vve3DdlPUELZLSDEFehPuU= github.com/grafana/gomemcache v0.0.0-20240229205252-cd6a66d6fb56/go.mod h1:PGk3RjYHpxMM8HFPhKKo+vve3DdlPUELZLSDEFehPuU=
github.com/grafana/pyroscope-go/godeltaprof v0.1.6/go.mod h1:Tk376Nbldo4Cha9RgiU7ik8WKFkNpfds98aUzS8omLE= github.com/grafana/pyroscope-go/godeltaprof v0.1.6/go.mod h1:Tk376Nbldo4Cha9RgiU7ik8WKFkNpfds98aUzS8omLE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
@ -730,6 +729,8 @@ github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b h1:7gd+rd8P3bqcn/96gOZa3F5dpJr/vEiDQYlNb/y2uNs= gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b h1:7gd+rd8P3bqcn/96gOZa3F5dpJr/vEiDQYlNb/y2uNs=
go.einride.tech/aip v0.66.0 h1:XfV+NQX6L7EOYK11yoHHFtndeaWh3KbD9/cN/6iWEt8= go.einride.tech/aip v0.66.0 h1:XfV+NQX6L7EOYK11yoHHFtndeaWh3KbD9/cN/6iWEt8=
go.etcd.io/gofail v0.1.0 h1:XItAMIhOojXFQMgrxjnd2EIIHun/d5qL0Pf7FzVTkFg=
go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M=
go.opentelemetry.io/collector v0.97.0 h1:qyOju13byHIKEK/JehmTiGMj4pFLa4kDyrOCtTmjHU0= go.opentelemetry.io/collector v0.97.0 h1:qyOju13byHIKEK/JehmTiGMj4pFLa4kDyrOCtTmjHU0=
go.opentelemetry.io/collector v0.97.0/go.mod h1:V6xquYAaO2VHVu4DBK28JYuikRdZajh7DH5Vl/Y8NiA= go.opentelemetry.io/collector v0.97.0/go.mod h1:V6xquYAaO2VHVu4DBK28JYuikRdZajh7DH5Vl/Y8NiA=
go.opentelemetry.io/collector/component v0.97.0 h1:vanKhXl5nptN8igRH4PqVYHOILif653vaPIKv6LCZCI= go.opentelemetry.io/collector/component v0.97.0 h1:vanKhXl5nptN8igRH4PqVYHOILif653vaPIKv6LCZCI=
@ -876,8 +877,6 @@ gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
honnef.co/go/tools v0.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o= honnef.co/go/tools v0.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o=
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
k8s.io/apimachinery v0.31.0-rc.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/apiserver v0.31.0-rc.1/go.mod h1:CdFvqtAIiWDfZl1LMixuXYGpttymfuopCol/F6AbxmI=
k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks= k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks=
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo= k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=

View File

@ -0,0 +1,4 @@
// +k8s:deepcopy-gen=package
// +groupName=aggregation.grafana.app
package aggregation // import "github.com/grafana/grafana/pkg/aggregator/apis/aggregation"

View File

@ -0,0 +1,16 @@
package install
import (
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
aggregation "github.com/grafana/grafana/pkg/aggregator/apis/aggregation"
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
)
// Install registers the API group and adds types to a scheme
func Install(scheme *runtime.Scheme) {
utilruntime.Must(aggregation.AddToScheme(scheme))
utilruntime.Must(v0alpha1.AddToScheme(scheme))
utilruntime.Must(scheme.SetVersionPriority(v0alpha1.SchemeGroupVersion))
}

View File

@ -0,0 +1,40 @@
package aggregation
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
const (
GROUP = "aggregation.grafana.app"
VERSION = runtime.APIVersionInternal
APIVERSION = GROUP + "/" + VERSION
)
var (
// SchemeGroupVersion is group version used to register these objects
SchemeGroupVersion = schema.GroupVersion{Group: GROUP, Version: VERSION}
// SchemaBuilder is used by standard codegen
SchemeBuilder runtime.SchemeBuilder
localSchemeBuilder = &SchemeBuilder
AddToScheme = localSchemeBuilder.AddToScheme
)
func init() {
localSchemeBuilder.Register(addKnownTypes)
}
// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&DataPlaneService{},
&DataPlaneServiceList{},
)
return nil
}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}

View File

@ -0,0 +1,136 @@
package aggregation
import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type DataPlaneService struct {
metav1.TypeMeta
metav1.ObjectMeta
Spec DataPlaneServiceSpec
Status DataPlaneServiceStatus
}
type DataPlaneServiceSpec struct {
PluginID string
PluginType PluginType
Group string
Version string
// Services is a list of services that the proxied service provides.
// +optional
// +listType=map
// +listMapKey=type
Services []Service
}
// Service defines the type of service the proxied service provides.
type Service struct {
// Type is the type of service to proxy.
Type ServiceType
// Method is the HTTP method to use when proxying the service.
// +optional
Method string
// Path is used by the CustomRouteServiceType and SubResourceServiceType to specify the path to the endpoint.
// +optional
Path string
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type DataPlaneServiceList struct {
metav1.TypeMeta
// +optional
metav1.ListMeta
Items []DataPlaneService
}
// PluginType defines the type of plugin backing the proxied service.
// +enum
type PluginType string
// PluginType values
const (
AppPluginType PluginType = "app"
DataSourcePluginType PluginType = "datasource"
)
// ServiceType defines the type of services the proxied service provides.
// +enum
type ServiceType string
// ServiceType values
const (
// AdmissionControlServiceType maps to pluginv2.AdmissionControl
AdmissionControlServiceType ServiceType = "admission"
// ConversionServiceType maps to pluginv2.ResourceConversion
ConversionServiceType ServiceType = "conversion"
// DataSourceServiceType maps to pluginv2.Data
DataServiceType ServiceType = "data"
// StreamServiceType maps to pluginv2.Stream
StreamServiceType ServiceType = "stream"
// RouteServiceType maps pluginv2.Resource
RouteServiceType ServiceType = "route"
// DataSourceProxyServiceType is a reverse proxy for making requests directly to the HTTP URL specified in datasource instance settings.
DataSourceProxyServiceType ServiceType = "datsource-proxy"
)
// ConditionStatus indicates the status of a condition (true, false, or unknown).
type ConditionStatus string
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition;
// "ConditionFalse" means a resource is not in the condition; "ConditionUnknown" means kubernetes
// can't decide if a resource is in the condition or not. In the future, we could add other
// intermediate conditions, e.g. ConditionDegraded.
const (
ConditionTrue ConditionStatus = "True"
ConditionFalse ConditionStatus = "False"
ConditionUnknown ConditionStatus = "Unknown"
)
// DataPlaneServiceConditionType is a valid value for DataPlaneServiceCondition.Type
type DataPlaneServiceConditionType string
const (
// Available indicates that the service exists and is reachable
Available DataPlaneServiceConditionType = "Available"
)
// DataPlaneServiceCondition describes the state of an DataPlaneService at a particular point
type DataPlaneServiceCondition struct {
// Type is the type of the condition.
Type DataPlaneServiceConditionType
// Status is the status of the condition.
// Can be True, False, Unknown.
Status ConditionStatus
// Last time the condition transitioned from one status to another.
// +optional
LastTransitionTime metav1.Time
// Unique, one-word, CamelCase reason for the condition's last transition.
// +optional
Reason string
// Human-readable message indicating details about last transition.
// +optional
Message string
}
// DataPlaneServiceStatus contains derived information about a remote DataPlaneService.
type DataPlaneServiceStatus struct {
// Current service state of DataPlaneService.
// +optional
// +listType=map
// +listMapKey=type
Conditions []DataPlaneServiceCondition
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type QueryDataResponse struct {
metav1.TypeMeta
// Backend wrapper (external dependency)
backend.QueryDataResponse
}

View File

@ -0,0 +1,7 @@
// +k8s:deepcopy-gen=package
// +k8s:openapi-gen=true
// +k8s:defaulter-gen=TypeMeta
// +k8s:conversion-gen=github.com/grafana/grafana/pkg/aggregator/apis/aggregation
// +groupName=aggregation.grafana.app
package v0alpha1 // import "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"

View File

@ -0,0 +1,54 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Provenance-includes-location: https://github.com/kubernetes/kube-aggregator/blob/master/pkg/apis/apiregistration/v1/helper/helpers.go
// Provenance-includes-license: Apache-2.0
// Provenance-includes-copyright: The Kubernetes Authors.
package helper
import (
"strings"
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// DataPlaneServiceNameToGroupVersion returns the GroupVersion for a given dataplaneServiceNam. The name
// must be valid, but any object you get back from an informer will be valid.
func DataPlaneServiceNameToGroupVersion(dataplaneServiceName string) schema.GroupVersion {
tokens := strings.SplitN(dataplaneServiceName, ".", 2)
return schema.GroupVersion{Group: tokens[1], Version: tokens[0]}
}
// SetDataPlaneServiceCondition sets the status condition. It either overwrites the existing one or
// creates a new one
func SetDataPlaneServiceCondition(dataplaneService *v0alpha1.DataPlaneService, newCondition v0alpha1.DataPlaneServiceCondition) {
existingCondition := GetDataPlaneServiceConditionByType(dataplaneService, newCondition.Type)
if existingCondition == nil {
dataplaneService.Status.Conditions = append(dataplaneService.Status.Conditions, newCondition)
return
}
if existingCondition.Status != newCondition.Status {
existingCondition.Status = newCondition.Status
existingCondition.LastTransitionTime = newCondition.LastTransitionTime
}
existingCondition.Reason = newCondition.Reason
existingCondition.Message = newCondition.Message
}
// IsDataPlaneServiceConditionTrue indicates if the condition is present and strictly true
func IsDataPlaneServiceConditionTrue(dataplaneService *v0alpha1.DataPlaneService, conditionType v0alpha1.DataPlaneServiceConditionType) bool {
condition := GetDataPlaneServiceConditionByType(dataplaneService, conditionType)
return condition != nil && condition.Status == v0alpha1.ConditionTrue
}
// GetDataPlaneServiceConditionByType gets an *DataPlaneServiceCondition by DataPlaneServiceConditionType if present
func GetDataPlaneServiceConditionByType(dataplaneService *v0alpha1.DataPlaneService, conditionType v0alpha1.DataPlaneServiceConditionType) *v0alpha1.DataPlaneServiceCondition {
for i := range dataplaneService.Status.Conditions {
if dataplaneService.Status.Conditions[i].Type == conditionType {
return &dataplaneService.Status.Conditions[i]
}
}
return nil
}

View File

@ -0,0 +1,52 @@
package v0alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
)
const (
GROUP = "aggregation.grafana.app"
VERSION = "v0alpha1"
APIVERSION = GROUP + "/" + VERSION
)
var DataPlaneServiceResourceInfo = common.NewResourceInfo(GROUP, VERSION,
"dataplaneservices", "dataplaneservice", "DataPlaneService",
func() runtime.Object { return &DataPlaneService{} },
func() runtime.Object { return &DataPlaneServiceList{} },
utils.TableColumns{}, // default table converter
)
var (
// SchemeGroupVersion is group version used to register these objects
SchemeGroupVersion = schema.GroupVersion{Group: GROUP, Version: VERSION}
// SchemaBuilder is used by standard codegen
SchemeBuilder runtime.SchemeBuilder
localSchemeBuilder = &SchemeBuilder
AddToScheme = localSchemeBuilder.AddToScheme
)
func init() {
localSchemeBuilder.Register(addKnownTypes, RegisterDefaults)
}
// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&DataPlaneService{},
&DataPlaneServiceList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}

View File

@ -0,0 +1,136 @@
package v0alpha1
import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type DataPlaneService struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec DataPlaneServiceSpec `json:"spec,omitempty"`
Status DataPlaneServiceStatus `json:"status,omitempty"`
}
type DataPlaneServiceSpec struct {
PluginID string `json:"pluginID"`
PluginType PluginType `json:"pluginType"`
Group string `json:"group"`
Version string `json:"version"`
// Services is a list of services that the proxied service provides.
// +optional
// +listType=map
// +listMapKey=type
Services []Service `json:"services"`
}
// Service defines the type of service the proxied service provides.
type Service struct {
// Type is the type of service to proxy.
Type ServiceType `json:"type"`
// Method is the HTTP method to use when proxying the service.
// +optional
Method string `json:"method,omitempty"`
// Path is used by the CustomRouteServiceType and SubResourceServiceType to specify the path to the endpoint.
// +optional
Path string `json:"path,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type DataPlaneServiceList struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ListMeta `json:"metadata,omitempty"`
Items []DataPlaneService `json:"items,omitempty"`
}
// PluginType defines the type of plugin backing the proxied service.
// +enum
type PluginType string
// PluginType values
const (
AppPluginType PluginType = "app"
DataSourcePluginType PluginType = "datasource"
)
// ServiceType defines the type of services the proxied service provides.
// +enum
type ServiceType string
// ServiceType values
const (
// AdmissionControlServiceType maps to pluginv2.AdmissionControl
AdmissionControlServiceType ServiceType = "admission"
// ConversionServiceType maps to pluginv2.ResourceConversion
ConversionServiceType ServiceType = "conversion"
// DataSourceServiceType maps to pluginv2.Data
DataServiceType ServiceType = "data"
// StreamServiceType maps to pluginv2.Stream
StreamServiceType ServiceType = "stream"
// RouteServiceType maps pluginv2.Resource
RouteServiceType ServiceType = "route"
// DataSourceProxyServiceType is a reverse proxy for making requests directly to the HTTP URL specified in datasource instance settings.
DataSourceProxyServiceType ServiceType = "datsource-proxy"
)
// ConditionStatus indicates the status of a condition (true, false, or unknown).
type ConditionStatus string
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition;
// "ConditionFalse" means a resource is not in the condition; "ConditionUnknown" means kubernetes
// can't decide if a resource is in the condition or not. In the future, we could add other
// intermediate conditions, e.g. ConditionDegraded.
const (
ConditionTrue ConditionStatus = "True"
ConditionFalse ConditionStatus = "False"
ConditionUnknown ConditionStatus = "Unknown"
)
// DataPlaneServiceConditionType is a valid value for DataPlaneServiceCondition.Type
type DataPlaneServiceConditionType string
const (
// Available indicates that the service exists and is reachable
Available DataPlaneServiceConditionType = "Available"
)
// DataPlaneServiceCondition describes the state of an DataPlaneService at a particular point
type DataPlaneServiceCondition struct {
// Type is the type of the condition.
Type DataPlaneServiceConditionType `json:"type"`
// Status is the status of the condition.
// Can be True, False, Unknown.
Status ConditionStatus `json:"status"`
// Last time the condition transitioned from one status to another.
// +optional
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
// Unique, one-word, CamelCase reason for the condition's last transition.
// +optional
Reason string `json:"reason,omitempty"`
// Human-readable message indicating details about last transition.
// +optional
Message string `json:"message,omitempty"`
}
// DataPlaneServiceStatus contains derived information about a remote DataPlaneService.
type DataPlaneServiceStatus struct {
// Current service state of DataPlaneService.
// +optional
// +listType=map
// +listMapKey=type
Conditions []DataPlaneServiceCondition `json:"conditions,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type QueryDataResponse struct {
metav1.TypeMeta `json:",inline"`
// Backend wrapper (external dependency)
backend.QueryDataResponse `json:",inline"`
}

View File

@ -0,0 +1,270 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by conversion-gen. DO NOT EDIT.
package v0alpha1
import (
unsafe "unsafe"
aggregation "github.com/grafana/grafana/pkg/aggregator/apis/aggregation"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
)
func init() {
localSchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*DataPlaneService)(nil), (*aggregation.DataPlaneService)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v0alpha1_DataPlaneService_To_aggregation_DataPlaneService(a.(*DataPlaneService), b.(*aggregation.DataPlaneService), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*aggregation.DataPlaneService)(nil), (*DataPlaneService)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_aggregation_DataPlaneService_To_v0alpha1_DataPlaneService(a.(*aggregation.DataPlaneService), b.(*DataPlaneService), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*DataPlaneServiceCondition)(nil), (*aggregation.DataPlaneServiceCondition)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v0alpha1_DataPlaneServiceCondition_To_aggregation_DataPlaneServiceCondition(a.(*DataPlaneServiceCondition), b.(*aggregation.DataPlaneServiceCondition), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*aggregation.DataPlaneServiceCondition)(nil), (*DataPlaneServiceCondition)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_aggregation_DataPlaneServiceCondition_To_v0alpha1_DataPlaneServiceCondition(a.(*aggregation.DataPlaneServiceCondition), b.(*DataPlaneServiceCondition), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*DataPlaneServiceList)(nil), (*aggregation.DataPlaneServiceList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v0alpha1_DataPlaneServiceList_To_aggregation_DataPlaneServiceList(a.(*DataPlaneServiceList), b.(*aggregation.DataPlaneServiceList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*aggregation.DataPlaneServiceList)(nil), (*DataPlaneServiceList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_aggregation_DataPlaneServiceList_To_v0alpha1_DataPlaneServiceList(a.(*aggregation.DataPlaneServiceList), b.(*DataPlaneServiceList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*DataPlaneServiceSpec)(nil), (*aggregation.DataPlaneServiceSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v0alpha1_DataPlaneServiceSpec_To_aggregation_DataPlaneServiceSpec(a.(*DataPlaneServiceSpec), b.(*aggregation.DataPlaneServiceSpec), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*aggregation.DataPlaneServiceSpec)(nil), (*DataPlaneServiceSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_aggregation_DataPlaneServiceSpec_To_v0alpha1_DataPlaneServiceSpec(a.(*aggregation.DataPlaneServiceSpec), b.(*DataPlaneServiceSpec), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*DataPlaneServiceStatus)(nil), (*aggregation.DataPlaneServiceStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v0alpha1_DataPlaneServiceStatus_To_aggregation_DataPlaneServiceStatus(a.(*DataPlaneServiceStatus), b.(*aggregation.DataPlaneServiceStatus), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*aggregation.DataPlaneServiceStatus)(nil), (*DataPlaneServiceStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_aggregation_DataPlaneServiceStatus_To_v0alpha1_DataPlaneServiceStatus(a.(*aggregation.DataPlaneServiceStatus), b.(*DataPlaneServiceStatus), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*QueryDataResponse)(nil), (*aggregation.QueryDataResponse)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v0alpha1_QueryDataResponse_To_aggregation_QueryDataResponse(a.(*QueryDataResponse), b.(*aggregation.QueryDataResponse), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*aggregation.QueryDataResponse)(nil), (*QueryDataResponse)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_aggregation_QueryDataResponse_To_v0alpha1_QueryDataResponse(a.(*aggregation.QueryDataResponse), b.(*QueryDataResponse), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Service)(nil), (*aggregation.Service)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v0alpha1_Service_To_aggregation_Service(a.(*Service), b.(*aggregation.Service), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*aggregation.Service)(nil), (*Service)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_aggregation_Service_To_v0alpha1_Service(a.(*aggregation.Service), b.(*Service), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_v0alpha1_DataPlaneService_To_aggregation_DataPlaneService(in *DataPlaneService, out *aggregation.DataPlaneService, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_v0alpha1_DataPlaneServiceSpec_To_aggregation_DataPlaneServiceSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
if err := Convert_v0alpha1_DataPlaneServiceStatus_To_aggregation_DataPlaneServiceStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
// Convert_v0alpha1_DataPlaneService_To_aggregation_DataPlaneService is an autogenerated conversion function.
func Convert_v0alpha1_DataPlaneService_To_aggregation_DataPlaneService(in *DataPlaneService, out *aggregation.DataPlaneService, s conversion.Scope) error {
return autoConvert_v0alpha1_DataPlaneService_To_aggregation_DataPlaneService(in, out, s)
}
func autoConvert_aggregation_DataPlaneService_To_v0alpha1_DataPlaneService(in *aggregation.DataPlaneService, out *DataPlaneService, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_aggregation_DataPlaneServiceSpec_To_v0alpha1_DataPlaneServiceSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
if err := Convert_aggregation_DataPlaneServiceStatus_To_v0alpha1_DataPlaneServiceStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
// Convert_aggregation_DataPlaneService_To_v0alpha1_DataPlaneService is an autogenerated conversion function.
func Convert_aggregation_DataPlaneService_To_v0alpha1_DataPlaneService(in *aggregation.DataPlaneService, out *DataPlaneService, s conversion.Scope) error {
return autoConvert_aggregation_DataPlaneService_To_v0alpha1_DataPlaneService(in, out, s)
}
func autoConvert_v0alpha1_DataPlaneServiceCondition_To_aggregation_DataPlaneServiceCondition(in *DataPlaneServiceCondition, out *aggregation.DataPlaneServiceCondition, s conversion.Scope) error {
out.Type = aggregation.DataPlaneServiceConditionType(in.Type)
out.Status = aggregation.ConditionStatus(in.Status)
out.LastTransitionTime = in.LastTransitionTime
out.Reason = in.Reason
out.Message = in.Message
return nil
}
// Convert_v0alpha1_DataPlaneServiceCondition_To_aggregation_DataPlaneServiceCondition is an autogenerated conversion function.
func Convert_v0alpha1_DataPlaneServiceCondition_To_aggregation_DataPlaneServiceCondition(in *DataPlaneServiceCondition, out *aggregation.DataPlaneServiceCondition, s conversion.Scope) error {
return autoConvert_v0alpha1_DataPlaneServiceCondition_To_aggregation_DataPlaneServiceCondition(in, out, s)
}
func autoConvert_aggregation_DataPlaneServiceCondition_To_v0alpha1_DataPlaneServiceCondition(in *aggregation.DataPlaneServiceCondition, out *DataPlaneServiceCondition, s conversion.Scope) error {
out.Type = DataPlaneServiceConditionType(in.Type)
out.Status = ConditionStatus(in.Status)
out.LastTransitionTime = in.LastTransitionTime
out.Reason = in.Reason
out.Message = in.Message
return nil
}
// Convert_aggregation_DataPlaneServiceCondition_To_v0alpha1_DataPlaneServiceCondition is an autogenerated conversion function.
func Convert_aggregation_DataPlaneServiceCondition_To_v0alpha1_DataPlaneServiceCondition(in *aggregation.DataPlaneServiceCondition, out *DataPlaneServiceCondition, s conversion.Scope) error {
return autoConvert_aggregation_DataPlaneServiceCondition_To_v0alpha1_DataPlaneServiceCondition(in, out, s)
}
func autoConvert_v0alpha1_DataPlaneServiceList_To_aggregation_DataPlaneServiceList(in *DataPlaneServiceList, out *aggregation.DataPlaneServiceList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
out.Items = *(*[]aggregation.DataPlaneService)(unsafe.Pointer(&in.Items))
return nil
}
// Convert_v0alpha1_DataPlaneServiceList_To_aggregation_DataPlaneServiceList is an autogenerated conversion function.
func Convert_v0alpha1_DataPlaneServiceList_To_aggregation_DataPlaneServiceList(in *DataPlaneServiceList, out *aggregation.DataPlaneServiceList, s conversion.Scope) error {
return autoConvert_v0alpha1_DataPlaneServiceList_To_aggregation_DataPlaneServiceList(in, out, s)
}
func autoConvert_aggregation_DataPlaneServiceList_To_v0alpha1_DataPlaneServiceList(in *aggregation.DataPlaneServiceList, out *DataPlaneServiceList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
out.Items = *(*[]DataPlaneService)(unsafe.Pointer(&in.Items))
return nil
}
// Convert_aggregation_DataPlaneServiceList_To_v0alpha1_DataPlaneServiceList is an autogenerated conversion function.
func Convert_aggregation_DataPlaneServiceList_To_v0alpha1_DataPlaneServiceList(in *aggregation.DataPlaneServiceList, out *DataPlaneServiceList, s conversion.Scope) error {
return autoConvert_aggregation_DataPlaneServiceList_To_v0alpha1_DataPlaneServiceList(in, out, s)
}
func autoConvert_v0alpha1_DataPlaneServiceSpec_To_aggregation_DataPlaneServiceSpec(in *DataPlaneServiceSpec, out *aggregation.DataPlaneServiceSpec, s conversion.Scope) error {
out.PluginID = in.PluginID
out.PluginType = aggregation.PluginType(in.PluginType)
out.Group = in.Group
out.Version = in.Version
out.Services = *(*[]aggregation.Service)(unsafe.Pointer(&in.Services))
return nil
}
// Convert_v0alpha1_DataPlaneServiceSpec_To_aggregation_DataPlaneServiceSpec is an autogenerated conversion function.
func Convert_v0alpha1_DataPlaneServiceSpec_To_aggregation_DataPlaneServiceSpec(in *DataPlaneServiceSpec, out *aggregation.DataPlaneServiceSpec, s conversion.Scope) error {
return autoConvert_v0alpha1_DataPlaneServiceSpec_To_aggregation_DataPlaneServiceSpec(in, out, s)
}
func autoConvert_aggregation_DataPlaneServiceSpec_To_v0alpha1_DataPlaneServiceSpec(in *aggregation.DataPlaneServiceSpec, out *DataPlaneServiceSpec, s conversion.Scope) error {
out.PluginID = in.PluginID
out.PluginType = PluginType(in.PluginType)
out.Group = in.Group
out.Version = in.Version
out.Services = *(*[]Service)(unsafe.Pointer(&in.Services))
return nil
}
// Convert_aggregation_DataPlaneServiceSpec_To_v0alpha1_DataPlaneServiceSpec is an autogenerated conversion function.
func Convert_aggregation_DataPlaneServiceSpec_To_v0alpha1_DataPlaneServiceSpec(in *aggregation.DataPlaneServiceSpec, out *DataPlaneServiceSpec, s conversion.Scope) error {
return autoConvert_aggregation_DataPlaneServiceSpec_To_v0alpha1_DataPlaneServiceSpec(in, out, s)
}
func autoConvert_v0alpha1_DataPlaneServiceStatus_To_aggregation_DataPlaneServiceStatus(in *DataPlaneServiceStatus, out *aggregation.DataPlaneServiceStatus, s conversion.Scope) error {
out.Conditions = *(*[]aggregation.DataPlaneServiceCondition)(unsafe.Pointer(&in.Conditions))
return nil
}
// Convert_v0alpha1_DataPlaneServiceStatus_To_aggregation_DataPlaneServiceStatus is an autogenerated conversion function.
func Convert_v0alpha1_DataPlaneServiceStatus_To_aggregation_DataPlaneServiceStatus(in *DataPlaneServiceStatus, out *aggregation.DataPlaneServiceStatus, s conversion.Scope) error {
return autoConvert_v0alpha1_DataPlaneServiceStatus_To_aggregation_DataPlaneServiceStatus(in, out, s)
}
func autoConvert_aggregation_DataPlaneServiceStatus_To_v0alpha1_DataPlaneServiceStatus(in *aggregation.DataPlaneServiceStatus, out *DataPlaneServiceStatus, s conversion.Scope) error {
out.Conditions = *(*[]DataPlaneServiceCondition)(unsafe.Pointer(&in.Conditions))
return nil
}
// Convert_aggregation_DataPlaneServiceStatus_To_v0alpha1_DataPlaneServiceStatus is an autogenerated conversion function.
func Convert_aggregation_DataPlaneServiceStatus_To_v0alpha1_DataPlaneServiceStatus(in *aggregation.DataPlaneServiceStatus, out *DataPlaneServiceStatus, s conversion.Scope) error {
return autoConvert_aggregation_DataPlaneServiceStatus_To_v0alpha1_DataPlaneServiceStatus(in, out, s)
}
func autoConvert_v0alpha1_QueryDataResponse_To_aggregation_QueryDataResponse(in *QueryDataResponse, out *aggregation.QueryDataResponse, s conversion.Scope) error {
out.QueryDataResponse = in.QueryDataResponse
return nil
}
// Convert_v0alpha1_QueryDataResponse_To_aggregation_QueryDataResponse is an autogenerated conversion function.
func Convert_v0alpha1_QueryDataResponse_To_aggregation_QueryDataResponse(in *QueryDataResponse, out *aggregation.QueryDataResponse, s conversion.Scope) error {
return autoConvert_v0alpha1_QueryDataResponse_To_aggregation_QueryDataResponse(in, out, s)
}
func autoConvert_aggregation_QueryDataResponse_To_v0alpha1_QueryDataResponse(in *aggregation.QueryDataResponse, out *QueryDataResponse, s conversion.Scope) error {
out.QueryDataResponse = in.QueryDataResponse
return nil
}
// Convert_aggregation_QueryDataResponse_To_v0alpha1_QueryDataResponse is an autogenerated conversion function.
func Convert_aggregation_QueryDataResponse_To_v0alpha1_QueryDataResponse(in *aggregation.QueryDataResponse, out *QueryDataResponse, s conversion.Scope) error {
return autoConvert_aggregation_QueryDataResponse_To_v0alpha1_QueryDataResponse(in, out, s)
}
func autoConvert_v0alpha1_Service_To_aggregation_Service(in *Service, out *aggregation.Service, s conversion.Scope) error {
out.Type = aggregation.ServiceType(in.Type)
out.Method = in.Method
out.Path = in.Path
return nil
}
// Convert_v0alpha1_Service_To_aggregation_Service is an autogenerated conversion function.
func Convert_v0alpha1_Service_To_aggregation_Service(in *Service, out *aggregation.Service, s conversion.Scope) error {
return autoConvert_v0alpha1_Service_To_aggregation_Service(in, out, s)
}
func autoConvert_aggregation_Service_To_v0alpha1_Service(in *aggregation.Service, out *Service, s conversion.Scope) error {
out.Type = ServiceType(in.Type)
out.Method = in.Method
out.Path = in.Path
return nil
}
// Convert_aggregation_Service_To_v0alpha1_Service is an autogenerated conversion function.
func Convert_aggregation_Service_To_v0alpha1_Service(in *aggregation.Service, out *Service, s conversion.Scope) error {
return autoConvert_aggregation_Service_To_v0alpha1_Service(in, out, s)
}

View File

@ -0,0 +1,176 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by deepcopy-gen. DO NOT EDIT.
package v0alpha1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataPlaneService) DeepCopyInto(out *DataPlaneService) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataPlaneService.
func (in *DataPlaneService) DeepCopy() *DataPlaneService {
if in == nil {
return nil
}
out := new(DataPlaneService)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *DataPlaneService) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataPlaneServiceCondition) DeepCopyInto(out *DataPlaneServiceCondition) {
*out = *in
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataPlaneServiceCondition.
func (in *DataPlaneServiceCondition) DeepCopy() *DataPlaneServiceCondition {
if in == nil {
return nil
}
out := new(DataPlaneServiceCondition)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataPlaneServiceList) DeepCopyInto(out *DataPlaneServiceList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]DataPlaneService, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataPlaneServiceList.
func (in *DataPlaneServiceList) DeepCopy() *DataPlaneServiceList {
if in == nil {
return nil
}
out := new(DataPlaneServiceList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *DataPlaneServiceList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataPlaneServiceSpec) DeepCopyInto(out *DataPlaneServiceSpec) {
*out = *in
if in.Services != nil {
in, out := &in.Services, &out.Services
*out = make([]Service, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataPlaneServiceSpec.
func (in *DataPlaneServiceSpec) DeepCopy() *DataPlaneServiceSpec {
if in == nil {
return nil
}
out := new(DataPlaneServiceSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataPlaneServiceStatus) DeepCopyInto(out *DataPlaneServiceStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]DataPlaneServiceCondition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataPlaneServiceStatus.
func (in *DataPlaneServiceStatus) DeepCopy() *DataPlaneServiceStatus {
if in == nil {
return nil
}
out := new(DataPlaneServiceStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *QueryDataResponse) DeepCopyInto(out *QueryDataResponse) {
*out = *in
out.TypeMeta = in.TypeMeta
in.QueryDataResponse.DeepCopyInto(&out.QueryDataResponse)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new QueryDataResponse.
func (in *QueryDataResponse) DeepCopy() *QueryDataResponse {
if in == nil {
return nil
}
out := new(QueryDataResponse)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *QueryDataResponse) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Service) DeepCopyInto(out *Service) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Service.
func (in *Service) DeepCopy() *Service {
if in == nil {
return nil
}
out := new(Service)
in.DeepCopyInto(out)
return out
}

View File

@ -0,0 +1,19 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by defaulter-gen. DO NOT EDIT.
package v0alpha1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
return nil
}

View File

@ -0,0 +1,357 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by openapi-gen. DO NOT EDIT.
// This file was autogenerated by openapi-gen. Do not edit it manually!
package v0alpha1
import (
common "k8s.io/kube-openapi/pkg/common"
spec "k8s.io/kube-openapi/pkg/validation/spec"
)
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.DataPlaneService": schema_aggregator_apis_aggregation_v0alpha1_DataPlaneService(ref),
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.DataPlaneServiceCondition": schema_aggregator_apis_aggregation_v0alpha1_DataPlaneServiceCondition(ref),
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.DataPlaneServiceList": schema_aggregator_apis_aggregation_v0alpha1_DataPlaneServiceList(ref),
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.DataPlaneServiceSpec": schema_aggregator_apis_aggregation_v0alpha1_DataPlaneServiceSpec(ref),
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.DataPlaneServiceStatus": schema_aggregator_apis_aggregation_v0alpha1_DataPlaneServiceStatus(ref),
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.QueryDataResponse": schema_aggregator_apis_aggregation_v0alpha1_QueryDataResponse(ref),
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.Service": schema_aggregator_apis_aggregation_v0alpha1_Service(ref),
}
}
func schema_aggregator_apis_aggregation_v0alpha1_DataPlaneService(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
"metadata": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
},
},
"spec": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.DataPlaneServiceSpec"),
},
},
"status": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.DataPlaneServiceStatus"),
},
},
},
},
},
Dependencies: []string{
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.DataPlaneServiceSpec", "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.DataPlaneServiceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
}
}
func schema_aggregator_apis_aggregation_v0alpha1_DataPlaneServiceCondition(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "DataPlaneServiceCondition describes the state of an DataPlaneService at a particular point",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"type": {
SchemaProps: spec.SchemaProps{
Description: "Type is the type of the condition.",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"status": {
SchemaProps: spec.SchemaProps{
Description: "Status is the status of the condition. Can be True, False, Unknown.",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"lastTransitionTime": {
SchemaProps: spec.SchemaProps{
Description: "Last time the condition transitioned from one status to another.",
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
},
},
"reason": {
SchemaProps: spec.SchemaProps{
Description: "Unique, one-word, CamelCase reason for the condition's last transition.",
Type: []string{"string"},
Format: "",
},
},
"message": {
SchemaProps: spec.SchemaProps{
Description: "Human-readable message indicating details about last transition.",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"type", "status"},
},
},
Dependencies: []string{
"k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
func schema_aggregator_apis_aggregation_v0alpha1_DataPlaneServiceList(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
"metadata": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
},
},
"items": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.DataPlaneService"),
},
},
},
},
},
},
},
},
Dependencies: []string{
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.DataPlaneService", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
}
}
func schema_aggregator_apis_aggregation_v0alpha1_DataPlaneServiceSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"pluginID": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"pluginType": {
SchemaProps: spec.SchemaProps{
Description: "Possible enum values:\n - `\"app\"`\n - `\"datasource\"`",
Default: "",
Type: []string{"string"},
Format: "",
Enum: []interface{}{"app", "datasource"},
},
},
"group": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"version": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"services": {
VendorExtensible: spec.VendorExtensible{
Extensions: spec.Extensions{
"x-kubernetes-list-map-keys": []interface{}{
"type",
},
"x-kubernetes-list-type": "map",
},
},
SchemaProps: spec.SchemaProps{
Description: "Services is a list of services that the proxied service provides.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.Service"),
},
},
},
},
},
},
Required: []string{"pluginID", "pluginType", "group", "version"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.Service"},
}
}
func schema_aggregator_apis_aggregation_v0alpha1_DataPlaneServiceStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "DataPlaneServiceStatus contains derived information about a remote DataPlaneService.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"conditions": {
VendorExtensible: spec.VendorExtensible{
Extensions: spec.Extensions{
"x-kubernetes-list-map-keys": []interface{}{
"type",
},
"x-kubernetes-list-type": "map",
},
},
SchemaProps: spec.SchemaProps{
Description: "Current service state of DataPlaneService.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.DataPlaneServiceCondition"),
},
},
},
},
},
},
},
},
Dependencies: []string{
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1.DataPlaneServiceCondition"},
}
}
func schema_aggregator_apis_aggregation_v0alpha1_QueryDataResponse(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
"results": {
SchemaProps: spec.SchemaProps{
Description: "Responses is a map of RefIDs (Unique Query ID) to *DataResponse.",
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana-plugin-sdk-go/backend.DataResponse"),
},
},
},
},
},
},
Required: []string{"results"},
},
},
Dependencies: []string{
"github.com/grafana/grafana-plugin-sdk-go/backend.DataResponse"},
}
}
func schema_aggregator_apis_aggregation_v0alpha1_Service(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "Service defines the type of service the proxied service provides.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"type": {
SchemaProps: spec.SchemaProps{
Description: "Type is the type of service to proxy.\n\nPossible enum values:\n - `\"admission\"` maps to pluginv2.AdmissionControl\n - `\"conversion\"` maps to pluginv2.ResourceConversion\n - `\"data\"` DataSourceServiceType maps to pluginv2.Data\n - `\"datsource-proxy\"` is a reverse proxy for making requests directly to the HTTP URL specified in datasource instance settings.\n - `\"route\"` maps pluginv2.Resource\n - `\"stream\"` maps to pluginv2.Stream",
Default: "",
Type: []string{"string"},
Format: "",
Enum: []interface{}{"admission", "conversion", "data", "datsource-proxy", "route", "stream"},
},
},
"method": {
SchemaProps: spec.SchemaProps{
Description: "Method is the HTTP method to use when proxying the service.",
Type: []string{"string"},
Format: "",
},
},
"path": {
SchemaProps: spec.SchemaProps{
Description: "Path is used by the CustomRouteServiceType and SubResourceServiceType to specify the path to the endpoint.",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"type"},
},
},
}
}

View File

@ -0,0 +1,176 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by deepcopy-gen. DO NOT EDIT.
package aggregation
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataPlaneService) DeepCopyInto(out *DataPlaneService) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataPlaneService.
func (in *DataPlaneService) DeepCopy() *DataPlaneService {
if in == nil {
return nil
}
out := new(DataPlaneService)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *DataPlaneService) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataPlaneServiceCondition) DeepCopyInto(out *DataPlaneServiceCondition) {
*out = *in
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataPlaneServiceCondition.
func (in *DataPlaneServiceCondition) DeepCopy() *DataPlaneServiceCondition {
if in == nil {
return nil
}
out := new(DataPlaneServiceCondition)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataPlaneServiceList) DeepCopyInto(out *DataPlaneServiceList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]DataPlaneService, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataPlaneServiceList.
func (in *DataPlaneServiceList) DeepCopy() *DataPlaneServiceList {
if in == nil {
return nil
}
out := new(DataPlaneServiceList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *DataPlaneServiceList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataPlaneServiceSpec) DeepCopyInto(out *DataPlaneServiceSpec) {
*out = *in
if in.Services != nil {
in, out := &in.Services, &out.Services
*out = make([]Service, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataPlaneServiceSpec.
func (in *DataPlaneServiceSpec) DeepCopy() *DataPlaneServiceSpec {
if in == nil {
return nil
}
out := new(DataPlaneServiceSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataPlaneServiceStatus) DeepCopyInto(out *DataPlaneServiceStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]DataPlaneServiceCondition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataPlaneServiceStatus.
func (in *DataPlaneServiceStatus) DeepCopy() *DataPlaneServiceStatus {
if in == nil {
return nil
}
out := new(DataPlaneServiceStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *QueryDataResponse) DeepCopyInto(out *QueryDataResponse) {
*out = *in
out.TypeMeta = in.TypeMeta
in.QueryDataResponse.DeepCopyInto(&out.QueryDataResponse)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new QueryDataResponse.
func (in *QueryDataResponse) DeepCopy() *QueryDataResponse {
if in == nil {
return nil
}
out := new(QueryDataResponse)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *QueryDataResponse) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Service) DeepCopyInto(out *Service) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Service.
func (in *Service) DeepCopy() *Service {
if in == nil {
return nil
}
out := new(Service)
in.DeepCopyInto(out)
return out
}

View File

@ -0,0 +1,207 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Provenance-includes-location: https://github.com/kubernetes/kube-aggregator/blob/master/pkg/apiserver/apiserver.go
// Provenance-includes-license: Apache-2.0
// Provenance-includes-copyright: The Kubernetes Authors.
package apiserver
import (
"context"
"net/http"
"time"
"k8s.io/apimachinery/pkg/util/sets"
genericapiserver "k8s.io/apiserver/pkg/server"
serverstorage "k8s.io/apiserver/pkg/server/storage"
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
v0alpha1helper "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1/helper"
"github.com/grafana/grafana/pkg/aggregator/apiserver/scheme"
clientset "github.com/grafana/grafana/pkg/aggregator/generated/clientset/versioned"
informers "github.com/grafana/grafana/pkg/aggregator/generated/informers/externalversions"
dataplaneservicerest "github.com/grafana/grafana/pkg/aggregator/registry/dataplaneservice/rest"
)
type ExtraConfig struct {
PluginClient PluginClient
PluginContextProvider PluginContextProvider
}
type Config struct {
GenericConfig *genericapiserver.RecommendedConfig
ExtraConfig ExtraConfig
}
type completedConfig struct {
GenericConfig genericapiserver.CompletedConfig
ExtraConfig *ExtraConfig
}
// CompletedConfig same as Config, just to swap private object.
type CompletedConfig struct {
// Embed a private pointer that cannot be instantiated outside of this package.
*completedConfig
}
type runnable interface {
RunWithContext(ctx context.Context) error
}
// preparedGenericAPIServer is a private wrapper that enforces a call of PrepareRun() before Run can be invoked.
type preparedGrafanaAggregator struct {
*GrafanaAggregator
runnable runnable
}
// GrafanaAggregator contains state for a Kubernetes cluster master/api server.
type GrafanaAggregator struct {
GenericAPIServer *genericapiserver.GenericAPIServer
RegistrationInformers informers.SharedInformerFactory
delegateHandler http.Handler
proxyHandlers map[string]*proxyHandler
handledGroupVersions map[string]sets.Set[string]
PluginClient PluginClient
PluginContextProvider PluginContextProvider
}
// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver.
func (cfg *Config) Complete() CompletedConfig {
c := completedConfig{
cfg.GenericConfig.Complete(),
&cfg.ExtraConfig,
}
c.GenericConfig.EnableDiscovery = true
return CompletedConfig{&c}
}
// NewWithDelegate returns a new instance of GrafanaAggregator from the given config.
func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.DelegationTarget) (*GrafanaAggregator, error) {
genericServer, err := c.GenericConfig.New("grafana-aggregator", delegationTarget)
if err != nil {
return nil, err
}
discoveryHandler := &apisProxyHandler{
delegationTarget: delegationTarget,
codecs: scheme.Codecs,
}
genericServer.Handler.GoRestfulContainer.Filter(discoveryHandler.handle)
dataplaneServiceRegistrationControllerInitiated := make(chan struct{})
if err := genericServer.RegisterMuxAndDiscoveryCompleteSignal("DataPlaneServiceRegistrationControllerInitiated", dataplaneServiceRegistrationControllerInitiated); err != nil {
return nil, err
}
dataplaneServiceClient, err := clientset.NewForConfig(c.GenericConfig.LoopbackClientConfig)
if err != nil {
return nil, err
}
informerFactory := informers.NewSharedInformerFactory(
dataplaneServiceClient,
5*time.Minute,
)
s := &GrafanaAggregator{
GenericAPIServer: genericServer,
RegistrationInformers: informerFactory,
delegateHandler: delegationTarget.UnprotectedHandler(),
handledGroupVersions: map[string]sets.Set[string]{},
proxyHandlers: map[string]*proxyHandler{},
PluginClient: c.ExtraConfig.PluginClient,
PluginContextProvider: c.ExtraConfig.PluginContextProvider,
}
dataplaneServiceRegistrationController := NewDataPlaneServiceRegistrationController(informerFactory.Aggregation().V0alpha1().DataPlaneServices(), s)
apiGroupInfo := dataplaneservicerest.NewRESTStorage(c.GenericConfig.MergedResourceConfig, c.GenericConfig.RESTOptionsGetter, true)
if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil {
return nil, err
}
s.GenericAPIServer.AddPostStartHookOrDie("start-dataplane-aggregator-informers", func(context genericapiserver.PostStartHookContext) error {
informerFactory.Start(context.Done())
return nil
})
s.GenericAPIServer.AddPostStartHookOrDie("dataplaneservice-registration-controller", func(context genericapiserver.PostStartHookContext) error {
go dataplaneServiceRegistrationController.Run(context, dataplaneServiceRegistrationControllerInitiated)
select {
case <-context.Done():
case <-dataplaneServiceRegistrationControllerInitiated:
}
return nil
})
return s, nil
}
// PrepareRun prepares the aggregator to run
func (s *GrafanaAggregator) PrepareRun() (preparedGrafanaAggregator, error) {
prepared := s.GenericAPIServer.PrepareRun()
return preparedGrafanaAggregator{GrafanaAggregator: s, runnable: prepared}, nil
}
func (s preparedGrafanaAggregator) RunWithContext(ctx context.Context) error {
return s.runnable.RunWithContext(ctx)
}
func (s *GrafanaAggregator) AddDataPlaneService(dataplaneService *v0alpha1.DataPlaneService) error {
if proxyHandler, exists := s.proxyHandlers[dataplaneService.Name]; exists {
proxyHandler.updateDataPlaneService(dataplaneService)
return nil
}
proxyPath := "/apis/dataplane/" + dataplaneService.Spec.Group + "/" + dataplaneService.Spec.Version
proxyHandler := &proxyHandler{
localDelegate: s.delegateHandler,
client: s.PluginClient,
pluginContextProvider: s.PluginContextProvider,
}
proxyHandler.updateDataPlaneService(dataplaneService)
s.proxyHandlers[dataplaneService.Name] = proxyHandler
s.GenericAPIServer.Handler.NonGoRestfulMux.Handle(proxyPath, proxyHandler)
s.GenericAPIServer.Handler.NonGoRestfulMux.UnlistedHandlePrefix(proxyPath+"/", proxyHandler)
versions, exist := s.handledGroupVersions[dataplaneService.Spec.Group]
if exist {
versions.Insert(dataplaneService.Spec.Version)
return nil
}
s.handledGroupVersions[dataplaneService.Spec.Group] = sets.New[string](dataplaneService.Spec.Version)
return nil
}
func (s *GrafanaAggregator) RemoveDataPlaneService(dataplaneServiceName string) {
version := v0alpha1helper.DataPlaneServiceNameToGroupVersion(dataplaneServiceName)
proxyPath := "/apis/dataplane/" + version.Group + "/" + version.Version
s.GenericAPIServer.Handler.NonGoRestfulMux.Unregister(proxyPath)
s.GenericAPIServer.Handler.NonGoRestfulMux.Unregister(proxyPath + "/")
delete(s.proxyHandlers, dataplaneServiceName)
versions, exist := s.handledGroupVersions[version.Group]
if !exist {
return
}
versions.Delete(version.Version)
if versions.Len() > 0 {
return
}
delete(s.handledGroupVersions, version.Group)
groupPath := "/apis/dataplane/" + version.Group
s.GenericAPIServer.Handler.NonGoRestfulMux.Unregister(groupPath)
s.GenericAPIServer.Handler.NonGoRestfulMux.Unregister(groupPath + "/")
}
// DefaultAPIResourceConfigSource returns default configuration for an APIResource.
func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig {
ret := serverstorage.NewResourceConfig()
ret.EnableVersions(
v0alpha1.SchemeGroupVersion,
)
return ret
}

View File

@ -0,0 +1,205 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Provenance-includes-location: https://github.com/kubernetes/kube-aggregator/blob/master/pkg/apiserver/apiservice_controller.go
// Provenance-includes-license: Apache-2.0
// Provenance-includes-copyright: The Kubernetes Authors.
package apiserver
import (
"context"
"fmt"
"time"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/server/dynamiccertificates"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
"k8s.io/klog/v2"
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
informers "github.com/grafana/grafana/pkg/aggregator/generated/informers/externalversions/aggregation/v0alpha1"
listers "github.com/grafana/grafana/pkg/aggregator/generated/listers/aggregation/v0alpha1"
)
// DataPlaneHandlerManager defines the behaviour that an API handler should have.
type DataPlaneHandlerManager interface {
AddDataPlaneService(dataPlaneService *v0alpha1.DataPlaneService) error
RemoveDataPlaneService(dataPlaneServiceName string)
}
// DataPlaneServiceRegistrationController is responsible for registering and removing API services.
type DataPlaneServiceRegistrationController struct {
dataPlaneHandlerManager DataPlaneHandlerManager
dataPlaneServiceLister listers.DataPlaneServiceLister
dataPlaneServiceSynced cache.InformerSynced
// To allow injection for testing.
syncFn func(key string) error
queue workqueue.TypedRateLimitingInterface[string]
}
var _ dynamiccertificates.Listener = &DataPlaneServiceRegistrationController{}
// NewDataPlaneServiceRegistrationController returns a new DataPlaneServiceRegistrationController.
func NewDataPlaneServiceRegistrationController(dataPlaneServiceInformer informers.DataPlaneServiceInformer, dataPlaneHandlerManager DataPlaneHandlerManager) *DataPlaneServiceRegistrationController {
c := &DataPlaneServiceRegistrationController{
dataPlaneHandlerManager: dataPlaneHandlerManager,
dataPlaneServiceLister: dataPlaneServiceInformer.Lister(),
dataPlaneServiceSynced: dataPlaneServiceInformer.Informer().HasSynced,
queue: workqueue.NewTypedRateLimitingQueueWithConfig(
// We want a fairly tight requeue time. The controller listens to the API, but because it relies on the routability of the
// service network, it is possible for an external, non-watchable factor to affect availability. This keeps
// the maximum disruption time to a minimum, but it does prevent hot loops.
workqueue.NewTypedItemExponentialFailureRateLimiter[string](5*time.Millisecond, 30*time.Second),
workqueue.TypedRateLimitingQueueConfig[string]{Name: "DataPlaneServiceRegistrationController"},
),
}
_, err := dataPlaneServiceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: c.addDataPlaneService,
UpdateFunc: c.updateDataPlaneService,
DeleteFunc: c.deleteDataPlaneService,
})
if err != nil {
klog.Errorf("Failed to register event handler for DataPlaneService: %v", err)
}
c.syncFn = c.sync
return c
}
func (c *DataPlaneServiceRegistrationController) sync(key string) error {
dataPlaneService, err := c.dataPlaneServiceLister.Get(key)
if apierrors.IsNotFound(err) {
c.dataPlaneHandlerManager.RemoveDataPlaneService(key)
return nil
}
if err != nil {
return err
}
return c.dataPlaneHandlerManager.AddDataPlaneService(dataPlaneService)
}
// Run starts DataPlaneServiceRegistrationController which will process all registration requests until stopCh is closed.
func (c *DataPlaneServiceRegistrationController) Run(ctx context.Context, handlerSyncedCh chan<- struct{}) {
defer utilruntime.HandleCrash()
defer c.queue.ShutDown()
klog.Info("Starting DataPlaneServiceRegistrationController")
defer klog.Info("Shutting down DataPlaneServiceRegistrationController")
if !cache.WaitForCacheSync(ctx.Done(), c.dataPlaneServiceSynced) {
return
}
// initially sync all DataPlaneServices to make sure the proxy handler is complete
err := wait.PollUntilContextCancel(ctx, time.Second, true, func(context.Context) (bool, error) {
services, err := c.dataPlaneServiceLister.List(labels.Everything())
if err != nil {
utilruntime.HandleError(fmt.Errorf("failed to initially list DataPlaneServices: %v", err))
return false, nil
}
for _, s := range services {
if err := c.dataPlaneHandlerManager.AddDataPlaneService(s); err != nil {
utilruntime.HandleError(fmt.Errorf("failed to initially sync DataPlaneService %s: %v", s.Name, err))
return false, nil
}
}
return true, nil
})
if err != nil {
utilruntime.HandleError(err)
return
}
close(handlerSyncedCh)
// only start one worker thread since its a slow moving API and the aggregation server adding bits
// aren't threadsafe
go wait.Until(c.runWorker, time.Second, ctx.Done())
<-ctx.Done()
}
func (c *DataPlaneServiceRegistrationController) runWorker() {
for c.processNextWorkItem() {
}
}
// processNextWorkItem deals with one key off the queue. It returns false when it's time to quit.
func (c *DataPlaneServiceRegistrationController) processNextWorkItem() bool {
key, quit := c.queue.Get()
if quit {
return false
}
defer c.queue.Done(key)
err := c.syncFn(key)
if err == nil {
c.queue.Forget(key)
return true
}
utilruntime.HandleError(fmt.Errorf("%v failed with : %v", key, err))
c.queue.AddRateLimited(key)
return true
}
func (c *DataPlaneServiceRegistrationController) enqueueInternal(obj *v0alpha1.DataPlaneService) {
key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj)
if err != nil {
klog.Errorf("Couldn't get key for object %#v: %v", obj, err)
return
}
c.queue.Add(key)
}
func (c *DataPlaneServiceRegistrationController) addDataPlaneService(obj interface{}) {
castObj := obj.(*v0alpha1.DataPlaneService)
klog.V(4).Infof("Adding %s", castObj.Name)
c.enqueueInternal(castObj)
}
func (c *DataPlaneServiceRegistrationController) updateDataPlaneService(obj, _ interface{}) {
castObj := obj.(*v0alpha1.DataPlaneService)
klog.V(4).Infof("Updating %s", castObj.Name)
c.enqueueInternal(castObj)
}
func (c *DataPlaneServiceRegistrationController) deleteDataPlaneService(obj interface{}) {
castObj, ok := obj.(*v0alpha1.DataPlaneService)
if !ok {
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
if !ok {
klog.Errorf("Couldn't get object from tombstone %#v", obj)
return
}
castObj, ok = tombstone.Obj.(*v0alpha1.DataPlaneService)
if !ok {
klog.Errorf("Tombstone contained object that is not expected %#v", obj)
return
}
}
klog.V(4).Infof("Deleting %q", castObj.Name)
c.enqueueInternal(castObj)
}
func (c *DataPlaneServiceRegistrationController) Enqueue() {
dataPlaneServices, err := c.dataPlaneServiceLister.List(labels.Everything())
if err != nil {
utilruntime.HandleError(err)
return
}
for _, dataPlaneService := range dataPlaneServices {
c.addDataPlaneService(dataPlaneService)
}
}

View File

@ -0,0 +1,68 @@
package apiserver
import (
"encoding/json"
"net/http"
"net/http/httptest"
"github.com/emicklei/go-restful/v3"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
genericapiserver "k8s.io/apiserver/pkg/server"
aggregationv0alpha1api "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
)
var (
discoveryGroup = metav1.APIGroup{
Name: aggregationv0alpha1api.SchemeGroupVersion.Group,
Versions: []metav1.GroupVersionForDiscovery{
{
GroupVersion: aggregationv0alpha1api.SchemeGroupVersion.String(),
Version: aggregationv0alpha1api.SchemeGroupVersion.Version,
},
},
PreferredVersion: metav1.GroupVersionForDiscovery{
GroupVersion: aggregationv0alpha1api.SchemeGroupVersion.String(),
Version: aggregationv0alpha1api.SchemeGroupVersion.Version,
},
}
)
// apisProxyHandler serves the `/apis` endpoint.
type apisProxyHandler struct {
delegationTarget genericapiserver.DelegationTarget
codecs serializer.CodecFactory
}
func (a *apisProxyHandler) handle(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
if req.Request.URL.Path != "/apis" && req.Request.URL.Path != "/apis/" {
chain.ProcessFilter(req, resp)
return
}
discoveryGroupList := &metav1.APIGroupList{
Groups: []metav1.APIGroup{discoveryGroup},
}
rw := httptest.NewRecorder()
a.delegationTarget.UnprotectedHandler().ServeHTTP(rw, req.Request)
if rw.Code != http.StatusOK {
http.Error(resp.ResponseWriter, rw.Body.String(), rw.Code)
return
}
proxiedGroups := metav1.APIGroupList{}
if err := json.Unmarshal(rw.Body.Bytes(), &proxiedGroups); err != nil {
http.Error(resp.ResponseWriter, err.Error(), http.StatusInternalServerError)
return
}
discoveryGroupList.Groups = append(discoveryGroupList.Groups, proxiedGroups.Groups...)
responsewriters.WriteObjectNegotiated(a.codecs, negotiation.DefaultEndpointRestrictions, schema.GroupVersion{}, resp.ResponseWriter, req.Request, http.StatusOK, discoveryGroupList, false)
}

View File

@ -0,0 +1,141 @@
package apiserver
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"github.com/grafana/grafana-plugin-sdk-go/backend"
data "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1"
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
"k8s.io/component-base/tracing"
"k8s.io/klog/v2"
aggregationv0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
grafanasemconv "github.com/grafana/grafana/pkg/semconv"
)
type pluginHandler struct {
mux *http.ServeMux
delegate http.Handler
client PluginClient
pluginContextProvider PluginContextProvider
dataplaneService aggregationv0alpha1.DataPlaneService
}
func newPluginHandler(
client PluginClient,
dataplaneService aggregationv0alpha1.DataPlaneService,
pluginContextProvider PluginContextProvider,
delegate http.Handler,
) *pluginHandler {
mux := http.NewServeMux()
h := &pluginHandler{
mux: mux,
delegate: delegate,
client: client,
pluginContextProvider: pluginContextProvider,
dataplaneService: dataplaneService,
}
for _, service := range dataplaneService.Spec.Services {
switch service.Type {
case aggregationv0alpha1.DataServiceType:
proxyPath := fmt.Sprintf("/apis/%s/%s/namespaces/{namespace}/connections/{uid}/query", dataplaneService.Spec.Group, dataplaneService.Spec.Version)
mux.Handle(proxyPath, h.QueryDataHandler())
case aggregationv0alpha1.StreamServiceType:
// TODO: implement in future PR
case aggregationv0alpha1.AdmissionControlServiceType:
// TODO: implement in future PR
case aggregationv0alpha1.RouteServiceType:
// TODO: implement in future PR
case aggregationv0alpha1.ConversionServiceType:
// TODO: implement in future PR
case aggregationv0alpha1.DataSourceProxyServiceType:
// TODO: implement in future PR
}
}
// fallback to the delegate
mux.Handle("/", delegate)
return h
}
func (h *pluginHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
h.mux.ServeHTTP(w, req)
}
func (h *pluginHandler) QueryDataHandler() http.HandlerFunc {
return func(w http.ResponseWriter, req *http.Request) {
ctx := req.Context()
span := tracing.SpanFromContext(ctx)
span.AddEvent("QueryDataHandler")
responder := &responder{w: w}
dqr := data.QueryDataRequest{}
if err := json.NewDecoder(req.Body).Decode(&dqr); err != nil {
responder.Error(w, req, err)
return
}
dsUID := req.PathValue("uid")
dsType := h.dataplaneService.Spec.PluginID
queries, dsRef, err := data.ToDataSourceQueries(dqr)
if err != nil {
responder.Error(w, req, err)
return
}
// this shouldn't happen, but just in case
if dsRef == nil {
responder.Error(w, req, fmt.Errorf("missing datasource reference"))
return
}
// the datasource type in the query body should match the plugin ID
if dsRef.Type != dsType {
err := errors.New("invalid datasource type")
klog.ErrorS(err, "type", dsType, "ref.Type", dsRef.Type)
responder.Error(w, req, err)
return
}
// the UID in the query body should match the UID in the URL
if dsRef.UID != dsUID {
err := errors.New("invalid datasource UID")
klog.ErrorS(err, "path", dsUID, "ref.UID", dsRef.UID)
responder.Error(w, req, err)
return
}
span.AddEvent("GetPluginContext",
grafanasemconv.GrafanaDatasourceUid(dsRef.UID),
grafanasemconv.GrafanaDatasourceType(dsRef.Type),
)
pluginContext, err := h.pluginContextProvider.GetPluginContext(ctx, dsRef.Type, dsRef.UID)
if err != nil {
responder.Error(w, req, fmt.Errorf("unable to get plugin context: %w", err))
return
}
ctx = backend.WithGrafanaConfig(ctx, pluginContext.GrafanaConfig)
span.AddEvent("QueryData start", grafanasemconv.GrafanaDatasourceRequestQueryCount(len(queries)))
rsp, err := h.client.QueryData(ctx, &backend.QueryDataRequest{
Queries: queries,
PluginContext: pluginContext,
})
if err != nil {
responder.Error(w, req, err)
return
}
statusCode := 200
span.AddEvent("QueryData end", semconv.HTTPResponseStatusCode(statusCode))
responder.Object(statusCode,
&aggregationv0alpha1.QueryDataResponse{QueryDataResponse: *rsp},
)
}
}

View File

@ -0,0 +1,202 @@
package apiserver
import (
"bytes"
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/data"
datav0alpha1 "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1"
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestQueryDataHandler(t *testing.T) {
dps := v0alpha1.DataPlaneService{
Spec: v0alpha1.DataPlaneServiceSpec{
PluginID: "testds",
Group: "testds.example.com",
Version: "v1",
Services: []v0alpha1.Service{
{
Type: v0alpha1.DataServiceType,
},
},
},
}
pluginContext := backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
ID: 1,
},
}
contextProvider := &fakePluginContextProvider{
pluginContext: pluginContext,
}
res := &backend.QueryDataResponse{
Responses: map[string]backend.DataResponse{
"A": {
Frames: []*data.Frame{
{
Name: "test-frame",
},
},
},
},
}
pc := &fakes.FakePluginClient{
QueryDataHandlerFunc: newfakeQueryDataHandler(res, nil),
}
delegate := newFakeHTTPHandler(http.StatusNotFound, []byte(`Not Found`))
handler := newPluginHandler(pc, dps, contextProvider, delegate)
qdr := datav0alpha1.QueryDataRequest{
TimeRange: datav0alpha1.TimeRange{},
Queries: []datav0alpha1.DataQuery{{
CommonQueryProperties: datav0alpha1.CommonQueryProperties{
RefID: "1",
ResultAssertions: &datav0alpha1.ResultAssertions{},
TimeRange: &datav0alpha1.TimeRange{},
Datasource: &datav0alpha1.DataSourceRef{
Type: "testds",
UID: "123",
APIVersion: "v1",
},
DatasourceID: 0,
QueryType: "",
MaxDataPoints: 0,
IntervalMS: 0,
Hide: false,
},
}},
Debug: false,
}
t.Run("should return query response", func(t *testing.T) {
buf := bytes.NewBuffer(nil)
assert.NoError(t, json.NewEncoder(buf).Encode(qdr))
req, err := http.NewRequest("POST", "/apis/testds.example.com/v1/namespaces/default/connections/123/query", buf)
assert.NoError(t, err)
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
assert.Equal(t, http.StatusOK, rr.Code)
res := &v0alpha1.QueryDataResponse{
TypeMeta: metav1.TypeMeta{
APIVersion: "aggregation.grafana.com/v0alpha1",
Kind: "QueryDataResponse",
},
QueryDataResponse: *res,
}
resBuf := bytes.NewBuffer(nil)
assert.NoError(t, json.NewEncoder(resBuf).Encode(res))
expected, err := json.MarshalIndent(res, "", " ")
require.NoError(t, err)
assert.Equal(t, string(expected), rr.Body.String())
})
t.Run("should return type error", func(t *testing.T) {
qdr.Queries[0].Datasource.Type = "wrongds"
buf := bytes.NewBuffer(nil)
assert.NoError(t, json.NewEncoder(buf).Encode(qdr))
req, err := http.NewRequest("POST", "/apis/testds.example.com/v1/namespaces/default/connections/123/query", buf)
assert.NoError(t, err)
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
assert.Equal(t, http.StatusInternalServerError, rr.Code)
res := &metav1.Status{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Status",
},
Status: metav1.StatusFailure,
Code: http.StatusInternalServerError,
Message: "invalid datasource type",
}
resBuf := bytes.NewBuffer(nil)
assert.NoError(t, json.NewEncoder(resBuf).Encode(res))
expected, err := json.MarshalIndent(res, "", " ")
require.NoError(t, err)
assert.Equal(t, string(expected), rr.Body.String())
})
t.Run("should return UID error", func(t *testing.T) {
qdr.Queries[0].Datasource.Type = "testds"
buf := bytes.NewBuffer(nil)
assert.NoError(t, json.NewEncoder(buf).Encode(qdr))
req, err := http.NewRequest("POST", "/apis/testds.example.com/v1/namespaces/default/connections/abc/query", buf)
assert.NoError(t, err)
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
assert.Equal(t, http.StatusInternalServerError, rr.Code)
res := &metav1.Status{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Status",
},
Status: metav1.StatusFailure,
Code: http.StatusInternalServerError,
Message: "invalid datasource UID",
}
resBuf := bytes.NewBuffer(nil)
assert.NoError(t, json.NewEncoder(resBuf).Encode(res))
expected, err := json.MarshalIndent(res, "", " ")
require.NoError(t, err)
assert.Equal(t, string(expected), rr.Body.String())
})
t.Run("should return delegate response if group does not match", func(t *testing.T) {
req, err := http.NewRequest("POST", "/apis/wrongds.example.com/v1/namespaces/default/connections/abc/query", bytes.NewBuffer(nil))
assert.NoError(t, err)
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
assert.Equal(t, http.StatusNotFound, rr.Code)
assert.Equal(t, "Not Found", rr.Body.String())
})
}
type fakePluginContextProvider struct {
pluginContext backend.PluginContext
err error
}
func (f fakePluginContextProvider) GetPluginContext(ctx context.Context, pluginID, dsUID string) (backend.PluginContext, error) {
return f.pluginContext, f.err
}
func newfakeQueryDataHandler(res *backend.QueryDataResponse, err error) backend.QueryDataHandlerFunc {
return func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
return res, err
}
}
func newFakeHTTPHandler(status int, res []byte) http.HandlerFunc {
return func(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(status)
_, err := w.Write(res)
if err != nil {
panic(err)
}
}
}

View File

@ -0,0 +1,102 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Provenance-includes-location: https://github.com/kubernetes/kube-aggregator/blob/master/pkg/apiserver/handler_proxy.go
// Provenance-includes-license: Apache-2.0
// Provenance-includes-copyright: The Kubernetes Authors.
package apiserver
import (
"context"
"net/http"
"sync/atomic"
"time"
"github.com/grafana/grafana-plugin-sdk-go/backend"
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/component-base/tracing"
aggregationv0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
grafanasemconv "github.com/grafana/grafana/pkg/semconv"
)
type PluginClient interface {
backend.QueryDataHandler
backend.StreamHandler
backend.AdmissionHandler
backend.CallResourceHandler
}
type PluginContextProvider interface {
GetPluginContext(ctx context.Context, pluginID, uid string) (backend.PluginContext, error)
}
// proxyHandler provides a http.Handler which will proxy traffic to a plugin client.
type proxyHandler struct {
localDelegate http.Handler
client PluginClient
pluginContextProvider PluginContextProvider
handlingInfo atomic.Value
}
type proxyHandlingInfo struct {
name string
handler *pluginHandler
}
func (r *proxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
value := r.handlingInfo.Load()
if value == nil {
r.localDelegate.ServeHTTP(w, req)
return
}
handlingInfo := value.(proxyHandlingInfo)
namespace, _ := request.NamespaceFrom(req.Context())
ctx, span := tracing.Start(
req.Context(),
"grafana-aggregator",
grafanasemconv.K8sDataplaneserviceName(handlingInfo.name),
semconv.K8SNamespaceName(namespace),
semconv.HTTPMethod(req.Method),
semconv.HTTPURL(req.URL.String()),
)
// log if the span has not ended after a minute
defer span.End(time.Minute)
handlingInfo.handler.ServeHTTP(w, req.WithContext(ctx))
}
func (r *proxyHandler) updateDataPlaneService(dataplaneService *aggregationv0alpha1.DataPlaneService) {
newInfo := proxyHandlingInfo{
name: dataplaneService.Name,
}
newInfo.handler = newPluginHandler(
r.client,
*dataplaneService,
r.pluginContextProvider,
r.localDelegate,
)
r.handlingInfo.Store(newInfo)
}
// responder implements rest.Responder for assisting a connector in writing objects or errors.
type responder struct {
w http.ResponseWriter
}
// TODO this should properly handle content type negotiation
// if the caller asked for protobuf and you write JSON bad things happen.
func (r *responder) Object(statusCode int, obj runtime.Object) {
responsewriters.WriteRawJSON(statusCode, obj, r.w)
}
func (r *responder) Error(_ http.ResponseWriter, req *http.Request, err error) {
tracing.SpanFromContext(req.Context()).RecordError(err)
s := responsewriters.ErrorToAPIStatus(err)
r.Object(http.StatusInternalServerError, s)
}

View File

@ -0,0 +1,32 @@
package scheme
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/install"
)
var (
Scheme = runtime.NewScheme()
Codecs = serializer.NewCodecFactory(Scheme)
)
func init() {
// we need to add the options to empty v1
// TODO fix the server code to avoid this
metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
// TODO: keep the generic API server from wanting this
unversioned := schema.GroupVersion{Group: "", Version: "v1"}
Scheme.AddUnversionedTypes(unversioned,
&metav1.Status{},
&metav1.APIVersions{},
&metav1.APIGroupList{},
&metav1.APIGroup{},
&metav1.APIResourceList{},
)
install.Install(Scheme)
}

View File

@ -0,0 +1,9 @@
apiVersion: aggregation.grafana.app/v0alpha1
kind: DataPlaneService
metadata:
name: v0alpha1.prometheus.grafana.app
spec:
group: prometheus.grafana.app
version: v0alpha1
services:
- type: data

View File

@ -0,0 +1,204 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by applyconfiguration-gen. DO NOT EDIT.
package v0alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// DataPlaneServiceApplyConfiguration represents an declarative configuration of the DataPlaneService type for use
// with apply.
type DataPlaneServiceApplyConfiguration struct {
v1.TypeMetaApplyConfiguration `json:",inline"`
*v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"`
Spec *DataPlaneServiceSpecApplyConfiguration `json:"spec,omitempty"`
Status *DataPlaneServiceStatusApplyConfiguration `json:"status,omitempty"`
}
// DataPlaneService constructs an declarative configuration of the DataPlaneService type for use with
// apply.
func DataPlaneService(name string) *DataPlaneServiceApplyConfiguration {
b := &DataPlaneServiceApplyConfiguration{}
b.WithName(name)
b.WithKind("DataPlaneService")
b.WithAPIVersion("aggregation.grafana.app/v0alpha1")
return b
}
// WithKind sets the Kind field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Kind field is set to the value of the last call.
func (b *DataPlaneServiceApplyConfiguration) WithKind(value string) *DataPlaneServiceApplyConfiguration {
b.Kind = &value
return b
}
// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the APIVersion field is set to the value of the last call.
func (b *DataPlaneServiceApplyConfiguration) WithAPIVersion(value string) *DataPlaneServiceApplyConfiguration {
b.APIVersion = &value
return b
}
// WithName sets the Name field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Name field is set to the value of the last call.
func (b *DataPlaneServiceApplyConfiguration) WithName(value string) *DataPlaneServiceApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.Name = &value
return b
}
// WithGenerateName sets the GenerateName field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the GenerateName field is set to the value of the last call.
func (b *DataPlaneServiceApplyConfiguration) WithGenerateName(value string) *DataPlaneServiceApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.GenerateName = &value
return b
}
// WithNamespace sets the Namespace field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Namespace field is set to the value of the last call.
func (b *DataPlaneServiceApplyConfiguration) WithNamespace(value string) *DataPlaneServiceApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.Namespace = &value
return b
}
// WithUID sets the UID field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the UID field is set to the value of the last call.
func (b *DataPlaneServiceApplyConfiguration) WithUID(value types.UID) *DataPlaneServiceApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.UID = &value
return b
}
// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the ResourceVersion field is set to the value of the last call.
func (b *DataPlaneServiceApplyConfiguration) WithResourceVersion(value string) *DataPlaneServiceApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ResourceVersion = &value
return b
}
// WithGeneration sets the Generation field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Generation field is set to the value of the last call.
func (b *DataPlaneServiceApplyConfiguration) WithGeneration(value int64) *DataPlaneServiceApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.Generation = &value
return b
}
// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CreationTimestamp field is set to the value of the last call.
func (b *DataPlaneServiceApplyConfiguration) WithCreationTimestamp(value metav1.Time) *DataPlaneServiceApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.CreationTimestamp = &value
return b
}
// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the DeletionTimestamp field is set to the value of the last call.
func (b *DataPlaneServiceApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *DataPlaneServiceApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.DeletionTimestamp = &value
return b
}
// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call.
func (b *DataPlaneServiceApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *DataPlaneServiceApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.DeletionGracePeriodSeconds = &value
return b
}
// WithLabels puts the entries into the Labels field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, the entries provided by each call will be put on the Labels field,
// overwriting an existing map entries in Labels field with the same key.
func (b *DataPlaneServiceApplyConfiguration) WithLabels(entries map[string]string) *DataPlaneServiceApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
if b.Labels == nil && len(entries) > 0 {
b.Labels = make(map[string]string, len(entries))
}
for k, v := range entries {
b.Labels[k] = v
}
return b
}
// WithAnnotations puts the entries into the Annotations field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, the entries provided by each call will be put on the Annotations field,
// overwriting an existing map entries in Annotations field with the same key.
func (b *DataPlaneServiceApplyConfiguration) WithAnnotations(entries map[string]string) *DataPlaneServiceApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
if b.Annotations == nil && len(entries) > 0 {
b.Annotations = make(map[string]string, len(entries))
}
for k, v := range entries {
b.Annotations[k] = v
}
return b
}
// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, values provided by each call will be appended to the OwnerReferences field.
func (b *DataPlaneServiceApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *DataPlaneServiceApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
for i := range values {
if values[i] == nil {
panic("nil value passed to WithOwnerReferences")
}
b.OwnerReferences = append(b.OwnerReferences, *values[i])
}
return b
}
// WithFinalizers adds the given value to the Finalizers field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, values provided by each call will be appended to the Finalizers field.
func (b *DataPlaneServiceApplyConfiguration) WithFinalizers(values ...string) *DataPlaneServiceApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
for i := range values {
b.Finalizers = append(b.Finalizers, values[i])
}
return b
}
func (b *DataPlaneServiceApplyConfiguration) ensureObjectMetaApplyConfigurationExists() {
if b.ObjectMetaApplyConfiguration == nil {
b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{}
}
}
// WithSpec sets the Spec field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Spec field is set to the value of the last call.
func (b *DataPlaneServiceApplyConfiguration) WithSpec(value *DataPlaneServiceSpecApplyConfiguration) *DataPlaneServiceApplyConfiguration {
b.Spec = value
return b
}
// WithStatus sets the Status field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Status field is set to the value of the last call.
func (b *DataPlaneServiceApplyConfiguration) WithStatus(value *DataPlaneServiceStatusApplyConfiguration) *DataPlaneServiceApplyConfiguration {
b.Status = value
return b
}

View File

@ -0,0 +1,66 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by applyconfiguration-gen. DO NOT EDIT.
package v0alpha1
import (
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// DataPlaneServiceConditionApplyConfiguration represents an declarative configuration of the DataPlaneServiceCondition type for use
// with apply.
type DataPlaneServiceConditionApplyConfiguration struct {
Type *v0alpha1.DataPlaneServiceConditionType `json:"type,omitempty"`
Status *v0alpha1.ConditionStatus `json:"status,omitempty"`
LastTransitionTime *v1.Time `json:"lastTransitionTime,omitempty"`
Reason *string `json:"reason,omitempty"`
Message *string `json:"message,omitempty"`
}
// DataPlaneServiceConditionApplyConfiguration constructs an declarative configuration of the DataPlaneServiceCondition type for use with
// apply.
func DataPlaneServiceCondition() *DataPlaneServiceConditionApplyConfiguration {
return &DataPlaneServiceConditionApplyConfiguration{}
}
// WithType sets the Type field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Type field is set to the value of the last call.
func (b *DataPlaneServiceConditionApplyConfiguration) WithType(value v0alpha1.DataPlaneServiceConditionType) *DataPlaneServiceConditionApplyConfiguration {
b.Type = &value
return b
}
// WithStatus sets the Status field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Status field is set to the value of the last call.
func (b *DataPlaneServiceConditionApplyConfiguration) WithStatus(value v0alpha1.ConditionStatus) *DataPlaneServiceConditionApplyConfiguration {
b.Status = &value
return b
}
// WithLastTransitionTime sets the LastTransitionTime field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the LastTransitionTime field is set to the value of the last call.
func (b *DataPlaneServiceConditionApplyConfiguration) WithLastTransitionTime(value v1.Time) *DataPlaneServiceConditionApplyConfiguration {
b.LastTransitionTime = &value
return b
}
// WithReason sets the Reason field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Reason field is set to the value of the last call.
func (b *DataPlaneServiceConditionApplyConfiguration) WithReason(value string) *DataPlaneServiceConditionApplyConfiguration {
b.Reason = &value
return b
}
// WithMessage sets the Message field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Message field is set to the value of the last call.
func (b *DataPlaneServiceConditionApplyConfiguration) WithMessage(value string) *DataPlaneServiceConditionApplyConfiguration {
b.Message = &value
return b
}

View File

@ -0,0 +1,70 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by applyconfiguration-gen. DO NOT EDIT.
package v0alpha1
import (
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
)
// DataPlaneServiceSpecApplyConfiguration represents an declarative configuration of the DataPlaneServiceSpec type for use
// with apply.
type DataPlaneServiceSpecApplyConfiguration struct {
PluginID *string `json:"pluginID,omitempty"`
PluginType *v0alpha1.PluginType `json:"pluginType,omitempty"`
Group *string `json:"group,omitempty"`
Version *string `json:"version,omitempty"`
Services []ServiceApplyConfiguration `json:"services,omitempty"`
}
// DataPlaneServiceSpecApplyConfiguration constructs an declarative configuration of the DataPlaneServiceSpec type for use with
// apply.
func DataPlaneServiceSpec() *DataPlaneServiceSpecApplyConfiguration {
return &DataPlaneServiceSpecApplyConfiguration{}
}
// WithPluginID sets the PluginID field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the PluginID field is set to the value of the last call.
func (b *DataPlaneServiceSpecApplyConfiguration) WithPluginID(value string) *DataPlaneServiceSpecApplyConfiguration {
b.PluginID = &value
return b
}
// WithPluginType sets the PluginType field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the PluginType field is set to the value of the last call.
func (b *DataPlaneServiceSpecApplyConfiguration) WithPluginType(value v0alpha1.PluginType) *DataPlaneServiceSpecApplyConfiguration {
b.PluginType = &value
return b
}
// WithGroup sets the Group field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Group field is set to the value of the last call.
func (b *DataPlaneServiceSpecApplyConfiguration) WithGroup(value string) *DataPlaneServiceSpecApplyConfiguration {
b.Group = &value
return b
}
// WithVersion sets the Version field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Version field is set to the value of the last call.
func (b *DataPlaneServiceSpecApplyConfiguration) WithVersion(value string) *DataPlaneServiceSpecApplyConfiguration {
b.Version = &value
return b
}
// WithServices adds the given value to the Services field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, values provided by each call will be appended to the Services field.
func (b *DataPlaneServiceSpecApplyConfiguration) WithServices(values ...*ServiceApplyConfiguration) *DataPlaneServiceSpecApplyConfiguration {
for i := range values {
if values[i] == nil {
panic("nil value passed to WithServices")
}
b.Services = append(b.Services, *values[i])
}
return b
}

View File

@ -0,0 +1,30 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by applyconfiguration-gen. DO NOT EDIT.
package v0alpha1
// DataPlaneServiceStatusApplyConfiguration represents an declarative configuration of the DataPlaneServiceStatus type for use
// with apply.
type DataPlaneServiceStatusApplyConfiguration struct {
Conditions []DataPlaneServiceConditionApplyConfiguration `json:"conditions,omitempty"`
}
// DataPlaneServiceStatusApplyConfiguration constructs an declarative configuration of the DataPlaneServiceStatus type for use with
// apply.
func DataPlaneServiceStatus() *DataPlaneServiceStatusApplyConfiguration {
return &DataPlaneServiceStatusApplyConfiguration{}
}
// WithConditions adds the given value to the Conditions field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, values provided by each call will be appended to the Conditions field.
func (b *DataPlaneServiceStatusApplyConfiguration) WithConditions(values ...*DataPlaneServiceConditionApplyConfiguration) *DataPlaneServiceStatusApplyConfiguration {
for i := range values {
if values[i] == nil {
panic("nil value passed to WithConditions")
}
b.Conditions = append(b.Conditions, *values[i])
}
return b
}

View File

@ -0,0 +1,47 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by applyconfiguration-gen. DO NOT EDIT.
package v0alpha1
import (
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
)
// ServiceApplyConfiguration represents an declarative configuration of the Service type for use
// with apply.
type ServiceApplyConfiguration struct {
Type *v0alpha1.ServiceType `json:"type,omitempty"`
Method *string `json:"method,omitempty"`
Path *string `json:"path,omitempty"`
}
// ServiceApplyConfiguration constructs an declarative configuration of the Service type for use with
// apply.
func Service() *ServiceApplyConfiguration {
return &ServiceApplyConfiguration{}
}
// WithType sets the Type field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Type field is set to the value of the last call.
func (b *ServiceApplyConfiguration) WithType(value v0alpha1.ServiceType) *ServiceApplyConfiguration {
b.Type = &value
return b
}
// WithMethod sets the Method field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Method field is set to the value of the last call.
func (b *ServiceApplyConfiguration) WithMethod(value string) *ServiceApplyConfiguration {
b.Method = &value
return b
}
// WithPath sets the Path field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Path field is set to the value of the last call.
func (b *ServiceApplyConfiguration) WithPath(value string) *ServiceApplyConfiguration {
b.Path = &value
return b
}

View File

@ -0,0 +1,48 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by applyconfiguration-gen. DO NOT EDIT.
package internal
import (
"fmt"
"sync"
typed "sigs.k8s.io/structured-merge-diff/v4/typed"
)
func Parser() *typed.Parser {
parserOnce.Do(func() {
var err error
parser, err = typed.NewParser(schemaYAML)
if err != nil {
panic(fmt.Sprintf("Failed to parse schema: %v", err))
}
})
return parser
}
var parserOnce sync.Once
var parser *typed.Parser
var schemaYAML = typed.YAMLObject(`types:
- name: __untyped_atomic_
scalar: untyped
list:
elementType:
namedType: __untyped_atomic_
elementRelationship: atomic
map:
elementType:
namedType: __untyped_atomic_
elementRelationship: atomic
- name: __untyped_deduced_
scalar: untyped
list:
elementType:
namedType: __untyped_atomic_
elementRelationship: atomic
map:
elementType:
namedType: __untyped_deduced_
elementRelationship: separable
`)

View File

@ -0,0 +1,31 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by applyconfiguration-gen. DO NOT EDIT.
package applyconfiguration
import (
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
aggregationv0alpha1 "github.com/grafana/grafana/pkg/aggregator/generated/applyconfiguration/aggregation/v0alpha1"
schema "k8s.io/apimachinery/pkg/runtime/schema"
)
// ForKind returns an apply configuration type for the given GroupVersionKind, or nil if no
// apply configuration type exists for the given GroupVersionKind.
func ForKind(kind schema.GroupVersionKind) interface{} {
switch kind {
// Group=aggregation.grafana.app, Version=v0alpha1
case v0alpha1.SchemeGroupVersion.WithKind("DataPlaneService"):
return &aggregationv0alpha1.DataPlaneServiceApplyConfiguration{}
case v0alpha1.SchemeGroupVersion.WithKind("DataPlaneServiceCondition"):
return &aggregationv0alpha1.DataPlaneServiceConditionApplyConfiguration{}
case v0alpha1.SchemeGroupVersion.WithKind("DataPlaneServiceSpec"):
return &aggregationv0alpha1.DataPlaneServiceSpecApplyConfiguration{}
case v0alpha1.SchemeGroupVersion.WithKind("DataPlaneServiceStatus"):
return &aggregationv0alpha1.DataPlaneServiceStatusApplyConfiguration{}
case v0alpha1.SchemeGroupVersion.WithKind("Service"):
return &aggregationv0alpha1.ServiceApplyConfiguration{}
}
return nil
}

View File

@ -0,0 +1,106 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by client-gen. DO NOT EDIT.
package versioned
import (
"fmt"
"net/http"
aggregationv0alpha1 "github.com/grafana/grafana/pkg/aggregator/generated/clientset/versioned/typed/aggregation/v0alpha1"
discovery "k8s.io/client-go/discovery"
rest "k8s.io/client-go/rest"
flowcontrol "k8s.io/client-go/util/flowcontrol"
)
type Interface interface {
Discovery() discovery.DiscoveryInterface
AggregationV0alpha1() aggregationv0alpha1.AggregationV0alpha1Interface
}
// Clientset contains the clients for groups.
type Clientset struct {
*discovery.DiscoveryClient
aggregationV0alpha1 *aggregationv0alpha1.AggregationV0alpha1Client
}
// AggregationV0alpha1 retrieves the AggregationV0alpha1Client
func (c *Clientset) AggregationV0alpha1() aggregationv0alpha1.AggregationV0alpha1Interface {
return c.aggregationV0alpha1
}
// Discovery retrieves the DiscoveryClient
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
if c == nil {
return nil
}
return c.DiscoveryClient
}
// NewForConfig creates a new Clientset for the given config.
// If config's RateLimiter is not set and QPS and Burst are acceptable,
// NewForConfig will generate a rate-limiter in configShallowCopy.
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
// where httpClient was generated with rest.HTTPClientFor(c).
func NewForConfig(c *rest.Config) (*Clientset, error) {
configShallowCopy := *c
if configShallowCopy.UserAgent == "" {
configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent()
}
// share the transport between all clients
httpClient, err := rest.HTTPClientFor(&configShallowCopy)
if err != nil {
return nil, err
}
return NewForConfigAndClient(&configShallowCopy, httpClient)
}
// NewForConfigAndClient creates a new Clientset for the given config and http client.
// Note the http client provided takes precedence over the configured transport values.
// If config's RateLimiter is not set and QPS and Burst are acceptable,
// NewForConfigAndClient will generate a rate-limiter in configShallowCopy.
func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) {
configShallowCopy := *c
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
if configShallowCopy.Burst <= 0 {
return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
}
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
}
var cs Clientset
var err error
cs.aggregationV0alpha1, err = aggregationv0alpha1.NewForConfigAndClient(&configShallowCopy, httpClient)
if err != nil {
return nil, err
}
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient)
if err != nil {
return nil, err
}
return &cs, nil
}
// NewForConfigOrDie creates a new Clientset for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *Clientset {
cs, err := NewForConfig(c)
if err != nil {
panic(err)
}
return cs
}
// New creates a new Clientset for the given RESTClient.
func New(c rest.Interface) *Clientset {
var cs Clientset
cs.aggregationV0alpha1 = aggregationv0alpha1.New(c)
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
return &cs
}

View File

@ -0,0 +1,71 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
clientset "github.com/grafana/grafana/pkg/aggregator/generated/clientset/versioned"
aggregationv0alpha1 "github.com/grafana/grafana/pkg/aggregator/generated/clientset/versioned/typed/aggregation/v0alpha1"
fakeaggregationv0alpha1 "github.com/grafana/grafana/pkg/aggregator/generated/clientset/versioned/typed/aggregation/v0alpha1/fake"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/discovery"
fakediscovery "k8s.io/client-go/discovery/fake"
"k8s.io/client-go/testing"
)
// NewSimpleClientset returns a clientset that will respond with the provided objects.
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
// without applying any validations and/or defaults. It shouldn't be considered a replacement
// for a real clientset and is mostly useful in simple unit tests.
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
for _, obj := range objects {
if err := o.Add(obj); err != nil {
panic(err)
}
}
cs := &Clientset{tracker: o}
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
cs.AddReactor("*", "*", testing.ObjectReaction(o))
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
gvr := action.GetResource()
ns := action.GetNamespace()
watch, err := o.Watch(gvr, ns)
if err != nil {
return false, nil, err
}
return true, watch, nil
})
return cs
}
// Clientset implements clientset.Interface. Meant to be embedded into a
// struct to get a default implementation. This makes faking out just the method
// you want to test easier.
type Clientset struct {
testing.Fake
discovery *fakediscovery.FakeDiscovery
tracker testing.ObjectTracker
}
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
return c.discovery
}
func (c *Clientset) Tracker() testing.ObjectTracker {
return c.tracker
}
var (
_ clientset.Interface = &Clientset{}
_ testing.FakeClient = &Clientset{}
)
// AggregationV0alpha1 retrieves the AggregationV0alpha1Client
func (c *Clientset) AggregationV0alpha1() aggregationv0alpha1.AggregationV0alpha1Interface {
return &fakeaggregationv0alpha1.FakeAggregationV0alpha1{Fake: &c.Fake}
}

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by client-gen. DO NOT EDIT.
// This package has the automatically generated fake clientset.
package fake

View File

@ -0,0 +1,42 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
aggregationv0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
)
var scheme = runtime.NewScheme()
var codecs = serializer.NewCodecFactory(scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
aggregationv0alpha1.AddToScheme,
}
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
// of clientsets, like in:
//
// import (
// "k8s.io/client-go/kubernetes"
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
// )
//
// kclientset, _ := kubernetes.NewForConfig(c)
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
//
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
// correctly.
var AddToScheme = localSchemeBuilder.AddToScheme
func init() {
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
utilruntime.Must(AddToScheme(scheme))
}

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by client-gen. DO NOT EDIT.
// This package contains the scheme of the automatically generated clientset.
package scheme

View File

@ -0,0 +1,42 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by client-gen. DO NOT EDIT.
package scheme
import (
aggregationv0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
)
var Scheme = runtime.NewScheme()
var Codecs = serializer.NewCodecFactory(Scheme)
var ParameterCodec = runtime.NewParameterCodec(Scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
aggregationv0alpha1.AddToScheme,
}
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
// of clientsets, like in:
//
// import (
// "k8s.io/client-go/kubernetes"
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
// )
//
// kclientset, _ := kubernetes.NewForConfig(c)
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
//
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
// correctly.
var AddToScheme = localSchemeBuilder.AddToScheme
func init() {
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
utilruntime.Must(AddToScheme(Scheme))
}

View File

@ -0,0 +1,93 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by client-gen. DO NOT EDIT.
package v0alpha1
import (
"net/http"
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
"github.com/grafana/grafana/pkg/aggregator/generated/clientset/versioned/scheme"
rest "k8s.io/client-go/rest"
)
type AggregationV0alpha1Interface interface {
RESTClient() rest.Interface
DataPlaneServicesGetter
}
// AggregationV0alpha1Client is used to interact with features provided by the aggregation.grafana.app group.
type AggregationV0alpha1Client struct {
restClient rest.Interface
}
func (c *AggregationV0alpha1Client) DataPlaneServices() DataPlaneServiceInterface {
return newDataPlaneServices(c)
}
// NewForConfig creates a new AggregationV0alpha1Client for the given config.
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
// where httpClient was generated with rest.HTTPClientFor(c).
func NewForConfig(c *rest.Config) (*AggregationV0alpha1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
httpClient, err := rest.HTTPClientFor(&config)
if err != nil {
return nil, err
}
return NewForConfigAndClient(&config, httpClient)
}
// NewForConfigAndClient creates a new AggregationV0alpha1Client for the given config and http client.
// Note the http client provided takes precedence over the configured transport values.
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*AggregationV0alpha1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientForConfigAndClient(&config, h)
if err != nil {
return nil, err
}
return &AggregationV0alpha1Client{client}, nil
}
// NewForConfigOrDie creates a new AggregationV0alpha1Client for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *AggregationV0alpha1Client {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
// New creates a new AggregationV0alpha1Client for the given RESTClient.
func New(c rest.Interface) *AggregationV0alpha1Client {
return &AggregationV0alpha1Client{c}
}
func setConfigDefaults(config *rest.Config) error {
gv := v0alpha1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()
}
return nil
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *AggregationV0alpha1Client) RESTClient() rest.Interface {
if c == nil {
return nil
}
return c.restClient
}

View File

@ -0,0 +1,229 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by client-gen. DO NOT EDIT.
package v0alpha1
import (
"context"
json "encoding/json"
"fmt"
"time"
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
aggregationv0alpha1 "github.com/grafana/grafana/pkg/aggregator/generated/applyconfiguration/aggregation/v0alpha1"
scheme "github.com/grafana/grafana/pkg/aggregator/generated/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
)
// DataPlaneServicesGetter has a method to return a DataPlaneServiceInterface.
// A group's client should implement this interface.
type DataPlaneServicesGetter interface {
DataPlaneServices() DataPlaneServiceInterface
}
// DataPlaneServiceInterface has methods to work with DataPlaneService resources.
type DataPlaneServiceInterface interface {
Create(ctx context.Context, dataPlaneService *v0alpha1.DataPlaneService, opts v1.CreateOptions) (*v0alpha1.DataPlaneService, error)
Update(ctx context.Context, dataPlaneService *v0alpha1.DataPlaneService, opts v1.UpdateOptions) (*v0alpha1.DataPlaneService, error)
UpdateStatus(ctx context.Context, dataPlaneService *v0alpha1.DataPlaneService, opts v1.UpdateOptions) (*v0alpha1.DataPlaneService, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v0alpha1.DataPlaneService, error)
List(ctx context.Context, opts v1.ListOptions) (*v0alpha1.DataPlaneServiceList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v0alpha1.DataPlaneService, err error)
Apply(ctx context.Context, dataPlaneService *aggregationv0alpha1.DataPlaneServiceApplyConfiguration, opts v1.ApplyOptions) (result *v0alpha1.DataPlaneService, err error)
ApplyStatus(ctx context.Context, dataPlaneService *aggregationv0alpha1.DataPlaneServiceApplyConfiguration, opts v1.ApplyOptions) (result *v0alpha1.DataPlaneService, err error)
DataPlaneServiceExpansion
}
// dataPlaneServices implements DataPlaneServiceInterface
type dataPlaneServices struct {
client rest.Interface
}
// newDataPlaneServices returns a DataPlaneServices
func newDataPlaneServices(c *AggregationV0alpha1Client) *dataPlaneServices {
return &dataPlaneServices{
client: c.RESTClient(),
}
}
// Get takes name of the dataPlaneService, and returns the corresponding dataPlaneService object, and an error if there is any.
func (c *dataPlaneServices) Get(ctx context.Context, name string, options v1.GetOptions) (result *v0alpha1.DataPlaneService, err error) {
result = &v0alpha1.DataPlaneService{}
err = c.client.Get().
Resource("dataplaneservices").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do(ctx).
Into(result)
return
}
// List takes label and field selectors, and returns the list of DataPlaneServices that match those selectors.
func (c *dataPlaneServices) List(ctx context.Context, opts v1.ListOptions) (result *v0alpha1.DataPlaneServiceList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v0alpha1.DataPlaneServiceList{}
err = c.client.Get().
Resource("dataplaneservices").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do(ctx).
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested dataPlaneServices.
func (c *dataPlaneServices) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Resource("dataplaneservices").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch(ctx)
}
// Create takes the representation of a dataPlaneService and creates it. Returns the server's representation of the dataPlaneService, and an error, if there is any.
func (c *dataPlaneServices) Create(ctx context.Context, dataPlaneService *v0alpha1.DataPlaneService, opts v1.CreateOptions) (result *v0alpha1.DataPlaneService, err error) {
result = &v0alpha1.DataPlaneService{}
err = c.client.Post().
Resource("dataplaneservices").
VersionedParams(&opts, scheme.ParameterCodec).
Body(dataPlaneService).
Do(ctx).
Into(result)
return
}
// Update takes the representation of a dataPlaneService and updates it. Returns the server's representation of the dataPlaneService, and an error, if there is any.
func (c *dataPlaneServices) Update(ctx context.Context, dataPlaneService *v0alpha1.DataPlaneService, opts v1.UpdateOptions) (result *v0alpha1.DataPlaneService, err error) {
result = &v0alpha1.DataPlaneService{}
err = c.client.Put().
Resource("dataplaneservices").
Name(dataPlaneService.Name).
VersionedParams(&opts, scheme.ParameterCodec).
Body(dataPlaneService).
Do(ctx).
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *dataPlaneServices) UpdateStatus(ctx context.Context, dataPlaneService *v0alpha1.DataPlaneService, opts v1.UpdateOptions) (result *v0alpha1.DataPlaneService, err error) {
result = &v0alpha1.DataPlaneService{}
err = c.client.Put().
Resource("dataplaneservices").
Name(dataPlaneService.Name).
SubResource("status").
VersionedParams(&opts, scheme.ParameterCodec).
Body(dataPlaneService).
Do(ctx).
Into(result)
return
}
// Delete takes name of the dataPlaneService and deletes it. Returns an error if one occurs.
func (c *dataPlaneServices) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
return c.client.Delete().
Resource("dataplaneservices").
Name(name).
Body(&opts).
Do(ctx).
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *dataPlaneServices) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
var timeout time.Duration
if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Resource("dataplaneservices").
VersionedParams(&listOpts, scheme.ParameterCodec).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
// Patch applies the patch and returns the patched dataPlaneService.
func (c *dataPlaneServices) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v0alpha1.DataPlaneService, err error) {
result = &v0alpha1.DataPlaneService{}
err = c.client.Patch(pt).
Resource("dataplaneservices").
Name(name).
SubResource(subresources...).
VersionedParams(&opts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}
// Apply takes the given apply declarative configuration, applies it and returns the applied dataPlaneService.
func (c *dataPlaneServices) Apply(ctx context.Context, dataPlaneService *aggregationv0alpha1.DataPlaneServiceApplyConfiguration, opts v1.ApplyOptions) (result *v0alpha1.DataPlaneService, err error) {
if dataPlaneService == nil {
return nil, fmt.Errorf("dataPlaneService provided to Apply must not be nil")
}
patchOpts := opts.ToPatchOptions()
data, err := json.Marshal(dataPlaneService)
if err != nil {
return nil, err
}
name := dataPlaneService.Name
if name == nil {
return nil, fmt.Errorf("dataPlaneService.Name must be provided to Apply")
}
result = &v0alpha1.DataPlaneService{}
err = c.client.Patch(types.ApplyPatchType).
Resource("dataplaneservices").
Name(*name).
VersionedParams(&patchOpts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}
// ApplyStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus().
func (c *dataPlaneServices) ApplyStatus(ctx context.Context, dataPlaneService *aggregationv0alpha1.DataPlaneServiceApplyConfiguration, opts v1.ApplyOptions) (result *v0alpha1.DataPlaneService, err error) {
if dataPlaneService == nil {
return nil, fmt.Errorf("dataPlaneService provided to Apply must not be nil")
}
patchOpts := opts.ToPatchOptions()
data, err := json.Marshal(dataPlaneService)
if err != nil {
return nil, err
}
name := dataPlaneService.Name
if name == nil {
return nil, fmt.Errorf("dataPlaneService.Name must be provided to Apply")
}
result = &v0alpha1.DataPlaneService{}
err = c.client.Patch(types.ApplyPatchType).
Resource("dataplaneservices").
Name(*name).
SubResource("status").
VersionedParams(&patchOpts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by client-gen. DO NOT EDIT.
// This package has the automatically generated typed clients.
package v0alpha1

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by client-gen. DO NOT EDIT.
// Package fake has the automatically generated clients.
package fake

View File

@ -0,0 +1,26 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/generated/clientset/versioned/typed/aggregation/v0alpha1"
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
)
type FakeAggregationV0alpha1 struct {
*testing.Fake
}
func (c *FakeAggregationV0alpha1) DataPlaneServices() v0alpha1.DataPlaneServiceInterface {
return &FakeDataPlaneServices{c}
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeAggregationV0alpha1) RESTClient() rest.Interface {
var ret *rest.RESTClient
return ret
}

View File

@ -0,0 +1,164 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
"context"
json "encoding/json"
"fmt"
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
aggregationv0alpha1 "github.com/grafana/grafana/pkg/aggregator/generated/applyconfiguration/aggregation/v0alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
)
// FakeDataPlaneServices implements DataPlaneServiceInterface
type FakeDataPlaneServices struct {
Fake *FakeAggregationV0alpha1
}
var dataplaneservicesResource = v0alpha1.SchemeGroupVersion.WithResource("dataplaneservices")
var dataplaneservicesKind = v0alpha1.SchemeGroupVersion.WithKind("DataPlaneService")
// Get takes name of the dataPlaneService, and returns the corresponding dataPlaneService object, and an error if there is any.
func (c *FakeDataPlaneServices) Get(ctx context.Context, name string, options v1.GetOptions) (result *v0alpha1.DataPlaneService, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootGetAction(dataplaneservicesResource, name), &v0alpha1.DataPlaneService{})
if obj == nil {
return nil, err
}
return obj.(*v0alpha1.DataPlaneService), err
}
// List takes label and field selectors, and returns the list of DataPlaneServices that match those selectors.
func (c *FakeDataPlaneServices) List(ctx context.Context, opts v1.ListOptions) (result *v0alpha1.DataPlaneServiceList, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootListAction(dataplaneservicesResource, dataplaneservicesKind, opts), &v0alpha1.DataPlaneServiceList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v0alpha1.DataPlaneServiceList{ListMeta: obj.(*v0alpha1.DataPlaneServiceList).ListMeta}
for _, item := range obj.(*v0alpha1.DataPlaneServiceList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested dataPlaneServices.
func (c *FakeDataPlaneServices) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewRootWatchAction(dataplaneservicesResource, opts))
}
// Create takes the representation of a dataPlaneService and creates it. Returns the server's representation of the dataPlaneService, and an error, if there is any.
func (c *FakeDataPlaneServices) Create(ctx context.Context, dataPlaneService *v0alpha1.DataPlaneService, opts v1.CreateOptions) (result *v0alpha1.DataPlaneService, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootCreateAction(dataplaneservicesResource, dataPlaneService), &v0alpha1.DataPlaneService{})
if obj == nil {
return nil, err
}
return obj.(*v0alpha1.DataPlaneService), err
}
// Update takes the representation of a dataPlaneService and updates it. Returns the server's representation of the dataPlaneService, and an error, if there is any.
func (c *FakeDataPlaneServices) Update(ctx context.Context, dataPlaneService *v0alpha1.DataPlaneService, opts v1.UpdateOptions) (result *v0alpha1.DataPlaneService, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootUpdateAction(dataplaneservicesResource, dataPlaneService), &v0alpha1.DataPlaneService{})
if obj == nil {
return nil, err
}
return obj.(*v0alpha1.DataPlaneService), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeDataPlaneServices) UpdateStatus(ctx context.Context, dataPlaneService *v0alpha1.DataPlaneService, opts v1.UpdateOptions) (*v0alpha1.DataPlaneService, error) {
obj, err := c.Fake.
Invokes(testing.NewRootUpdateSubresourceAction(dataplaneservicesResource, "status", dataPlaneService), &v0alpha1.DataPlaneService{})
if obj == nil {
return nil, err
}
return obj.(*v0alpha1.DataPlaneService), err
}
// Delete takes name of the dataPlaneService and deletes it. Returns an error if one occurs.
func (c *FakeDataPlaneServices) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewRootDeleteActionWithOptions(dataplaneservicesResource, name, opts), &v0alpha1.DataPlaneService{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeDataPlaneServices) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewRootDeleteCollectionAction(dataplaneservicesResource, listOpts)
_, err := c.Fake.Invokes(action, &v0alpha1.DataPlaneServiceList{})
return err
}
// Patch applies the patch and returns the patched dataPlaneService.
func (c *FakeDataPlaneServices) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v0alpha1.DataPlaneService, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootPatchSubresourceAction(dataplaneservicesResource, name, pt, data, subresources...), &v0alpha1.DataPlaneService{})
if obj == nil {
return nil, err
}
return obj.(*v0alpha1.DataPlaneService), err
}
// Apply takes the given apply declarative configuration, applies it and returns the applied dataPlaneService.
func (c *FakeDataPlaneServices) Apply(ctx context.Context, dataPlaneService *aggregationv0alpha1.DataPlaneServiceApplyConfiguration, opts v1.ApplyOptions) (result *v0alpha1.DataPlaneService, err error) {
if dataPlaneService == nil {
return nil, fmt.Errorf("dataPlaneService provided to Apply must not be nil")
}
data, err := json.Marshal(dataPlaneService)
if err != nil {
return nil, err
}
name := dataPlaneService.Name
if name == nil {
return nil, fmt.Errorf("dataPlaneService.Name must be provided to Apply")
}
obj, err := c.Fake.
Invokes(testing.NewRootPatchSubresourceAction(dataplaneservicesResource, *name, types.ApplyPatchType, data), &v0alpha1.DataPlaneService{})
if obj == nil {
return nil, err
}
return obj.(*v0alpha1.DataPlaneService), err
}
// ApplyStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus().
func (c *FakeDataPlaneServices) ApplyStatus(ctx context.Context, dataPlaneService *aggregationv0alpha1.DataPlaneServiceApplyConfiguration, opts v1.ApplyOptions) (result *v0alpha1.DataPlaneService, err error) {
if dataPlaneService == nil {
return nil, fmt.Errorf("dataPlaneService provided to Apply must not be nil")
}
data, err := json.Marshal(dataPlaneService)
if err != nil {
return nil, err
}
name := dataPlaneService.Name
if name == nil {
return nil, fmt.Errorf("dataPlaneService.Name must be provided to Apply")
}
obj, err := c.Fake.
Invokes(testing.NewRootPatchSubresourceAction(dataplaneservicesResource, *name, types.ApplyPatchType, data, "status"), &v0alpha1.DataPlaneService{})
if obj == nil {
return nil, err
}
return obj.(*v0alpha1.DataPlaneService), err
}

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by client-gen. DO NOT EDIT.
package v0alpha1
type DataPlaneServiceExpansion interface{}

View File

@ -0,0 +1,32 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by informer-gen. DO NOT EDIT.
package aggregation
import (
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/generated/informers/externalversions/aggregation/v0alpha1"
internalinterfaces "github.com/grafana/grafana/pkg/aggregator/generated/informers/externalversions/internalinterfaces"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V0alpha1 provides access to shared informers for resources in V0alpha1.
V0alpha1() v0alpha1.Interface
}
type group struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// V0alpha1 returns a new v0alpha1.Interface.
func (g *group) V0alpha1() v0alpha1.Interface {
return v0alpha1.New(g.factory, g.namespace, g.tweakListOptions)
}

View File

@ -0,0 +1,75 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by informer-gen. DO NOT EDIT.
package v0alpha1
import (
"context"
time "time"
aggregationv0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
versioned "github.com/grafana/grafana/pkg/aggregator/generated/clientset/versioned"
internalinterfaces "github.com/grafana/grafana/pkg/aggregator/generated/informers/externalversions/internalinterfaces"
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/generated/listers/aggregation/v0alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
// DataPlaneServiceInformer provides access to a shared informer and lister for
// DataPlaneServices.
type DataPlaneServiceInformer interface {
Informer() cache.SharedIndexInformer
Lister() v0alpha1.DataPlaneServiceLister
}
type dataPlaneServiceInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// NewDataPlaneServiceInformer constructs a new informer for DataPlaneService type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewDataPlaneServiceInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredDataPlaneServiceInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredDataPlaneServiceInformer constructs a new informer for DataPlaneService type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredDataPlaneServiceInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AggregationV0alpha1().DataPlaneServices().List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AggregationV0alpha1().DataPlaneServices().Watch(context.TODO(), options)
},
},
&aggregationv0alpha1.DataPlaneService{},
resyncPeriod,
indexers,
)
}
func (f *dataPlaneServiceInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredDataPlaneServiceInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *dataPlaneServiceInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&aggregationv0alpha1.DataPlaneService{}, f.defaultInformer)
}
func (f *dataPlaneServiceInformer) Lister() v0alpha1.DataPlaneServiceLister {
return v0alpha1.NewDataPlaneServiceLister(f.Informer().GetIndexer())
}

View File

@ -0,0 +1,31 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by informer-gen. DO NOT EDIT.
package v0alpha1
import (
internalinterfaces "github.com/grafana/grafana/pkg/aggregator/generated/informers/externalversions/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// DataPlaneServices returns a DataPlaneServiceInformer.
DataPlaneServices() DataPlaneServiceInformer
}
type version struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// DataPlaneServices returns a DataPlaneServiceInformer.
func (v *version) DataPlaneServices() DataPlaneServiceInformer {
return &dataPlaneServiceInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
}

View File

@ -0,0 +1,247 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by informer-gen. DO NOT EDIT.
package externalversions
import (
reflect "reflect"
sync "sync"
time "time"
versioned "github.com/grafana/grafana/pkg/aggregator/generated/clientset/versioned"
aggregation "github.com/grafana/grafana/pkg/aggregator/generated/informers/externalversions/aggregation"
internalinterfaces "github.com/grafana/grafana/pkg/aggregator/generated/informers/externalversions/internalinterfaces"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
cache "k8s.io/client-go/tools/cache"
)
// SharedInformerOption defines the functional option type for SharedInformerFactory.
type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory
type sharedInformerFactory struct {
client versioned.Interface
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
lock sync.Mutex
defaultResync time.Duration
customResync map[reflect.Type]time.Duration
transform cache.TransformFunc
informers map[reflect.Type]cache.SharedIndexInformer
// startedInformers is used for tracking which informers have been started.
// This allows Start() to be called multiple times safely.
startedInformers map[reflect.Type]bool
// wg tracks how many goroutines were started.
wg sync.WaitGroup
// shuttingDown is true when Shutdown has been called. It may still be running
// because it needs to wait for goroutines.
shuttingDown bool
}
// WithCustomResyncConfig sets a custom resync period for the specified informer types.
func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {
return func(factory *sharedInformerFactory) *sharedInformerFactory {
for k, v := range resyncConfig {
factory.customResync[reflect.TypeOf(k)] = v
}
return factory
}
}
// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.
func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {
return func(factory *sharedInformerFactory) *sharedInformerFactory {
factory.tweakListOptions = tweakListOptions
return factory
}
}
// WithNamespace limits the SharedInformerFactory to the specified namespace.
func WithNamespace(namespace string) SharedInformerOption {
return func(factory *sharedInformerFactory) *sharedInformerFactory {
factory.namespace = namespace
return factory
}
}
// WithTransform sets a transform on all informers.
func WithTransform(transform cache.TransformFunc) SharedInformerOption {
return func(factory *sharedInformerFactory) *sharedInformerFactory {
factory.transform = transform
return factory
}
}
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {
return NewSharedInformerFactoryWithOptions(client, defaultResync)
}
// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
// Listers obtained via this SharedInformerFactory will be subject to the same filters
// as specified here.
// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
}
// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {
factory := &sharedInformerFactory{
client: client,
namespace: v1.NamespaceAll,
defaultResync: defaultResync,
informers: make(map[reflect.Type]cache.SharedIndexInformer),
startedInformers: make(map[reflect.Type]bool),
customResync: make(map[reflect.Type]time.Duration),
}
// Apply all options
for _, opt := range options {
factory = opt(factory)
}
return factory
}
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
f.lock.Lock()
defer f.lock.Unlock()
if f.shuttingDown {
return
}
for informerType, informer := range f.informers {
if !f.startedInformers[informerType] {
f.wg.Add(1)
// We need a new variable in each loop iteration,
// otherwise the goroutine would use the loop variable
// and that keeps changing.
informer := informer
go func() {
defer f.wg.Done()
informer.Run(stopCh)
}()
f.startedInformers[informerType] = true
}
}
}
func (f *sharedInformerFactory) Shutdown() {
f.lock.Lock()
f.shuttingDown = true
f.lock.Unlock()
// Will return immediately if there is nothing to wait for.
f.wg.Wait()
}
func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
informers := func() map[reflect.Type]cache.SharedIndexInformer {
f.lock.Lock()
defer f.lock.Unlock()
informers := map[reflect.Type]cache.SharedIndexInformer{}
for informerType, informer := range f.informers {
if f.startedInformers[informerType] {
informers[informerType] = informer
}
}
return informers
}()
res := map[reflect.Type]bool{}
for informType, informer := range informers {
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
}
return res
}
// InformerFor returns the SharedIndexInformer for obj using an internal
// client.
func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
f.lock.Lock()
defer f.lock.Unlock()
informerType := reflect.TypeOf(obj)
informer, exists := f.informers[informerType]
if exists {
return informer
}
resyncPeriod, exists := f.customResync[informerType]
if !exists {
resyncPeriod = f.defaultResync
}
informer = newFunc(f.client, resyncPeriod)
informer.SetTransform(f.transform)
f.informers[informerType] = informer
return informer
}
// SharedInformerFactory provides shared informers for resources in all known
// API group versions.
//
// It is typically used like this:
//
// ctx, cancel := context.Background()
// defer cancel()
// factory := NewSharedInformerFactory(client, resyncPeriod)
// defer factory.WaitForStop() // Returns immediately if nothing was started.
// genericInformer := factory.ForResource(resource)
// typedInformer := factory.SomeAPIGroup().V1().SomeType()
// factory.Start(ctx.Done()) // Start processing these informers.
// synced := factory.WaitForCacheSync(ctx.Done())
// for v, ok := range synced {
// if !ok {
// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v)
// return
// }
// }
//
// // Creating informers can also be created after Start, but then
// // Start must be called again:
// anotherGenericInformer := factory.ForResource(resource)
// factory.Start(ctx.Done())
type SharedInformerFactory interface {
internalinterfaces.SharedInformerFactory
// Start initializes all requested informers. They are handled in goroutines
// which run until the stop channel gets closed.
Start(stopCh <-chan struct{})
// Shutdown marks a factory as shutting down. At that point no new
// informers can be started anymore and Start will return without
// doing anything.
//
// In addition, Shutdown blocks until all goroutines have terminated. For that
// to happen, the close channel(s) that they were started with must be closed,
// either before Shutdown gets called or while it is waiting.
//
// Shutdown may be called multiple times, even concurrently. All such calls will
// block until all goroutines have terminated.
Shutdown()
// WaitForCacheSync blocks until all started informers' caches were synced
// or the stop channel gets closed.
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
// ForResource gives generic access to a shared informer of the matching type.
ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
// InformerFor returns the SharedIndexInformer for obj using an internal
// client.
InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer
Aggregation() aggregation.Interface
}
func (f *sharedInformerFactory) Aggregation() aggregation.Interface {
return aggregation.New(f, f.namespace, f.tweakListOptions)
}

View File

@ -0,0 +1,48 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by informer-gen. DO NOT EDIT.
package externalversions
import (
"fmt"
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
schema "k8s.io/apimachinery/pkg/runtime/schema"
cache "k8s.io/client-go/tools/cache"
)
// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
// sharedInformers based on type
type GenericInformer interface {
Informer() cache.SharedIndexInformer
Lister() cache.GenericLister
}
type genericInformer struct {
informer cache.SharedIndexInformer
resource schema.GroupResource
}
// Informer returns the SharedIndexInformer.
func (f *genericInformer) Informer() cache.SharedIndexInformer {
return f.informer
}
// Lister returns the GenericLister.
func (f *genericInformer) Lister() cache.GenericLister {
return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)
}
// ForResource gives generic access to a shared informer of the matching type
// TODO extend this to unknown resources with a client pool
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
switch resource {
// Group=aggregation.grafana.app, Version=v0alpha1
case v0alpha1.SchemeGroupVersion.WithResource("dataplaneservices"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Aggregation().V0alpha1().DataPlaneServices().Informer()}, nil
}
return nil, fmt.Errorf("no informer found for %v", resource)
}

View File

@ -0,0 +1,26 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by informer-gen. DO NOT EDIT.
package internalinterfaces
import (
time "time"
versioned "github.com/grafana/grafana/pkg/aggregator/generated/clientset/versioned"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
cache "k8s.io/client-go/tools/cache"
)
// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer.
type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer
// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
type SharedInformerFactory interface {
Start(stopCh <-chan struct{})
InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
}
// TweakListOptionsFunc is a function that transforms a v1.ListOptions.
type TweakListOptionsFunc func(*v1.ListOptions)

View File

@ -0,0 +1,54 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by lister-gen. DO NOT EDIT.
package v0alpha1
import (
v0alpha1 "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
)
// DataPlaneServiceLister helps list DataPlaneServices.
// All objects returned here must be treated as read-only.
type DataPlaneServiceLister interface {
// List lists all DataPlaneServices in the indexer.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v0alpha1.DataPlaneService, err error)
// Get retrieves the DataPlaneService from the index for a given name.
// Objects returned here must be treated as read-only.
Get(name string) (*v0alpha1.DataPlaneService, error)
DataPlaneServiceListerExpansion
}
// dataPlaneServiceLister implements the DataPlaneServiceLister interface.
type dataPlaneServiceLister struct {
indexer cache.Indexer
}
// NewDataPlaneServiceLister returns a new DataPlaneServiceLister.
func NewDataPlaneServiceLister(indexer cache.Indexer) DataPlaneServiceLister {
return &dataPlaneServiceLister{indexer: indexer}
}
// List lists all DataPlaneServices in the indexer.
func (s *dataPlaneServiceLister) List(selector labels.Selector) (ret []*v0alpha1.DataPlaneService, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v0alpha1.DataPlaneService))
})
return ret, err
}
// Get retrieves the DataPlaneService from the index for a given name.
func (s *dataPlaneServiceLister) Get(name string) (*v0alpha1.DataPlaneService, error) {
obj, exists, err := s.indexer.GetByKey(name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v0alpha1.Resource("dataplaneservice"), name)
}
return obj.(*v0alpha1.DataPlaneService), nil
}

View File

@ -0,0 +1,9 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by lister-gen. DO NOT EDIT.
package v0alpha1
// DataPlaneServiceListerExpansion allows custom methods to be added to
// DataPlaneServiceLister.
type DataPlaneServiceListerExpansion interface{}

157
pkg/aggregator/go.mod Normal file
View File

@ -0,0 +1,157 @@
module github.com/grafana/grafana/pkg/aggregator
go 1.22.4
require (
github.com/emicklei/go-restful/v3 v3.11.0
github.com/grafana/grafana-plugin-sdk-go v0.241.0
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435
github.com/grafana/grafana/pkg/semconv v0.0.0-20240808213237-f4d2e064f435
github.com/stretchr/testify v1.9.0
go.opentelemetry.io/otel v1.28.0
k8s.io/apimachinery v0.31.0
k8s.io/apiserver v0.31.0
k8s.io/client-go v0.31.0
k8s.io/component-base v0.31.0
k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340
sigs.k8s.io/structured-merge-diff/v4 v4.4.1
)
require (
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/apache/arrow/go/v15 v15.0.2 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cheekybits/genny v1.0.0 // indirect
github.com/chromedp/cdproto v0.0.0-20240426225625-909263490071 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/getkin/kin-openapi v0.125.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.20.4 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/cel-go v0.20.1 // indirect
github.com/google/flatbuffers v24.3.25+incompatible // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/grafana/otel-profiling-go v0.5.1 // indirect
github.com/grafana/pyroscope-go/godeltaprof v0.1.7 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
github.com/hashicorp/go-hclog v1.6.3 // indirect
github.com/hashicorp/go-plugin v1.6.1 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/invopop/yaml v0.3.1 // indirect
github.com/jonboulle/clockwork v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/jszwedko/go-datemath v0.1.1-0.20230526204004-640a500621d6 // indirect
github.com/klauspost/compress v1.17.8 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/magefile/mage v1.15.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattetti/filebuffer v1.0.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.19.1 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8 // indirect
github.com/unknwon/com v1.0.1 // indirect
github.com/unknwon/log v0.0.0-20200308114134-929b1006e34a // indirect
github.com/urfave/cli v1.22.15 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/zeebo/xxh3 v1.0.2 // indirect
go.etcd.io/etcd/api/v3 v3.5.14 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect
go.etcd.io/etcd/client/v3 v3.5.14 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.53.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
go.opentelemetry.io/contrib/propagators/jaeger v1.28.0 // indirect
go.opentelemetry.io/contrib/samplers/jaegerremote v0.20.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/sdk v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.26.0 // indirect
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
golang.org/x/mod v0.18.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.23.0 // indirect
golang.org/x/term v0.23.0 // indirect
golang.org/x/text v0.17.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.22.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
gonum.org/v1/gonum v0.14.0 // indirect
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
google.golang.org/grpc v1.65.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.31.0 // indirect
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)

530
pkg/aggregator/go.sum Normal file
View File

@ -0,0 +1,530 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
github.com/apache/arrow/go/v15 v15.0.2 h1:60IliRbiyTWCWjERBCkO1W4Qun9svcYoZrSLcyOsMLE=
github.com/apache/arrow/go/v15 v15.0.2/go.mod h1:DGXsR3ajT524njufqf95822i+KTh+yea1jass9YXgjA=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
github.com/chromedp/cdproto v0.0.0-20240426225625-909263490071 h1:RdCf9hH3xq5vJifrjGB7zQlFkdRB3pAppcX2helDq2U=
github.com/chromedp/cdproto v0.0.0-20240426225625-909263490071/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5 h1:m62nsMU279qRD9PQSWD1l66kmkXzuYcnVJqL4XLeV2M=
github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/elazarl/goproxy/ext v0.0.0-20220115173737-adb46da277ac h1:9yrT5tmn9Zc0ytWPASlaPwQfQMQYnRf0RSDe1XvHw0Q=
github.com/elazarl/goproxy/ext v0.0.0-20220115173737-adb46da277ac/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/getkin/kin-openapi v0.125.0 h1:jyQCyf2qXS1qvs2U00xQzkGCqYPhEhZDmSmVt65fXno=
github.com/getkin/kin-openapi v0.125.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU=
github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84=
github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg=
github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI=
github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM=
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grafana/grafana-plugin-sdk-go v0.241.0 h1:zBcSW9xV9gA9hD8UN+HjJtD7tESMZcaQhA1BI76MTxM=
github.com/grafana/grafana-plugin-sdk-go v0.241.0/go.mod h1:2HjNwzGCfaFAyR2HGoECTwAmq8vSIn2L1/1yOt4XRS4=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435 h1:lmw60EW7JWlAEvgggktOyVkH4hF1m/+LSF/Ap0NCyi8=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435/go.mod h1:ORVFiW/KNRY52lNjkGwnFWCxNVfE97bJG2jr2fetq0I=
github.com/grafana/grafana/pkg/semconv v0.0.0-20240808213237-f4d2e064f435 h1:SNEeqY22DrGr5E9kGF1mKSqlOom14W9+b1u4XEGJowA=
github.com/grafana/grafana/pkg/semconv v0.0.0-20240808213237-f4d2e064f435/go.mod h1:8cz+z0i57IjN6MYmu/zZQdCg9CQcsnEHbaJBBEf3KQo=
github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8=
github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls=
github.com/grafana/pyroscope-go/godeltaprof v0.1.7 h1:C11j63y7gymiW8VugJ9ZW0pWfxTZugdSJyC48olk5KY=
github.com/grafana/pyroscope-go/godeltaprof v0.1.7/go.mod h1:Tk376Nbldo4Cha9RgiU7ik8WKFkNpfds98aUzS8omLE=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI=
github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso=
github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA=
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jszwedko/go-datemath v0.1.1-0.20230526204004-640a500621d6 h1:SwcnSwBR7X/5EHJQlXBockkJVIMRVt5yKaesBPMtyZQ=
github.com/jszwedko/go-datemath v0.1.1-0.20230526204004-640a500621d6/go.mod h1:WrYiIuiXUMIvTDAQw97C+9l0CnBmCcvosPjN3XDqS/o=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattetti/filebuffer v1.0.1 h1:gG7pyfnSIZCxdoKq+cPa8T0hhYtD9NxCdI4D7PTjRLM=
github.com/mattetti/filebuffer v1.0.1/go.mod h1:YdMURNDOttIiruleeVr6f56OrMc+MydEnTcXwtkxNVs=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY=
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8 h1:aVGB3YnaS/JNfOW3tiHIlmNmTDg618va+eT0mVomgyI=
github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8/go.mod h1:fVle4kNr08ydeohzYafr20oZzbAkhQT39gKK/pFQ5M4=
github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs=
github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
github.com/unknwon/log v0.0.0-20150304194804-e617c87089d3/go.mod h1:1xEUf2abjfP92w2GZTV+GgaRxXErwRXcClbUwrNJffU=
github.com/unknwon/log v0.0.0-20200308114134-929b1006e34a h1:vcrhXnj9g9PIE+cmZgaPSwOyJ8MAQTRmsgGrB0x5rF4=
github.com/unknwon/log v0.0.0-20200308114134-929b1006e34a/go.mod h1:1xEUf2abjfP92w2GZTV+GgaRxXErwRXcClbUwrNJffU=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.15 h1:nuqt+pdC/KqswQKhETJjo7pvn/k4xMUxgW6liI7XpnM=
github.com/urfave/cli v1.22.15/go.mod h1:wSan1hmo5zeyLGBjRJbzRTNk8gwoYa2B9n4q9dmRIc0=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
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/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0=
go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU=
go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ=
go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI=
go.etcd.io/etcd/client/v2 v2.305.13 h1:RWfV1SX5jTU0lbCvpVQe3iPQeAHETWdOTb6pxhd77C8=
go.etcd.io/etcd/client/v2 v2.305.13/go.mod h1:iQnL7fepbiomdXMb3om1rHq96htNNGv2sJkEcZGDRRg=
go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg=
go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk=
go.etcd.io/etcd/pkg/v3 v3.5.13 h1:st9bDWNsKkBNpP4PR1MvM/9NqUPfvYZx/YXegsYEH8M=
go.etcd.io/etcd/pkg/v3 v3.5.13/go.mod h1:N+4PLrp7agI/Viy+dUYpX7iRtSPvKq+w8Y14d1vX+m0=
go.etcd.io/etcd/raft/v3 v3.5.13 h1:7r/NKAOups1YnKcfro2RvGGo2PTuizF/xh26Z2CTAzA=
go.etcd.io/etcd/raft/v3 v3.5.13/go.mod h1:uUFibGLn2Ksm2URMxN1fICGhk8Wu96EfDQyuLhAcAmw=
go.etcd.io/etcd/server/v3 v3.5.13 h1:V6KG+yMfMSqWt+lGnhFpP5z5dRUj1BDRJ5k1fQ9DFok=
go.etcd.io/etcd/server/v3 v3.5.13/go.mod h1:K/8nbsGupHqmr5MkgaZpLlH1QdX1pcNQLAkODy44XcQ=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74=
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.53.0 h1:IVtyPth4Rs5P8wIf0mP2KVKFNTJ4paX9qQ4Hkh5gFdc=
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.53.0/go.mod h1:ImRBLMJv177/pwiLZ7tU7HDGNdBv7rS0HQ99eN/zBl8=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
go.opentelemetry.io/contrib/propagators/jaeger v1.28.0 h1:xQ3ktSVS128JWIaN1DiPGIjcH+GsvkibIAVRWFjS9eM=
go.opentelemetry.io/contrib/propagators/jaeger v1.28.0/go.mod h1:O9HIyI2kVBrFoEwQZ0IN6PHXykGoit4mZV2aEjkTRH4=
go.opentelemetry.io/contrib/samplers/jaegerremote v0.20.0 h1:ja+d7Aea/9PgGxB63+E0jtRFpma717wubS0KFkZpmYw=
go.opentelemetry.io/contrib/samplers/jaegerremote v0.20.0/go.mod h1:Yc1eg51SJy7xZdOTyg1xyFcwE+ghcWh3/0hKeLo6Wlo=
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw=
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
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.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191020152052-9984515f0562/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/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.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY=
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo=
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0=
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 h1:XNNYLJHt73EyYiCZi6+xjupS9CpvmiDgjPTAjrBlQbo=
gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo=
k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE=
k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc=
k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/apiserver v0.31.0 h1:p+2dgJjy+bk+B1Csz+mc2wl5gHwvNkC9QJV+w55LVrY=
k8s.io/apiserver v0.31.0/go.mod h1:KI9ox5Yu902iBnnyMmy7ajonhKnkeZYJhTZ/YI+WEMk=
k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8=
k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU=
k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs=
k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

View File

@ -0,0 +1,33 @@
package rest
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest"
genericapiserver "k8s.io/apiserver/pkg/server"
serverstorage "k8s.io/apiserver/pkg/server/storage"
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation"
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
aggregatorscheme "github.com/grafana/grafana/pkg/aggregator/apiserver/scheme"
dataplaneservicestorage "github.com/grafana/grafana/pkg/aggregator/registry/dataplaneservice/storage"
)
// NewRESTStorage returns an APIGroupInfo object that will work against dataplaneservice.
func NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter, shouldServeBeta bool) genericapiserver.APIGroupInfo {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(aggregation.GROUP, aggregatorscheme.Scheme, metav1.ParameterCodec, aggregatorscheme.Codecs)
storage := map[string]rest.Storage{}
if resource := "dataplaneservices"; apiResourceConfigSource.ResourceEnabled(v0alpha1.SchemeGroupVersion.WithResource(resource)) {
dataplaneServiceREST := dataplaneservicestorage.NewREST(aggregatorscheme.Scheme, restOptionsGetter)
storage[resource] = dataplaneServiceREST
storage[resource+"/status"] = dataplaneservicestorage.NewStatusREST(aggregatorscheme.Scheme, dataplaneServiceREST)
}
if len(storage) > 0 {
apiGroupInfo.VersionedResourcesStorageMap["v0alpha1"] = storage
}
return apiGroupInfo
}

View File

@ -0,0 +1,151 @@
package storage
import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/api/meta"
metatable "k8s.io/apimachinery/pkg/api/meta/table"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/generic"
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
"k8s.io/apiserver/pkg/registry/rest"
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation"
"github.com/grafana/grafana/pkg/aggregator/registry/dataplaneservice"
)
// REST implements a RESTStorage for Data Plane services.
type REST struct {
*genericregistry.Store
}
// NewREST returns a RESTStorage object that will work against Data Plane services.
func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) *REST {
strategy := dataplaneservice.NewStrategy(scheme)
store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &aggregation.DataPlaneService{} },
NewListFunc: func() runtime.Object { return &aggregation.DataPlaneServiceList{} },
PredicateFunc: dataplaneservice.MatchDataPlaneService,
DefaultQualifiedResource: aggregation.Resource("dataplaneservices"),
SingularQualifiedResource: aggregation.Resource("dataplaneservice"),
CreateStrategy: strategy,
UpdateStrategy: strategy,
DeleteStrategy: strategy,
ResetFieldsStrategy: strategy,
TableConvertor: rest.NewDefaultTableConvertor(aggregation.Resource("dataplaneservices")),
}
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: dataplaneservice.GetAttrs}
if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up
}
return &REST{store}
}
// Implement CategoriesProvider
var _ rest.CategoriesProvider = &REST{}
// Categories implements the CategoriesProvider interface. Returns a list of categories a resource is part of.
func (c *REST) Categories() []string {
return []string{"dataplane"}
}
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
// ConvertToTable implements the TableConvertor interface for REST.
func (c *REST) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
table := &metav1.Table{
ColumnDefinitions: []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]},
{Name: "Available", Type: "string", Description: "Whether this service is available."},
{Name: "Age", Type: "string", Description: swaggerMetadataDescriptions["creationTimestamp"]},
},
}
if m, err := meta.ListAccessor(obj); err == nil {
table.ResourceVersion = m.GetResourceVersion()
table.Continue = m.GetContinue()
table.RemainingItemCount = m.GetRemainingItemCount()
} else {
if m, err := meta.CommonAccessor(obj); err == nil {
table.ResourceVersion = m.GetResourceVersion()
}
}
var err error
table.Rows, err = metatable.MetaToTableRow(obj, func(obj runtime.Object, m metav1.Object, name, age string) ([]interface{}, error) {
svc := obj.(*aggregation.DataPlaneService)
status := string(aggregation.ConditionUnknown)
if condition := getCondition(svc.Status.Conditions, "Available"); condition != nil {
switch {
case condition.Status == aggregation.ConditionTrue:
status = string(condition.Status)
case len(condition.Reason) > 0:
status = fmt.Sprintf("%s (%s)", condition.Status, condition.Reason)
default:
status = string(condition.Status)
}
}
return []interface{}{name, status, age}, nil
})
return table, err
}
func getCondition(conditions []aggregation.DataPlaneServiceCondition, conditionType aggregation.DataPlaneServiceConditionType) *aggregation.DataPlaneServiceCondition {
for i, condition := range conditions {
if condition.Type == conditionType {
return &conditions[i]
}
}
return nil
}
// NewStatusREST makes a RESTStorage for status that has more limited options.
// It is based on the original REST so that we can share the same underlying store
func NewStatusREST(scheme *runtime.Scheme, rest *REST) *StatusREST {
strategy := dataplaneservice.NewStatusStrategy(scheme)
statusStore := *rest.Store
statusStore.CreateStrategy = nil
statusStore.DeleteStrategy = nil
statusStore.UpdateStrategy = strategy
statusStore.ResetFieldsStrategy = strategy
return &StatusREST{store: &statusStore}
}
// StatusREST implements the REST endpoint for changing the status of an DataPlaneService.
type StatusREST struct {
store *genericregistry.Store
}
var _ = rest.Patcher(&StatusREST{})
// New creates a new DataPlaneService object.
func (r *StatusREST) New() runtime.Object {
return &aggregation.DataPlaneService{}
}
// Destroy cleans up resources on shutdown.
func (r *StatusREST) Destroy() {
// Given that underlying store is shared with REST,
// we don't destroy it here explicitly.
}
// Get retrieves the object from the storage. It is required to support Patch.
func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
return r.store.Get(ctx, name, options)
}
// Update alters the status subset of an object.
func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
// We are explicitly setting forceAllowCreate to false in the call to the underlying storage because
// subresources should never allow create on update.
return r.store.Update(ctx, name, objInfo, createValidation, updateValidation, false, options)
}
// GetResetFields implements rest.ResetFieldsStrategy
func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
return r.store.GetResetFields()
}

View File

@ -0,0 +1,170 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Provenance-includes-location: https://github.com/kubernetes/kube-aggregator/blob/master/pkg/registry/apiservice/strategy.go
// Provenance-includes-license: Apache-2.0
// Provenance-includes-copyright: The Kubernetes Authors.
package dataplaneservice
import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage"
"k8s.io/apiserver/pkg/storage/names"
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation"
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
)
type dataPlaneServiceStrategy struct {
runtime.ObjectTyper
names.NameGenerator
}
// dataPlaneServiceStrategy must implement rest.RESTCreateUpdateStrategy
var _ rest.RESTCreateUpdateStrategy = dataPlaneServiceStrategy{}
var Strategy = dataPlaneServiceStrategy{}
// NewStrategy creates a new dataPlaneServiceStrategy.
func NewStrategy(typer runtime.ObjectTyper) rest.CreateUpdateResetFieldsStrategy {
return dataPlaneServiceStrategy{typer, names.SimpleNameGenerator}
}
func (dataPlaneServiceStrategy) NamespaceScoped() bool {
return false
}
func (dataPlaneServiceStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
fields := map[fieldpath.APIVersion]*fieldpath.Set{
"aggregation.grafana.app/v0alpha1": fieldpath.NewSet(
fieldpath.MakePathOrDie("status"),
),
}
return fields
}
func (dataPlaneServiceStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
}
func (dataPlaneServiceStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
newDataPlaneService := obj.(*aggregation.DataPlaneService)
oldDataPlaneService := old.(*aggregation.DataPlaneService)
newDataPlaneService.Status = oldDataPlaneService.Status
}
func (dataPlaneServiceStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
return field.ErrorList{}
}
// WarningsOnCreate returns warnings for the creation of the given object.
func (dataPlaneServiceStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string {
return nil
}
func (dataPlaneServiceStrategy) AllowCreateOnUpdate() bool {
return false
}
func (dataPlaneServiceStrategy) AllowUnconditionalUpdate() bool {
return false
}
func (dataPlaneServiceStrategy) Canonicalize(obj runtime.Object) {
}
func (dataPlaneServiceStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
return field.ErrorList{}
}
// WarningsOnUpdate returns warnings for the given update.
func (dataPlaneServiceStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
return nil
}
type dataPlaneServiceStatusStrategy struct {
runtime.ObjectTyper
names.NameGenerator
}
// NewStatusStrategy creates a new dataPlaneServiceStatusStrategy.
func NewStatusStrategy(typer runtime.ObjectTyper) rest.UpdateResetFieldsStrategy {
return dataPlaneServiceStatusStrategy{typer, names.SimpleNameGenerator}
}
func (dataPlaneServiceStatusStrategy) NamespaceScoped() bool {
return false
}
func (dataPlaneServiceStatusStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
fields := map[fieldpath.APIVersion]*fieldpath.Set{
"aggregation.grafana.app/v0alpha1": fieldpath.NewSet(
fieldpath.MakePathOrDie("spec"),
fieldpath.MakePathOrDie("metadata"),
),
}
return fields
}
func (dataPlaneServiceStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
newDataPlaneService := obj.(*aggregation.DataPlaneService)
oldDataPlaneService := old.(*aggregation.DataPlaneService)
newDataPlaneService.Spec = oldDataPlaneService.Spec
newDataPlaneService.Labels = oldDataPlaneService.Labels
newDataPlaneService.Annotations = oldDataPlaneService.Annotations
newDataPlaneService.Finalizers = oldDataPlaneService.Finalizers
newDataPlaneService.OwnerReferences = oldDataPlaneService.OwnerReferences
}
func (dataPlaneServiceStatusStrategy) AllowCreateOnUpdate() bool {
return false
}
func (dataPlaneServiceStatusStrategy) AllowUnconditionalUpdate() bool {
return false
}
// Canonicalize normalizes the object after validation.
func (dataPlaneServiceStatusStrategy) Canonicalize(obj runtime.Object) {
}
// ValidateUpdate validates an update of dataPlaneServiceStatusStrategy.
func (dataPlaneServiceStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
return field.ErrorList{}
}
// WarningsOnUpdate returns warnings for the given update.
func (dataPlaneServiceStatusStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
return nil
}
// GetAttrs returns the labels and fields of an API server for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
s, ok := obj.(*aggregation.DataPlaneService)
if !ok {
return nil, nil, fmt.Errorf("given object is not a DataPlaneService")
}
return labels.Set(s.ObjectMeta.Labels), ToSelectableFields(s), nil
}
// MatchDataPlaneService is the filter used by the generic etcd backend to watch events
// from etcd to clients of the apiserver only interested in specific labels/fields.
func MatchDataPlaneService(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
return storage.SelectionPredicate{
Label: label,
Field: field,
GetAttrs: GetAttrs,
}
}
// ToSelectableFields returns a field set that represents the object.
func ToSelectableFields(obj *aggregation.DataPlaneService) fields.Set {
return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true)
}

View File

@ -124,8 +124,8 @@ func CreateAggregatorConfig(commandOptions *options.Options, sharedConfig generi
ClientConfig: sharedConfig.LoopbackClientConfig, ClientConfig: sharedConfig.LoopbackClientConfig,
}, },
ExtraConfig: aggregatorapiserver.ExtraConfig{ ExtraConfig: aggregatorapiserver.ExtraConfig{
ProxyClientCertFile: commandOptions.AggregatorOptions.ProxyClientCertFile, ProxyClientCertFile: commandOptions.KubeAggregatorOptions.ProxyClientCertFile,
ProxyClientKeyFile: commandOptions.AggregatorOptions.ProxyClientKeyFile, ProxyClientKeyFile: commandOptions.KubeAggregatorOptions.ProxyClientKeyFile,
// NOTE: while ProxyTransport can be skipped in the configuration, it allows honoring // NOTE: while ProxyTransport can be skipped in the configuration, it allows honoring
// DISABLE_HTTP2, HTTPS_PROXY and NO_PROXY env vars as needed // DISABLE_HTTP2, HTTPS_PROXY and NO_PROXY env vars as needed
ProxyTransport: createProxyTransport(), ProxyTransport: createProxyTransport(),
@ -133,7 +133,7 @@ func CreateAggregatorConfig(commandOptions *options.Options, sharedConfig generi
}, },
} }
if err := commandOptions.AggregatorOptions.ApplyTo(aggregatorConfig, commandOptions.RecommendedOptions.Etcd); err != nil { if err := commandOptions.KubeAggregatorOptions.ApplyTo(aggregatorConfig, commandOptions.RecommendedOptions.Etcd); err != nil {
return nil, err return nil, err
} }
@ -144,15 +144,15 @@ func CreateAggregatorConfig(commandOptions *options.Options, sharedConfig generi
APIVersionPriorities[serviceAPIBuilder.GetGroupVersion()] = Priority{Group: 15000, Version: int32(1)} APIVersionPriorities[serviceAPIBuilder.GetGroupVersion()] = Priority{Group: 15000, Version: int32(1)}
// Exit early, if no remote services file is configured // Exit early, if no remote services file is configured
if commandOptions.AggregatorOptions.RemoteServicesFile == "" { if commandOptions.KubeAggregatorOptions.RemoteServicesFile == "" {
return NewConfig(aggregatorConfig, sharedInformerFactory, []builder.APIGroupBuilder{serviceAPIBuilder}, nil), nil return NewConfig(aggregatorConfig, sharedInformerFactory, []builder.APIGroupBuilder{serviceAPIBuilder}, nil), nil
} }
_, err = readCABundlePEM(commandOptions.AggregatorOptions.APIServiceCABundleFile, commandOptions.ExtraOptions.DevMode) _, err = readCABundlePEM(commandOptions.KubeAggregatorOptions.APIServiceCABundleFile, commandOptions.ExtraOptions.DevMode)
if err != nil { if err != nil {
return nil, err return nil, err
} }
remoteServices, err := readRemoteServices(commandOptions.AggregatorOptions.RemoteServicesFile) remoteServices, err := readRemoteServices(commandOptions.KubeAggregatorOptions.RemoteServicesFile)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -43,11 +43,11 @@ func applyGrafanaConfig(cfg *setting.Cfg, features featuremgmt.FeatureToggles, o
o.RecommendedOptions.Authentication.RemoteKubeConfigFileOptional = true o.RecommendedOptions.Authentication.RemoteKubeConfigFileOptional = true
o.RecommendedOptions.Authorization.RemoteKubeConfigFileOptional = true o.RecommendedOptions.Authorization.RemoteKubeConfigFileOptional = true
o.AggregatorOptions.ProxyClientCertFile = apiserverCfg.Key("proxy_client_cert_file").MustString("") o.KubeAggregatorOptions.ProxyClientCertFile = apiserverCfg.Key("proxy_client_cert_file").MustString("")
o.AggregatorOptions.ProxyClientKeyFile = apiserverCfg.Key("proxy_client_key_file").MustString("") o.KubeAggregatorOptions.ProxyClientKeyFile = apiserverCfg.Key("proxy_client_key_file").MustString("")
o.AggregatorOptions.APIServiceCABundleFile = apiserverCfg.Key("apiservice_ca_bundle_file").MustString("") o.KubeAggregatorOptions.APIServiceCABundleFile = apiserverCfg.Key("apiservice_ca_bundle_file").MustString("")
o.AggregatorOptions.RemoteServicesFile = apiserverCfg.Key("remote_services_file").MustString("") o.KubeAggregatorOptions.RemoteServicesFile = apiserverCfg.Key("remote_services_file").MustString("")
o.RecommendedOptions.Admission = nil o.RecommendedOptions.Admission = nil
o.RecommendedOptions.CoreAPI = nil o.RecommendedOptions.CoreAPI = nil

View File

@ -0,0 +1,94 @@
package options
import (
"maps"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/endpoints/openapi"
genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/apiserver/pkg/server/options"
"k8s.io/apiserver/pkg/server/resourceconfig"
"k8s.io/kube-openapi/pkg/common"
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
aggregatorapiserver "github.com/grafana/grafana/pkg/aggregator/apiserver"
aggregatorscheme "github.com/grafana/grafana/pkg/aggregator/apiserver/scheme"
commonv0alpha1 "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
"github.com/grafana/grafana/pkg/storage/unified/apistore"
)
// GrafanaAggregatorOptions contains the state for the aggregator apiserver
type GrafanaAggregatorOptions struct {
}
func NewGrafanaAggregatorOptions() *GrafanaAggregatorOptions {
return &GrafanaAggregatorOptions{}
}
func (o *GrafanaAggregatorOptions) AddFlags(fs *pflag.FlagSet) {
if o == nil {
return
}
// TODO: do we need any CLI flags here?
}
func (o *GrafanaAggregatorOptions) Validate() []error {
if o == nil {
return nil
}
// TODO: do we need to validate anything here?
return nil
}
func (o *GrafanaAggregatorOptions) ApplyTo(aggregatorConfig *aggregatorapiserver.Config, etcdOpts *options.EtcdOptions) error {
genericConfig := aggregatorConfig.GenericConfig
genericConfig.PostStartHooks = map[string]genericapiserver.PostStartHookConfigEntry{}
genericConfig.RESTOptionsGetter = nil
getOpenAPIDefinitions := func(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
defs := commonv0alpha1.GetOpenAPIDefinitions(ref)
maps.Copy(defs, v0alpha1.GetOpenAPIDefinitions(ref))
return defs
}
genericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(getOpenAPIDefinitions, openapi.NewDefinitionNamer(aggregatorscheme.Scheme))
genericConfig.OpenAPIConfig.Info.Title = "Grafana Aggregator"
genericConfig.OpenAPIConfig.Info.Version = "0.1"
genericConfig.OpenAPIV3Config = genericapiserver.DefaultOpenAPIV3Config(getOpenAPIDefinitions, openapi.NewDefinitionNamer(aggregatorscheme.Scheme))
genericConfig.OpenAPIV3Config.Info.Title = "Grafana Aggregator"
genericConfig.OpenAPIV3Config.Info.Version = "0.1"
// copy the etcd options so we don't mutate originals.
// we assume that the etcd options have been completed already. avoid messing with anything outside
// of changes to StorageConfig as that may lead to unexpected behavior when the options are applied.
etcdOptions := *etcdOpts
etcdOptions.StorageConfig.Codec = aggregatorscheme.Codecs.LegacyCodec(v0alpha1.SchemeGroupVersion)
etcdOptions.StorageConfig.EncodeVersioner = runtime.NewMultiGroupVersioner(v0alpha1.SchemeGroupVersion, schema.GroupKind{Group: v0alpha1.SchemeGroupVersion.Group})
etcdOptions.SkipHealthEndpoints = true // avoid double wiring of health checks
if err := etcdOptions.ApplyTo(&genericConfig.Config); err != nil {
return err
}
// override the RESTOptionsGetter to use the in memory storage options
restOptionsGetter, err := apistore.NewRESTOptionsGetterMemory(etcdOptions.StorageConfig)
if err != nil {
return err
}
aggregatorConfig.GenericConfig.RESTOptionsGetter = restOptionsGetter
// prevent generic API server from installing the OpenAPI handler. Aggregator server has its own customized OpenAPI handler.
genericConfig.SkipOpenAPIInstallation = true
mergedResourceConfig, err := resourceconfig.MergeAPIResourceConfigs(aggregatorapiserver.DefaultAPIResourceConfigSource(), nil, aggregatorscheme.Scheme)
if err != nil {
return err
}
genericConfig.MergedResourceConfig = mergedResourceConfig
genericConfig.PostStartHooks = map[string]genericapiserver.PostStartHookConfigEntry{}
return nil
}

View File

@ -18,8 +18,8 @@ import (
"github.com/grafana/grafana/pkg/storage/unified/apistore" "github.com/grafana/grafana/pkg/storage/unified/apistore"
) )
// AggregatorServerOptions contains the state for the aggregator apiserver // KubeAggregatorOptions contains the state for the aggregator apiserver
type AggregatorServerOptions struct { type KubeAggregatorOptions struct {
AlternateDNS []string AlternateDNS []string
ProxyClientCertFile string ProxyClientCertFile string
ProxyClientKeyFile string ProxyClientKeyFile string
@ -27,11 +27,11 @@ type AggregatorServerOptions struct {
APIServiceCABundleFile string APIServiceCABundleFile string
} }
func NewAggregatorServerOptions() *AggregatorServerOptions { func NewAggregatorServerOptions() *KubeAggregatorOptions {
return &AggregatorServerOptions{} return &KubeAggregatorOptions{}
} }
func (o *AggregatorServerOptions) AddFlags(fs *pflag.FlagSet) { func (o *KubeAggregatorOptions) AddFlags(fs *pflag.FlagSet) {
if o == nil { if o == nil {
return return
} }
@ -43,7 +43,7 @@ func (o *AggregatorServerOptions) AddFlags(fs *pflag.FlagSet) {
"path to proxy client key file") "path to proxy client key file")
} }
func (o *AggregatorServerOptions) Validate() []error { func (o *KubeAggregatorOptions) Validate() []error {
if o == nil { if o == nil {
return nil return nil
} }
@ -52,7 +52,7 @@ func (o *AggregatorServerOptions) Validate() []error {
return nil return nil
} }
func (o *AggregatorServerOptions) ApplyTo(aggregatorConfig *aggregatorapiserver.Config, etcdOpts *options.EtcdOptions) error { func (o *KubeAggregatorOptions) ApplyTo(aggregatorConfig *aggregatorapiserver.Config, etcdOpts *options.EtcdOptions) error {
genericConfig := aggregatorConfig.GenericConfig genericConfig := aggregatorConfig.GenericConfig
genericConfig.PostStartHooks = map[string]genericapiserver.PostStartHookConfigEntry{} genericConfig.PostStartHooks = map[string]genericapiserver.PostStartHookConfigEntry{}

View File

@ -19,25 +19,28 @@ type OptionsProvider interface {
const defaultEtcdPathPrefix = "/registry/grafana.app" const defaultEtcdPathPrefix = "/registry/grafana.app"
type Options struct { type Options struct {
RecommendedOptions *genericoptions.RecommendedOptions RecommendedOptions *genericoptions.RecommendedOptions
AggregatorOptions *AggregatorServerOptions GrafanaAggregatorOptions *GrafanaAggregatorOptions
StorageOptions *StorageOptions KubeAggregatorOptions *KubeAggregatorOptions
ExtraOptions *ExtraOptions StorageOptions *StorageOptions
APIOptions []OptionsProvider ExtraOptions *ExtraOptions
APIOptions []OptionsProvider
} }
func NewOptions(codec runtime.Codec) *Options { func NewOptions(codec runtime.Codec) *Options {
return &Options{ return &Options{
RecommendedOptions: NewRecommendedOptions(codec), RecommendedOptions: NewRecommendedOptions(codec),
AggregatorOptions: NewAggregatorServerOptions(), GrafanaAggregatorOptions: NewGrafanaAggregatorOptions(),
StorageOptions: NewStorageOptions(), KubeAggregatorOptions: NewAggregatorServerOptions(),
ExtraOptions: NewExtraOptions(), StorageOptions: NewStorageOptions(),
ExtraOptions: NewExtraOptions(),
} }
} }
func (o *Options) AddFlags(fs *pflag.FlagSet) { func (o *Options) AddFlags(fs *pflag.FlagSet) {
o.RecommendedOptions.AddFlags(fs) o.RecommendedOptions.AddFlags(fs)
o.AggregatorOptions.AddFlags(fs) o.GrafanaAggregatorOptions.AddFlags(fs)
o.KubeAggregatorOptions.AddFlags(fs)
o.StorageOptions.AddFlags(fs) o.StorageOptions.AddFlags(fs)
o.ExtraOptions.AddFlags(fs) o.ExtraOptions.AddFlags(fs)
@ -55,7 +58,11 @@ func (o *Options) Validate() []error {
return errs return errs
} }
if errs := o.AggregatorOptions.Validate(); len(errs) != 0 { if errs := o.GrafanaAggregatorOptions.Validate(); len(errs) != 0 {
return errs
}
if errs := o.KubeAggregatorOptions.Validate(); len(errs) != 0 {
return errs return errs
} }

View File

@ -7,6 +7,7 @@ import (
"path" "path"
"github.com/grafana/dskit/services" "github.com/grafana/dskit/services"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
"google.golang.org/grpc" "google.golang.org/grpc"
@ -19,7 +20,9 @@ import (
genericapiserver "k8s.io/apiserver/pkg/server" genericapiserver "k8s.io/apiserver/pkg/server"
clientrest "k8s.io/client-go/rest" clientrest "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
aggregatorapiserver "k8s.io/kube-aggregator/pkg/apiserver"
dataplaneaggregator "github.com/grafana/grafana/pkg/aggregator/apiserver"
"github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/apimachinery/identity"
grafanaresponsewriter "github.com/grafana/grafana/pkg/apiserver/endpoints/responsewriter" grafanaresponsewriter "github.com/grafana/grafana/pkg/apiserver/endpoints/responsewriter"
@ -30,8 +33,10 @@ import (
"github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/middleware" "github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/modules" "github.com/grafana/grafana/pkg/modules"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/registry" "github.com/grafana/grafana/pkg/registry"
"github.com/grafana/grafana/pkg/services/apiserver/aggregator" "github.com/grafana/grafana/pkg/registry/apis/datasource"
kubeaggregator "github.com/grafana/grafana/pkg/services/apiserver/aggregator"
"github.com/grafana/grafana/pkg/services/apiserver/auth/authenticator" "github.com/grafana/grafana/pkg/services/apiserver/auth/authenticator"
"github.com/grafana/grafana/pkg/services/apiserver/auth/authorizer" "github.com/grafana/grafana/pkg/services/apiserver/auth/authorizer"
"github.com/grafana/grafana/pkg/services/apiserver/builder" "github.com/grafana/grafana/pkg/services/apiserver/builder"
@ -41,6 +46,7 @@ import (
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/storage/unified/apistore" "github.com/grafana/grafana/pkg/storage/unified/apistore"
"github.com/grafana/grafana/pkg/storage/unified/resource" "github.com/grafana/grafana/pkg/storage/unified/resource"
@ -117,6 +123,11 @@ type service struct {
authorizer *authorizer.GrafanaAuthorizer authorizer *authorizer.GrafanaAuthorizer
serverLockService builder.ServerLockService serverLockService builder.ServerLockService
kvStore kvstore.KVStore kvStore kvstore.KVStore
pluginClient plugins.Client
datasources datasource.ScopedPluginDatasourceProvider
contextProvider datasource.PluginContextWrapper
pluginStore pluginstore.Store
} }
func ProvideService( func ProvideService(
@ -128,19 +139,27 @@ func ProvideService(
serverLockService *serverlock.ServerLockService, serverLockService *serverlock.ServerLockService,
db db.DB, db db.DB,
kvStore kvstore.KVStore, kvStore kvstore.KVStore,
pluginClient plugins.Client,
datasources datasource.ScopedPluginDatasourceProvider,
contextProvider datasource.PluginContextWrapper,
pluginStore pluginstore.Store,
) (*service, error) { ) (*service, error) {
s := &service{ s := &service{
cfg: cfg, cfg: cfg,
features: features, features: features,
rr: rr, rr: rr,
startedCh: make(chan struct{}), startedCh: make(chan struct{}),
stopCh: make(chan struct{}), stopCh: make(chan struct{}),
builders: []builder.APIGroupBuilder{}, builders: []builder.APIGroupBuilder{},
authorizer: authorizer.NewGrafanaAuthorizer(cfg, orgService), authorizer: authorizer.NewGrafanaAuthorizer(cfg, orgService),
tracing: tracing, tracing: tracing,
db: db, // For Unified storage db: db, // For Unified storage
metrics: metrics.ProvideRegisterer(), metrics: metrics.ProvideRegisterer(),
kvStore: kvStore, kvStore: kvStore,
pluginClient: pluginClient,
datasources: datasources,
contextProvider: contextProvider,
pluginStore: pluginStore,
} }
// This will be used when running as a dskit service // This will be used when running as a dskit service
@ -214,7 +233,7 @@ func (s *service) start(ctx context.Context) error {
groupVersions := make([]schema.GroupVersion, 0, len(builders)) groupVersions := make([]schema.GroupVersion, 0, len(builders))
// Install schemas // Install schemas
initialSize := len(aggregator.APIVersionPriorities) initialSize := len(kubeaggregator.APIVersionPriorities)
for i, b := range builders { for i, b := range builders {
groupVersions = append(groupVersions, b.GetGroupVersion()) groupVersions = append(groupVersions, b.GetGroupVersion())
if err := b.InstallSchema(Scheme); err != nil { if err := b.InstallSchema(Scheme); err != nil {
@ -223,7 +242,7 @@ func (s *service) start(ctx context.Context) error {
if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesAggregator) { if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesAggregator) {
// set the priority for the group+version // set the priority for the group+version
aggregator.APIVersionPriorities[b.GetGroupVersion()] = aggregator.Priority{Group: 15000, Version: int32(i + initialSize)} kubeaggregator.APIVersionPriorities[b.GetGroupVersion()] = kubeaggregator.Priority{Group: 15000, Version: int32(i + initialSize)}
} }
auth := b.GetAuthorizer() auth := b.GetAuthorizer()
@ -339,9 +358,24 @@ func (s *service) start(ctx context.Context) error {
// stash the options for later use // stash the options for later use
s.options = o s.options = o
var runningServer *genericapiserver.GenericAPIServer delegate := server
var aggregatorServer *aggregatorapiserver.APIAggregator
if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesAggregator) { if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesAggregator) {
runningServer, err = s.startAggregator(ctx, transport, serverConfig, server, s.metrics) aggregatorServer, err = s.createKubeAggregator(serverConfig, server, s.metrics)
if err != nil {
return err
}
delegate = aggregatorServer.GenericAPIServer
}
var runningServer *genericapiserver.GenericAPIServer
if s.features.IsEnabledGlobally(featuremgmt.FlagDataplaneAggregator) {
runningServer, err = s.startDataplaneAggregator(ctx, transport, serverConfig, delegate)
if err != nil {
return err
}
} else if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesAggregator) {
runningServer, err = s.startKubeAggregator(ctx, transport, aggregatorServer)
if err != nil { if err != nil {
return err return err
} }
@ -387,25 +421,74 @@ func (s *service) startCoreServer(
return server, nil return server, nil
} }
func (s *service) startAggregator( func (s *service) startDataplaneAggregator(
ctx context.Context, ctx context.Context,
transport *roundTripperFunc, transport *roundTripperFunc,
serverConfig *genericapiserver.RecommendedConfig,
delegate *genericapiserver.GenericAPIServer,
) (*genericapiserver.GenericAPIServer, error) {
config := &dataplaneaggregator.Config{
GenericConfig: serverConfig,
ExtraConfig: dataplaneaggregator.ExtraConfig{
PluginClient: s.pluginClient,
PluginContextProvider: &pluginContextProvider{
pluginStore: s.pluginStore,
datasources: s.datasources,
contextProvider: s.contextProvider,
},
},
}
if err := s.options.GrafanaAggregatorOptions.ApplyTo(config, s.options.RecommendedOptions.Etcd); err != nil {
return nil, err
}
completedConfig := config.Complete()
aggregatorServer, err := completedConfig.NewWithDelegate(delegate)
if err != nil {
return nil, err
}
// setup the loopback transport for the aggregator server and signal that it's ready
// ignore the lint error because the response is passed directly to the client,
// so the client will be responsible for closing the response body.
// nolint:bodyclose
transport.fn = grafanaresponsewriter.WrapHandler(aggregatorServer.GenericAPIServer.Handler)
close(transport.ready)
prepared, err := aggregatorServer.PrepareRun()
if err != nil {
return nil, err
}
go func() {
s.stoppedCh <- prepared.RunWithContext(ctx)
}()
return aggregatorServer.GenericAPIServer, nil
}
func (s *service) createKubeAggregator(
serverConfig *genericapiserver.RecommendedConfig, serverConfig *genericapiserver.RecommendedConfig,
server *genericapiserver.GenericAPIServer, server *genericapiserver.GenericAPIServer,
reg prometheus.Registerer, reg prometheus.Registerer,
) (*genericapiserver.GenericAPIServer, error) { ) (*aggregatorapiserver.APIAggregator, error) {
namespaceMapper := request.GetNamespaceMapper(s.cfg) namespaceMapper := request.GetNamespaceMapper(s.cfg)
aggregatorConfig, err := aggregator.CreateAggregatorConfig(s.options, *serverConfig, namespaceMapper(1)) aggregatorConfig, err := kubeaggregator.CreateAggregatorConfig(s.options, *serverConfig, namespaceMapper(1))
if err != nil { if err != nil {
return nil, err return nil, err
} }
aggregatorServer, err := aggregator.CreateAggregatorServer(aggregatorConfig, server, reg) return kubeaggregator.CreateAggregatorServer(aggregatorConfig, server, reg)
if err != nil { }
return nil, err
}
func (s *service) startKubeAggregator(
ctx context.Context,
transport *roundTripperFunc,
aggregatorServer *aggregatorapiserver.APIAggregator,
) (*genericapiserver.GenericAPIServer, error) {
// setup the loopback transport for the aggregator server and signal that it's ready // setup the loopback transport for the aggregator server and signal that it's ready
// ignore the lint error because the response is passed directly to the client, // ignore the lint error because the response is passed directly to the client,
// so the client will be responsible for closing the response body. // so the client will be responsible for closing the response body.
@ -473,3 +556,30 @@ func (f *roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error)
} }
return f.fn(req) return f.fn(req)
} }
type pluginContextProvider struct {
pluginStore pluginstore.Store
datasources datasource.ScopedPluginDatasourceProvider
contextProvider datasource.PluginContextWrapper
}
func (p *pluginContextProvider) GetPluginContext(ctx context.Context, pluginID string, uid string) (backend.PluginContext, error) {
all := p.pluginStore.Plugins(ctx)
var datasourceProvider datasource.PluginDatasourceProvider
for _, plugin := range all {
if plugin.ID == pluginID {
datasourceProvider = p.datasources.GetDatasourceProvider(plugin.JSONData)
}
}
if datasourceProvider == nil {
return backend.PluginContext{}, fmt.Errorf("plugin not found")
}
s, err := datasourceProvider.GetInstanceSettings(ctx, uid)
if err != nil {
return backend.PluginContext{}, err
}
return p.contextProvider.PluginContextForDataSource(ctx, s)
}