@@ -23,15 +23,20 @@ import (
2323"strings"
2424"testing"
2525
26+ "github.com/emicklei/go-restful/v3"
2627"github.com/stretchr/testify/assert"
2728
29+ "k8s.io/apimachinery/pkg/runtime"
2830"k8s.io/apiserver/pkg/endpoints/metrics"
31+ openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
2932genericapiserver "k8s.io/apiserver/pkg/server"
3033"k8s.io/apiserver/pkg/server/mux"
3134"k8s.io/component-base/metrics/legacyregistry"
3235"k8s.io/component-base/metrics/testutil"
3336v1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
37+ openapicommon "k8s.io/kube-openapi/pkg/common"
3438"k8s.io/kube-openapi/pkg/handler3"
39+ kubeopenapispec "k8s.io/kube-openapi/pkg/validation/spec"
3540)
3641
3742type testV3APIService struct {
@@ -170,6 +175,54 @@ func TestV3APIService(t *testing.T) {
170175assert .ElementsMatch (t , []string {openAPIV2Converter , apiService .Name }, apiServiceNames )
171176}
172177
178+ func TestV3RootAPIService (t * testing.T ) {
179+ ws := new (restful.WebService )
180+ {
181+ ws .Path ("/apis/apiregistration.k8s.io/v1" )
182+ ws .Doc ("API at/apis/apiregistration.k8s.io/v1 " )
183+ ws .Consumes ("*/*" )
184+ ws .Produces ("application/json" )
185+ ws .ApiVersion ("apiregistration.k8s.io/v1" )
186+ routeBuilder := ws .GET ("apiservices" ).
187+ To (func (request * restful.Request , response * restful.Response ) {}).
188+ Doc ("list or watch objects of kind APIService" ).
189+ Operation ("listAPIService" ).
190+ Produces ("application/json" ).
191+ Returns (http .StatusOK , "OK" , v1.APIService {}).
192+ Writes (v1.APIService {})
193+ ws .Route (routeBuilder )
194+ }
195+ openapiConfig := genericapiserver .DefaultOpenAPIV3Config (getTestAPIServiceOpenAPIDefinitions , openapinamer .NewDefinitionNamer (runtime .NewScheme ()))
196+
197+ downloader := Downloader {}
198+ goRestfulContainer := restful .NewContainer ()
199+ goRestfulContainer .Add (ws )
200+ pathHandler := mux .NewPathRecorderMux ("aggregator_test" )
201+ var serveHandler http.Handler = pathHandler
202+ specProxier , err := BuildAndRegisterAggregator (downloader , genericapiserver .NewEmptyDelegate (), goRestfulContainer , openapiConfig , pathHandler )
203+ if err != nil {
204+ t .Error (err )
205+ }
206+ expectedSpecJSON := []byte (`{"openapi":"3.0.0","info":{"title":"Generic API Server"},"paths":{"/apis/apiregistration.k8s.io/v1/apiservices":{"get":{"tags":["apiregistration_v1"],"description":"list or watch objects of kind APIService","operationId":"listApiregistrationV1APIService","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIService"}}}}}}}},"components":{"schemas":{"io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIService":{"description":"APIService represents a server for a particular GroupVersion. Name must be \"version.group\".","type":"object"}}}}` )
207+
208+ data := sendReq (t , serveHandler , "/openapi/v3" )
209+ groupVersionList := handler3.OpenAPIV3Discovery {}
210+ if err := json .Unmarshal (data , & groupVersionList ); err != nil {
211+ t .Fatal (err )
212+ }
213+ path , ok := groupVersionList .Paths ["apis/apiregistration.k8s.io/v1" ]
214+ if ! ok {
215+ t .Error ("Expected apiregistration.k8s.io/v1 to be in group version list" )
216+ }
217+ gotSpecJSON := sendReq (t , serveHandler , path .ServerRelativeURL )
218+ if bytes .Compare (gotSpecJSON , expectedSpecJSON ) != 0 {
219+ t .Errorf ("Spec mismatch, expected %s, got %s" , expectedSpecJSON , gotSpecJSON )
220+ }
221+
222+ apiServiceNames := specProxier .GetAPIServiceNames ()
223+ assert .ElementsMatch (t , []string {"k8s_internal_local_kube_aggregator_types" , openAPIV2Converter }, apiServiceNames )
224+ }
225+
173226func TestOpenAPIRequestMetrics (t * testing.T ) {
174227metrics .Register ()
175228metrics .Reset ()
@@ -239,3 +292,20 @@ func sendReq(t *testing.T, handler http.Handler, path string) []byte {
239292handler .ServeHTTP (writer , req )
240293return writer .data
241294}
295+
296+ func getTestAPIServiceOpenAPIDefinitions (_ openapicommon.ReferenceCallback ) map [string ]openapicommon.OpenAPIDefinition {
297+ return map [string ]openapicommon.OpenAPIDefinition {
298+ "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1.APIService" : buildTestAPIServiceOpenAPIDefinition (),
299+ }
300+ }
301+
302+ func buildTestAPIServiceOpenAPIDefinition () openapicommon.OpenAPIDefinition {
303+ return openapicommon.OpenAPIDefinition {
304+ Schema : kubeopenapispec.Schema {
305+ SchemaProps : kubeopenapispec.SchemaProps {
306+ Description : "APIService represents a server for a particular GroupVersion. Name must be \" version.group\" ." ,
307+ Type : []string {"object" },
308+ },
309+ },
310+ }
311+ }
0 commit comments