| ... | ... |
@@ -31,16 +31,6 @@ var originTypes map[unversioned.GroupVersionKind]bool |
| 31 | 31 |
// but that is not onerous |
| 32 | 32 |
var originTypesLock sync.Once |
| 33 | 33 |
|
| 34 |
-// UserResources are the resource names that apply to the primary, user facing resources used by |
|
| 35 |
-// client tools. They are in deletion-first order - dependent resources should be last. |
|
| 36 |
-var UserResources = []string{
|
|
| 37 |
- "buildConfigs", "builds", |
|
| 38 |
- "imageStreams", |
|
| 39 |
- "deploymentConfigs", "replicationControllers", |
|
| 40 |
- "routes", "services", |
|
| 41 |
- "pods", |
|
| 42 |
-} |
|
| 43 |
- |
|
| 44 | 34 |
// OriginKind returns true if OpenShift owns the GroupVersionKind. |
| 45 | 35 |
func OriginKind(gvk unversioned.GroupVersionKind) bool {
|
| 46 | 36 |
return getOrCreateOriginKinds()[gvk] |
| 47 | 37 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,73 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "net/url" |
|
| 4 |
+ |
|
| 5 |
+ "k8s.io/kubernetes/pkg/api/errors" |
|
| 6 |
+ "k8s.io/kubernetes/pkg/api/unversioned" |
|
| 7 |
+ kclient "k8s.io/kubernetes/pkg/client/unversioned" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// DiscoveryClient implements the functions that dicovery server-supported API groups, |
|
| 11 |
+// versions and resources. |
|
| 12 |
+type DiscoveryClient struct {
|
|
| 13 |
+ *kclient.DiscoveryClient |
|
| 14 |
+} |
|
| 15 |
+ |
|
| 16 |
+// ServerResourcesForGroupVersion returns the supported resources for a group and version. |
|
| 17 |
+func (d *DiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (resources *unversioned.APIResourceList, err error) {
|
|
| 18 |
+ // we don't expose this version |
|
| 19 |
+ if groupVersion == "v1beta3" {
|
|
| 20 |
+ return &unversioned.APIResourceList{}, nil
|
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ parentList, err := d.DiscoveryClient.ServerResourcesForGroupVersion(groupVersion) |
|
| 24 |
+ if err != nil {
|
|
| 25 |
+ return parentList, err |
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ if groupVersion != "v1" {
|
|
| 29 |
+ return parentList, nil |
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ // we request v1, we must combine the parent list with the list from /oapi |
|
| 33 |
+ |
|
| 34 |
+ url := url.URL{}
|
|
| 35 |
+ url.Path = "/oapi/" + groupVersion |
|
| 36 |
+ originResources := &unversioned.APIResourceList{}
|
|
| 37 |
+ err = d.Get().AbsPath(url.String()).Do().Into(originResources) |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ // ignore 403 or 404 error to be compatible with an v1.0 server. |
|
| 40 |
+ if groupVersion == "v1" && (errors.IsNotFound(err) || errors.IsForbidden(err)) {
|
|
| 41 |
+ return parentList, nil |
|
| 42 |
+ } else {
|
|
| 43 |
+ return nil, err |
|
| 44 |
+ } |
|
| 45 |
+ } |
|
| 46 |
+ |
|
| 47 |
+ parentList.APIResources = append(parentList.APIResources, originResources.APIResources...) |
|
| 48 |
+ return parentList, nil |
|
| 49 |
+} |
|
| 50 |
+ |
|
| 51 |
+// ServerResources returns the supported resources for all groups and versions. |
|
| 52 |
+func (d *DiscoveryClient) ServerResources() (map[string]*unversioned.APIResourceList, error) {
|
|
| 53 |
+ apiGroups, err := d.ServerGroups() |
|
| 54 |
+ if err != nil {
|
|
| 55 |
+ return nil, err |
|
| 56 |
+ } |
|
| 57 |
+ groupVersions := kclient.ExtractGroupVersions(apiGroups) |
|
| 58 |
+ result := map[string]*unversioned.APIResourceList{}
|
|
| 59 |
+ for _, groupVersion := range groupVersions {
|
|
| 60 |
+ resources, err := d.ServerResourcesForGroupVersion(groupVersion) |
|
| 61 |
+ if err != nil {
|
|
| 62 |
+ return nil, err |
|
| 63 |
+ } |
|
| 64 |
+ result[groupVersion] = resources |
|
| 65 |
+ } |
|
| 66 |
+ return result, nil |
|
| 67 |
+} |
|
| 68 |
+ |
|
| 69 |
+// New creates a new DiscoveryClient for the given RESTClient. |
|
| 70 |
+func NewDiscoveryClient(c *kclient.RESTClient) *DiscoveryClient {
|
|
| 71 |
+ return &DiscoveryClient{kclient.NewDiscoveryClient(c)}
|
|
| 72 |
+} |
| ... | ... |
@@ -167,7 +167,6 @@ func NewFactory(clientConfig kclientcmd.ClientConfig) *Factory {
|
| 167 | 167 |
} |
| 168 | 168 |
restMapper = meta.MultiRESTMapper(append(restMapper, groupMeta.RESTMapper)) |
| 169 | 169 |
} |
| 170 |
- mapper := ShortcutExpander{RESTMapper: kubectl.ShortcutExpander{RESTMapper: restMapper}}
|
|
| 171 | 170 |
|
| 172 | 171 |
clients := &clientCache{
|
| 173 | 172 |
clients: make(map[string]*client.Client), |
| ... | ... |
@@ -182,16 +181,30 @@ func NewFactory(clientConfig kclientcmd.ClientConfig) *Factory {
|
| 182 | 182 |
} |
| 183 | 183 |
|
| 184 | 184 |
w.Object = func() (meta.RESTMapper, runtime.ObjectTyper) {
|
| 185 |
+ |
|
| 186 |
+ defaultMapper := ShortcutExpander{RESTMapper: kubectl.ShortcutExpander{RESTMapper: restMapper}}
|
|
| 187 |
+ defaultTyper := api.Scheme |
|
| 188 |
+ |
|
| 185 | 189 |
// Output using whatever version was negotiated in the client cache. The |
| 186 | 190 |
// version we decode with may not be the same as what the server requires. |
| 187 |
- if cfg, err := clients.ClientConfigForVersion(nil); err == nil {
|
|
| 188 |
- cmdApiVersion := unversioned.GroupVersion{}
|
|
| 189 |
- if cfg.GroupVersion != nil {
|
|
| 190 |
- cmdApiVersion = *cfg.GroupVersion |
|
| 191 |
- } |
|
| 192 |
- return kubectl.OutputVersionMapper{RESTMapper: mapper, OutputVersions: []unversioned.GroupVersion{cmdApiVersion}}, api.Scheme
|
|
| 191 |
+ cfg, err := clients.ClientConfigForVersion(nil) |
|
| 192 |
+ if err != nil {
|
|
| 193 |
+ return defaultMapper, defaultTyper |
|
| 194 |
+ } |
|
| 195 |
+ |
|
| 196 |
+ cmdApiVersion := unversioned.GroupVersion{}
|
|
| 197 |
+ if cfg.GroupVersion != nil {
|
|
| 198 |
+ cmdApiVersion = *cfg.GroupVersion |
|
| 193 | 199 |
} |
| 194 |
- return mapper, api.Scheme |
|
| 200 |
+ |
|
| 201 |
+ // at this point we've negotiated and can get the client |
|
| 202 |
+ oclient, err := clients.ClientForVersion(nil) |
|
| 203 |
+ if err != nil {
|
|
| 204 |
+ return defaultMapper, defaultTyper |
|
| 205 |
+ } |
|
| 206 |
+ |
|
| 207 |
+ mapper := NewShortcutExpander(client.NewDiscoveryClient(oclient.RESTClient), kubectl.ShortcutExpander{RESTMapper: restMapper})
|
|
| 208 |
+ return kubectl.OutputVersionMapper{RESTMapper: mapper, OutputVersions: []unversioned.GroupVersion{cmdApiVersion}}, api.Scheme
|
|
| 195 | 209 |
} |
| 196 | 210 |
|
| 197 | 211 |
kClientForMapping := w.Factory.ClientForMapping |
| ... | ... |
@@ -581,76 +594,6 @@ func (f *Factory) OriginSwaggerSchema(client *kclient.RESTClient, version unvers |
| 581 | 581 |
return &schema, nil |
| 582 | 582 |
} |
| 583 | 583 |
|
| 584 |
-// ShortcutExpander is a RESTMapper that can be used for OpenShift resources. It expands the resource first, then invokes the wrapped |
|
| 585 |
-type ShortcutExpander struct {
|
|
| 586 |
- RESTMapper meta.RESTMapper |
|
| 587 |
-} |
|
| 588 |
- |
|
| 589 |
-var _ meta.RESTMapper = &ShortcutExpander{}
|
|
| 590 |
- |
|
| 591 |
-func (e ShortcutExpander) KindFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error) {
|
|
| 592 |
- return e.RESTMapper.KindFor(expandResourceShortcut(resource)) |
|
| 593 |
-} |
|
| 594 |
- |
|
| 595 |
-func (e ShortcutExpander) KindsFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionKind, error) {
|
|
| 596 |
- return e.RESTMapper.KindsFor(expandResourceShortcut(resource)) |
|
| 597 |
-} |
|
| 598 |
- |
|
| 599 |
-func (e ShortcutExpander) ResourcesFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error) {
|
|
| 600 |
- return e.RESTMapper.ResourcesFor(expandResourceShortcut(resource)) |
|
| 601 |
-} |
|
| 602 |
- |
|
| 603 |
-func (e ShortcutExpander) ResourceFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error) {
|
|
| 604 |
- return e.RESTMapper.ResourceFor(expandResourceShortcut(resource)) |
|
| 605 |
-} |
|
| 606 |
- |
|
| 607 |
-func (e ShortcutExpander) ResourceIsValid(resource unversioned.GroupVersionResource) bool {
|
|
| 608 |
- return e.RESTMapper.ResourceIsValid(expandResourceShortcut(resource)) |
|
| 609 |
-} |
|
| 610 |
- |
|
| 611 |
-func (e ShortcutExpander) ResourceSingularizer(resource string) (string, error) {
|
|
| 612 |
- return e.RESTMapper.ResourceSingularizer(expandResourceShortcut(unversioned.GroupVersionResource{Resource: resource}).Resource)
|
|
| 613 |
-} |
|
| 614 |
- |
|
| 615 |
-func (e ShortcutExpander) RESTMapping(gk unversioned.GroupKind, versions ...string) (*meta.RESTMapping, error) {
|
|
| 616 |
- return e.RESTMapper.RESTMapping(gk, versions...) |
|
| 617 |
-} |
|
| 618 |
- |
|
| 619 |
-// AliasesForResource returns whether a resource has an alias or not |
|
| 620 |
-func (e ShortcutExpander) AliasesForResource(resource string) ([]string, bool) {
|
|
| 621 |
- aliases := map[string][]string{
|
|
| 622 |
- "all": latest.UserResources, |
|
| 623 |
- } |
|
| 624 |
- |
|
| 625 |
- if res, ok := aliases[resource]; ok {
|
|
| 626 |
- return res, true |
|
| 627 |
- } |
|
| 628 |
- return e.RESTMapper.AliasesForResource(expandResourceShortcut(unversioned.GroupVersionResource{Resource: resource}).Resource)
|
|
| 629 |
-} |
|
| 630 |
- |
|
| 631 |
-// shortForms is the list of short names to their expanded names |
|
| 632 |
-var shortForms = map[string]string{
|
|
| 633 |
- "dc": "deploymentconfigs", |
|
| 634 |
- "bc": "buildconfigs", |
|
| 635 |
- "is": "imagestreams", |
|
| 636 |
- "istag": "imagestreamtags", |
|
| 637 |
- "isimage": "imagestreamimages", |
|
| 638 |
- "sa": "serviceaccounts", |
|
| 639 |
- "pv": "persistentvolumes", |
|
| 640 |
- "pvc": "persistentvolumeclaims", |
|
| 641 |
-} |
|
| 642 |
- |
|
| 643 |
-// expandResourceShortcut will return the expanded version of resource |
|
| 644 |
-// (something that a pkg/api/meta.RESTMapper can understand), if it is |
|
| 645 |
-// indeed a shortcut. Otherwise, will return resource unmodified. |
|
| 646 |
-func expandResourceShortcut(resource unversioned.GroupVersionResource) unversioned.GroupVersionResource {
|
|
| 647 |
- if expanded, ok := shortForms[resource.Resource]; ok {
|
|
| 648 |
- resource.Resource = expanded |
|
| 649 |
- return resource |
|
| 650 |
- } |
|
| 651 |
- return resource |
|
| 652 |
-} |
|
| 653 |
- |
|
| 654 | 584 |
// clientCache caches previously loaded clients for reuse. This is largely |
| 655 | 585 |
// copied from upstream (because of typing) but reuses the negotiation logic. |
| 656 | 586 |
// TODO: Consolidate this entire concept with upstream's ClientCache. |
| 657 | 587 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,126 @@ |
| 0 |
+package clientcmd |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "k8s.io/kubernetes/pkg/api/meta" |
|
| 4 |
+ "k8s.io/kubernetes/pkg/api/unversioned" |
|
| 5 |
+ kclient "k8s.io/kubernetes/pkg/client/unversioned" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+// ShortcutExpander is a RESTMapper that can be used for OpenShift resources. It expands the resource first, then invokes the wrapped |
|
| 9 |
+type ShortcutExpander struct {
|
|
| 10 |
+ RESTMapper meta.RESTMapper |
|
| 11 |
+ |
|
| 12 |
+ All []string |
|
| 13 |
+} |
|
| 14 |
+ |
|
| 15 |
+var _ meta.RESTMapper = &ShortcutExpander{}
|
|
| 16 |
+ |
|
| 17 |
+func NewShortcutExpander(discoveryClient kclient.DiscoveryInterface, delegate meta.RESTMapper) ShortcutExpander {
|
|
| 18 |
+ defaultMapper := ShortcutExpander{RESTMapper: delegate}
|
|
| 19 |
+ |
|
| 20 |
+ // this assumes that legacy kube versions and legacy origin versions are the same, probably fair |
|
| 21 |
+ apiResources, err := discoveryClient.ServerResources() |
|
| 22 |
+ if err != nil {
|
|
| 23 |
+ return defaultMapper |
|
| 24 |
+ } |
|
| 25 |
+ |
|
| 26 |
+ availableResources := []unversioned.GroupVersionResource{}
|
|
| 27 |
+ for groupVersionString, resourceList := range apiResources {
|
|
| 28 |
+ currVersion, err := unversioned.ParseGroupVersion(groupVersionString) |
|
| 29 |
+ if err != nil {
|
|
| 30 |
+ return defaultMapper |
|
| 31 |
+ } |
|
| 32 |
+ |
|
| 33 |
+ for _, resource := range resourceList.APIResources {
|
|
| 34 |
+ availableResources = append(availableResources, currVersion.WithResource(resource.Name)) |
|
| 35 |
+ } |
|
| 36 |
+ } |
|
| 37 |
+ |
|
| 38 |
+ availableAll := []string{}
|
|
| 39 |
+ for _, requestedResource := range userResources {
|
|
| 40 |
+ for _, availableResource := range availableResources {
|
|
| 41 |
+ if requestedResource == availableResource.Resource {
|
|
| 42 |
+ availableAll = append(availableAll, requestedResource) |
|
| 43 |
+ break |
|
| 44 |
+ } |
|
| 45 |
+ } |
|
| 46 |
+ } |
|
| 47 |
+ |
|
| 48 |
+ return ShortcutExpander{All: availableAll, RESTMapper: delegate}
|
|
| 49 |
+} |
|
| 50 |
+ |
|
| 51 |
+func (e ShortcutExpander) KindFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error) {
|
|
| 52 |
+ return e.RESTMapper.KindFor(expandResourceShortcut(resource)) |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+func (e ShortcutExpander) KindsFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionKind, error) {
|
|
| 56 |
+ return e.RESTMapper.KindsFor(expandResourceShortcut(resource)) |
|
| 57 |
+} |
|
| 58 |
+ |
|
| 59 |
+func (e ShortcutExpander) ResourcesFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error) {
|
|
| 60 |
+ return e.RESTMapper.ResourcesFor(expandResourceShortcut(resource)) |
|
| 61 |
+} |
|
| 62 |
+ |
|
| 63 |
+func (e ShortcutExpander) ResourceFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error) {
|
|
| 64 |
+ return e.RESTMapper.ResourceFor(expandResourceShortcut(resource)) |
|
| 65 |
+} |
|
| 66 |
+ |
|
| 67 |
+func (e ShortcutExpander) ResourceIsValid(resource unversioned.GroupVersionResource) bool {
|
|
| 68 |
+ return e.RESTMapper.ResourceIsValid(expandResourceShortcut(resource)) |
|
| 69 |
+} |
|
| 70 |
+ |
|
| 71 |
+func (e ShortcutExpander) ResourceSingularizer(resource string) (string, error) {
|
|
| 72 |
+ return e.RESTMapper.ResourceSingularizer(expandResourceShortcut(unversioned.GroupVersionResource{Resource: resource}).Resource)
|
|
| 73 |
+} |
|
| 74 |
+ |
|
| 75 |
+func (e ShortcutExpander) RESTMapping(gk unversioned.GroupKind, versions ...string) (*meta.RESTMapping, error) {
|
|
| 76 |
+ return e.RESTMapper.RESTMapping(gk, versions...) |
|
| 77 |
+} |
|
| 78 |
+ |
|
| 79 |
+// userResources are the resource names that apply to the primary, user facing resources used by |
|
| 80 |
+// client tools. They are in deletion-first order - dependent resources should be last. |
|
| 81 |
+var userResources = []string{
|
|
| 82 |
+ "buildconfigs", "builds", |
|
| 83 |
+ "imagestreams", |
|
| 84 |
+ "deploymentconfigs", "replicationcontrollers", |
|
| 85 |
+ "routes", "services", |
|
| 86 |
+ "pods", |
|
| 87 |
+} |
|
| 88 |
+ |
|
| 89 |
+// AliasesForResource returns whether a resource has an alias or not |
|
| 90 |
+func (e ShortcutExpander) AliasesForResource(resource string) ([]string, bool) {
|
|
| 91 |
+ aliases := map[string][]string{
|
|
| 92 |
+ "all": userResources, |
|
| 93 |
+ } |
|
| 94 |
+ if len(e.All) != 0 {
|
|
| 95 |
+ aliases["all"] = e.All |
|
| 96 |
+ } |
|
| 97 |
+ |
|
| 98 |
+ if res, ok := aliases[resource]; ok {
|
|
| 99 |
+ return res, true |
|
| 100 |
+ } |
|
| 101 |
+ return e.RESTMapper.AliasesForResource(expandResourceShortcut(unversioned.GroupVersionResource{Resource: resource}).Resource)
|
|
| 102 |
+} |
|
| 103 |
+ |
|
| 104 |
+// shortForms is the list of short names to their expanded names |
|
| 105 |
+var shortForms = map[string]string{
|
|
| 106 |
+ "dc": "deploymentconfigs", |
|
| 107 |
+ "bc": "buildconfigs", |
|
| 108 |
+ "is": "imagestreams", |
|
| 109 |
+ "istag": "imagestreamtags", |
|
| 110 |
+ "isimage": "imagestreamimages", |
|
| 111 |
+ "sa": "serviceaccounts", |
|
| 112 |
+ "pv": "persistentvolumes", |
|
| 113 |
+ "pvc": "persistentvolumeclaims", |
|
| 114 |
+} |
|
| 115 |
+ |
|
| 116 |
+// expandResourceShortcut will return the expanded version of resource |
|
| 117 |
+// (something that a pkg/api/meta.RESTMapper can understand), if it is |
|
| 118 |
+// indeed a shortcut. Otherwise, will return resource unmodified. |
|
| 119 |
+func expandResourceShortcut(resource unversioned.GroupVersionResource) unversioned.GroupVersionResource {
|
|
| 120 |
+ if expanded, ok := shortForms[resource.Resource]; ok {
|
|
| 121 |
+ resource.Resource = expanded |
|
| 122 |
+ return resource |
|
| 123 |
+ } |
|
| 124 |
+ return resource |
|
| 125 |
+} |
| ... | ... |
@@ -22,6 +22,7 @@ os::log::install_errexit |
| 22 | 22 |
|
| 23 | 23 |
os::cmd::expect_success_and_text 'oc types' 'Deployment Configuration' |
| 24 | 24 |
os::cmd::expect_failure_and_text 'oc get' 'deploymentconfig' |
| 25 |
+os::cmd::expect_success_and_text 'oc get all --loglevel=6' 'buildconfigs' |
|
| 25 | 26 |
os::cmd::expect_success_and_text 'oc explain pods' 'Pod is a collection of containers that can run on a host' |
| 26 | 27 |
os::cmd::expect_success_and_text 'oc explain pods.spec' 'SecurityContext holds pod-level security attributes' |
| 27 | 28 |
os::cmd::expect_success_and_text 'oc explain deploymentconfig' 'a desired deployment state' |
| 28 | 29 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,60 @@ |
| 0 |
+// +build integration |
|
| 1 |
+ |
|
| 2 |
+package integration |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "testing" |
|
| 6 |
+ |
|
| 7 |
+ "k8s.io/kubernetes/pkg/util/sets" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/openshift/origin/pkg/client" |
|
| 10 |
+ configapi "github.com/openshift/origin/pkg/cmd/server/api" |
|
| 11 |
+ "github.com/openshift/origin/pkg/cmd/util/clientcmd" |
|
| 12 |
+ testutil "github.com/openshift/origin/test/util" |
|
| 13 |
+ testserver "github.com/openshift/origin/test/util/server" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+func TestFullExpansion(t *testing.T) {
|
|
| 17 |
+ testutil.RequireEtcd(t) |
|
| 18 |
+ _, clusterAdminKubeConfig, err := testserver.StartTestMasterAPI() |
|
| 19 |
+ if err != nil {
|
|
| 20 |
+ t.Fatalf("unexpected error: %v", err)
|
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) |
|
| 24 |
+ if err != nil {
|
|
| 25 |
+ t.Fatalf("unexpected error: %v", err)
|
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ mapper := clientcmd.NewShortcutExpander(client.NewDiscoveryClient(clusterAdminClient.RESTClient), nil) |
|
| 29 |
+ |
|
| 30 |
+ if !sets.NewString(mapper.All...).Has("buildconfigs") {
|
|
| 31 |
+ t.Errorf("expected buildconfigs, got: %v", mapper.All)
|
|
| 32 |
+ } |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+func TestExpansionWithoutBuilds(t *testing.T) {
|
|
| 36 |
+ testutil.RequireEtcd(t) |
|
| 37 |
+ |
|
| 38 |
+ masterConfig, err := testserver.DefaultMasterOptions() |
|
| 39 |
+ if err != nil {
|
|
| 40 |
+ t.Fatalf("unexpected error: %v", err)
|
|
| 41 |
+ } |
|
| 42 |
+ |
|
| 43 |
+ masterConfig.DisabledFeatures = configapi.AtomicDisabledFeatures |
|
| 44 |
+ clusterAdminKubeConfig, err := testserver.StartConfiguredMasterAPI(masterConfig) |
|
| 45 |
+ if err != nil {
|
|
| 46 |
+ t.Fatalf("unexpected error: %v", err)
|
|
| 47 |
+ } |
|
| 48 |
+ |
|
| 49 |
+ clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) |
|
| 50 |
+ if err != nil {
|
|
| 51 |
+ t.Fatalf("unexpected error: %v", err)
|
|
| 52 |
+ } |
|
| 53 |
+ |
|
| 54 |
+ mapper := clientcmd.NewShortcutExpander(client.NewDiscoveryClient(clusterAdminClient.RESTClient), nil) |
|
| 55 |
+ |
|
| 56 |
+ if sets.NewString(mapper.All...).Has("buildconfigs") {
|
|
| 57 |
+ t.Errorf("expected no buildconfigs, got: %v", mapper.All)
|
|
| 58 |
+ } |
|
| 59 |
+} |