apiextensions: merge OpenAPI specs once after cache sync

This commit is contained in:
Dr. Stefan Schimanski 2019-03-15 10:35:13 +01:00
parent d5a3db0039
commit a7f9ffd39f
2 changed files with 42 additions and 5 deletions

View File

@ -21,6 +21,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",

View File

@ -24,6 +24,7 @@ import (
"github.com/go-openapi/spec" "github.com/go-openapi/spec"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
utilruntime "k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/cache"
@ -89,6 +90,29 @@ func (c *Controller) Run(staticSpec *spec.Swagger, openAPIService *handler.OpenA
return return
} }
// create initial spec to avoid merging once per CRD on startup
crds, err := c.crdLister.List(labels.Everything())
if err != nil {
utilruntime.HandleError(fmt.Errorf("failed to initially list all CRDs: %v", err))
return
}
for _, crd := range crds {
if !apiextensions.IsCRDConditionTrue(crd, apiextensions.Established) {
continue
}
newSpecs, changed, err := buildVersionSpecs(crd, nil)
if err != nil {
utilruntime.HandleError(fmt.Errorf("failed to build OpenAPI spec of CRD %s: %v", crd.Name, err))
} else if !changed {
continue
}
c.crdSpecs[crd.Name] = newSpecs
}
if err := c.updateSpecLocked(); err != nil {
utilruntime.HandleError(fmt.Errorf("failed to initially create OpenAPI spec for CRDs: %v", err))
return
}
// only start one worker thread since its a slow moving API // only start one worker thread since its a slow moving API
go wait.Until(c.runWorker, time.Second, stopCh) go wait.Until(c.runWorker, time.Second, stopCh)
@ -147,6 +171,20 @@ func (c *Controller) sync(name string) error {
// compute CRD spec and see whether it changed // compute CRD spec and see whether it changed
oldSpecs := c.crdSpecs[crd.Name] oldSpecs := c.crdSpecs[crd.Name]
newSpecs, changed, err := buildVersionSpecs(crd, oldSpecs)
if err != nil {
return err
}
if !changed {
return nil
}
// update specs of this CRD
c.crdSpecs[crd.Name] = newSpecs
return c.updateSpecLocked()
}
func buildVersionSpecs(crd *apiextensions.CustomResourceDefinition, oldSpecs map[string]*spec.Swagger) (map[string]*spec.Swagger, bool, error) {
newSpecs := map[string]*spec.Swagger{} newSpecs := map[string]*spec.Swagger{}
anyChanged := false anyChanged := false
for _, v := range crd.Spec.Versions { for _, v := range crd.Spec.Versions {
@ -155,7 +193,7 @@ func (c *Controller) sync(name string) error {
} }
spec, err := BuildSwagger(crd, v.Name) spec, err := BuildSwagger(crd, v.Name)
if err != nil { if err != nil {
return err return nil, false, err
} }
newSpecs[v.Name] = spec newSpecs[v.Name] = spec
if oldSpecs[v.Name] == nil || !reflect.DeepEqual(oldSpecs[v.Name], spec) { if oldSpecs[v.Name] == nil || !reflect.DeepEqual(oldSpecs[v.Name], spec) {
@ -163,12 +201,10 @@ func (c *Controller) sync(name string) error {
} }
} }
if !anyChanged && len(oldSpecs) == len(newSpecs) { if !anyChanged && len(oldSpecs) == len(newSpecs) {
return nil return newSpecs, false, nil
} }
// update specs of this CRD return newSpecs, true, nil
c.crdSpecs[crd.Name] = newSpecs
return c.updateSpecLocked()
} }
// updateSpecLocked aggregates all OpenAPI specs and updates openAPIService. // updateSpecLocked aggregates all OpenAPI specs and updates openAPIService.