Merge pull request #15808 from caesarxuchao/fix-kubectl-explain

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot 2015-10-21 07:04:32 -07:00
commit 071d21257f
3 changed files with 49 additions and 17 deletions

View File

@ -26,7 +26,6 @@ import (
"github.com/emicklei/go-restful/swagger" "github.com/emicklei/go-restful/swagger"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/latest"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/version" "k8s.io/kubernetes/pkg/version"
) )
@ -184,26 +183,32 @@ func (c *Client) ValidateComponents() (*api.ComponentStatusList, error) {
// SwaggerSchemaInterface has a method to retrieve the swagger schema. Used in // SwaggerSchemaInterface has a method to retrieve the swagger schema. Used in
// client.Interface // client.Interface
type SwaggerSchemaInterface interface { type SwaggerSchemaInterface interface {
SwaggerSchema(version string) (*swagger.ApiDeclaration, error) SwaggerSchema(groupVersion string) (*swagger.ApiDeclaration, error)
} }
// SwaggerSchema retrieves and parses the swagger API schema the server supports. // SwaggerSchema retrieves and parses the swagger API schema the server supports.
func (c *Client) SwaggerSchema(version string) (*swagger.ApiDeclaration, error) { func (c *Client) SwaggerSchema(groupVersion string) (*swagger.ApiDeclaration, error) {
if version == "" { if groupVersion == "" {
version = latest.GroupOrDie("").Version return nil, fmt.Errorf("groupVersion cannot be empty")
} }
vers, err := c.ServerAPIVersions() groupList, err := c.Discovery().ServerGroups()
if err != nil { if err != nil {
return nil, err return nil, err
} }
groupVersions := extractGroupVersions(groupList)
// This check also takes care the case that kubectl is newer than the running endpoint // This check also takes care the case that kubectl is newer than the running endpoint
if stringDoesntExistIn(version, vers.Versions) { if stringDoesntExistIn(groupVersion, groupVersions) {
return nil, fmt.Errorf("API version: %s is not supported by the server. Use one of: %v", version, vers.Versions) return nil, fmt.Errorf("API version: %s is not supported by the server. Use one of: %v", groupVersion, groupVersions)
}
var path string
if groupVersion == "v1" {
path = "/swaggerapi/api/" + groupVersion
} else {
path = "/swaggerapi/apis/" + groupVersion
} }
body, err := c.Get().AbsPath("/swaggerapi/api/" + version).Do().Raw() body, err := c.Get().AbsPath(path).Do().Raw()
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -21,6 +21,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/kubernetes/pkg/api/latest"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
) )
@ -70,13 +71,28 @@ func RunExplain(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st
recursive := cmdutil.GetFlagBool(cmd, "recursive") recursive := cmdutil.GetFlagBool(cmd, "recursive")
apiV := cmdutil.GetFlagString(cmd, "api-version") apiV := cmdutil.GetFlagString(cmd, "api-version")
swagSchema, err := kubectl.GetSwaggerSchema(apiV, client) mapper, _ := f.Object()
group, inModel, fieldsPath, err := kubectl.SplitAndParseResourceRequest(args[0], mapper)
if err != nil { if err != nil {
return err return err
} }
mapper, _ := f.Object() if len(group) == 0 {
inModel, fieldsPath, err := kubectl.SplitAndParseResourceRequest(args[0], mapper) // TODO: We should deduce the group for a resource by discovering the supported resources at server.
group, err = mapper.GroupForResource(inModel)
if err != nil {
return err
}
}
if len(apiV) == 0 {
groupMeta, err := latest.Group(group)
if err != nil {
return err
}
apiV = groupMeta.GroupVersion
}
swagSchema, err := kubectl.GetSwaggerSchema(apiV, client)
if err != nil { if err != nil {
return err return err
} }

View File

@ -24,6 +24,7 @@ import (
"github.com/emicklei/go-restful/swagger" "github.com/emicklei/go-restful/swagger"
"k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/meta"
apiutil "k8s.io/kubernetes/pkg/api/util"
client "k8s.io/kubernetes/pkg/client/unversioned" client "k8s.io/kubernetes/pkg/client/unversioned"
) )
@ -40,16 +41,17 @@ func GetSwaggerSchema(apiVer string, kubeClient client.Interface) (*swagger.ApiD
} }
// SplitAndParseResourceRequest separates the users input into a model and fields // SplitAndParseResourceRequest separates the users input into a model and fields
func SplitAndParseResourceRequest(inResource string, mapper meta.RESTMapper) (string, []string, error) { func SplitAndParseResourceRequest(inResource string, mapper meta.RESTMapper) (string, string, []string, error) {
inResource, fieldsPath := splitDotNotation(inResource) inResource, fieldsPath := splitDotNotation(inResource)
group, inResource := splitGroupFromResource(inResource)
inResource, _ = mapper.ResourceSingularizer(expandResourceShortcut(inResource)) inResource, _ = mapper.ResourceSingularizer(expandResourceShortcut(inResource))
return inResource, fieldsPath, nil return group, inResource, fieldsPath, nil
} }
// PrintModelDescription prints the description of a specific model or dot path // PrintModelDescription prints the description of a specific model or dot path
func PrintModelDescription(inModel string, fieldsPath []string, w io.Writer, swaggerSchema *swagger.ApiDeclaration, r bool) error { func PrintModelDescription(inModel string, fieldsPath []string, w io.Writer, swaggerSchema *swagger.ApiDeclaration, r bool) error {
recursive = r // this is global for convenience recursive = r // this is global for convenience
apiVer := swaggerSchema.ApiVersion + "." apiVer := apiutil.GetVersion(swaggerSchema.ApiVersion) + "."
var pointedModel *swagger.NamedModel var pointedModel *swagger.NamedModel
for i := range swaggerSchema.Models.List { for i := range swaggerSchema.Models.List {
@ -61,7 +63,7 @@ func PrintModelDescription(inModel string, fieldsPath []string, w io.Writer, swa
} }
} }
if pointedModel == nil { if pointedModel == nil {
return fmt.Errorf("Requested resourse: %s doesn't exit", inModel) return fmt.Errorf("Requested resource: %s doesn't exist", inModel)
} }
if len(fieldsPath) == 0 { if len(fieldsPath) == 0 {
@ -84,6 +86,15 @@ func PrintModelDescription(inModel string, fieldsPath []string, w io.Writer, swa
return printModelInfo(w, pointedModel, pointedModelAsProp) return printModelInfo(w, pointedModel, pointedModelAsProp)
} }
func splitGroupFromResource(resource string) (string, string) {
seg := strings.SplitN(resource, "/", 2)
if len(seg) == 1 {
return "", seg[0]
} else {
return seg[0], seg[1]
}
}
func splitDotNotation(model string) (string, []string) { func splitDotNotation(model string) (string, []string) {
var fieldsPath []string var fieldsPath []string
dotModel := strings.Split(model, ".") dotModel := strings.Split(model, ".")