Skip to content

Commit a7064b7

Browse files
author
Matt Rogers
committed
Use discovery based version gating for policy commands
1 parent 01d9694 commit a7064b7

File tree

5 files changed

+336
-46
lines changed

5 files changed

+336
-46
lines changed

pkg/cmd/server/admin/overwrite_bootstrappolicy.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,12 @@ func (o OverwriteBootstrapPolicyOptions) Validate(args []string) error {
100100
}
101101

102102
func (o OverwriteBootstrapPolicyOptions) Complete(f *clientcmd.Factory) error {
103-
oClient, _, err := f.Clients()
103+
_, kclient, err := f.Clients()
104104
if err != nil {
105105
return err
106106
}
107107

108-
return clientcmd.Gate(oClient, "", "3.7.0")
108+
return clientcmd.LegacyPolicyResourceGate(kclient.Discovery())
109109
}
110110

111111
func (o OverwriteBootstrapPolicyOptions) OverwriteBootstrapPolicy() error {

pkg/cmd/util/clientcmd/gating.go

Lines changed: 91 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,115 @@
11
package clientcmd
22

33
import (
4-
"encoding/json"
54
"fmt"
65

7-
"github.com/blang/semver"
6+
"k8s.io/apimachinery/pkg/api/errors"
7+
"k8s.io/apimachinery/pkg/runtime/schema"
8+
"k8s.io/client-go/discovery"
89

9-
"github.com/openshift/origin/pkg/client"
10-
"github.com/openshift/origin/pkg/version"
10+
"github.com/openshift/origin/pkg/authorization/apis/authorization"
1111
)
1212

13-
// Gate returns an error if the server is below minServerVersion or above/equal maxServerVersion.
14-
// To test only for min or only max version, set the other string to the empty value.
15-
func Gate(ocClient *client.Client, minServerVersion, maxServerVersion string) error {
16-
if len(minServerVersion) == 0 && len(maxServerVersion) == 0 {
17-
return fmt.Errorf("No version info passed to gate command")
18-
}
13+
// LegacyPolicyResourceGate returns err if the server does not support the set of legacy policy objects (< 3.7)
14+
func LegacyPolicyResourceGate(client discovery.DiscoveryInterface) error {
15+
// The server must support the 4 legacy policy objects in either of the GV schemes.
16+
_, all, err := DiscoverGroupVersionResources(client,
17+
schema.GroupVersionResource{
18+
Group: authorization.LegacySchemeGroupVersion.Group,
19+
Version: authorization.LegacySchemeGroupVersion.Version,
20+
Resource: "clusterpolicies",
21+
},
22+
schema.GroupVersionResource{
23+
Group: authorization.LegacySchemeGroupVersion.Group,
24+
Version: authorization.LegacySchemeGroupVersion.Version,
25+
Resource: "clusterpolicybindings",
26+
},
27+
schema.GroupVersionResource{
28+
Group: authorization.LegacySchemeGroupVersion.Group,
29+
Version: authorization.LegacySchemeGroupVersion.Version,
30+
Resource: "policies",
31+
},
32+
schema.GroupVersionResource{
33+
Group: authorization.LegacySchemeGroupVersion.Group,
34+
Version: authorization.LegacySchemeGroupVersion.Version,
35+
Resource: "policybindings",
36+
},
37+
)
1938

20-
ocVersionBody, err := ocClient.Get().AbsPath("/version/openshift").Do().Raw()
2139
if err != nil {
2240
return err
2341
}
24-
ocServerInfo := &version.Info{}
25-
if err := json.Unmarshal(ocVersionBody, ocServerInfo); err != nil {
26-
return err
42+
if all {
43+
return nil
2744
}
28-
ocVersion := ocServerInfo.String()
29-
// skip first chracter as Openshift returns a 'v' preceding the actual
30-
// version string which semver does not grok
31-
semVersion, err := semver.Parse(ocVersion[1:])
45+
_, all, err = DiscoverGroupVersionResources(client,
46+
schema.GroupVersionResource{
47+
Group: authorization.SchemeGroupVersion.Group,
48+
Version: authorization.SchemeGroupVersion.Version,
49+
Resource: "clusterpolicies",
50+
},
51+
schema.GroupVersionResource{
52+
Group: authorization.SchemeGroupVersion.Group,
53+
Version: authorization.SchemeGroupVersion.Version,
54+
Resource: "clusterpolicybindings",
55+
},
56+
schema.GroupVersionResource{
57+
Group: authorization.SchemeGroupVersion.Group,
58+
Version: authorization.SchemeGroupVersion.Version,
59+
Resource: "policies",
60+
},
61+
schema.GroupVersionResource{
62+
Group: authorization.SchemeGroupVersion.Group,
63+
Version: authorization.SchemeGroupVersion.Version,
64+
Resource: "policybindings",
65+
},
66+
)
67+
3268
if err != nil {
33-
return fmt.Errorf("Failed to parse server version %s: %v", ocVersion, err)
69+
return err
70+
}
71+
if all {
72+
return nil
3473
}
35-
// ignore pre-release version info
36-
semVersion.Pre = nil
3774

38-
if len(minServerVersion) > 0 {
39-
min, err := semver.Parse(minServerVersion)
40-
if err != nil {
41-
return fmt.Errorf("Failed to parse min gate version %s: %v", minServerVersion, err)
42-
}
43-
// ignore pre-release version info
44-
min.Pre = nil
45-
if semVersion.LT(min) {
46-
return fmt.Errorf("This command works only with server versions > %s, found %s", minServerVersion, ocVersion)
47-
}
75+
return fmt.Errorf("the server does not support legacy policy resources")
76+
}
77+
78+
// DiscoverGroupVersionResources performs a server resource discovery for each filterGVR, returning a slice of
79+
// GVRs for the matching Resources, and a bool for "all" indicating that each item in filterGVR was found.
80+
func DiscoverGroupVersionResources(client discovery.ServerResourcesInterface, filterGVR ...schema.GroupVersionResource) ([]schema.GroupVersionResource, bool, error) {
81+
if len(filterGVR) == 0 {
82+
return nil, false, fmt.Errorf("at least one GroupVersionResource must be provided")
4883
}
4984

50-
if len(maxServerVersion) > 0 {
51-
max, err := semver.Parse(maxServerVersion)
85+
all := true
86+
87+
// var cache map[schema.GroupVersion][]string TODO: possibly needed if not cached
88+
89+
ret := []schema.GroupVersionResource{}
90+
for i := range filterGVR {
91+
// Discover the list of resources for this GVR
92+
gv := filterGVR[i].GroupVersion()
93+
serverResources, err := client.ServerResourcesForGroupVersion(gv.String())
94+
if err != nil && errors.IsNotFound(err) {
95+
all = false
96+
continue
97+
}
5298
if err != nil {
53-
return fmt.Errorf("Failed to parse max gate version %s: %v", maxServerVersion, err)
99+
return nil, false, err
54100
}
55-
// ignore pre-release version info
56-
max.Pre = nil
57-
if semVersion.GTE(max) {
58-
return fmt.Errorf("This command works only with server versions < %s, found %s", maxServerVersion, ocVersion)
101+
102+
seen := false
103+
// Add matching resources to the return slice
104+
for _, resource := range serverResources.APIResources {
105+
if filterGVR[i].Resource == resource.Name {
106+
seen = true
107+
ret = append(ret, filterGVR[i])
108+
break
109+
}
59110
}
111+
all = all && seen
60112
}
61113

62-
// OK this is within min/max all good!
63-
return nil
114+
return ret, all, nil
64115
}

0 commit comments

Comments
 (0)