1
0
mirror of https://github.com/rancher/steve.git synced 2025-04-27 11:00:48 +00:00

Adding APIGroups back to the schema

Prior schema calculations started with openapiv2 models which included a
model for APIGroups. However, new schema calculations use
ServerGroupsAndResources first, which omitted these values. This
re-adds this type using a static schema.
This commit is contained in:
Michael Bolot 2024-07-02 13:27:04 -05:00
parent 9ac9be9c0e
commit e7a76d14f0
3 changed files with 84 additions and 27 deletions

View File

@ -7,10 +7,22 @@ import (
"github.com/rancher/apiserver/pkg/store/empty"
"github.com/rancher/apiserver/pkg/types"
wschemas "github.com/rancher/wrangler/v3/pkg/schemas"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/discovery"
)
var BaseSchema = types.APISchema{
Schema: &wschemas.Schema{
ID: "apigroup",
Attributes: map[string]interface{}{
"group": "",
"kind": "APIGroup",
"version": "v1",
},
},
}
func Template(discovery discovery.DiscoveryInterface) schema.Template {
return schema.Template{
ID: "apigroup",

View File

@ -8,6 +8,8 @@ import (
"github.com/rancher/apiserver/pkg/types"
"github.com/rancher/norman/types/convert"
"github.com/rancher/steve/pkg/attributes"
"github.com/rancher/steve/pkg/resources/apigroups"
v1 "github.com/rancher/wrangler/v3/pkg/generated/controllers/apiextensions.k8s.io/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/discovery"
@ -82,6 +84,8 @@ func GetGVKForKind(kind *proto.Kind) *schema.GroupVersionKind {
func ToSchemas(crd v1.CustomResourceDefinitionClient, client discovery.DiscoveryInterface) (map[string]*types.APISchema, error) {
result := map[string]*types.APISchema{}
addTemplateBased(result)
if err := addDiscovery(client, result); err != nil {
return nil, err
}
@ -96,3 +100,10 @@ func ToSchemas(crd v1.CustomResourceDefinitionClient, client discovery.Discovery
return result, nil
}
// some schemas are not based on real resources but are filled-in by a template later on. This function adds the base
// schema so that these endpoints are still recognizable in the api
func addTemplateBased(schemas map[string]*types.APISchema) {
apiGroupGVK := attributes.GVK(&apigroups.BaseSchema)
schemas[GVKToVersionedSchemaID(apiGroupGVK)] = &apigroups.BaseSchema
}

View File

@ -7,6 +7,7 @@ import (
"github.com/golang/mock/gomock"
openapiv2 "github.com/google/gnostic-models/openapiv2"
"github.com/rancher/apiserver/pkg/types"
"github.com/rancher/steve/pkg/resources/apigroups"
"github.com/rancher/steve/pkg/schema/table"
"github.com/rancher/wrangler/v3/pkg/generic/fake"
wranglerSchema "github.com/rancher/wrangler/v3/pkg/schemas"
@ -20,34 +21,51 @@ import (
)
func TestToSchemas(t *testing.T) {
gvkExtensionMap := map[any]any{
gvkExtensionGroup: "TestGroup",
gvkExtensionVersion: "v1",
gvkExtensionKind: "TestResource",
}
gvkExtensionSlice := []any{gvkExtensionMap}
extensionSliceYaml, err := yaml.Marshal(gvkExtensionSlice)
require.NoError(t, err)
gvkSchema := openapiv2.NamedSchema{
Name: "TestResources",
Value: &openapiv2.Schema{
Description: "TestResources are test resource created for unit tests",
Type: &openapiv2.TypeItem{
Value: []string{"object"},
},
Properties: &openapiv2.Properties{
AdditionalProperties: []*openapiv2.NamedSchema{},
},
VendorExtension: []*openapiv2.NamedAny{
{
Name: gvkExtensionName,
Value: &openapiv2.Any{
Yaml: string(extensionSliceYaml),
createNamedSchema := func(name string, description string, gvk schema.GroupVersionKind) (*openapiv2.NamedSchema, error) {
gvkExtensionMap := map[any]any{
gvkExtensionGroup: gvk.Group,
gvkExtensionVersion: gvk.Version,
gvkExtensionKind: gvk.Kind,
}
gvkExtensionSlice := []any{gvkExtensionMap}
extensionSliceYaml, err := yaml.Marshal(gvkExtensionSlice)
if err != nil {
return nil, fmt.Errorf("unable to create named schema for %s: %w", name, err)
}
return &openapiv2.NamedSchema{
Name: name,
Value: &openapiv2.Schema{
Description: description,
Type: &openapiv2.TypeItem{
Value: []string{"object"},
},
Properties: &openapiv2.Properties{
AdditionalProperties: []*openapiv2.NamedSchema{},
},
VendorExtension: []*openapiv2.NamedAny{
{
Name: gvkExtensionName,
Value: &openapiv2.Any{
Yaml: string(extensionSliceYaml),
},
},
},
},
},
}, nil
}
apiGroupDescription := "APIGroup contains the name, the supported versions, and the preferred version of a group"
gvkSchema, err := createNamedSchema("TestResources", "TestResources are test resource created for unit tests", schema.GroupVersionKind{
Group: "TestGroup",
Version: "v1",
Kind: "TestResource",
})
require.NoError(t, err)
apiGroupSchema, err := createNamedSchema("ApiGroups", apiGroupDescription, schema.GroupVersionKind{
Group: "",
Version: "v1",
Kind: "APIGroup",
})
require.NoError(t, err)
tests := []struct {
name string
groups []schema.GroupVersion
@ -160,6 +178,7 @@ func TestToSchemas(t *testing.T) {
Description: "Test Resource for unit tests",
},
},
"core.v1.apigroup": &apigroups.BaseSchema,
},
},
{
@ -194,6 +213,7 @@ func TestToSchemas(t *testing.T) {
},
},
},
"core.v1.apigroup": &apigroups.BaseSchema,
},
},
{
@ -260,8 +280,10 @@ func TestToSchemas(t *testing.T) {
},
},
},
wantError: false,
desiredSchema: map[string]*types.APISchema{},
wantError: false,
desiredSchema: map[string]*types.APISchema{
"core.v1.apigroup": &apigroups.BaseSchema,
},
},
{
name: "discovery error",
@ -305,6 +327,7 @@ func TestToSchemas(t *testing.T) {
},
},
},
"core.v1.apigroup": &apigroups.BaseSchema,
},
},
{
@ -326,7 +349,7 @@ func TestToSchemas(t *testing.T) {
crds: []v1.CustomResourceDefinition{},
document: &openapiv2.Document{
Definitions: &openapiv2.Definitions{
AdditionalProperties: []*openapiv2.NamedSchema{&gvkSchema},
AdditionalProperties: []*openapiv2.NamedSchema{gvkSchema, apiGroupSchema},
},
},
wantError: false,
@ -346,6 +369,17 @@ func TestToSchemas(t *testing.T) {
},
},
},
"core.v1.apigroup": {
Schema: &wranglerSchema.Schema{
ID: "apigroup",
Attributes: map[string]interface{}{
"group": "",
"kind": "APIGroup",
"version": "v1",
},
Description: apiGroupDescription,
},
},
},
},
{