OpenAPIResourcesGetter allows lazy-loading OpenAPI V2

This commit is contained in:
Sean Sullivan 2023-03-13 20:28:40 -07:00
parent b84e4a1333
commit 2eb06e79ef
2 changed files with 50 additions and 8 deletions

View File

@ -73,8 +73,8 @@ type ExplainOptions struct {
args []string
Mapper meta.RESTMapper
Schema openapi.Resources
Mapper meta.RESTMapper
openAPIGetter openapi.OpenAPIResourcesGetter
// Name of the template to use with the openapiv3 template renderer.
OutputFormat string
@ -123,17 +123,14 @@ func (o *ExplainOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
return err
}
o.Schema, err = f.OpenAPISchema()
if err != nil {
return err
}
// Only openapi v3 needs the discovery client.
o.OpenAPIV3Client, err = f.OpenAPIV3Client()
if err != nil {
return err
}
// Lazy-load the OpenAPI V2 Resources, so they're not loaded when using OpenAPI V3.
o.openAPIGetter = f
o.args = args
return nil
}
@ -224,7 +221,11 @@ func (o *ExplainOptions) renderOpenAPIV2(
gvk = apiVersion.WithKind(gvk.Kind)
}
schema := o.Schema.LookupResource(gvk)
resources, err := o.openAPIGetter.OpenAPISchema()
if err != nil {
return err
}
schema := resources.LookupResource(gvk)
if schema == nil {
return fmt.Errorf("couldn't find resource for %q", gvk)
}

View File

@ -275,3 +275,44 @@ func runExplainTestCases(t *testing.T, cases []explainTestCase) {
buf.Reset()
}
}
// OpenAPI V2 specifications retrieval -- should never be called.
func panicOpenAPISchemaFn() (openapi.Resources, error) {
panic("should never be called")
}
// OpenAPI V3 specifications retrieval does *not* retrieve V2 specifications.
func TestExplainOpenAPIV3DoesNotLoadOpenAPIV2Specs(t *testing.T) {
// Set up OpenAPI V3 specifications endpoint for explain.
fakeServer, err := clienttestutil.NewFakeOpenAPIV3Server(filepath.Join(testDataPath, "openapi", "v3"))
if err != nil {
t.Fatalf("error starting fake openapi server: %v", err.Error())
}
defer fakeServer.HttpServer.Close()
tf := cmdtesting.NewTestFactory()
defer tf.Cleanup()
tf.OpenAPIV3ClientFunc = func() (openapiclient.Client, error) {
fakeDiscoveryClient := discovery.NewDiscoveryClientForConfigOrDie(&rest.Config{Host: fakeServer.HttpServer.URL})
return fakeDiscoveryClient.OpenAPIV3(), nil
}
// OpenAPI V2 specifications retrieval will panic if called.
tf.OpenAPISchemaFunc = panicOpenAPISchemaFn
// Explain the following resources, validating the command does not panic.
cmd := explain.NewCmdExplain("kubectl", tf, genericiooptions.NewTestIOStreamsDiscard())
resources := []string{"pods", "services", "endpoints", "configmaps"}
for _, resource := range resources {
cmd.Run(cmd, []string{resource})
}
// Verify retrieving OpenAPI V2 specifications will panic.
defer func() {
if panicErr := recover(); panicErr == nil {
t.Fatal("expecting panic for openapi v2 retrieval")
}
}()
// Set OpenAPI V2 output flag for explain.
if err := cmd.Flags().Set("output", "plaintext-openapiv2"); err != nil {
t.Fatal(err)
}
cmd.Run(cmd, []string{"pods"})
}