Merge pull request #87044 from jennybuckley/smd-prob

Enable tracking field management for some objects before they are applied to
This commit is contained in:
Kubernetes Prow Robot 2020-01-12 15:07:37 -08:00 committed by GitHub
commit 36e40fb850
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 2 deletions

View File

@ -33,6 +33,10 @@ import (
// TODO(jennybuckley): Determine if this is really the best value. Ideally we wouldn't unnecessarily merge too many entries. // TODO(jennybuckley): Determine if this is really the best value. Ideally we wouldn't unnecessarily merge too many entries.
const DefaultMaxUpdateManagers int = 10 const DefaultMaxUpdateManagers int = 10
// DefaultTrackOnCreateProbability defines the default probability that the field management of an object
// starts being tracked from the object's creation, instead of from the first time the object is applied to.
const DefaultTrackOnCreateProbability float32 = 0.5
// Managed groups a fieldpath.ManagedFields together with the timestamps associated with each operation. // Managed groups a fieldpath.ManagedFields together with the timestamps associated with each operation.
type Managed interface { type Managed interface {
// Fields gets the fieldpath.ManagedFields. // Fields gets the fieldpath.ManagedFields.
@ -92,7 +96,7 @@ func newDefaultFieldManager(f Manager, objectCreater runtime.ObjectCreater, kind
f = NewStripMetaManager(f) f = NewStripMetaManager(f)
f = NewBuildManagerInfoManager(f, kind.GroupVersion()) f = NewBuildManagerInfoManager(f, kind.GroupVersion())
f = NewCapManagersManager(f, DefaultMaxUpdateManagers) f = NewCapManagersManager(f, DefaultMaxUpdateManagers)
f = NewSkipNonAppliedManager(f, objectCreater, kind) f = NewProbabilisticSkipNonAppliedManager(f, objectCreater, kind, DefaultTrackOnCreateProbability)
return NewFieldManager(f) return NewFieldManager(f)
} }

View File

@ -18,7 +18,9 @@ package fieldmanager
import ( import (
"fmt" "fmt"
"math/rand"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
) )
@ -28,25 +30,48 @@ type skipNonAppliedManager struct {
objectCreater runtime.ObjectCreater objectCreater runtime.ObjectCreater
gvk schema.GroupVersionKind gvk schema.GroupVersionKind
beforeApplyManagerName string beforeApplyManagerName string
probability float32
} }
var _ Manager = &skipNonAppliedManager{} var _ Manager = &skipNonAppliedManager{}
// NewSkipNonAppliedManager creates a new wrapped FieldManager that only starts tracking managers after the first apply. // NewSkipNonAppliedManager creates a new wrapped FieldManager that only starts tracking managers after the first apply.
func NewSkipNonAppliedManager(fieldManager Manager, objectCreater runtime.ObjectCreater, gvk schema.GroupVersionKind) Manager { func NewSkipNonAppliedManager(fieldManager Manager, objectCreater runtime.ObjectCreater, gvk schema.GroupVersionKind) Manager {
return NewProbabilisticSkipNonAppliedManager(fieldManager, objectCreater, gvk, 0.0)
}
// NewProbabilisticSkipNonAppliedManager creates a new wrapped FieldManager that starts tracking managers after the first apply,
// or starts tracking on create with p probability.
func NewProbabilisticSkipNonAppliedManager(fieldManager Manager, objectCreater runtime.ObjectCreater, gvk schema.GroupVersionKind, p float32) Manager {
return &skipNonAppliedManager{ return &skipNonAppliedManager{
fieldManager: fieldManager, fieldManager: fieldManager,
objectCreater: objectCreater, objectCreater: objectCreater,
gvk: gvk, gvk: gvk,
beforeApplyManagerName: "before-first-apply", beforeApplyManagerName: "before-first-apply",
probability: p,
} }
} }
// Update implements Manager. // Update implements Manager.
func (f *skipNonAppliedManager) Update(liveObj, newObj runtime.Object, managed Managed, manager string) (runtime.Object, Managed, error) { func (f *skipNonAppliedManager) Update(liveObj, newObj runtime.Object, managed Managed, manager string) (runtime.Object, Managed, error) {
if len(managed.Fields()) == 0 { accessor, err := meta.Accessor(liveObj)
if err != nil {
return newObj, managed, nil return newObj, managed, nil
} }
// If managed fields is empty, we need to determine whether to skip tracking managed fields.
if len(managed.Fields()) == 0 {
// Check if the operation is a create, by checking whether lastObj's UID is empty.
// If the operation is create, P(tracking managed fields) = f.probability
// If the operation is update, skip tracking managed fields, since we already know managed fields is empty.
if len(accessor.GetUID()) == 0 {
if f.probability <= rand.Float32() {
return newObj, managed, nil
}
} else {
return newObj, managed, nil
}
}
return f.fieldManager.Update(liveObj, newObj, managed, manager) return f.fieldManager.Update(liveObj, newObj, managed, manager)
} }