|
4 | 4 | "context"
|
5 | 5 | "encoding/json"
|
6 | 6 | "fmt"
|
| 7 | + "reflect" |
7 | 8 | "sort"
|
8 | 9 | "strings"
|
9 | 10 | "sync"
|
@@ -1005,6 +1006,40 @@ func (sc *syncContext) applyObject(t *syncTask, dryRun, validate bool) (common.R
|
1005 | 1006 | message, err = sc.resourceOps.ApplyResource(context.TODO(), t.targetObj, dryRunStrategy, force, validate, serverSideApply, sc.serverSideApplyManager, false)
|
1006 | 1007 | }
|
1007 | 1008 | if err != nil {
|
| 1009 | + // Check if this is a StatefulSet immutable field error |
| 1010 | + if strings.Contains(err.Error(), "updates to statefulset spec for fields other than") { |
| 1011 | + current := t.liveObj |
| 1012 | + desired := t.targetObj |
| 1013 | + |
| 1014 | + if current != nil && desired != nil { |
| 1015 | + currentSpec, _, _ := unstructured.NestedMap(current.Object, "spec") |
| 1016 | + desiredSpec, _, _ := unstructured.NestedMap(desired.Object, "spec") |
| 1017 | + |
| 1018 | + mutableFields := map[string]bool{ |
| 1019 | + "replicas": true, |
| 1020 | + "ordinals": true, |
| 1021 | + "template": true, |
| 1022 | + "updateStrategy": true, |
| 1023 | + "persistentVolumeClaimRetentionPolicy": true, |
| 1024 | + "minReadySeconds": true, |
| 1025 | + } |
| 1026 | + |
| 1027 | + var changes []string |
| 1028 | + for k, desiredVal := range desiredSpec { |
| 1029 | + if !mutableFields[k] { |
| 1030 | + currentVal, exists := currentSpec[k] |
| 1031 | + if !exists || !reflect.DeepEqual(currentVal, desiredVal) { |
| 1032 | + changes = append(changes, fmt.Sprintf(" %s -> from %v to %v", k, currentVal, desiredVal)) |
| 1033 | + } |
| 1034 | + } |
| 1035 | + } |
| 1036 | + |
| 1037 | + if len(changes) > 0 { |
| 1038 | + return common.ResultCodeSyncFailed, fmt.Sprintf("one or more objects failed to apply, reason: attempting to change immutable fields:\n%s\nForbidden: updates to statefulset spec for fields other than 'replicas', 'ordinals', 'template', 'updateStrategy', 'persistentVolumeClaimRetentionPolicy' and 'minReadySeconds' are forbidden", |
| 1039 | + strings.Join(changes, "\n")) |
| 1040 | + } |
| 1041 | + } |
| 1042 | + } |
1008 | 1043 | return common.ResultCodeSyncFailed, err.Error()
|
1009 | 1044 | }
|
1010 | 1045 | if kube.IsCRD(t.targetObj) && !dryRun {
|
|
0 commit comments