mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
client can return swagger schema
This commit is contained in:
parent
d49ca164ef
commit
495433fbb7
@ -23,7 +23,10 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/emicklei/go-restful/swagger"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/latest"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/version"
|
||||
)
|
||||
@ -47,6 +50,7 @@ type Interface interface {
|
||||
PersistentVolumesInterface
|
||||
PersistentVolumeClaimsNamespacer
|
||||
ComponentStatusesInterface
|
||||
SwaggerSchemaInterface
|
||||
Experimental() ExperimentalInterface
|
||||
}
|
||||
|
||||
@ -174,6 +178,49 @@ func (c *Client) ValidateComponents() (*api.ComponentStatusList, error) {
|
||||
return &api.ComponentStatusList{Items: statuses}, nil
|
||||
}
|
||||
|
||||
// SwaggerSchemaInterface has a method to retrieve the swagger schema. Used in
|
||||
// client.Interface
|
||||
type SwaggerSchemaInterface interface {
|
||||
SwaggerSchema(version string) (*swagger.ApiDeclaration, error)
|
||||
}
|
||||
|
||||
// SwaggerSchema retrieves and parses the swagger API schema the server supports.
|
||||
func (c *Client) SwaggerSchema(version string) (*swagger.ApiDeclaration, error) {
|
||||
if version == "" {
|
||||
version = latest.GroupOrDie("").Version
|
||||
}
|
||||
|
||||
vers, err := c.ServerAPIVersions()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// This check also takes care the case that kubectl is newer than the running endpoint
|
||||
if stringDoesntExistIn(version, vers.Versions) {
|
||||
return nil, fmt.Errorf("API version: %s is not supported by the server. Use one of: %v", version, vers.Versions)
|
||||
}
|
||||
|
||||
body, err := c.Get().AbsPath("/swaggerapi/api/" + version).Do().Raw()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var schema swagger.ApiDeclaration
|
||||
err = json.Unmarshal(body, &schema)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("got '%s': %v", string(body), err)
|
||||
}
|
||||
return &schema, nil
|
||||
}
|
||||
|
||||
func stringDoesntExistIn(str string, slice []string) bool {
|
||||
for _, s := range slice {
|
||||
if s == str {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsTimeout tests if this is a timeout error in the underlying transport.
|
||||
// This is unbelievably ugly.
|
||||
// See: http://stackoverflow.com/questions/23494950/specifically-check-for-timeout-error for details
|
||||
|
@ -26,6 +26,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/emicklei/go-restful/swagger"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
@ -290,3 +292,63 @@ func TestGetServerAPIVersions(t *testing.T) {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
}
|
||||
|
||||
func swaggerSchemaFakeServer() (*httptest.Server, error) {
|
||||
request := 1
|
||||
var sErr error
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
var resp interface{}
|
||||
if request == 1 {
|
||||
resp = api.APIVersions{Versions: []string{"v1", "v2", "v3"}}
|
||||
request++
|
||||
} else {
|
||||
resp = swagger.ApiDeclaration{}
|
||||
}
|
||||
output, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
sErr = err
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(output)
|
||||
}))
|
||||
return server, sErr
|
||||
}
|
||||
|
||||
func TestGetSwaggerSchema(t *testing.T) {
|
||||
expect := swagger.ApiDeclaration{}
|
||||
|
||||
server, err := swaggerSchemaFakeServer()
|
||||
if err != nil {
|
||||
t.Errorf("unexpected encoding error: %v", err)
|
||||
}
|
||||
|
||||
client := NewOrDie(&Config{Host: server.URL})
|
||||
got, err := client.SwaggerSchema("v1")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected encoding error: %v", err)
|
||||
}
|
||||
if e, a := expect, *got; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSwaggerSchemaFail(t *testing.T) {
|
||||
expErr := "API version: v4 is not supported by the server. Use one of: [v1 v2 v3]"
|
||||
|
||||
server, err := swaggerSchemaFakeServer()
|
||||
if err != nil {
|
||||
t.Errorf("unexpected encoding error: %v", err)
|
||||
}
|
||||
|
||||
client := NewOrDie(&Config{Host: server.URL})
|
||||
got, err := client.SwaggerSchema("v4")
|
||||
if got != nil {
|
||||
t.Fatalf("unexpected response: %v", got)
|
||||
}
|
||||
if err.Error() != expErr {
|
||||
t.Errorf("expected an error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/emicklei/go-restful/swagger"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/registered"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
@ -282,6 +284,16 @@ func (c *Fake) ComponentStatuses() client.ComponentStatusInterface {
|
||||
return &FakeComponentStatuses{Fake: c}
|
||||
}
|
||||
|
||||
// SwaggerSchema returns an empty swagger.ApiDeclaration for testing
|
||||
func (c *Fake) SwaggerSchema(version string) (*swagger.ApiDeclaration, error) {
|
||||
action := ActionImpl{}
|
||||
action.Verb = "get"
|
||||
action.Resource = "/swaggerapi/api/" + version
|
||||
|
||||
c.Invokes(action, nil)
|
||||
return &swagger.ApiDeclaration{}, nil
|
||||
}
|
||||
|
||||
type FakeExperimental struct {
|
||||
*Fake
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user