Change:
It would be nice if let me explain experimental resources to aid users ability to experiment.
It's possible this works today, but it was non-obvious how to use. Attempts:
cc
cc
No, this isn't supported, since current implementation only use v1 Client but not experimental Client.
do we need to fix this for 1.1?
How difficult do you think it would be to fix?
It has dependency on ServerAPIVersions(), for which we plan to make a clean-up PR. I guess it needs 3-4 days to get two PRs merged.
With , this can be fixed now. What's the expected behavior of ? I assume in case of , it should search hpa in both v1 and extensions/v1bata1, and determines hpa as a resource in the extensions group? BTW, the use of "api-version" flag is problematic It adds extra meaning to the generic "api-version" flag.

Discussion:
"github.com/emicklei/go-restful/swagger" "k8s.io/kubernetes/pkg/api" <del> "k8s.io/kubernetes/pkg/api/latest" </del> "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/version" )

// SwaggerSchemaInterface has a method to retrieve the swagger schema. Used in // client.Interface type SwaggerSchemaInterface interface { <del> SwaggerSchema(version string) (*swagger.ApiDeclaration, error) </del> <ins> SwaggerSchema(groupVersion string) (*swagger.ApiDeclaration, error) </ins> } // SwaggerSchema retrieves and parses the swagger API schema the server supports. <del> func (c *Client) SwaggerSchema(version string) (*swagger.ApiDeclaration, error) { if version == "" { version = latest.GroupOrDie("").Version </del> <ins> func (c *Client) SwaggerSchema(groupVersion string) (*swagger.ApiDeclaration, error) { if groupVersion == "" { return nil, fmt.Errorf("groupVersion cannot be empty") </ins> } <del> vers, err := c.ServerAPIVersions() </del> <ins> groupList, err := c.Discovery().ServerGroups() </ins> if err != nil { return nil, err } <ins> groupVersions := extractGroupVersions(groupList) </ins> // This check also takes care the case that kubectl is newer than the running endpoint <del> 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) </del> <ins> if stringDoesntExistIn(groupVersion, groupVersions) { 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 </ins> } <del> body, err := c.Get().AbsPath("/swaggerapi/api/" + version).Do().Raw() </del> <ins> body, err := c.Get().AbsPath(path).Do().Raw() </ins> if err != nil { return nil, err }

"github.com/spf13/cobra" <ins> "k8s.io/kubernetes/pkg/api/latest" </ins> "k8s.io/kubernetes/pkg/kubectl" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" )

recursive := cmdutil.GetFlagBool(cmd, "recursive") apiV := cmdutil.GetFlagString(cmd, "api-version") <del> swagSchema, err := kubectl.GetSwaggerSchema(apiV, client) </del> <ins> mapper, _ := f.Object() group, inModel, fieldsPath, err := kubectl.SplitAndParseResourceRequest(args[0], mapper) </ins> if err != nil { return err } <del> mapper, _ := f.Object() inModel, fieldsPath, err := kubectl.SplitAndParseResourceRequest(args[0], mapper) </del> <ins> if len(group) == 0 { // 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) </ins> if err != nil { return err }

"github.com/emicklei/go-restful/swagger" "k8s.io/kubernetes/pkg/api/meta" <ins> apiutil "k8s.io/kubernetes/pkg/api/util" </ins> client "k8s.io/kubernetes/pkg/client/unversioned" )

} // SplitAndParseResourceRequest separates the users input into a model and fields <del> func SplitAndParseResourceRequest(inResource string, mapper meta.RESTMapper) (string, []string, error) { </del> <ins> func SplitAndParseResourceRequest(inResource string, mapper meta.RESTMapper) (string, string, []string, error) { </ins> inResource, fieldsPath := splitDotNotation(inResource) <ins> group, inResource := splitGroupFromResource(inResource) </ins> inResource, _ = mapper.ResourceSingularizer(expandResourceShortcut(inResource)) <del> return inResource, fieldsPath, nil </del> <ins> return group, inResource, fieldsPath, nil </ins> } // 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 { recursive = r // this is global for convenience <del> apiVer := swaggerSchema.ApiVersion + "." </del> <ins> apiVer := apiutil.GetVersion(swaggerSchema.ApiVersion) + "." </ins> var pointedModel *swagger.NamedModel for i := range swaggerSchema.Models.List {

} } if pointedModel == nil { <del> return fmt.Errorf("Requested resourse: %s doesn't exit", inModel) </del> <ins> return fmt.Errorf("Requested resource: %s doesn't exist", inModel) </ins> } if len(fieldsPath) == 0 {

return printModelInfo(w, pointedModel, pointedModelAsProp) } <ins> func splitGroupFromResource(resource string) (string, string) { seg := strings.SplitN(resource, "/", 2) if len(seg) == 1 { return "", seg[0] } else { return seg[0], seg[1] } } </ins> func splitDotNotation(model string) (string, []string) { var fieldsPath []string dotModel := strings.Split(model, ".")