Skip to content

Commit

Permalink
Merge pull request #29 from kubevirt-bot/cherry-pick-27-to-release-v0.3
Browse files Browse the repository at this point in the history
[release-v0.3] fix: API discovery
  • Loading branch information
kubevirt-bot authored Aug 29, 2023
2 parents ed2602e + ff2c259 commit e160686
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 8 deletions.
83 changes: 75 additions & 8 deletions pkg/console/console.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,7 @@ func Run() error {
func webService(handlers service.Service) *restful.WebService {
ws := new(restful.WebService)

ws.Path("/apis/" + api.Group + "/" + api.Version)

ws.Route(ws.GET("/namespaces/{namespace:[a-z0-9][a-z0-9\\-]*}/virtualmachines/{name:[a-z0-9][a-z0-9\\-]*}/vnc").
ws.Route(ws.GET("/apis/" + api.Group + "/" + api.Version + "/namespaces/{namespace:[a-z0-9][a-z0-9\\-]*}/virtualmachines/{name:[a-z0-9][a-z0-9\\-]*}/vnc").
To(handlers.TokenHandler).
Doc("generate token").
Operation("token").
Expand All @@ -99,17 +97,86 @@ func webService(handlers service.Service) *restful.WebService {
Param(ws.QueryParameter("duration", "duration")))

// This endpoint is called by the API Server to get available resources.
// We can return an empty list here, it does not block the functionality.
ws.Route(ws.GET("/").
ws.Route(ws.GET("/apis/"+api.Group+"/"+api.Version).
Produces(restful.MIME_JSON).Writes(metav1.APIResourceList{}).
To(func(request *restful.Request, response *restful.Response) {
list := &metav1.APIResourceList{
TypeMeta: metav1.TypeMeta{
Kind: "APIResourceList",
Kind: "APIResourceList",
APIVersion: "v1",
},
APIResources: []metav1.APIResource{},
GroupVersion: api.Group + "/" + api.Version,
APIResources: []metav1.APIResource{{
Name: "virtualmachines/vnc",
Namespaced: true,
}},
}
response.WriteAsJson(list)
}))
}).
Operation("getAPIResources").
Doc("Get API resources").
Returns(http.StatusOK, "OK", metav1.APIResourceList{}).
Returns(http.StatusNotFound, "NotFound", ""))

gv := metav1.GroupVersionForDiscovery{
GroupVersion: api.Group + "/" + api.Version,
Version: api.Version,
}

apiGroup := metav1.APIGroup{
TypeMeta: metav1.TypeMeta{
Kind: "APIGroup",
APIVersion: "v1",
},
Name: api.Group,
Versions: []metav1.GroupVersionForDiscovery{gv},
PreferredVersion: gv,
}

// K8s needs the ability to query info about a specific API group
ws.Route(ws.GET("/apis/"+api.Group).
Produces(restful.MIME_JSON).Writes(metav1.APIGroup{}).
To(func(request *restful.Request, response *restful.Response) {
response.WriteAsJson(apiGroup)
}).
Operation("GetSubAPIGroup").
Doc("Get API Group").
Returns(http.StatusOK, "OK", metav1.APIGroup{}).
Returns(http.StatusNotFound, "NotFound", ""))

// K8s needs the ability to query the list of API groups this endpoint supports
ws.Route(ws.GET("apis").
Produces(restful.MIME_JSON).Writes(metav1.APIGroupList{}).
To(func(request *restful.Request, response *restful.Response) {
list := &metav1.APIGroupList{
TypeMeta: metav1.TypeMeta{
Kind: "APIGroupList",
APIVersion: "v1",
},
Groups: []metav1.APIGroup{apiGroup},
}
response.WriteAsJson(list)
}).
Operation("getAPIGroupList").
Doc("Get API GroupList").
Returns(http.StatusOK, "OK", metav1.APIGroupList{}).
Returns(http.StatusNotFound, "NotFound", ""))

// K8s needs the ability to query the root paths
ws.Route(ws.GET("/").
Produces(restful.MIME_JSON).Writes(metav1.RootPaths{}).
To(func(request *restful.Request, response *restful.Response) {
response.WriteAsJson(&metav1.RootPaths{
Paths: []string{
"/apis",
"/apis/" + api.Group,
"/apis/" + api.Group + "/" + api.Version,
},
})
}).
Operation("getRootPaths").
Doc("Get API root paths").
Returns(http.StatusOK, "OK", metav1.RootPaths{}))

return ws
}
36 changes: 36 additions & 0 deletions tests/api_extension_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package tests

import (
"context"
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var _ = Describe("API extension", func() {
// This test case checks fix for bug: https://issues.redhat.com/browse/CNV-32267
It("should be able to delete a namespace", func() {
testNamespace := &v1.Namespace{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "test-namespace-",
},
}

testNamespace, err := ApiClient.CoreV1().Namespaces().Create(context.TODO(), testNamespace, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())

Expect(ApiClient.CoreV1().Namespaces().Delete(context.TODO(), testNamespace.Name, metav1.DeleteOptions{})).To(Succeed())

// The namespace should be deleted
Eventually(func() metav1.StatusReason {
_, err := ApiClient.CoreV1().Namespaces().Get(context.TODO(), testNamespace.Name, metav1.GetOptions{})
return errors.ReasonForError(err)
}, time.Minute, time.Second).
Should(Equal(metav1.StatusReasonNotFound))
})
})

0 comments on commit e160686

Please sign in to comment.