From b66e6a91700ab596ad266525aaef4da0299e9500 Mon Sep 17 00:00:00 2001 From: Ted Petersson Date: Thu, 26 Nov 2020 10:55:22 +0100 Subject: [PATCH] fix: rollback to release containing resource with resource-policy=keep annotation When rollback to a previous release revision that contains a resource having the annotaion 'helm.sh/resource-policy=keep', while the current release revision dosen't have this resource, rollback will fail with an error message: 'Error: no with the name "" found' First of all the error message is misleading, since the resource actually exists. But the resource is not part of the current manifest (it is left there in a previous update due to the resource-policy=keep annotation). So helm cannot create a patch to update the given resource from the current to the target manifest, and fails with an error. The logic is updated to in this scenario (resource is part of the target manifest but NOT part of the current manifest) skip the upgrade IF the resource-policy=keep annotation is set. The error message is also updated and the the logic for checking the resource-policy annotation is broken out into a separate function. fix #8228 Signed-off-by: Ted Petersson --- pkg/kube/client.go | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 795ebb388..8a295000e 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -211,8 +211,11 @@ func (c *Client) Update(original, target ResourceList, force bool) (*Result, err originalInfo := original.Get(info) if originalInfo == nil { - kind := info.Mapping.GroupVersionKind.Kind - return errors.Errorf("no %s with the name %q found", kind, info.Name) + if hasResourcePolicyKeep(c, info) { + c.Log("Resource %q not found in current manifest, skip update due to annotation [%s=%s]", info.Name, ResourcePolicyAnno, KeepPolicy) + return nil + } + return errors.Errorf("Cannot update the resource %q, was not found in current manifest", info.Name) } if err := updateResource(c, info, originalInfo.Object, force); err != nil { @@ -239,11 +242,7 @@ func (c *Client) Update(original, target ResourceList, force bool) (*Result, err c.Log("Unable to get obj %q, err: %s", info.Name, err) continue } - annotations, err := metadataAccessor.Annotations(info.Object) - if err != nil { - c.Log("Unable to get annotations on %q, err: %s", info.Name, err) - } - if annotations != nil && annotations[ResourcePolicyAnno] == KeepPolicy { + if hasResourcePolicyKeep(c, info) { c.Log("Skipping delete of %q due to annotation [%s=%s]", info.Name, ResourcePolicyAnno, KeepPolicy) continue } @@ -256,6 +255,14 @@ func (c *Client) Update(original, target ResourceList, force bool) (*Result, err return res, nil } +func hasResourcePolicyKeep(c *Client, info *resource.Info) bool { + annotations, err := metadataAccessor.Annotations(info.Object) + if err != nil { + c.Log("Unable to get annotations on %q, err: %s", info.Name, err) + } + return annotations != nil && annotations[ResourcePolicyAnno] == KeepPolicy +} + // Delete deletes Kubernetes resources specified in the resources list. It will // attempt to delete all resources even if one or more fail and collect any // errors. All successfully deleted items will be returned in the `Deleted`