Skip to content

Commit 60c41a9

Browse files
committed
add oc adm prune role command to replace the existing reapear
1 parent 166c2e9 commit 60c41a9

File tree

8 files changed

+185
-52
lines changed

8 files changed

+185
-52
lines changed

pkg/authorization/reaper/role.go

-47
This file was deleted.

pkg/authorization/reaper/cluster_role.go pkg/oc/admin/prune/authorizationreaper/cluster_role.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package reaper
1+
package authorizationreaper
22

33
import (
44
"time"

pkg/authorization/reaper/cluster_role_test.go pkg/oc/admin/prune/authorizationreaper/cluster_role_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package reaper
1+
package authorizationreaper
22

33
import (
44
"reflect"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package authorizationreaper
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"io/ioutil"
7+
"time"
8+
9+
"github.com/golang/glog"
10+
kerrors "k8s.io/apimachinery/pkg/api/errors"
11+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12+
utilerrors "k8s.io/apimachinery/pkg/util/errors"
13+
rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1"
14+
"k8s.io/kubernetes/pkg/kubectl"
15+
16+
authclient "github.com/openshift/origin/pkg/authorization/generated/internalclientset/typed/authorization/internalversion"
17+
)
18+
19+
func NewRoleReaper(roleClient authclient.RolesGetter, bindingClient rbacv1client.RoleBindingsGetter) kubectl.Reaper {
20+
return &RoleReaper{
21+
roleClient: roleClient,
22+
bindingClient: bindingClient,
23+
}
24+
}
25+
26+
type RoleReaper struct {
27+
roleClient authclient.RolesGetter
28+
bindingClient rbacv1client.RoleBindingsGetter
29+
}
30+
31+
// Stop on a reaper is actually used for deletion. In this case, we'll delete referencing rolebindings
32+
// then delete the role.
33+
func (r *RoleReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *metav1.DeleteOptions) error {
34+
err := reapForRole(r.bindingClient, namespace, name, ioutil.Discard)
35+
36+
if err != nil {
37+
glog.Infof("Cannot prune for role/%s: %v", name, err)
38+
}
39+
40+
if err := r.roleClient.Roles(namespace).Delete(name, &metav1.DeleteOptions{}); err != nil && !kerrors.IsNotFound(err) {
41+
return err
42+
}
43+
44+
return nil
45+
}
46+
47+
// Stop on a reaper is actually used for deletion. In this case, we'll delete referencing rolebindings
48+
// then delete the role.
49+
func reapForRole(bindingClient rbacv1client.RoleBindingsGetter, namespace, name string, out io.Writer) error {
50+
bindings, err := bindingClient.RoleBindings(namespace).List(metav1.ListOptions{})
51+
if err != nil {
52+
return err
53+
}
54+
55+
errors := []error{}
56+
for _, binding := range bindings.Items {
57+
if binding.RoleRef.Name == name {
58+
foreground := metav1.DeletePropagationForeground
59+
if err := bindingClient.RoleBindings(namespace).Delete(binding.Name, &metav1.DeleteOptions{PropagationPolicy: &foreground}); err != nil && !kerrors.IsNotFound(err) {
60+
errors = append(errors, err)
61+
} else {
62+
fmt.Fprintf(out, "rolebinding.rbac.authorization.k8s.io/"+binding.Name+" deleted\n")
63+
}
64+
}
65+
}
66+
67+
return utilerrors.NewAggregate(errors)
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package authorizationreaper
2+
3+
import (
4+
"io"
5+
6+
"github.com/spf13/cobra"
7+
8+
rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1"
9+
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
10+
"k8s.io/kubernetes/pkg/kubectl/resource"
11+
)
12+
13+
// PruneRolesOptions holds all the required options for pruning roles.
14+
type PruneRolesOptions struct {
15+
FilenameOptions resource.FilenameOptions
16+
Selector string
17+
All bool
18+
19+
Builder *resource.Builder
20+
RoleBindingClient rbacv1client.RoleBindingsGetter
21+
22+
Out io.Writer
23+
}
24+
25+
// NewCmdPruneRoles implements the OpenShift cli prune roles command.
26+
func NewCmdPruneRoles(f kcmdutil.Factory, name string, out io.Writer) *cobra.Command {
27+
o := &PruneRolesOptions{
28+
Out: out,
29+
}
30+
31+
cmd := &cobra.Command{
32+
Use: name,
33+
Short: "Deletes all rolebindings references the specified roles.",
34+
Long: "Deletes all rolebindings references the specified roles.",
35+
36+
Run: func(cmd *cobra.Command, args []string) {
37+
kcmdutil.CheckErr(o.Complete(f, cmd, args))
38+
kcmdutil.CheckErr(o.RunPrune())
39+
},
40+
}
41+
42+
kcmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "containing the resource to delete.")
43+
44+
cmd.Flags().StringVarP(&o.Selector, "selector", "l", "", "Selector (label query) to filter on.")
45+
cmd.Flags().BoolVar(&o.All, "all", o.All, "Prune all roles in the namespace.")
46+
47+
return cmd
48+
}
49+
50+
func (o *PruneRolesOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error {
51+
var err error
52+
53+
clientConfig, err := f.ClientConfig()
54+
if err != nil {
55+
return nil
56+
}
57+
o.RoleBindingClient, err = rbacv1client.NewForConfig(clientConfig)
58+
if err != nil {
59+
return nil
60+
}
61+
62+
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
63+
if err != nil {
64+
return err
65+
}
66+
67+
o.Builder = f.NewBuilder().
68+
Unstructured().
69+
ContinueOnError().
70+
NamespaceParam(cmdNamespace).DefaultNamespace().
71+
FilenameParam(enforceNamespace, &o.FilenameOptions).
72+
LabelSelectorParam(o.Selector).
73+
SelectAllParam(o.All).
74+
ResourceTypeOrNameArgs(false, args...).
75+
RequireObject(false).
76+
Flatten()
77+
78+
return nil
79+
}
80+
81+
func (o *PruneRolesOptions) RunPrune() error {
82+
r := o.Builder.Do()
83+
if r.Err() != nil {
84+
return r.Err()
85+
}
86+
87+
// this is weird, but we do this here for easy compatibility with existing reapers. This command doesn't make sense
88+
// without a server connection. Still. Don't do this at home.
89+
err := r.Visit(func(info *resource.Info, err error) error {
90+
if err != nil {
91+
return err
92+
}
93+
if info.Mapping.GroupVersionKind.Group != "rbac.authorization.k8s.io" && info.Mapping.GroupVersionKind.Group != "authorization.openshift.io" {
94+
return nil
95+
}
96+
if info.Mapping.Resource != "roles" {
97+
return nil
98+
}
99+
100+
reapForRole(o.RoleBindingClient, info.Namespace, info.Name, o.Out)
101+
102+
return nil
103+
})
104+
105+
return err
106+
}

pkg/authorization/reaper/role_test.go pkg/oc/admin/prune/authorizationreaper/role_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package reaper
1+
package authorizationreaper
22

33
import (
44
"reflect"

pkg/oc/admin/prune/prune.go

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
99

1010
groups "github.com/openshift/origin/pkg/oc/admin/groups/sync/cli"
11+
"github.com/openshift/origin/pkg/oc/admin/prune/authorizationreaper"
1112
"github.com/openshift/origin/pkg/oc/cli/util/clientcmd"
1213
)
1314

@@ -35,5 +36,6 @@ func NewCommandPrune(name, fullName string, f *clientcmd.Factory, out, errOut io
3536
cmds.AddCommand(NewCmdPruneDeployments(f, fullName, PruneDeploymentsRecommendedName, out))
3637
cmds.AddCommand(NewCmdPruneImages(f, fullName, PruneImagesRecommendedName, out))
3738
cmds.AddCommand(groups.NewCmdPrune(PruneGroupsRecommendedName, fullName+" "+PruneGroupsRecommendedName, f, out))
39+
cmds.AddCommand(authorizationreaper.NewCmdPruneRoles(f, "roles", out))
3840
return cmds
3941
}

pkg/oc/cli/util/clientcmd/factory_builder.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
appsclient "github.com/openshift/origin/pkg/apps/generated/internalclientset"
1313
authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization"
1414
authorizationclientinternal "github.com/openshift/origin/pkg/authorization/generated/internalclientset"
15-
authorizationreaper "github.com/openshift/origin/pkg/authorization/reaper"
15+
authorizationreaper "github.com/openshift/origin/pkg/oc/admin/prune/authorizationreaper"
1616
buildapi "github.com/openshift/origin/pkg/build/apis/build"
1717
buildclientinternal "github.com/openshift/origin/pkg/build/generated/internalclientset"
1818
oauthclientinternal "github.com/openshift/origin/pkg/oauth/generated/internalclientset"
@@ -91,7 +91,11 @@ func (f *ring2Factory) Reaper(mapping *meta.RESTMapping) (kubectl.Reaper, error)
9191
if err != nil {
9292
return nil, err
9393
}
94-
return authorizationreaper.NewRoleReaper(authClient.Authorization(), authClient.Authorization()), nil
94+
kubeClient, err := f.clientAccessFactory.KubernetesClientSet()
95+
if err != nil {
96+
return nil, err
97+
}
98+
return authorizationreaper.NewRoleReaper(authClient.Authorization(), kubeClient.RbacV1()), nil
9599
case authorizationapi.IsKindOrLegacy("ClusterRole", gk):
96100
authClient, err := authorizationclientinternal.NewForConfig(clientConfig)
97101
if err != nil {

0 commit comments

Comments
 (0)