Refactor to use openapi fake client

This commit is contained in:
Sean Sullivan 2023-02-14 18:00:08 -08:00
parent 3bf57e3ded
commit e352d94e45
2 changed files with 91 additions and 47 deletions

View File

@ -0,0 +1,79 @@
/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package openapitest
import (
"fmt"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/openapi"
)
// FakeClient implements openapi.Client interface, with hard-coded
// return values, including the possibility to force errors.
type FakeClient struct {
// Hard-coded paths to return from Paths() function.
PathsMap map[string]openapi.GroupVersion
// Hard-coded returned error.
ForcedErr error
}
// Validate FakeClient implements openapi.Client interface.
var _ openapi.Client = &FakeClient{}
// NewFakeClient returns a fake openapi client with an empty PathsMap.
func NewFakeClient() *FakeClient {
return &FakeClient{PathsMap: make(map[string]openapi.GroupVersion)}
}
// Paths returns stored PathsMap field, creating an empty one if
// it does not already exist. If ForcedErr is set, this function
// returns the error instead.
func (f FakeClient) Paths() (map[string]openapi.GroupVersion, error) {
if f.ForcedErr != nil {
return nil, f.ForcedErr
}
return f.PathsMap, nil
}
// FakeGroupVersion implements openapi.GroupVersion with hard-coded
// return GroupVersion specification bytes. If ForcedErr is set, then
// "Schema()" function returns the error instead of the GVSpec.
type FakeGroupVersion struct {
// Hard-coded GroupVersion specification
GVSpec []byte
// Hard-coded returned error.
ForcedErr error
}
// FileOpenAPIGroupVersion implements the openapi.GroupVersion interface.
var _ openapi.GroupVersion = &FakeGroupVersion{}
// Schema returns the hard-coded byte slice, including creating an
// empty slice if it has not been set yet. If the ForcedErr is set,
// this function returns the error instead of the GVSpec field. If
// content type other than application/json is passed, and error is
// returned.
func (f FakeGroupVersion) Schema(contentType string) ([]byte, error) {
if contentType != runtime.ContentTypeJSON {
return nil, fmt.Errorf("application/json is only content type supported: %s", contentType)
}
if f.ForcedErr != nil {
return nil, f.ForcedErr
}
return f.GVSpec, nil
}

View File

@ -24,7 +24,6 @@ import (
"github.com/stretchr/testify/require"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/openapi"
"k8s.io/client-go/openapi/openapitest"
)
@ -39,22 +38,24 @@ var apiGroupsGVR = schema.GroupVersionResource{
func TestExplainErrors(t *testing.T) {
var buf bytes.Buffer
// Validate error when "Paths()" returns error.
err := PrintModelDescription(nil, &buf, &forceErrorClient{}, apiGroupsGVR, false, "unknown-format")
require.ErrorContains(t, err, "failed to fetch list of groupVersions")
// Validate error when GVR is not found in returned paths map.
emptyClient := &emptyPathsClient{}
err = PrintModelDescription(nil, &buf, emptyClient, schema.GroupVersionResource{
fakeClient := openapitest.NewFakeClient()
err := PrintModelDescription(nil, &buf, fakeClient, schema.GroupVersionResource{
Group: "test0.example.com",
Version: "v1",
Resource: "doesntmatter",
}, false, "unknown-format")
require.ErrorContains(t, err, "could not locate schema")
// Validate error when openapi client returns error.
fakeClient.ForcedErr = fmt.Errorf("Always fails")
err = PrintModelDescription(nil, &buf, fakeClient, apiGroupsGVR, false, "unknown-format")
require.ErrorContains(t, err, "failed to fetch list of groupVersions")
// Validate error when GroupVersion "Schema()" call returns error.
fakeClient := &fakeOpenAPIClient{values: make(map[string]openapi.GroupVersion)}
fakeClient.values["apis/test1.example.com/v1"] = &forceErrorGV{}
fakeClient = openapitest.NewFakeClient()
forceErrorGV := openapitest.FakeGroupVersion{ForcedErr: fmt.Errorf("Always fails")}
fakeClient.PathsMap["apis/test1.example.com/v1"] = &forceErrorGV
err = PrintModelDescription(nil, &buf, fakeClient, schema.GroupVersionResource{
Group: "test1.example.com",
Version: "v1",
@ -63,7 +64,8 @@ func TestExplainErrors(t *testing.T) {
require.ErrorContains(t, err, "failed to fetch openapi schema ")
// Validate error when returned bytes from GroupVersion "Schema" are invalid.
fakeClient.values["apis/test2.example.com/v1"] = &parseErrorGV{}
parseErrorGV := openapitest.FakeGroupVersion{GVSpec: []byte(`<some invalid json!>`)}
fakeClient.PathsMap["apis/test2.example.com/v1"] = &parseErrorGV
err = PrintModelDescription(nil, &buf, fakeClient, schema.GroupVersionResource{
Group: "test2.example.com",
Version: "v1",
@ -113,40 +115,3 @@ func TestExplainOpenAPIClient(t *testing.T) {
require.NoError(t, err)
require.Equal(t, expectedContext, actualContext)
}
// forceErrorClient always returns an error for "Paths()".
type forceErrorClient struct{}
func (f *forceErrorClient) Paths() (map[string]openapi.GroupVersion, error) {
return nil, fmt.Errorf("Always fails")
}
// emptyPathsClient returns an empty map for "Paths()".
type emptyPathsClient struct{}
func (f *emptyPathsClient) Paths() (map[string]openapi.GroupVersion, error) {
return map[string]openapi.GroupVersion{}, nil
}
// fakeOpenAPIClient returns hard-coded map for "Paths()".
type fakeOpenAPIClient struct {
values map[string]openapi.GroupVersion
}
func (f *fakeOpenAPIClient) Paths() (map[string]openapi.GroupVersion, error) {
return f.values, nil
}
// forceErrorGV always returns an error for "Schema()".
type forceErrorGV struct{}
func (f *forceErrorGV) Schema(contentType string) ([]byte, error) {
return nil, fmt.Errorf("Always fails")
}
// parseErrorGV always returns invalid JSON for "Schema()".
type parseErrorGV struct{}
func (f *parseErrorGV) Schema(contentType string) ([]byte, error) {
return []byte(`<some invalid json!>`), nil
}