diff --git a/pkg/oc/admin/migrate/migrator.go b/pkg/oc/admin/migrate/migrator.go index 20f24d10215a..69ddb4eeb790 100644 --- a/pkg/oc/admin/migrate/migrator.go +++ b/pkg/oc/admin/migrate/migrator.go @@ -503,6 +503,11 @@ func DefaultRetriable(info *resource.Info, err error) error { return ErrNotRetriable{err} case errors.IsConflict(err): if refreshErr := info.Get(); refreshErr != nil { + // tolerate the deletion of resources during migration + // report unchanged since we did not actually migrate this object + if isNotFoundForInfo(info, refreshErr) { + return ErrUnchanged + } return ErrNotRetriable{err} } return ErrRetriable{err} @@ -526,11 +531,14 @@ func isNotFoundForInfo(info *resource.Info, err error) bool { if details == nil { return false } - // get schema.GroupKind from the mapping since the actual object may not have type meta filled out + // get schema.GroupKind and Resource from the mapping since the actual object may not have type meta filled out gk := info.Mapping.GroupVersionKind.GroupKind() + mappingResource := info.Mapping.Resource // based on case-insensitive string comparisons, the error matches info iff - // the name and kind match - // the group match, but only if both the error and info specify a group - return strings.EqualFold(details.Name, info.Name) && strings.EqualFold(details.Kind, gk.Kind) && + // the names match + // the error's kind matches the mapping's kind or the mapping's resource + // the groups match, but only if both the error and info specify a group + return strings.EqualFold(details.Name, info.Name) && + (strings.EqualFold(details.Kind, gk.Kind) || strings.EqualFold(details.Kind, mappingResource)) && (len(details.Group) == 0 || len(gk.Group) == 0 || strings.EqualFold(details.Group, gk.Group)) } diff --git a/pkg/oc/admin/migrate/migrator_test.go b/pkg/oc/admin/migrate/migrator_test.go index a8c62a392988..73826febf3f6 100644 --- a/pkg/oc/admin/migrate/migrator_test.go +++ b/pkg/oc/admin/migrate/migrator_test.go @@ -334,6 +334,72 @@ func TestIsNotFoundForInfo(t *testing.T) { }, want: false, }, + { + name: "case-insensitive match due to different kinds but same resource", + args: args{ + info: &resource.Info{ + Mapping: &meta.RESTMapping{ + Resource: "KIND2", + GroupVersionKind: schema.GroupVersionKind{ + Group: "group1", + Kind: "kind1", + }, + }, + Name: "NOTname", + }, + err: errors.NewNotFound(schema.GroupResource{ + Group: "GROUP1", + Resource: "kind2", // this is the kind + }, + "notNAME", + ), + }, + want: true, + }, + { + name: "case-insensitive match due to different resource but same kinds", + args: args{ + info: &resource.Info{ + Mapping: &meta.RESTMapping{ + Resource: "kind1", + GroupVersionKind: schema.GroupVersionKind{ + Group: "group1", + Kind: "KIND2", + }, + }, + Name: "NOTname", + }, + err: errors.NewNotFound(schema.GroupResource{ + Group: "GROUP1", + Resource: "kind2", // this is the kind + }, + "notNAME", + ), + }, + want: true, + }, + { + name: "case-insensitive not match due to different resource and different kinds", + args: args{ + info: &resource.Info{ + Mapping: &meta.RESTMapping{ + Resource: "kind1", + GroupVersionKind: schema.GroupVersionKind{ + Group: "group1", + Kind: "kind3", + }, + }, + Name: "NOTname", + }, + err: errors.NewNotFound(schema.GroupResource{ + Group: "GROUP1", + Resource: "kind2", // this is the kind + }, + "notNAME", + ), + }, + want: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {