Skip to content

Commit 0b48018

Browse files
authored
Merge pull request kubernetes#71192 from roycaihw/crd-publish-openapi
Publish CRD openapi
2 parents bf4e93d + 54b9941 commit 0b48018

File tree

22 files changed

+1680
-26
lines changed

22 files changed

+1680
-26
lines changed

build/root/Makefile.generated_files

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,10 @@ $(CONVERSION_GEN): $(k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/conversi
409409
OPENAPI_BASENAME := $(GENERATED_FILE_PREFIX)openapi
410410
OPENAPI_FILENAME := $(OPENAPI_BASENAME).go
411411
OPENAPI_OUTPUT_PKG := pkg/generated/openapi
412+
CRD_OPENAPI_OUTPUT_PKG := staging/src/k8s.io/apiextensions-apiserver/pkg/generated/openapi
412413
BOILERPLATE_FILENAME := vendor/k8s.io/code-generator/hack/boilerplate.go.txt
413414
REPORT_FILENAME := $(OUT_DIR)/violations.report
415+
IGNORED_REPORT_FILENAME := $(OUT_DIR)/ignored_violations.report
414416
KNOWN_VIOLATION_FILENAME := api/api-rules/violation_exceptions.list
415417
# When UPDATE_API_KNOWN_VIOLATIONS is set to be true, let the generator to write
416418
# updated API violations to the known API violation exceptions list.
@@ -436,10 +438,11 @@ OPENAPI_DIRS := $(shell \
436438
)
437439

438440
OPENAPI_OUTFILE := $(OPENAPI_OUTPUT_PKG)/$(OPENAPI_FILENAME)
441+
CRD_OPENAPI_OUTFILE := $(CRD_OPENAPI_OUTPUT_PKG)/$(OPENAPI_FILENAME)
439442

440443
# This rule is the user-friendly entrypoint for openapi generation.
441444
.PHONY: gen_openapi
442-
gen_openapi: $(OPENAPI_OUTFILE) $(OPENAPI_GEN)
445+
gen_openapi: $(OPENAPI_OUTFILE) $(OPENAPI_GEN) $(CRD_OPENAPI_OUTFILE)
443446

444447
# For each dir in OPENAPI_DIRS, this establishes a dependency between the
445448
# output file and the input files that should trigger a rebuild.
@@ -469,6 +472,17 @@ $(OPENAPI_OUTFILE): $(OPENAPI_GEN) $(KNOWN_VIOLATION_FILENAME)
469472
diff $(REPORT_FILENAME) $(KNOWN_VIOLATION_FILENAME) || \
470473
(echo -e $(API_RULE_CHECK_FAILURE_MESSAGE); exit 1)
471474

475+
# TODO(roycaihw): move the automation to apiextensions-apiserver
476+
$(CRD_OPENAPI_OUTFILE): $(OPENAPI_GEN)
477+
./hack/run-in-gopath.sh $(OPENAPI_GEN) \
478+
--v $(KUBE_VERBOSE) \
479+
--logtostderr \
480+
-i "k8s.io/apimachinery/pkg/apis/meta/v1,k8s.io/api/autoscaling/v1" \
481+
-p $(PRJ_SRC_PATH)/$(CRD_OPENAPI_OUTPUT_PKG) \
482+
-O $(OPENAPI_BASENAME) \
483+
-h $(BOILERPLATE_FILENAME) \
484+
-r $(IGNORED_REPORT_FILENAME) \
485+
"$$@"
472486

473487
# How to build the generator tool. The deps for this are defined in
474488
# the $(GO_PKGDEPS_FILE), above.

pkg/features/kube_features.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
510510
apiextensionsfeatures.CustomResourceValidation: {Default: true, PreRelease: utilfeature.Beta},
511511
apiextensionsfeatures.CustomResourceSubresources: {Default: true, PreRelease: utilfeature.Beta},
512512
apiextensionsfeatures.CustomResourceWebhookConversion: {Default: false, PreRelease: utilfeature.Alpha},
513+
apiextensionsfeatures.CustomResourcePublishOpenAPI: {Default: false, PreRelease: utilfeature.Alpha},
513514

514515
// features that enable backwards compatibility but are scheduled to be removed
515516
// ...

staging/src/k8s.io/apiextensions-apiserver/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ filegroup(
5151
"//staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status:all-srcs",
5252
"//staging/src/k8s.io/apiextensions-apiserver/pkg/crdserverscheme:all-srcs",
5353
"//staging/src/k8s.io/apiextensions-apiserver/pkg/features:all-srcs",
54+
"//staging/src/k8s.io/apiextensions-apiserver/pkg/generated/openapi:all-srcs",
5455
"//staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource:all-srcs",
5556
"//staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition:all-srcs",
5657
"//staging/src/k8s.io/apiextensions-apiserver/test/integration:all-srcs",

staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ go_library(
3232
"//staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion:go_default_library",
3333
"//staging/src/k8s.io/apiextensions-apiserver/pkg/controller/establish:go_default_library",
3434
"//staging/src/k8s.io/apiextensions-apiserver/pkg/controller/finalizer:go_default_library",
35+
"//staging/src/k8s.io/apiextensions-apiserver/pkg/controller/openapi:go_default_library",
3536
"//staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status:go_default_library",
3637
"//staging/src/k8s.io/apiextensions-apiserver/pkg/crdserverscheme:go_default_library",
3738
"//staging/src/k8s.io/apiextensions-apiserver/pkg/features:go_default_library",

staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ import (
3131
internalinformers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion"
3232
"k8s.io/apiextensions-apiserver/pkg/controller/establish"
3333
"k8s.io/apiextensions-apiserver/pkg/controller/finalizer"
34+
openapicontroller "k8s.io/apiextensions-apiserver/pkg/controller/openapi"
3435
"k8s.io/apiextensions-apiserver/pkg/controller/status"
36+
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
3537
"k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition"
3638
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3739
"k8s.io/apimachinery/pkg/runtime"
@@ -44,6 +46,7 @@ import (
4446
"k8s.io/apiserver/pkg/registry/rest"
4547
genericapiserver "k8s.io/apiserver/pkg/server"
4648
serverstorage "k8s.io/apiserver/pkg/server/storage"
49+
utilfeature "k8s.io/apiserver/pkg/util/feature"
4750
"k8s.io/apiserver/pkg/util/webhook"
4851
)
4952

@@ -198,12 +201,20 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget)
198201
crdClient.Apiextensions(),
199202
crdHandler,
200203
)
204+
var openapiController *openapicontroller.Controller
205+
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourcePublishOpenAPI) {
206+
openapiController = openapicontroller.NewController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions())
207+
}
201208

