pull/31412/merge
Feruzjon Muyassarov 3 days ago committed by GitHub
commit 49fc61e370
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -575,7 +575,32 @@ func (c *Client) update(originals, targets ResourceList, createApplyFunc CreateA
original := originals.Get(target)
if original == nil {
kind := target.Mapping.GroupVersionKind.Kind
return fmt.Errorf("original object %s with the name %q not found", kind, target.Name)
slog.Warn("resource exists on cluster but not in original release, using cluster state as baseline",
"namespace", target.Namespace, "name", target.Name, "kind", kind)
currentObj, err := helper.Get(target.Namespace, target.Name)
if err != nil {
return fmt.Errorf("failed to get current resource state: %w", err)
}
// Create a temporary Info with the current cluster state to use as "original"
currentInfo := &resource.Info{
Client: target.Client,
Mapping: target.Mapping,
Namespace: target.Namespace,
Name: target.Name,
Object: currentObj,
}
if err := updateApplyFunc(currentInfo, target); err != nil {
updateErrors = append(updateErrors, err)
}
// Because we check for errors later, append the info regardless
res.Updated = append(res.Updated, target)
return nil
}
if err := updateApplyFunc(original, target); err != nil {
@ -631,7 +656,9 @@ func (c *Client) update(originals, targets ResourceList, createApplyFunc CreateA
slog.Any("error", err),
)
if !apierrors.IsNotFound(err) {
updateErrors = append(updateErrors, fmt.Errorf("failed to delete resource %s: %w", info.Name, err))
updateErrors = append(updateErrors, fmt.Errorf(
"failed to delete resource namespace=%s, name=%s, kind=%s: %w",
info.Namespace, info.Name, info.Mapping.GroupVersionKind.Kind, err))
}
continue
}

@ -411,7 +411,25 @@ func TestUpdate(t *testing.T) {
"/namespaces/default/pods/forbidden:GET",
"/namespaces/default/pods/forbidden:DELETE",
),
ExpectedError: "failed to delete resource forbidden:",
ExpectedError: "failed to delete resource namespace=default, name=forbidden, kind=Pod:",
},
"rollback after failed upgrade with removed resource": {
// Simulates rollback scenario:
// - Revision 1 had "newpod"
// - Revision 2 removed "newpod" but upgrade failed (OriginalPods is empty)
// - Cluster still has "newpod" from Revision 1
// - Rolling back to Revision 1 (TargetPods with "newpod") should succeed
OriginalPods: v1.PodList{}, // Revision 2 (failed) - resource was removed
TargetPods: newPodList("newpod"), // Revision 1 - rolling back to this
ThreeWayMergeForUnstructured: false,
ServerSideApply: true,
ExpectedActions: []string{
"/namespaces/default/pods/newpod:GET", // Check if resource exists
"/namespaces/default/pods/newpod:GET", // Get current state (first call in update path)
"/namespaces/default/pods/newpod:GET", // Get current cluster state to use as baseline
"/namespaces/default/pods/newpod:PATCH", // Update using cluster state as baseline
},
ExpectedError: "",
},
}
@ -428,6 +446,10 @@ func TestUpdate(t *testing.T) {
p, m := req.URL.Path, req.Method
switch {
case p == "/namespaces/default/pods/newpod" && m == http.MethodGet:
return newResponse(http.StatusOK, &listTarget.Items[0])
case p == "/namespaces/default/pods/newpod" && m == http.MethodPatch:
return newResponse(http.StatusOK, &listTarget.Items[0])
case p == "/namespaces/default/pods/starfish" && m == http.MethodGet:
return newResponse(http.StatusOK, &listOriginal.Items[0])
case p == "/namespaces/default/pods/otter" && m == http.MethodGet:
@ -519,9 +541,23 @@ func TestUpdate(t *testing.T) {
require.NoError(t, err)
}
assert.Len(t, result.Created, 1, "expected 1 resource created, got %d", len(result.Created))
assert.Len(t, result.Updated, 2, "expected 2 resource updated, got %d", len(result.Updated))
assert.Len(t, result.Deleted, 1, "expected 1 resource deleted, got %d", len(result.Deleted))
// Special handling for the rollback test case
if name == "rollback after failed upgrade with removed resource" {
assert.Len(t, result.Created, 0, "expected 0 resource created, got %d", len(result.Created))
assert.Len(t, result.Updated, 1, "expected 1 resource updated, got %d", len(result.Updated))
assert.Len(t, result.Deleted, 0, "expected 0 resource deleted, got %d", len(result.Deleted))
} else {
assert.Len(t, result.Created, 1, "expected 1 resource created, got %d", len(result.Created))
assert.Len(t, result.Updated, 2, "expected 2 resource updated, got %d", len(result.Updated))
assert.Len(t, result.Deleted, 1, "expected 1 resource deleted, got %d", len(result.Deleted))
}
if tc.ExpectedError != "" {
require.Error(t, err)
require.Contains(t, err.Error(), tc.ExpectedError)
} else {
require.NoError(t, err)
}
actions := []string{}
for _, action := range client.Actions {

Loading…
Cancel
Save