Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release-3.7] Migrate: handle NotFound via resource matching and during conflicts #18287

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions pkg/oc/admin/migrate/migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand All @@ -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))
}
66 changes: 66 additions & 0 deletions pkg/oc/admin/migrate/migrator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down