Add a method to clientcmd.Factory that enables retrieving a list of
valid resource names.
| ... | ... |
@@ -10,6 +10,7 @@ import ( |
| 10 | 10 |
kapi "k8s.io/kubernetes/pkg/api" |
| 11 | 11 |
"k8s.io/kubernetes/pkg/api/errors" |
| 12 | 12 |
"k8s.io/kubernetes/pkg/client/restclient" |
| 13 |
+ "k8s.io/kubernetes/pkg/client/typed/discovery" |
|
| 13 | 14 |
|
| 14 | 15 |
"github.com/openshift/origin/pkg/api/latest" |
| 15 | 16 |
"github.com/openshift/origin/pkg/version" |
| ... | ... |
@@ -283,6 +284,12 @@ func New(c *restclient.Config) (*Client, error) {
|
| 283 | 283 |
return &Client{client}, nil
|
| 284 | 284 |
} |
| 285 | 285 |
|
| 286 |
+// DiscoveryClient returns a discovery client. |
|
| 287 |
+func (c *Client) Discovery() discovery.DiscoveryInterface {
|
|
| 288 |
+ d := NewDiscoveryClient(c.RESTClient) |
|
| 289 |
+ return d |
|
| 290 |
+} |
|
| 291 |
+ |
|
| 286 | 292 |
// SetOpenShiftDefaults sets the default settings on the passed |
| 287 | 293 |
// client configuration |
| 288 | 294 |
func SetOpenShiftDefaults(config *restclient.Config) error {
|
| ... | ... |
@@ -41,9 +41,8 @@ func (d *DiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (r |
| 41 | 41 |
// ignore 403 or 404 error to be compatible with an v1.0 server. |
| 42 | 42 |
if groupVersion == "v1" && (errors.IsNotFound(err) || errors.IsForbidden(err)) {
|
| 43 | 43 |
return parentList, nil |
| 44 |
- } else {
|
|
| 45 |
- return nil, err |
|
| 46 | 44 |
} |
| 45 |
+ return nil, err |
|
| 47 | 46 |
} |
| 48 | 47 |
|
| 49 | 48 |
parentList.APIResources = append(parentList.APIResources, originResources.APIResources...) |
| ... | ... |
@@ -25,6 +25,7 @@ import ( |
| 25 | 25 |
"k8s.io/kubernetes/pkg/apis/batch" |
| 26 | 26 |
"k8s.io/kubernetes/pkg/apis/extensions" |
| 27 | 27 |
"k8s.io/kubernetes/pkg/client/restclient" |
| 28 |
+ "k8s.io/kubernetes/pkg/client/typed/discovery" |
|
| 28 | 29 |
kclient "k8s.io/kubernetes/pkg/client/unversioned" |
| 29 | 30 |
kclientcmd "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" |
| 30 | 31 |
kclientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" |
| ... | ... |
@@ -774,3 +775,57 @@ func (c *clientCache) ClientForVersion(version *unversioned.GroupVersion) (*clie |
| 774 | 774 |
c.clients[config.GroupVersion.String()] = client |
| 775 | 775 |
return client, nil |
| 776 | 776 |
} |
| 777 |
+ |
|
| 778 |
+// FindAllCanonicalResources returns all resource names that map directly to their kind (Kind -> Resource -> Kind) |
|
| 779 |
+// and are not subresources. This is the closest mapping possible from the client side to resources that can be |
|
| 780 |
+// listed and updated. Note that this may return some virtual resources (like imagestreamtags) that can be otherwise |
|
| 781 |
+// represented. |
|
| 782 |
+// TODO: add a field to APIResources for "virtual" (or that points to the canonical resource). |
|
| 783 |
+// TODO: fallback to the scheme when discovery is not possible. |
|
| 784 |
+func FindAllCanonicalResources(d discovery.DiscoveryInterface, m meta.RESTMapper) ([]unversioned.GroupResource, error) {
|
|
| 785 |
+ set := make(map[unversioned.GroupResource]struct{})
|
|
| 786 |
+ all, err := d.ServerResources() |
|
| 787 |
+ if err != nil {
|
|
| 788 |
+ return nil, err |
|
| 789 |
+ } |
|
| 790 |
+ for apiVersion, v := range all {
|
|
| 791 |
+ gv, err := unversioned.ParseGroupVersion(apiVersion) |
|
| 792 |
+ if err != nil {
|
|
| 793 |
+ continue |
|
| 794 |
+ } |
|
| 795 |
+ for _, r := range v.APIResources {
|
|
| 796 |
+ // ignore subresources |
|
| 797 |
+ if strings.Contains(r.Name, "/") {
|
|
| 798 |
+ continue |
|
| 799 |
+ } |
|
| 800 |
+ // because discovery info doesn't tell us whether the object is virtual or not, perform a lookup |
|
| 801 |
+ // by the kind for resource (which should be the canonical resource) and then verify that the reverse |
|
| 802 |
+ // lookup (KindsFor) does not error. |
|
| 803 |
+ if mapping, err := m.RESTMapping(unversioned.GroupKind{Group: gv.Group, Kind: r.Kind}, gv.Version); err == nil {
|
|
| 804 |
+ if _, err := m.KindsFor(mapping.GroupVersionKind.GroupVersion().WithResource(mapping.Resource)); err == nil {
|
|
| 805 |
+ set[unversioned.GroupResource{Group: mapping.GroupVersionKind.Group, Resource: mapping.Resource}] = struct{}{}
|
|
| 806 |
+ } |
|
| 807 |
+ } |
|
| 808 |
+ } |
|
| 809 |
+ } |
|
| 810 |
+ var groupResources []unversioned.GroupResource |
|
| 811 |
+ for k := range set {
|
|
| 812 |
+ groupResources = append(groupResources, k) |
|
| 813 |
+ } |
|
| 814 |
+ sort.Sort(groupResourcesByName(groupResources)) |
|
| 815 |
+ return groupResources, nil |
|
| 816 |
+} |
|
| 817 |
+ |
|
| 818 |
+type groupResourcesByName []unversioned.GroupResource |
|
| 819 |
+ |
|
| 820 |
+func (g groupResourcesByName) Len() int { return len(g) }
|
|
| 821 |
+func (g groupResourcesByName) Less(i, j int) bool {
|
|
| 822 |
+ if g[i].Resource < g[j].Resource {
|
|
| 823 |
+ return true |
|
| 824 |
+ } |
|
| 825 |
+ if g[i].Resource > g[j].Resource {
|
|
| 826 |
+ return false |
|
| 827 |
+ } |
|
| 828 |
+ return g[i].Group < g[j].Group |
|
| 829 |
+} |
|
| 830 |
+func (g groupResourcesByName) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|