feat: add hello world subresource (#96425)

This adds the infrastructure we need for a basic subresource.
This commit is contained in:
Mariell Hoversholm authored and GitHub committed 2024-11-14 09:25:02 +01:00
1 parent 6e408f19fa
commit f2ab3dfa18
6 files changed
+149 -1

No files matched your search

@@ -85,6 +85,7 @@ func AddKnownTypes(gv schema.GroupVersion, scheme *runtime.Scheme) error {
scheme.AddKnownTypes(gv,
&Repository{},
&RepositoryList{},
&HelloWorld{},
)
return nil
}
+7
View File
@@ -109,3 +109,10 @@ type RepositoryList struct {
Items []Repository `json:"items,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type HelloWorld struct {
metav1.TypeMeta `json:",inline"`
Whom string `json:"whom,omitempty"`
}
@@ -27,6 +27,31 @@ func (in *GitHubRepository) DeepCopy() *GitHubRepository {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HelloWorld) DeepCopyInto(out *HelloWorld) {
*out = *in
out.TypeMeta = in.TypeMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelloWorld.
func (in *HelloWorld) DeepCopy() *HelloWorld {
if in == nil {
return nil
}
out := new(HelloWorld)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *HelloWorld) 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 *LocalRepository) DeepCopyInto(out *LocalRepository) {
*out = *in
@@ -15,6 +15,7 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.GitHubRepository": schema_pkg_apis_provisioning_v0alpha1_GitHubRepository(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.HelloWorld": schema_pkg_apis_provisioning_v0alpha1_HelloWorld(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.LocalRepository": schema_pkg_apis_provisioning_v0alpha1_LocalRepository(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.Repository": schema_pkg_apis_provisioning_v0alpha1_Repository(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RepositoryList": schema_pkg_apis_provisioning_v0alpha1_RepositoryList(ref),
@@ -63,6 +64,38 @@ func schema_pkg_apis_provisioning_v0alpha1_GitHubRepository(ref common.Reference
}
}
func schema_pkg_apis_provisioning_v0alpha1_HelloWorld(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: "",
},
},
"whom": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
},
},
}
}
func schema_pkg_apis_provisioning_v0alpha1_LocalRepository(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
+62
View File
@@ -0,0 +1,62 @@
package provisioning
import (
"context"
"net/http"
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest"
)
type helloWorldSubresource struct{}
func (*helloWorldSubresource) New() runtime.Object {
// This is added as the "ResponseType" regardless what ProducesObject() returns
return &v0alpha1.HelloWorld{}
}
func (*helloWorldSubresource) Destroy() {}
func (*helloWorldSubresource) NamespaceScoped() bool {
return true
}
func (*helloWorldSubresource) GetSingularName() string {
return "HelloWorld"
}
func (*helloWorldSubresource) ProducesMIMETypes(verb string) []string {
return []string{"application/json"}
}
func (*helloWorldSubresource) ProducesObject(verb string) any {
return &v0alpha1.HelloWorld{}
}
func (*helloWorldSubresource) ConnectMethods() []string {
return []string{http.MethodGet}
}
func (*helloWorldSubresource) NewConnectOptions() (runtime.Object, bool, string) {
return nil, false, ""
}
func (*helloWorldSubresource) Connect(ctx context.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
whom := r.URL.Query().Get("whom")
if whom == "" {
whom = "World"
}
responder.Object(http.StatusTeapot, &v0alpha1.HelloWorld{Whom: whom})
}), nil
}
var (
_ rest.Storage = (*helloWorldSubresource)(nil)
_ rest.Connecter = (*helloWorldSubresource)(nil)
_ rest.Scoper = (*helloWorldSubresource)(nil)
_ rest.SingularNameProvider = (*helloWorldSubresource)(nil)
_ rest.StorageMetadata = (*helloWorldSubresource)(nil)
)
+21 -1
View File
@@ -15,6 +15,7 @@ import (
genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/kube-openapi/pkg/common"
"k8s.io/kube-openapi/pkg/spec3"
"k8s.io/kube-openapi/pkg/validation/spec"
)
var _ builder.APIGroupBuilder = (*ProvisioningAPIBuilder)(nil)
@@ -69,8 +70,11 @@ func (b *ProvisioningAPIBuilder) UpdateAPIGroupInfo(apiGroupInfo *genericapiserv
return fmt.Errorf("failed to create repository storage: %w", err)
}
helloWorld := &helloWorldSubresource{}
storage := map[string]rest.Storage{}
storage[v0alpha1.RepositoryResourceInfo.StoragePath()] = repositoryStorage
storage[v0alpha1.RepositoryResourceInfo.StoragePath("hello")] = helloWorld
apiGroupInfo.VersionedResourcesStorageMap[v0alpha1.VERSION] = storage
return nil
}
@@ -89,9 +93,25 @@ func (b *ProvisioningAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.
root := "/apis/" + b.GetGroupVersion().String() + "/"
// TODO: we might want to register some extras for subresources here.
sub := oas.Paths.Paths[root+"namespaces/{namespace}/repositories/{name}/hello"]
if sub != nil && sub.Get != nil {
sub.Get.Description = "Get a nice hello :)"
sub.Get.Parameters = []*spec3.Parameter{
{
ParameterProps: spec3.ParameterProps{
Name: "whom",
In: "query",
Example: "World!",
Description: "Who should get the nice greeting?",
Schema: spec.StringProperty(),
Required: false,
},
},
}
}
// The root API discovery list
sub := oas.Paths.Paths[root]
sub = oas.Paths.Paths[root]
if sub != nil && sub.Get != nil {
sub.Get.Tags = []string{"API Discovery"} // sorts first in the list
}