Skip to content

Commit 6079ceb

Browse files
authored
Merge pull request kubernetes#90187 from julianvmodesto/last-applied-updater
Implement server-side apply upgrade and downgrade
2 parents 240a72b + e4368eb commit 6079ceb

File tree

14 files changed

+1462
-65
lines changed

14 files changed

+1462
-65
lines changed

staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/BUILD

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ go_library(
66
"buildmanagerinfo.go",
77
"capmanagers.go",
88
"fieldmanager.go",
9+
"lastappliedmanager.go",
10+
"lastappliedupdater.go",
911
"managedfieldsupdater.go",
1012
"skipnonapplied.go",
1113
"stripmeta.go",
@@ -15,9 +17,11 @@ go_library(
1517
importpath = "k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager",
1618
visibility = ["//visibility:public"],
1719
deps = [
20+
"//staging/src/k8s.io/api/core/v1:go_default_library",
1821
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
1922
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
2023
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
24+
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
2125
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
2226
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
2327
"//staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal:go_default_library",
@@ -50,6 +54,8 @@ go_test(
5054
srcs = [
5155
"capmanagers_test.go",
5256
"fieldmanager_test.go",
57+
"lastappliedmanager_test.go",
58+
"lastappliedupdater_test.go",
5359
"skipnonapplied_test.go",
5460
],
5561
data = [
@@ -69,6 +75,7 @@ go_test(
6975
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
7076
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
7177
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
78+
"//staging/src/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
7279
"//staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal:go_default_library",
7380
"//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library",
7481
"//vendor/k8s.io/kube-openapi/pkg/util/proto/testing:go_default_library",

staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/capmanagers_test.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,16 @@ func (*fakeManager) Update(_, newObj runtime.Object, managed fieldmanager.Manage
4141
return newObj, managed, nil
4242
}
4343

44-
func (*fakeManager) Apply(_, _ runtime.Object, _ fieldmanager.Managed, _ string, force bool) (runtime.Object, fieldmanager.Managed, error) {
44+
func (*fakeManager) Apply(_, _ runtime.Object, _ fieldmanager.Managed, _ string, _ bool) (runtime.Object, fieldmanager.Managed, error) {
4545
panic("not implemented")
4646
return nil, nil, nil
4747
}
4848

4949
func TestCapManagersManagerMergesEntries(t *testing.T) {
50-
f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod"))
51-
f.fieldManager = fieldmanager.NewCapManagersManager(f.fieldManager, 3)
50+
f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod"),
51+
func(m fieldmanager.Manager) fieldmanager.Manager {
52+
return fieldmanager.NewCapManagersManager(m, 3)
53+
})
5254

5355
podWithLabels := func(labels ...string) runtime.Object {
5456
labelMap := map[string]interface{}{}
@@ -110,8 +112,10 @@ func TestCapManagersManagerMergesEntries(t *testing.T) {
110112
}
111113

112114
func TestCapUpdateManagers(t *testing.T) {
113-
f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod"))
114-
f.fieldManager = fieldmanager.NewCapManagersManager(&fakeManager{}, 3)
115+
f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod"),
116+
func(m fieldmanager.Manager) fieldmanager.Manager {
117+
return fieldmanager.NewCapManagersManager(m, 3)
118+
})
115119

116120
set := func(fields ...string) *metav1.FieldsV1 {
117121
s := fieldpath.NewSet()

staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"k8s.io/klog/v2"
3030
openapiproto "k8s.io/kube-openapi/pkg/util/proto"
3131
"sigs.k8s.io/structured-merge-diff/v3/fieldpath"
32+
"sigs.k8s.io/structured-merge-diff/v3/merge"
3233
)
3334

3435
// DefaultMaxUpdateManagers defines the default maximum retained number of managedFields entries from updates
@@ -78,31 +79,46 @@ func NewFieldManager(f Manager) *FieldManager {
7879
// NewDefaultFieldManager creates a new FieldManager that merges apply requests
7980
// and update managed fields for other types of requests.
8081
func NewDefaultFieldManager(models openapiproto.Models, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, hub schema.GroupVersion) (*FieldManager, error) {
81-
f, err := NewStructuredMergeManager(models, objectConverter, objectDefaulter, kind.GroupVersion(), hub)
82+
typeConverter, err := internal.NewTypeConverter(models, false)
83+
if err != nil {
84+
return nil, err
85+
}
86+
87+
f, err := NewStructuredMergeManager(typeConverter, objectConverter, objectDefaulter, kind.GroupVersion(), hub)
8288
if err != nil {
8389
return nil, fmt.Errorf("failed to create field manager: %v", err)
8490
}
85-
return newDefaultFieldManager(f, objectCreater, kind), nil
91+
return newDefaultFieldManager(f, typeConverter, objectConverter, objectCreater, kind), nil
8692
}
8793

8894
// NewDefaultCRDFieldManager creates a new FieldManager specifically for
8995
// CRDs. This allows for the possibility of fields which are not defined
9096
// in models, as well as having no models defined at all.
9197
func NewDefaultCRDFieldManager(models openapiproto.Models, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, hub schema.GroupVersion, preserveUnknownFields bool) (_ *FieldManager, err error) {
92-
f, err := NewCRDStructuredMergeManager(models, objectConverter, objectDefaulter, kind.GroupVersion(), hub, preserveUnknownFields)
98+
var typeConverter internal.TypeConverter = internal.DeducedTypeConverter{}
99+
if models != nil {
100+
typeConverter, err = internal.NewTypeConverter(models, preserveUnknownFields)
101+
if err != nil {
102+
return nil, err
103+
}
104+
}
105+
f, err := NewCRDStructuredMergeManager(typeConverter, objectConverter, objectDefaulter, kind.GroupVersion(), hub, preserveUnknownFields)
93106
if err != nil {
94107
return nil, fmt.Errorf("failed to create field manager: %v", err)
95108
}
96-
return newDefaultFieldManager(f, objectCreater, kind), nil
109+
return newDefaultFieldManager(f, typeConverter, objectConverter, objectCreater, kind), nil
97110
}
98111

99112
// newDefaultFieldManager is a helper function which wraps a Manager with certain default logic.
100-
func newDefaultFieldManager(f Manager, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind) *FieldManager {
113+
func newDefaultFieldManager(f Manager, typeConverter internal.TypeConverter, objectConverter runtime.ObjectConvertor, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind) *FieldManager {
101114
f = NewStripMetaManager(f)
102115
f = NewManagedFieldsUpdater(f)
103116
f = NewBuildManagerInfoManager(f, kind.GroupVersion())
104117
f = NewCapManagersManager(f, DefaultMaxUpdateManagers)
105118
f = NewProbabilisticSkipNonAppliedManager(f, objectCreater, kind, DefaultTrackOnCreateProbability)
119+
f = NewLastAppliedManager(f, typeConverter, objectConverter, kind.GroupVersion())
120+
f = NewLastAppliedUpdater(f)
121+
106122
return NewFieldManager(f)
107123
}
108124

@@ -200,7 +216,11 @@ func (f *FieldManager) Apply(liveObj, appliedObj runtime.Object, manager string,
200216

201217
internal.RemoveObjectManagedFields(liveObj)
202218

203-
if object, managed, err = f.fieldManager.Apply(liveObj, appliedObj, managed, manager, force); err != nil {
219+
object, managed, err = f.fieldManager.Apply(liveObj, appliedObj, managed, manager, force)
220+
if err != nil {
221+
if conflicts, ok := err.(merge.Conflicts); ok {
222+
return nil, internal.NewConflictError(conflicts)
223+
}
204224
return nil, err
205225
}
206226

0 commit comments

Comments
 (0)