mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
K8s: remove (not great) example api (#89524)
This commit is contained in:
parent
f74afa5e7f
commit
93ef90a1e4
@ -1,11 +0,0 @@
|
|||||||
// +k8s:deepcopy-gen=package
|
|
||||||
// +k8s:openapi-gen=true
|
|
||||||
// +k8s:defaulter-gen=TypeMeta
|
|
||||||
// +groupName=example.grafana.app
|
|
||||||
|
|
||||||
// The testing api is a dependency free service that we can use to experiment with
|
|
||||||
// api aggregation across multiple deployment models. Specifically:
|
|
||||||
// - standalone: running as part of the standard grafana build
|
|
||||||
// - aggregated: running as the target
|
|
||||||
|
|
||||||
package v0alpha1 // import "github.com/grafana/grafana/pkg/apis/example/v0alpha1"
|
|
@ -1,30 +0,0 @@
|
|||||||
package v0alpha1
|
|
||||||
|
|
||||||
import (
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
|
|
||||||
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
GROUP = "example.grafana.app"
|
|
||||||
VERSION = "v0alpha1"
|
|
||||||
APIVERSION = GROUP + "/" + VERSION
|
|
||||||
)
|
|
||||||
|
|
||||||
var RuntimeResourceInfo = common.NewResourceInfo(GROUP, VERSION,
|
|
||||||
"runtime", "runtime", "RuntimeInfo",
|
|
||||||
func() runtime.Object { return &RuntimeInfo{} },
|
|
||||||
func() runtime.Object { return &RuntimeInfo{} },
|
|
||||||
)
|
|
||||||
var DummyResourceInfo = common.NewResourceInfo(GROUP, VERSION,
|
|
||||||
"dummy", "dummy", "DummyResource",
|
|
||||||
func() runtime.Object { return &DummyResource{} },
|
|
||||||
func() runtime.Object { return &DummyResourceList{} },
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// SchemeGroupVersion is group version used to register these objects
|
|
||||||
SchemeGroupVersion = schema.GroupVersion{Group: GROUP, Version: VERSION}
|
|
||||||
)
|
|
@ -1,48 +0,0 @@
|
|||||||
package v0alpha1
|
|
||||||
|
|
||||||
import (
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
|
|
||||||
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Mirrors the info exposed in "github.com/grafana/grafana/pkg/setting"
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
|
||||||
type RuntimeInfo struct {
|
|
||||||
metav1.TypeMeta `json:",inline"`
|
|
||||||
|
|
||||||
// Unix timestamp when the process started
|
|
||||||
StartupTime int64 `json:"startupTime,omitempty"`
|
|
||||||
|
|
||||||
BuildVersion string `json:"buildVersion,omitempty"`
|
|
||||||
BuildCommit string `json:"buildCommit,omitempty"`
|
|
||||||
EnterpriseBuildCommit string `json:"enterpriseBuildCommit,omitempty"`
|
|
||||||
BuildBranch string `json:"buildBranch,omitempty"`
|
|
||||||
BuildStamp int64 `json:"buildStamp,omitempty"`
|
|
||||||
IsEnterprise bool `json:"enterprise,omitempty"`
|
|
||||||
Packaging string `json:"packaging,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
|
||||||
type DummyResource struct {
|
|
||||||
metav1.TypeMeta `json:",inline"`
|
|
||||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
Spec common.Unstructured `json:"spec,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
|
||||||
type DummyResourceList struct {
|
|
||||||
metav1.TypeMeta `json:",inline"`
|
|
||||||
metav1.ListMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
Items []DummyResource `json:"items,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
|
||||||
type DummySubresource struct {
|
|
||||||
metav1.TypeMeta `json:",inline"`
|
|
||||||
|
|
||||||
// add subresource info here
|
|
||||||
Info string `json:"info,omitempty"`
|
|
||||||
}
|
|
@ -1,122 +0,0 @@
|
|||||||
//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 *DummyResource) DeepCopyInto(out *DummyResource) {
|
|
||||||
*out = *in
|
|
||||||
out.TypeMeta = in.TypeMeta
|
|
||||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
|
||||||
in.Spec.DeepCopyInto(&out.Spec)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DummyResource.
|
|
||||||
func (in *DummyResource) DeepCopy() *DummyResource {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(DummyResource)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
|
||||||
func (in *DummyResource) 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 *DummyResourceList) DeepCopyInto(out *DummyResourceList) {
|
|
||||||
*out = *in
|
|
||||||
out.TypeMeta = in.TypeMeta
|
|
||||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
|
||||||
if in.Items != nil {
|
|
||||||
in, out := &in.Items, &out.Items
|
|
||||||
*out = make([]DummyResource, len(*in))
|
|
||||||
for i := range *in {
|
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DummyResourceList.
|
|
||||||
func (in *DummyResourceList) DeepCopy() *DummyResourceList {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(DummyResourceList)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
|
||||||
func (in *DummyResourceList) 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 *DummySubresource) DeepCopyInto(out *DummySubresource) {
|
|
||||||
*out = *in
|
|
||||||
out.TypeMeta = in.TypeMeta
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DummySubresource.
|
|
||||||
func (in *DummySubresource) DeepCopy() *DummySubresource {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(DummySubresource)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
|
||||||
func (in *DummySubresource) 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 *RuntimeInfo) DeepCopyInto(out *RuntimeInfo) {
|
|
||||||
*out = *in
|
|
||||||
out.TypeMeta = in.TypeMeta
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuntimeInfo.
|
|
||||||
func (in *RuntimeInfo) DeepCopy() *RuntimeInfo {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(RuntimeInfo)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
|
||||||
func (in *RuntimeInfo) DeepCopyObject() runtime.Object {
|
|
||||||
if c := in.DeepCopy(); c != nil {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
//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
|
|
||||||
}
|
|
@ -1,219 +0,0 @@
|
|||||||
//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/apis/example/v0alpha1.DummyResource": schema_pkg_apis_example_v0alpha1_DummyResource(ref),
|
|
||||||
"github.com/grafana/grafana/pkg/apis/example/v0alpha1.DummyResourceList": schema_pkg_apis_example_v0alpha1_DummyResourceList(ref),
|
|
||||||
"github.com/grafana/grafana/pkg/apis/example/v0alpha1.DummySubresource": schema_pkg_apis_example_v0alpha1_DummySubresource(ref),
|
|
||||||
"github.com/grafana/grafana/pkg/apis/example/v0alpha1.RuntimeInfo": schema_pkg_apis_example_v0alpha1_RuntimeInfo(ref),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func schema_pkg_apis_example_v0alpha1_DummyResource(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{
|
|
||||||
Ref: ref("github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1.Unstructured"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Dependencies: []string{
|
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1.Unstructured", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func schema_pkg_apis_example_v0alpha1_DummyResourceList(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/apis/example/v0alpha1.DummyResource"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Dependencies: []string{
|
|
||||||
"github.com/grafana/grafana/pkg/apis/example/v0alpha1.DummyResource", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func schema_pkg_apis_example_v0alpha1_DummySubresource(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: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"info": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "add subresource info here",
|
|
||||||
Type: []string{"string"},
|
|
||||||
Format: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func schema_pkg_apis_example_v0alpha1_RuntimeInfo(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
|
||||||
return common.OpenAPIDefinition{
|
|
||||||
Schema: spec.Schema{
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "Mirrors the info exposed in \"github.com/grafana/grafana/pkg/setting\"",
|
|
||||||
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: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"startupTime": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "Unix timestamp when the process started",
|
|
||||||
Type: []string{"integer"},
|
|
||||||
Format: "int64",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"buildVersion": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Type: []string{"string"},
|
|
||||||
Format: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"buildCommit": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Type: []string{"string"},
|
|
||||||
Format: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"enterpriseBuildCommit": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Type: []string{"string"},
|
|
||||||
Format: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"buildBranch": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Type: []string{"string"},
|
|
||||||
Format: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"buildStamp": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Type: []string{"integer"},
|
|
||||||
Format: "int64",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"enterprise": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Type: []string{"boolean"},
|
|
||||||
Format: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"packaging": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Type: []string{"string"},
|
|
||||||
Format: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
API rule violation: names_match,github.com/grafana/grafana/pkg/apis/example/v0alpha1,RuntimeInfo,IsEnterprise
|
|
@ -8,7 +8,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/registry/apis/dashboard"
|
"github.com/grafana/grafana/pkg/registry/apis/dashboard"
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/dashboardsnapshot"
|
"github.com/grafana/grafana/pkg/registry/apis/dashboardsnapshot"
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/datasource"
|
"github.com/grafana/grafana/pkg/registry/apis/datasource"
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/example"
|
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/featuretoggle"
|
"github.com/grafana/grafana/pkg/registry/apis/featuretoggle"
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/folders"
|
"github.com/grafana/grafana/pkg/registry/apis/folders"
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/peakq"
|
"github.com/grafana/grafana/pkg/registry/apis/peakq"
|
||||||
@ -28,7 +27,6 @@ type Service struct{}
|
|||||||
func ProvideRegistryServiceSink(
|
func ProvideRegistryServiceSink(
|
||||||
_ *dashboard.DashboardsAPIBuilder,
|
_ *dashboard.DashboardsAPIBuilder,
|
||||||
_ *playlist.PlaylistAPIBuilder,
|
_ *playlist.PlaylistAPIBuilder,
|
||||||
_ *example.TestingAPIBuilder,
|
|
||||||
_ *dashboardsnapshot.SnapshotsAPIBuilder,
|
_ *dashboardsnapshot.SnapshotsAPIBuilder,
|
||||||
_ *featuretoggle.FeatureFlagAPIBuilder,
|
_ *featuretoggle.FeatureFlagAPIBuilder,
|
||||||
_ *datasource.DataSourceAPIBuilder,
|
_ *datasource.DataSourceAPIBuilder,
|
||||||
|
@ -1,128 +0,0 @@
|
|||||||
package example
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"slices"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
|
||||||
|
|
||||||
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
|
||||||
example "github.com/grafana/grafana/pkg/apis/example/v0alpha1"
|
|
||||||
grafanaregistry "github.com/grafana/grafana/pkg/apiserver/registry/generic"
|
|
||||||
grafanarequest "github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ rest.Storage = (*dummyStorage)(nil)
|
|
||||||
_ rest.Scoper = (*dummyStorage)(nil)
|
|
||||||
_ rest.SingularNameProvider = (*dummyStorage)(nil)
|
|
||||||
_ rest.Getter = (*dummyStorage)(nil)
|
|
||||||
_ rest.Lister = (*dummyStorage)(nil)
|
|
||||||
)
|
|
||||||
|
|
||||||
type dummyStorage struct {
|
|
||||||
store *genericregistry.Store
|
|
||||||
names []string
|
|
||||||
creationTimestamp metav1.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func newDummyStorage(gv schema.GroupVersion, scheme *runtime.Scheme, names ...string) *dummyStorage {
|
|
||||||
var resourceInfo = example.DummyResourceInfo
|
|
||||||
strategy := grafanaregistry.NewStrategy(scheme)
|
|
||||||
store := &genericregistry.Store{
|
|
||||||
NewFunc: resourceInfo.NewFunc,
|
|
||||||
NewListFunc: resourceInfo.NewListFunc,
|
|
||||||
PredicateFunc: grafanaregistry.Matcher,
|
|
||||||
DefaultQualifiedResource: resourceInfo.GroupResource(),
|
|
||||||
SingularQualifiedResource: resourceInfo.SingularGroupResource(),
|
|
||||||
TableConvertor: rest.NewDefaultTableConvertor(resourceInfo.GroupResource()),
|
|
||||||
CreateStrategy: strategy,
|
|
||||||
UpdateStrategy: strategy,
|
|
||||||
DeleteStrategy: strategy,
|
|
||||||
}
|
|
||||||
|
|
||||||
return &dummyStorage{
|
|
||||||
store: store,
|
|
||||||
names: names,
|
|
||||||
creationTimestamp: metav1.Now(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *dummyStorage) New() runtime.Object {
|
|
||||||
return s.store.New()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *dummyStorage) Destroy() {}
|
|
||||||
|
|
||||||
func (s *dummyStorage) NamespaceScoped() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *dummyStorage) GetSingularName() string {
|
|
||||||
return example.DummyResourceInfo.GetSingularName()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *dummyStorage) NewList() runtime.Object {
|
|
||||||
return s.store.NewListFunc()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *dummyStorage) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
|
|
||||||
return s.store.TableConvertor.ConvertToTable(ctx, object, tableOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *dummyStorage) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
|
|
||||||
info, err := grafanarequest.NamespaceInfoFrom(ctx, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
idx := slices.Index(s.names, name)
|
|
||||||
if idx < 0 {
|
|
||||||
return nil, fmt.Errorf("dummy not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &example.DummyResource{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: name,
|
|
||||||
Namespace: info.Value,
|
|
||||||
CreationTimestamp: s.creationTimestamp,
|
|
||||||
ResourceVersion: "1",
|
|
||||||
},
|
|
||||||
Spec: common.Unstructured{
|
|
||||||
Object: map[string]any{
|
|
||||||
"Dummy": name,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *dummyStorage) List(ctx context.Context, options *internalversion.ListOptions) (runtime.Object, error) {
|
|
||||||
info, err := grafanarequest.NamespaceInfoFrom(ctx, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
res := &example.DummyResourceList{}
|
|
||||||
for _, name := range s.names {
|
|
||||||
res.Items = append(res.Items, example.DummyResource{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: name,
|
|
||||||
Namespace: info.Value,
|
|
||||||
CreationTimestamp: s.creationTimestamp,
|
|
||||||
ResourceVersion: "1",
|
|
||||||
},
|
|
||||||
Spec: common.Unstructured{
|
|
||||||
Object: map[string]any{
|
|
||||||
"Dummy": name,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return res, nil
|
|
||||||
}
|
|
@ -1,226 +0,0 @@
|
|||||||
package example
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
||||||
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"
|
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
|
||||||
"k8s.io/apiserver/pkg/registry/generic"
|
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
|
||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
|
||||||
common "k8s.io/kube-openapi/pkg/common"
|
|
||||||
"k8s.io/kube-openapi/pkg/spec3"
|
|
||||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
|
||||||
example "github.com/grafana/grafana/pkg/apis/example/v0alpha1"
|
|
||||||
"github.com/grafana/grafana/pkg/apiserver/builder"
|
|
||||||
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
|
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ builder.APIGroupBuilder = (*TestingAPIBuilder)(nil)
|
|
||||||
|
|
||||||
// This is used just so wire has something unique to return
|
|
||||||
type TestingAPIBuilder struct {
|
|
||||||
codecs serializer.CodecFactory
|
|
||||||
gv schema.GroupVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTestingAPIBuilder() *TestingAPIBuilder {
|
|
||||||
return &TestingAPIBuilder{
|
|
||||||
gv: schema.GroupVersion{Group: example.GROUP, Version: example.VERSION},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterAPIService(features featuremgmt.FeatureToggles, apiregistration builder.APIRegistrar, reg prometheus.Registerer) *TestingAPIBuilder {
|
|
||||||
if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) {
|
|
||||||
return nil // skip registration unless opting into experimental apis
|
|
||||||
}
|
|
||||||
builder := NewTestingAPIBuilder()
|
|
||||||
apiregistration.RegisterAPI(builder)
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *TestingAPIBuilder) GetGroupVersion() schema.GroupVersion {
|
|
||||||
return b.gv
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *TestingAPIBuilder) GetDesiredDualWriterMode(dualWrite bool, modeMap map[string]grafanarest.DualWriterMode) grafanarest.DualWriterMode {
|
|
||||||
// Add required configuration support in order to enable other modes. For an example, see pkg/registry/apis/playlist/register.go
|
|
||||||
return grafanarest.Mode0
|
|
||||||
}
|
|
||||||
|
|
||||||
func addKnownTypes(scheme *runtime.Scheme, gv schema.GroupVersion) {
|
|
||||||
scheme.AddKnownTypes(gv,
|
|
||||||
&example.RuntimeInfo{},
|
|
||||||
&example.DummyResource{},
|
|
||||||
&example.DummyResourceList{},
|
|
||||||
&example.DummySubresource{},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *TestingAPIBuilder) InstallSchema(scheme *runtime.Scheme) error {
|
|
||||||
addKnownTypes(scheme, b.gv)
|
|
||||||
|
|
||||||
// Link this version to the internal representation.
|
|
||||||
// This is used for server-side-apply (PATCH), and avoids the error:
|
|
||||||
// "no kind is registered for the type"
|
|
||||||
addKnownTypes(scheme, schema.GroupVersion{
|
|
||||||
Group: b.gv.Group,
|
|
||||||
Version: runtime.APIVersionInternal,
|
|
||||||
})
|
|
||||||
|
|
||||||
// If multiple versions exist, then register conversions from zz_generated.conversion.go
|
|
||||||
// if err := playlist.RegisterConversions(scheme); err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
metav1.AddToGroupVersion(scheme, b.gv)
|
|
||||||
return scheme.SetVersionPriority(b.gv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *TestingAPIBuilder) GetAPIGroupInfo(
|
|
||||||
scheme *runtime.Scheme,
|
|
||||||
codecs serializer.CodecFactory, // pointer?
|
|
||||||
_ generic.RESTOptionsGetter,
|
|
||||||
_ grafanarest.DualWriterMode,
|
|
||||||
_ prometheus.Registerer,
|
|
||||||
) (*genericapiserver.APIGroupInfo, error) {
|
|
||||||
b.codecs = codecs
|
|
||||||
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(b.gv.Group, scheme, metav1.ParameterCodec, codecs)
|
|
||||||
|
|
||||||
storage := map[string]rest.Storage{}
|
|
||||||
storage[example.RuntimeResourceInfo.StoragePath()] = newDeploymentInfoStorage(b.gv, scheme)
|
|
||||||
storage[example.DummyResourceInfo.StoragePath()] = newDummyStorage(b.gv, scheme, "test1", "test2", "test3")
|
|
||||||
storage[example.DummyResourceInfo.StoragePath("sub")] = &dummySubresourceREST{}
|
|
||||||
apiGroupInfo.VersionedResourcesStorageMap[b.gv.Version] = storage
|
|
||||||
return &apiGroupInfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *TestingAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefinitions {
|
|
||||||
return example.GetOpenAPIDefinitions
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register additional routes with the server
|
|
||||||
func (b *TestingAPIBuilder) GetAPIRoutes() *builder.APIRoutes {
|
|
||||||
return &builder.APIRoutes{
|
|
||||||
Root: []builder.APIRouteHandler{
|
|
||||||
{
|
|
||||||
Path: "aaa",
|
|
||||||
Spec: &spec3.PathProps{
|
|
||||||
Summary: "an example at the root level",
|
|
||||||
Description: "longer description here?",
|
|
||||||
Get: &spec3.Operation{
|
|
||||||
OperationProps: spec3.OperationProps{
|
|
||||||
Parameters: []*spec3.Parameter{
|
|
||||||
{ParameterProps: spec3.ParameterProps{
|
|
||||||
Name: "a",
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
Responses: &spec3.Responses{
|
|
||||||
ResponsesProps: spec3.ResponsesProps{
|
|
||||||
StatusCodeResponses: map[int]*spec3.Response{
|
|
||||||
200: {
|
|
||||||
ResponseProps: spec3.ResponseProps{
|
|
||||||
Description: "OK",
|
|
||||||
Content: map[string]*spec3.MediaType{
|
|
||||||
"text/plain": {
|
|
||||||
MediaTypeProps: spec3.MediaTypeProps{
|
|
||||||
Schema: &spec.Schema{
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Type: []string{"string"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Handler: func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
_, _ = w.Write([]byte("Root level handler (aaa)"))
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Path: "bbb",
|
|
||||||
Spec: &spec3.PathProps{
|
|
||||||
Summary: "an example at the root level",
|
|
||||||
Description: "longer description here?",
|
|
||||||
Get: &spec3.Operation{
|
|
||||||
OperationProps: spec3.OperationProps{
|
|
||||||
Parameters: []*spec3.Parameter{
|
|
||||||
{ParameterProps: spec3.ParameterProps{
|
|
||||||
Name: "b",
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Handler: func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
_, _ = w.Write([]byte("Root level handler (bbb)"))
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Namespace: []builder.APIRouteHandler{
|
|
||||||
{
|
|
||||||
Path: "ccc",
|
|
||||||
Spec: &spec3.PathProps{
|
|
||||||
Summary: "an example at the root level",
|
|
||||||
Description: "longer description here?",
|
|
||||||
Get: &spec3.Operation{
|
|
||||||
OperationProps: spec3.OperationProps{
|
|
||||||
Parameters: []*spec3.Parameter{
|
|
||||||
{ParameterProps: spec3.ParameterProps{
|
|
||||||
Name: "a",
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Handler: func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
info, ok := request.RequestInfoFrom(r.Context())
|
|
||||||
if !ok {
|
|
||||||
responsewriters.ErrorNegotiated(
|
|
||||||
apierrors.NewInternalError(fmt.Errorf("no RequestInfo found in the context")),
|
|
||||||
b.codecs, schema.GroupVersion{}, w, r,
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _ = w.Write([]byte("Custom namespace route ccc: " + info.Namespace))
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *TestingAPIBuilder) GetAuthorizer() authorizer.Authorizer {
|
|
||||||
return authorizer.AuthorizerFunc(
|
|
||||||
func(ctx context.Context, attr authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
|
||||||
if !attr.IsResourceRequest() {
|
|
||||||
return authorizer.DecisionNoOpinion, "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// require a user
|
|
||||||
_, err = identity.GetRequester(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return authorizer.DecisionDeny, "valid user is required", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return authorizer.DecisionNoOpinion, "", err // fallback to org/role logic
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
package example
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
|
||||||
|
|
||||||
example "github.com/grafana/grafana/pkg/apis/example/v0alpha1"
|
|
||||||
grafanaregistry "github.com/grafana/grafana/pkg/apiserver/registry/generic"
|
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ rest.Storage = (*staticStorage)(nil)
|
|
||||||
_ rest.Scoper = (*staticStorage)(nil)
|
|
||||||
_ rest.SingularNameProvider = (*staticStorage)(nil)
|
|
||||||
_ rest.Lister = (*staticStorage)(nil)
|
|
||||||
)
|
|
||||||
|
|
||||||
type staticStorage struct {
|
|
||||||
Store *genericregistry.Store
|
|
||||||
info example.RuntimeInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
func newDeploymentInfoStorage(gv schema.GroupVersion, scheme *runtime.Scheme) *staticStorage {
|
|
||||||
var resourceInfo = example.RuntimeResourceInfo
|
|
||||||
strategy := grafanaregistry.NewStrategy(scheme)
|
|
||||||
store := &genericregistry.Store{
|
|
||||||
NewFunc: resourceInfo.NewFunc,
|
|
||||||
NewListFunc: resourceInfo.NewListFunc,
|
|
||||||
PredicateFunc: grafanaregistry.Matcher,
|
|
||||||
DefaultQualifiedResource: resourceInfo.GroupResource(),
|
|
||||||
SingularQualifiedResource: resourceInfo.SingularGroupResource(),
|
|
||||||
TableConvertor: rest.NewDefaultTableConvertor(resourceInfo.GroupResource()),
|
|
||||||
CreateStrategy: strategy,
|
|
||||||
UpdateStrategy: strategy,
|
|
||||||
DeleteStrategy: strategy,
|
|
||||||
}
|
|
||||||
|
|
||||||
return &staticStorage{
|
|
||||||
Store: store,
|
|
||||||
info: example.RuntimeInfo{
|
|
||||||
TypeMeta: example.RuntimeResourceInfo.TypeMeta(),
|
|
||||||
BuildVersion: setting.BuildVersion,
|
|
||||||
BuildCommit: setting.BuildCommit,
|
|
||||||
BuildBranch: setting.BuildBranch,
|
|
||||||
EnterpriseBuildCommit: setting.EnterpriseBuildCommit,
|
|
||||||
BuildStamp: setting.BuildStamp,
|
|
||||||
IsEnterprise: setting.IsEnterprise,
|
|
||||||
Packaging: setting.Packaging,
|
|
||||||
StartupTime: time.Now().UnixMilli(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *staticStorage) New() runtime.Object {
|
|
||||||
return s.Store.New()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *staticStorage) Destroy() {}
|
|
||||||
|
|
||||||
func (s *staticStorage) NamespaceScoped() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *staticStorage) GetSingularName() string {
|
|
||||||
return example.RuntimeResourceInfo.GetSingularName()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *staticStorage) NewList() runtime.Object {
|
|
||||||
return s.Store.NewListFunc()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *staticStorage) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
|
|
||||||
return s.Store.TableConvertor.ConvertToTable(ctx, object, tableOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *staticStorage) List(ctx context.Context, options *internalversion.ListOptions) (runtime.Object, error) {
|
|
||||||
return &s.info, nil
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
package example
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
|
||||||
example "github.com/grafana/grafana/pkg/apis/example/v0alpha1"
|
|
||||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
|
||||||
)
|
|
||||||
|
|
||||||
type dummySubresourceREST struct{}
|
|
||||||
|
|
||||||
var _ = rest.Connecter(&dummySubresourceREST{})
|
|
||||||
|
|
||||||
func (r *dummySubresourceREST) New() runtime.Object {
|
|
||||||
return &example.DummySubresource{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *dummySubresourceREST) Destroy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *dummySubresourceREST) ConnectMethods() []string {
|
|
||||||
return []string{"GET"}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *dummySubresourceREST) NewConnectOptions() (runtime.Object, bool, string) {
|
|
||||||
return nil, false, "" // true means you can use the trailing path as a variable
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *dummySubresourceREST) Connect(ctx context.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) {
|
|
||||||
info, err := request.NamespaceInfoFrom(ctx, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := identity.GetRequester(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// This response object format is negotiated by k8s
|
|
||||||
dummy := &example.DummySubresource{
|
|
||||||
Info: fmt.Sprintf("%s/%s", info.Value, user.GetLogin()),
|
|
||||||
}
|
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
responder.Object(http.StatusOK, dummy)
|
|
||||||
}), nil
|
|
||||||
}
|
|
@ -7,7 +7,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/registry/apis/dashboard"
|
"github.com/grafana/grafana/pkg/registry/apis/dashboard"
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/dashboardsnapshot"
|
"github.com/grafana/grafana/pkg/registry/apis/dashboardsnapshot"
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/datasource"
|
"github.com/grafana/grafana/pkg/registry/apis/datasource"
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/example"
|
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/featuretoggle"
|
"github.com/grafana/grafana/pkg/registry/apis/featuretoggle"
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/folders"
|
"github.com/grafana/grafana/pkg/registry/apis/folders"
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/peakq"
|
"github.com/grafana/grafana/pkg/registry/apis/peakq"
|
||||||
@ -29,7 +28,6 @@ var WireSet = wire.NewSet(
|
|||||||
// Each must be added here *and* in the ServiceSink above
|
// Each must be added here *and* in the ServiceSink above
|
||||||
playlist.RegisterAPIService,
|
playlist.RegisterAPIService,
|
||||||
dashboard.RegisterAPIService,
|
dashboard.RegisterAPIService,
|
||||||
example.RegisterAPIService,
|
|
||||||
dashboardsnapshot.RegisterAPIService,
|
dashboardsnapshot.RegisterAPIService,
|
||||||
featuretoggle.RegisterAPIService,
|
featuretoggle.RegisterAPIService,
|
||||||
datasource.RegisterAPIService,
|
datasource.RegisterAPIService,
|
||||||
|
@ -15,7 +15,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/datasource"
|
"github.com/grafana/grafana/pkg/registry/apis/datasource"
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/example"
|
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/featuretoggle"
|
"github.com/grafana/grafana/pkg/registry/apis/featuretoggle"
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/query"
|
"github.com/grafana/grafana/pkg/registry/apis/query"
|
||||||
"github.com/grafana/grafana/pkg/registry/apis/query/client"
|
"github.com/grafana/grafana/pkg/registry/apis/query/client"
|
||||||
@ -75,9 +74,6 @@ func (p *DummyAPIFactory) MakeAPIServer(_ context.Context, tracer tracing.Tracer
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch gv.Group {
|
switch gv.Group {
|
||||||
case "example.grafana.app":
|
|
||||||
return example.NewTestingAPIBuilder(), nil
|
|
||||||
|
|
||||||
// Only works with testdata
|
// Only works with testdata
|
||||||
case "query.grafana.app":
|
case "query.grafana.app":
|
||||||
return query.NewQueryAPIBuilder(
|
return query.NewQueryAPIBuilder(
|
||||||
|
@ -1,176 +0,0 @@
|
|||||||
package playlist
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
||||||
"github.com/grafana/grafana/pkg/tests/apis"
|
|
||||||
"github.com/grafana/grafana/pkg/tests/testinfra"
|
|
||||||
"github.com/grafana/grafana/pkg/tests/testsuite"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
|
||||||
testsuite.Run(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntegrationExampleApp(t *testing.T) {
|
|
||||||
if testing.Short() {
|
|
||||||
t.Skip("skipping integration test")
|
|
||||||
}
|
|
||||||
helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{
|
|
||||||
AppModeProduction: false, // required for experimental APIs
|
|
||||||
DisableAnonymous: true,
|
|
||||||
EnableFeatureToggles: []string{
|
|
||||||
featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs, // Required to start the example service
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Check runtime info resource", func(t *testing.T) {
|
|
||||||
// Resource is not namespaced!
|
|
||||||
client := helper.Org1.Admin.ResourceClient(t, schema.GroupVersionResource{
|
|
||||||
Group: "example.grafana.app",
|
|
||||||
Version: "v0alpha1",
|
|
||||||
Resource: "runtime",
|
|
||||||
})
|
|
||||||
rsp, err := client.List(context.Background(), metav1.ListOptions{})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
v, ok := rsp.Object["startupTime"].(int64)
|
|
||||||
require.True(t, ok)
|
|
||||||
require.Greater(t, v, time.Now().Add(-1*time.Hour).UnixMilli()) // should be within the last hour
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Check discovery client", func(t *testing.T) {
|
|
||||||
disco := helper.NewDiscoveryClient()
|
|
||||||
resources, err := disco.ServerResourcesForGroupVersion("example.grafana.app/v0alpha1")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
v1Disco, err := json.MarshalIndent(resources, "", " ")
|
|
||||||
require.NoError(t, err)
|
|
||||||
//fmt.Printf("%s", string(v1Disco))
|
|
||||||
|
|
||||||
require.JSONEq(t, `{
|
|
||||||
"kind": "APIResourceList",
|
|
||||||
"apiVersion": "v1",
|
|
||||||
"groupVersion": "example.grafana.app/v0alpha1",
|
|
||||||
"resources": [
|
|
||||||
{
|
|
||||||
"name": "dummy",
|
|
||||||
"singularName": "dummy",
|
|
||||||
"namespaced": true,
|
|
||||||
"kind": "DummyResource",
|
|
||||||
"verbs": [
|
|
||||||
"get",
|
|
||||||
"list"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "dummy/sub",
|
|
||||||
"singularName": "",
|
|
||||||
"namespaced": true,
|
|
||||||
"kind": "DummySubresource",
|
|
||||||
"verbs": [
|
|
||||||
"get"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "runtime",
|
|
||||||
"singularName": "runtime",
|
|
||||||
"namespaced": false,
|
|
||||||
"kind": "RuntimeInfo",
|
|
||||||
"verbs": [
|
|
||||||
"list"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}`, string(v1Disco))
|
|
||||||
|
|
||||||
//fmt.Printf("%s", string(v1Disco))
|
|
||||||
require.JSONEq(t, `[
|
|
||||||
{
|
|
||||||
"version": "v0alpha1",
|
|
||||||
"freshness": "Current",
|
|
||||||
"resources": [
|
|
||||||
{
|
|
||||||
"resource": "dummy",
|
|
||||||
"responseKind": {
|
|
||||||
"group": "",
|
|
||||||
"kind": "DummyResource",
|
|
||||||
"version": ""
|
|
||||||
},
|
|
||||||
"scope": "Namespaced",
|
|
||||||
"singularResource": "dummy",
|
|
||||||
"subresources": [
|
|
||||||
{
|
|
||||||
"responseKind": {
|
|
||||||
"group": "",
|
|
||||||
"kind": "DummySubresource",
|
|
||||||
"version": ""
|
|
||||||
},
|
|
||||||
"subresource": "sub",
|
|
||||||
"verbs": [
|
|
||||||
"get"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"verbs": [
|
|
||||||
"get",
|
|
||||||
"list"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resource": "runtime",
|
|
||||||
"responseKind": {
|
|
||||||
"group": "",
|
|
||||||
"kind": "RuntimeInfo",
|
|
||||||
"version": ""
|
|
||||||
},
|
|
||||||
"scope": "Cluster",
|
|
||||||
"singularResource": "runtime",
|
|
||||||
"verbs": [
|
|
||||||
"list"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]`, helper.GetGroupVersionInfoJSON("example.grafana.app"))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Check dummy with subresource", func(t *testing.T) {
|
|
||||||
client := helper.Org1.Viewer.ResourceClient(t, schema.GroupVersionResource{
|
|
||||||
Group: "example.grafana.app",
|
|
||||||
Version: "v0alpha1",
|
|
||||||
Resource: "dummy",
|
|
||||||
}).Namespace("default")
|
|
||||||
rsp, err := client.Get(context.Background(), "test2", metav1.GetOptions{})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
v, ok, err := unstructured.NestedString(rsp.Object, "spec", "Dummy")
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.True(t, ok)
|
|
||||||
|
|
||||||
require.Equal(t, "test2", v)
|
|
||||||
require.Equal(t, "DummyResource", rsp.GetObjectKind().GroupVersionKind().Kind)
|
|
||||||
|
|
||||||
// Now a sub-resource
|
|
||||||
rsp, err = client.Get(context.Background(), "test2", metav1.GetOptions{}, "sub")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
raw, err := json.MarshalIndent(rsp, "", " ")
|
|
||||||
require.NoError(t, err)
|
|
||||||
//fmt.Printf("%s", string(raw))
|
|
||||||
require.JSONEq(t, `{
|
|
||||||
"apiVersion": "example.grafana.app/v0alpha1",
|
|
||||||
"kind": "DummySubresource",
|
|
||||||
"info": "default/viewer-1"
|
|
||||||
}`, string(raw))
|
|
||||||
})
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user