202209
s.GenericAPIServer.AddPostStartHookOrDie("start-apiextensions-informers", func(context genericapiserver.PostStartHookContext) error {
203210
s.Informers.Start(context.StopCh)
204211
return nil
205212
})
206213
s.GenericAPIServer.AddPostStartHookOrDie("start-apiextensions-controllers", func(context genericapiserver.PostStartHookContext) error {
214+
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourcePublishOpenAPI) {
215+
go openapiController.Run(s.GenericAPIServer.StaticOpenAPISpec, s.GenericAPIServer.OpenAPIVersionedService, context.StopCh)
216+
}
217+
207218
go crdController.Run(context.StopCh)
208219
go namingController.Run(context.StopCh)
209220
go establishingController.Run(context.StopCh)

staging/src/k8s.io/apiextensions-apiserver/pkg/controller/openapi/BUILD

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,55 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
22

33
go_library(
44
name = "go_default_library",
5-
srcs = ["conversion.go"],
5+
srcs = [
6+
"aggregator.go",
7+
"builder.go",
8+
"controller.go",
9+
"conversion.go",
10+
],
611
importmap = "k8s.io/kubernetes/vendor/k8s.io/apiextensions-apiserver/pkg/controller/openapi",
712
importpath = "k8s.io/apiextensions-apiserver/pkg/controller/openapi",
813
visibility = ["//visibility:public"],
914
deps = [
15+
"//staging/src/k8s.io/api/autoscaling/v1:go_default_library",
1016
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library",
1117
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation:go_default_library",
18+
"//staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion:go_default_library",
19+
"//staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion:go_default_library",
20+
"//staging/src/k8s.io/apiextensions-apiserver/pkg/generated/openapi:go_default_library",
21+
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
22+
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
23+
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
24+
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
25+
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
26+
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
27+
"//staging/src/k8s.io/apiserver/pkg/endpoints:go_default_library",
28+
"//staging/src/k8s.io/apiserver/pkg/endpoints/openapi:go_default_library",
29+
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
30+
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
31+
"//vendor/github.com/emicklei/go-restful:go_default_library",
1232
"//vendor/github.com/go-openapi/spec:go_default_library",
33+
"//vendor/k8s.io/klog:go_default_library",
34+
"//vendor/k8s.io/kube-openapi/pkg/builder:go_default_library",
35+
"//vendor/k8s.io/kube-openapi/pkg/common:go_default_library",
36+
"//vendor/k8s.io/kube-openapi/pkg/handler:go_default_library",
37+
"//vendor/k8s.io/kube-openapi/pkg/util:go_default_library",
1338
],
1439
)
1540

1641
go_test(
1742
name = "go_default_test",
18-
srcs = ["conversion_test.go"],
43+
srcs = [
44+
"builder_test.go",
45+
"conversion_test.go",
46+
],
1947
embed = [":go_default_library"],
2048
deps = [
2149
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library",
2250
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
2351
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
52+
"//staging/src/k8s.io/apimachinery/pkg/util/json:go_default_library",
53+
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
2454
"//vendor/github.com/go-openapi/spec:go_default_library",
2555
"//vendor/github.com/google/gofuzz:go_default_library",
2656
"//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library",
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package openapi
18+
19+
import (
20+
"github.com/go-openapi/spec"
21+
)
22+
23+
// mergeSpecs aggregates all OpenAPI specs, reusing the metadata of the first, static spec as the basis.
24+
func mergeSpecs(staticSpec *spec.Swagger, crdSpecs ...*spec.Swagger) *spec.Swagger {
25+
// create shallow copy of staticSpec, but replace paths and definitions because we modify them.
26+
specToReturn := *staticSpec
27+
if staticSpec.Definitions != nil {
28+
specToReturn.Definitions = spec.Definitions{}
29+
for k, s := range staticSpec.Definitions {
30+
specToReturn.Definitions[k] = s
31+
}
32+
}
33+
if staticSpec.Paths != nil {
34+
specToReturn.Paths = &spec.Paths{
35+
Paths: map[string]spec.PathItem{},
36+
}
37+
for k, p := range staticSpec.Paths.Paths {
38+
specToReturn.Paths.Paths[k] = p
39+
}
40+
}
41+
42+
for _, s := range crdSpecs {
43+
mergeSpec(&specToReturn, s)
44+
}
45+
46+
return &specToReturn
47+
}
48+
49+
// mergeSpec copies paths and definitions from source to dest, mutating dest, but not source.
50+
// We assume that conflicts do not matter.
51+
func mergeSpec(dest, source *spec.Swagger) {
52+
if source == nil || source.Paths == nil {
53+
return
54+
}
55+
if dest.Paths == nil {
56+
dest.Paths = &spec.Paths{}
57+
}
58+
for k, v := range source.Definitions {
59+
if dest.Definitions == nil {
60+
dest.Definitions = spec.Definitions{}
61+
}
62+
dest.Definitions[k] = v
63+
}
64+
for k, v := range source.Paths.Paths {
65+
if dest.Paths.Paths == nil {
66+
dest.Paths.Paths = map[string]spec.PathItem{}
67+
}
68+
dest.Paths.Paths[k] = v
69+
}
70+
}

0 commit comments

Comments
 (0)