Skip to content

Commit 0e6e3b6

Browse files
author
OpenShift Bot
authored
Merge pull request #11639 from pweil-/bulk-level-filter
Merged by openshift-bot
2 parents 3b97ee7 + 08423a7 commit 0e6e3b6

File tree

2 files changed

+72
-14
lines changed

2 files changed

+72
-14
lines changed

pkg/cmd/admin/router/router.go

+39-2
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ func RunCmdRouter(f *clientcmd.Factory, cmd *cobra.Command, out, errout io.Write
711711
objects = append(objects,
712712
&kapi.ServiceAccount{ObjectMeta: kapi.ObjectMeta{Name: cfg.ServiceAccount}},
713713
&authapi.ClusterRoleBinding{
714-
ObjectMeta: kapi.ObjectMeta{Name: fmt.Sprintf("router-%s-role", cfg.Name)},
714+
ObjectMeta: kapi.ObjectMeta{Name: generateRoleBindingName(cfg.Name)},
715715
Subjects: []kapi.ObjectReference{
716716
{
717717
Kind: "ServiceAccount",
@@ -789,12 +789,49 @@ func RunCmdRouter(f *clientcmd.Factory, cmd *cobra.Command, out, errout io.Write
789789
return defaultOutputErr
790790
}
791791

792-
if errs := cfg.Action.WithMessage(fmt.Sprintf("Creating router %s", cfg.Name), "created").Run(list, namespace); len(errs) > 0 {
792+
levelPrefixFilter := func(e error) string {
793+
// only ignore SA/RB errors if we were creating the service account
794+
if createServiceAccount && ignoreError(e, cfg.ServiceAccount, generateRoleBindingName(cfg.Name)) {
795+
return "warning"
796+
}
797+
return "error"
798+
}
799+
800+
cfg.Action.Bulk.IgnoreError = func(e error) bool {
801+
return levelPrefixFilter(e) == "warning"
802+
}
803+
804+
if errs := cfg.Action.WithMessageAndPrefix(fmt.Sprintf("Creating router %s", cfg.Name), "created", levelPrefixFilter).Run(list, namespace); len(errs) > 0 {
793805
return cmdutil.ErrExit
794806
}
795807
return nil
796808
}
797809

810+
// ignoreError will return true if the error is an already exists status error and
811+
// 1. it is for a cluster role binding named roleBindingName
812+
// 2. it is for a serivce account name saName
813+
func ignoreError(e error, saName string, roleBindingName string) bool {
814+
if !errors.IsAlreadyExists(e) {
815+
return false
816+
}
817+
statusError, ok := e.(*errors.StatusError)
818+
if !ok {
819+
return false
820+
}
821+
details := statusError.Status().Details
822+
if details == nil {
823+
return false
824+
}
825+
return (details.Kind == "serviceaccounts" && details.Name == saName) ||
826+
(details.Kind == "clusterrolebinding" && details.Name == roleBindingName)
827+
}
828+
829+
// generateRoleBindingName generates a name for the rolebinding object if it is
830+
// being created.
831+
func generateRoleBindingName(name string) string {
832+
return fmt.Sprintf("router-%s-role", name)
833+
}
834+
798835
// generateStatsPassword creates a random password.
799836
func generateStatsPassword() string {
800837
allowableChars := []rune("abcdefghijlkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")

pkg/config/cmd/cmd.go

+33-12
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,21 @@ type Mapper interface {
3535
InfoForObject(obj runtime.Object, preferredGVKs []unversioned.GroupVersionKind) (*resource.Info, error)
3636
}
3737

38+
// IgnoreErrorFunc provides a way to filter errors during the Bulk.Run. If this function returns
39+
// true the error will NOT be added to the slice of errors returned by Bulk.Run.
40+
//
41+
// This may be used in conjunction with
42+
// BulkAction.WithMessageAndPrefix if you are reporting some errors as warnings.
43+
type IgnoreErrorFunc func(e error) bool
44+
3845
// Bulk provides helpers for iterating over a list of items
3946
type Bulk struct {
4047
Mapper Mapper
4148

42-
Op OpFunc
43-
After AfterFunc
44-
Retry RetryFunc
49+
Op OpFunc
50+
After AfterFunc
51+
Retry RetryFunc
52+
IgnoreError IgnoreErrorFunc
4553
}
4654

4755
// Create attempts to create each item generically, gathering all errors in the
@@ -52,6 +60,10 @@ func (b *Bulk) Run(list *kapi.List, namespace string) []error {
5260
if after == nil {
5361
after = func(*resource.Info, error) bool { return false }
5462
}
63+
ignoreError := b.IgnoreError
64+
if ignoreError == nil {
65+
ignoreError = func(e error) bool { return false }
66+
}
5567

5668
errs := []error{}
5769
for i, item := range list.Items {
@@ -70,7 +82,9 @@ func (b *Bulk) Run(list *kapi.List, namespace string) []error {
7082
}
7183
}
7284
if err != nil {
73-
errs = append(errs, err)
85+
if !ignoreError(err) {
86+
errs = append(errs, err)
87+
}
7488
if after(info, err) {
7589
break
7690
}
@@ -85,22 +99,22 @@ func (b *Bulk) Run(list *kapi.List, namespace string) []error {
8599
return errs
86100
}
87101

88-
func NewPrintNameOrErrorAfterIndent(mapper meta.RESTMapper, short bool, operation string, out, errs io.Writer, dryRun bool, indent string) AfterFunc {
102+
func NewPrintNameOrErrorAfterIndent(mapper meta.RESTMapper, short bool, operation string, out, errs io.Writer, dryRun bool, indent string, prefixForError PrefixForError) AfterFunc {
89103
return func(info *resource.Info, err error) bool {
90104
if err == nil {
91105
fmt.Fprintf(out, indent)
92106
cmdutil.PrintSuccess(mapper, short, out, info.Mapping.Resource, info.Name, dryRun, operation)
93107
} else {
94-
fmt.Fprintf(errs, "%serror: %v\n", indent, err)
108+
fmt.Fprintf(errs, "%s%s: %v\n", indent, prefixForError(err), err)
95109
}
96110
return false
97111
}
98112
}
99113

100-
func NewPrintErrorAfter(mapper meta.RESTMapper, errs io.Writer) func(*resource.Info, error) bool {
114+
func NewPrintErrorAfter(mapper meta.RESTMapper, errs io.Writer, prefixForError PrefixForError) func(*resource.Info, error) bool {
101115
return func(info *resource.Info, err error) bool {
102116
if err != nil {
103-
fmt.Fprintf(errs, "error: %v\n", err)
117+
fmt.Fprintf(errs, "%s: %v\n", prefixForError(err), err)
104118
}
105119
return false
106120
}
@@ -186,24 +200,31 @@ func (b *BulkAction) DefaultIndent() string {
186200
return ""
187201
}
188202

189-
func (b BulkAction) WithMessage(action, individual string) Runner {
203+
// PrefixForError allows customization of the prefix that will be printed for any error that occurs in the BulkAction.
204+
type PrefixForError func(e error) string
205+
206+
func (b BulkAction) WithMessageAndPrefix(action, individual string, prefixForError PrefixForError) Runner {
190207
b.Action = action
191208
switch {
192209
// TODO: this should be b printer
193210
case b.Output == "":
194-
b.Bulk.After = NewPrintNameOrErrorAfterIndent(b.Bulk.Mapper, false, individual, b.Out, b.ErrOut, b.DryRun, b.DefaultIndent())
211+
b.Bulk.After = NewPrintNameOrErrorAfterIndent(b.Bulk.Mapper, false, individual, b.Out, b.ErrOut, b.DryRun, b.DefaultIndent(), prefixForError)
195212
// TODO: needs to be unified with the name printer (incremental vs exact execution), possibly by creating b synthetic printer?
196213
case b.Output == "name":
197-
b.Bulk.After = NewPrintNameOrErrorAfterIndent(b.Bulk.Mapper, true, individual, b.Out, b.ErrOut, b.DryRun, b.DefaultIndent())
214+
b.Bulk.After = NewPrintNameOrErrorAfterIndent(b.Bulk.Mapper, true, individual, b.Out, b.ErrOut, b.DryRun, b.DefaultIndent(), prefixForError)
198215
default:
199-
b.Bulk.After = NewPrintErrorAfter(b.Bulk.Mapper, b.ErrOut)
216+
b.Bulk.After = NewPrintErrorAfter(b.Bulk.Mapper, b.ErrOut, prefixForError)
200217
if b.StopOnError {
201218
b.Bulk.After = HaltOnError(b.Bulk.After)
202219
}
203220
}
204221
return &b
205222
}
206223

224+
func (b BulkAction) WithMessage(action, individual string) Runner {
225+
return b.WithMessageAndPrefix(action, individual, func(e error) string { return "error" })
226+
}
227+
207228
func (b *BulkAction) Run(list *kapi.List, namespace string) []error {
208229
run := b.Bulk
209230

0 commit comments

Comments
 (0)