updateLastCall

// updateLastCall returns true if the lastCall time has been updated,
// false if it was too early.
func (s *AtMostEvery) updateLastCall() bool {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if time.Since(s.lastCall) < s.delay {
		return false
	}
	s.lastCall = time.Now()
	return true
}


Do

// Do will run the method if enough time has passed, and return true.
// Otherwise, it does nothing and returns false.
func (s *AtMostEvery) Do(fn func()) bool {
	if !s.updateLastCall() {
		return false
	}
	fn()
	return true
}


NewBuildManagerInfoManager

// NewBuildManagerInfoManager creates a new Manager that converts the manager name into a unique identifier
// combining operation and version for update requests, and just operation for apply requests.
func NewBuildManagerInfoManager(f Manager, gv schema.GroupVersion, subresource string) Manager {
	return &buildManagerInfoManager{
		fieldManager: f,
		groupVersion: gv,
		subresource:  subresource,
	}
}


Update

// Update implements Manager.
func (f *buildManagerInfoManager) Update(liveObj, newObj runtime.Object, managed Managed, manager string) (runtime.Object, Managed, error) {
	manager, err := f.buildManagerInfo(manager, metav1.ManagedFieldsOperationUpdate)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to build manager identifier: %v", err)
	}
	return f.fieldManager.Update(liveObj, newObj, managed, manager)
}


Apply

// Apply implements Manager.
func (f *buildManagerInfoManager) Apply(liveObj, appliedObj runtime.Object, managed Managed, manager string, force bool) (runtime.Object, Managed, error) {
	manager, err := f.buildManagerInfo(manager, metav1.ManagedFieldsOperationApply)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to build manager identifier: %v", err)
	}
	return f.fieldManager.Apply(liveObj, appliedObj, managed, manager, force)
}


buildManagerInfo

func (f *buildManagerInfoManager) buildManagerInfo(prefix string, operation metav1.ManagedFieldsOperationType) (string, error) {
	managerInfo := metav1.ManagedFieldsEntry{
		Manager:     prefix,
		Operation:   operation,
		APIVersion:  f.groupVersion.String(),
		Subresource: f.subresource,
	}
	if managerInfo.Manager == "" {
		managerInfo.Manager = "unknown"
	}
	return BuildManagerIdentifier(&managerInfo)
}


NewCapManagersManager

// NewCapManagersManager creates a new wrapped FieldManager which ensures that the number of managers from updates
// does not exceed maxUpdateManagers, by merging some of the oldest entries on each update.
func NewCapManagersManager(fieldManager Manager, maxUpdateManagers int) Manager {
	return &capManagersManager{
		fieldManager:          fieldManager,
		maxUpdateManagers:     maxUpdateManagers,
		oldUpdatesManagerName: "ancient-changes",
	}
}


Update

// Update implements Manager.
func (f *capManagersManager) Update(liveObj, newObj runtime.Object, managed Managed, manager string) (runtime.Object, Managed, error) {
	object, managed, err := f.fieldManager.Update(liveObj, newObj, managed, manager)
	if err != nil {
		return object, managed, err
	}
	if managed, err = f.capUpdateManagers(managed); err != nil {
		return nil, nil, fmt.Errorf("failed to cap update managers: %v", err)
	}
	return object, managed, nil
}


Apply

// Apply implements Manager.
func (f *capManagersManager) Apply(liveObj, appliedObj runtime.Object, managed Managed, fieldManager string, force bool) (runtime.Object, Managed, error) {
	return f.fieldManager.Apply(liveObj, appliedObj, managed, fieldManager, force)
}


capUpdateManagers

// capUpdateManagers merges a number of the oldest update entries into versioned buckets,
// such that the number of entries from updates does not exceed f.maxUpdateManagers.
func (f *capManagersManager) capUpdateManagers(managed Managed) (newManaged Managed, err error) {
	// Gather all entries from updates
	updaters := []string{}
	for manager, fields := range managed.Fields() {
		if !fields.Applied() {
			updaters = append(updaters, manager)
		}
	}
	if len(updaters) <= f.maxUpdateManagers {
		return managed, nil
	}

	// If we have more than the maximum, sort the update entries by time, oldest first.
	sort.Slice(updaters, func(i, j int) bool {
		iTime, jTime, iSeconds, jSeconds := managed.Times()[updaters[i]], managed.Times()[updaters[j]], int64(0), int64(0)
		if iTime != nil {
			iSeconds = iTime.Unix()
		}
		if jTime != nil {
			jSeconds = jTime.Unix()
		}
		if iSeconds != jSeconds {
			return iSeconds < jSeconds
		}
		return updaters[i] < updaters[j]
	})

	// Merge the oldest updaters with versioned bucket managers until the number of updaters is under the cap
	versionToFirstManager := map[string]string{}
	for i, length := 0, len(updaters); i < len(updaters) && length > f.maxUpdateManagers; i++ {
		manager := updaters[i]
		vs := managed.Fields()[manager]
		time := managed.Times()[manager]
		version := string(vs.APIVersion())

		// Create a new manager identifier for the versioned bucket entry.
		// The version for this manager comes from the version of the update being merged into the bucket.
		bucket, err := BuildManagerIdentifier(&metav1.ManagedFieldsEntry{
			Manager:    f.oldUpdatesManagerName,
			Operation:  metav1.ManagedFieldsOperationUpdate,
			APIVersion: version,
		})
		if err != nil {
			return managed, fmt.Errorf("failed to create bucket manager for version %v: %v", version, err)
		}

		// Merge the fieldets if this is not the first time the version was seen.
		// Otherwise just record the manager name in versionToFirstManager
		if first, ok := versionToFirstManager[version]; ok {
			// If the bucket doesn't exists yet, create one.
			if _, ok := managed.Fields()[bucket]; !ok {
				s := managed.Fields()[first]
				delete(managed.Fields(), first)
				managed.Fields()[bucket] = s
			}

			managed.Fields()[bucket] = fieldpath.NewVersionedSet(vs.Set().Union(managed.Fields()[bucket].Set()), vs.APIVersion(), vs.Applied())
			delete(managed.Fields(), manager)
			length--

			// Use the time from the update being merged into the bucket, since it is more recent.
			managed.Times()[bucket] = time
		} else {
			versionToFirstManager[version] = manager
		}
	}

	return managed, nil
}


NewConflictError

// NewConflictError returns an error including details on the requests apply conflicts
func NewConflictError(conflicts merge.Conflicts) *errors.StatusError {
	causes := []metav1.StatusCause{}
	for _, conflict := range conflicts {
		causes = append(causes, metav1.StatusCause{
			Type:    metav1.CauseTypeFieldManagerConflict,
			Message: fmt.Sprintf("conflict with %v", printManager(conflict.Manager)),
			Field:   conflict.Path.String(),
		})
	}
	return errors.NewApplyConflict(causes, getConflictMessage(conflicts))
}


getConflictMessage

func getConflictMessage(conflicts merge.Conflicts) string {
	if len(conflicts) == 1 {
		return fmt.Sprintf("Apply failed with 1 conflict: conflict with %v: %v", printManager(conflicts[0].Manager), conflicts[0].Path)
	}

	m := map[string][]fieldpath.Path{}
	for _, conflict := range conflicts {
		m[conflict.Manager] = append(m[conflict.Manager], conflict.Path)
	}

	uniqueManagers := []string{}
	for manager := range m {
		uniqueManagers = append(uniqueManagers, manager)
	}

	// Print conflicts by sorted managers.
	sort.Strings(uniqueManagers)

	messages := []string{}
	for _, manager := range uniqueManagers {
		messages = append(messages, fmt.Sprintf("conflicts with %v:", printManager(manager)))
		for _, path := range m[manager] {
			messages = append(messages, fmt.Sprintf("- %v", path))
		}
	}
	return fmt.Sprintf("Apply failed with %d conflicts: %s", len(conflicts), strings.Join(messages, "\n"))
}


printManager

func printManager(manager string) string {
	encodedManager := &metav1.ManagedFieldsEntry{}
	if err := json.Unmarshal([]byte(manager), encodedManager); err != nil {
		return fmt.Sprintf("%q", manager)
	}
	managerStr := fmt.Sprintf("%q", encodedManager.Manager)
	if encodedManager.Subresource != "" {
		managerStr = fmt.Sprintf("%s with subresource %q", managerStr, encodedManager.Subresource)
	}
	if encodedManager.Operation == metav1.ManagedFieldsOperationUpdate {
		if encodedManager.Time == nil {
			return fmt.Sprintf("%s using %v", managerStr, encodedManager.APIVersion)
		}
		return fmt.Sprintf("%s using %v at %v", managerStr, encodedManager.APIVersion, encodedManager.Time.UTC().Format(time.RFC3339))
	}
	return managerStr
}


NewFieldManager

// NewFieldManager creates a new FieldManager that decodes, manages, then re-encodes managedFields
// on update and apply requests.
func NewFieldManager(f Manager, subresource string) *FieldManager {
	return &FieldManager{fieldManager: f, subresource: subresource}
}


NewDefaultFieldManager

// newDefaultFieldManager is a helper function which wraps a Manager with certain default logic.
func NewDefaultFieldManager(f Manager, typeConverter TypeConverter, objectConverter runtime.ObjectConvertor, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, subresource string) *FieldManager {
	return NewFieldManager(
		NewLastAppliedUpdater(
			NewLastAppliedManager(
				NewProbabilisticSkipNonAppliedManager(
					NewCapManagersManager(
						NewBuildManagerInfoManager(
							NewManagedFieldsUpdater(
								NewStripMetaManager(f),
							), kind.GroupVersion(), subresource,
						), DefaultMaxUpdateManagers,
					), objectCreater, kind, DefaultTrackOnCreateProbability,
				), typeConverter, objectConverter, kind.GroupVersion()),
		), subresource,
	)
}


decodeLiveOrNew

func decodeLiveOrNew(liveObj, newObj runtime.Object, ignoreManagedFieldsFromRequestObject bool) (Managed, error) {
	liveAccessor, err := meta.Accessor(liveObj)
	if err != nil {
		return nil, err
	}

	// We take the managedFields of the live object in case the request tries to
	// manually set managedFields via a subresource.
	if ignoreManagedFieldsFromRequestObject {
		return emptyManagedFieldsOnErr(DecodeManagedFields(liveAccessor.GetManagedFields()))
	}

	// If the object doesn't have metadata, we should just return without trying to
	// set the managedFields at all, so creates/updates/patches will work normally.
	newAccessor, err := meta.Accessor(newObj)
	if err != nil {
		return nil, err
	}

	if isResetManagedFields(newAccessor.GetManagedFields()) {
		return NewEmptyManaged(), nil
	}

	// If the managed field is empty or we failed to decode it,
	// let's try the live object. This is to prevent clients who
	// don't understand managedFields from deleting it accidentally.
	managed, err := DecodeManagedFields(newAccessor.GetManagedFields())
	if err != nil || len(managed.Fields()) == 0 {
		return emptyManagedFieldsOnErr(DecodeManagedFields(liveAccessor.GetManagedFields()))
	}
	return managed, nil
}


emptyManagedFieldsOnErr

func emptyManagedFieldsOnErr(managed Managed, err error) (Managed, error) {
	if err != nil {
		return NewEmptyManaged(), nil
	}
	return managed, nil
}


Update

// Update is used when the object has already been merged (non-apply
// use-case), and simply updates the managed fields in the output
// object.
func (f *FieldManager) Update(liveObj, newObj runtime.Object, manager string) (object runtime.Object, err error) {
	// First try to decode the managed fields provided in the update,
	// This is necessary to allow directly updating managed fields.
	isSubresource := f.subresource != ""
	managed, err := decodeLiveOrNew(liveObj, newObj, isSubresource)
	if err != nil {
		return newObj, nil
	}

	RemoveObjectManagedFields(newObj)

	if object, managed, err = f.fieldManager.Update(liveObj, newObj, managed, manager); err != nil {
		return nil, err
	}

	if err = EncodeObjectManagedFields(object, managed); err != nil {
		return nil, fmt.Errorf("failed to encode managed fields: %v", err)
	}

	return object, nil
}


UpdateNoErrors

// UpdateNoErrors is the same as Update, but it will not return
// errors. If an error happens, the object is returned with
// managedFields cleared.
func (f *FieldManager) UpdateNoErrors(liveObj, newObj runtime.Object, manager string) runtime.Object {
	obj, err := f.Update(liveObj, newObj, manager)
	if err != nil {
		atMostEverySecond.Do(func() {
			ns, name := "unknown", "unknown"
			if accessor, err := meta.Accessor(newObj); err == nil {
				ns = accessor.GetNamespace()
				name = accessor.GetName()
			}

			klog.ErrorS(err, "[SHOULD NOT HAPPEN] failed to update managedFields", "versionKind",
				newObj.GetObjectKind().GroupVersionKind(), "namespace", ns, "name", name)
		})
		// Explicitly remove managedFields on failure, so that
		// we can't have garbage in it.
		RemoveObjectManagedFields(newObj)
		return newObj
	}
	return obj
}


isResetManagedFields

// Returns true if the managedFields indicate that the user is trying to
// reset the managedFields, i.e. if the list is non-nil but empty, or if
// the list has one empty item.
func isResetManagedFields(managedFields []metav1.ManagedFieldsEntry) bool {
	if len(managedFields) == 0 {
		return managedFields != nil
	}

	if len(managedFields) == 1 {
		return reflect.DeepEqual(managedFields[0], metav1.ManagedFieldsEntry{})
	}

	return false
}


Apply

// Apply is used when server-side apply is called, as it merges the
// object and updates the managed fields.
func (f *FieldManager) Apply(liveObj, appliedObj runtime.Object, manager string, force bool) (object runtime.Object, err error) {
	// If the object doesn't have metadata, apply isn't allowed.
	accessor, err := meta.Accessor(liveObj)
	if err != nil {
		return nil, fmt.Errorf("couldn't get accessor: %v", err)
	}

	// Decode the managed fields in the live object, since it isn't allowed in the patch.
	managed, err := DecodeManagedFields(accessor.GetManagedFields())
	if err != nil {
		return nil, fmt.Errorf("failed to decode managed fields: %v", err)
	}

	object, managed, err = f.fieldManager.Apply(liveObj, appliedObj, managed, manager, force)
	if err != nil {
		if conflicts, ok := err.(merge.Conflicts); ok {
			return nil, NewConflictError(conflicts)
		}
		return nil, err
	}

	if err = EncodeObjectManagedFields(object, managed); err != nil {
		return nil, fmt.Errorf("failed to encode managed fields: %v", err)
	}

	return object, nil
}


FieldsToSet

// FieldsToSet creates a set paths from an input trie of fields
func FieldsToSet(f metav1.FieldsV1) (s fieldpath.Set, err error) {
	err = s.FromJSON(bytes.NewReader(f.Raw))
	return s, err
}


SetToFields

// SetToFields creates a trie of fields from an input set of paths
func SetToFields(s fieldpath.Set) (f metav1.FieldsV1, err error) {
	f.Raw, err = s.ToJSON()
	return f, err
}


SetLastApplied

// SetLastApplied sets the last-applied annotation the given value in
// the object.
func SetLastApplied(obj runtime.Object, value string) error {
	accessor, err := meta.Accessor(obj)
	if err != nil {
		panic(fmt.Sprintf("couldn't get accessor: %v", err))
	}
	var annotations = accessor.GetAnnotations()
	if annotations == nil {
		annotations = map[string]string{}
	}
	annotations[LastAppliedConfigAnnotation] = value
	if err := apimachineryvalidation.ValidateAnnotationsSize(annotations); err != nil {
		delete(annotations, LastAppliedConfigAnnotation)
	}
	accessor.SetAnnotations(annotations)
	return nil
}


NewLastAppliedManager

// NewLastAppliedManager converts the client-side apply annotation to
// server-side apply managed fields
func NewLastAppliedManager(fieldManager Manager, typeConverter TypeConverter, objectConverter runtime.ObjectConvertor, groupVersion schema.GroupVersion) Manager {
	return &lastAppliedManager{
		fieldManager:    fieldManager,
		typeConverter:   typeConverter,
		objectConverter: objectConverter,
		groupVersion:    groupVersion,
	}
}


Update

// Update implements Manager.
func (f *lastAppliedManager) Update(liveObj, newObj runtime.Object, managed Managed, manager string) (runtime.Object, Managed, error) {
	return f.fieldManager.Update(liveObj, newObj, managed, manager)
}


Apply

// Apply will consider the last-applied annotation
// for upgrading an object managed by client-side apply to server-side apply
// without conflicts.
func (f *lastAppliedManager) Apply(liveObj, newObj runtime.Object, managed Managed, manager string, force bool) (runtime.Object, Managed, error) {
	newLiveObj, newManaged, newErr := f.fieldManager.Apply(liveObj, newObj, managed, manager, force)
	// Upgrade the client-side apply annotation only from kubectl server-side-apply.
	// To opt-out of this behavior, users may specify a different field manager.
	if manager != "kubectl" {
		return newLiveObj, newManaged, newErr
	}

	// Check if we have conflicts
	if newErr == nil {
		return newLiveObj, newManaged, newErr
	}
	conflicts, ok := newErr.(merge.Conflicts)
	if !ok {
		return newLiveObj, newManaged, newErr
	}
	conflictSet := conflictsToSet(conflicts)

	// Check if conflicts are allowed due to client-side apply,
	// and if so, then force apply
	allowedConflictSet, err := f.allowedConflictsFromLastApplied(liveObj)
	if err != nil {
		return newLiveObj, newManaged, newErr
	}
	if !conflictSet.Difference(allowedConflictSet).Empty() {
		newConflicts := conflictsDifference(conflicts, allowedConflictSet)
		return newLiveObj, newManaged, newConflicts
	}

	return f.fieldManager.Apply(liveObj, newObj, managed, manager, true)
}


allowedConflictsFromLastApplied

func (f *lastAppliedManager) allowedConflictsFromLastApplied(liveObj runtime.Object) (*fieldpath.Set, error) {
	var accessor, err = meta.Accessor(liveObj)
	if err != nil {
		panic(fmt.Sprintf("couldn't get accessor: %v", err))
	}

	// If there is no client-side apply annotation, then there is nothing to do
	var annotations = accessor.GetAnnotations()
	if annotations == nil {
		return nil, fmt.Errorf("no last applied annotation")
	}
	var lastApplied, ok = annotations[LastAppliedConfigAnnotation]
	if !ok || lastApplied == "" {
		return nil, fmt.Errorf("no last applied annotation")
	}

	liveObjVersioned, err := f.objectConverter.ConvertToVersion(liveObj, f.groupVersion)
	if err != nil {
		return nil, fmt.Errorf("failed to convert live obj to versioned: %v", err)
	}

	liveObjTyped, err := f.typeConverter.ObjectToTyped(liveObjVersioned)
	if err != nil {
		return nil, fmt.Errorf("failed to convert live obj to typed: %v", err)
	}

	var lastAppliedObj = &unstructured.Unstructured{Object: map[string]interface{}{}}
	err = json.Unmarshal([]byte(lastApplied), lastAppliedObj)
	if err != nil {
		return nil, fmt.Errorf("failed to decode last applied obj: %v in '%s'", err, lastApplied)
	}

	if lastAppliedObj.GetAPIVersion() != f.groupVersion.String() {
		return nil, fmt.Errorf("expected version of last applied to match live object '%s', but got '%s': %v", f.groupVersion.String(), lastAppliedObj.GetAPIVersion(), err)
	}

	lastAppliedObjTyped, err := f.typeConverter.ObjectToTyped(lastAppliedObj)
	if err != nil {
		return nil, fmt.Errorf("failed to convert last applied to typed: %v", err)
	}

	lastAppliedObjFieldSet, err := lastAppliedObjTyped.ToFieldSet()
	if err != nil {
		return nil, fmt.Errorf("failed to create fieldset for last applied object: %v", err)
	}

	comparison, err := lastAppliedObjTyped.Compare(liveObjTyped)
	if err != nil {
		return nil, fmt.Errorf("failed to compare last applied object and live object: %v", err)
	}

	// Remove fields in last applied that are different, added, or missing in
	// the live object.
	// Because last-applied fields don't match the live object fields,
	// then we don't own these fields.
	lastAppliedObjFieldSet = lastAppliedObjFieldSet.
		Difference(comparison.Modified).
		Difference(comparison.Added).
		Difference(comparison.Removed)

	return lastAppliedObjFieldSet, nil
}


conflictsToSet

// TODO: replace with merge.Conflicts.ToSet()
func conflictsToSet(conflicts merge.Conflicts) *fieldpath.Set {
	conflictSet := fieldpath.NewSet()
	for _, conflict := range []merge.Conflict(conflicts) {
		conflictSet.Insert(conflict.Path)
	}
	return conflictSet
}


conflictsDifference

func conflictsDifference(conflicts merge.Conflicts, s *fieldpath.Set) merge.Conflicts {
	newConflicts := []merge.Conflict{}
	for _, conflict := range []merge.Conflict(conflicts) {
		if !s.Has(conflict.Path) {
			newConflicts = append(newConflicts, conflict)
		}
	}
	return newConflicts
}


NewLastAppliedUpdater

// NewLastAppliedUpdater sets the client-side apply annotation up to date with
// server-side apply managed fields
func NewLastAppliedUpdater(fieldManager Manager) Manager {
	return &lastAppliedUpdater{
		fieldManager: fieldManager,
	}
}


Update

// Update implements Manager.
func (f *lastAppliedUpdater) Update(liveObj, newObj runtime.Object, managed Managed, manager string) (runtime.Object, Managed, error) {
	return f.fieldManager.Update(liveObj, newObj, managed, manager)
}


Apply

// server-side apply managed fields
func (f *lastAppliedUpdater) Apply(liveObj, newObj runtime.Object, managed Managed, manager string, force bool) (runtime.Object, Managed, error) {
	liveObj, managed, err := f.fieldManager.Apply(liveObj, newObj, managed, manager, force)
	if err != nil {
		return liveObj, managed, err
	}

	// Sync the client-side apply annotation only from kubectl server-side apply.
	// To opt-out of this behavior, users may specify a different field manager.
	//
	// If the client-side apply annotation doesn't exist,
	// then continue because we have no annotation to update
	if manager == "kubectl" && hasLastApplied(liveObj) {
		lastAppliedValue, err := buildLastApplied(newObj)
		if err != nil {
			return nil, nil, fmt.Errorf("failed to build last-applied annotation: %v", err)
		}
		err = SetLastApplied(liveObj, lastAppliedValue)
		if err != nil {
			return nil, nil, fmt.Errorf("failed to set last-applied annotation: %v", err)
		}
	}
	return liveObj, managed, err
}


hasLastApplied

func hasLastApplied(obj runtime.Object) bool {
	var accessor, err = meta.Accessor(obj)
	if err != nil {
		panic(fmt.Sprintf("couldn't get accessor: %v", err))
	}
	var annotations = accessor.GetAnnotations()
	if annotations == nil {
		return false
	}
	lastApplied, ok := annotations[LastAppliedConfigAnnotation]
	return ok && len(lastApplied) > 0
}


buildLastApplied

func buildLastApplied(obj runtime.Object) (string, error) {
	obj = obj.DeepCopyObject()

	var accessor, err = meta.Accessor(obj)
	if err != nil {
		panic(fmt.Sprintf("couldn't get accessor: %v", err))
	}

	// Remove the annotation from the object before encoding the object
	var annotations = accessor.GetAnnotations()
	delete(annotations, LastAppliedConfigAnnotation)
	accessor.SetAnnotations(annotations)

	lastApplied, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
	if err != nil {
		return "", fmt.Errorf("couldn't encode object into last applied annotation: %v", err)
	}
	return string(lastApplied), nil
}


Fields

// Fields implements ManagedInterface.
func (m *managedStruct) Fields() fieldpath.ManagedFields {
	return m.fields
}


Times

// Times implements ManagedInterface.
func (m *managedStruct) Times() map[string]*metav1.Time {
	return m.times
}


NewEmptyManaged

// NewEmptyManaged creates an empty ManagedInterface.
func NewEmptyManaged() ManagedInterface {
	return NewManaged(fieldpath.ManagedFields{}, map[string]*metav1.Time{})
}


NewManaged

// NewManaged creates a ManagedInterface from a fieldpath.ManagedFields and the timestamps associated with each operation.
func NewManaged(f fieldpath.ManagedFields, t map[string]*metav1.Time) ManagedInterface {
	return &managedStruct{
		fields: f,
		times:  t,
	}
}


RemoveObjectManagedFields

// RemoveObjectManagedFields removes the ManagedFields from the object
// before we merge so that it doesn't appear in the ManagedFields
// recursively.
func RemoveObjectManagedFields(obj runtime.Object) {
	accessor, err := meta.Accessor(obj)
	if err != nil {
		panic(fmt.Sprintf("couldn't get accessor: %v", err))
	}
	accessor.SetManagedFields(nil)
}


EncodeObjectManagedFields

// EncodeObjectManagedFields converts and stores the fieldpathManagedFields into the objects ManagedFields
func EncodeObjectManagedFields(obj runtime.Object, managed ManagedInterface) error {
	accessor, err := meta.Accessor(obj)
	if err != nil {
		panic(fmt.Sprintf("couldn't get accessor: %v", err))
	}

	encodedManagedFields, err := encodeManagedFields(managed)
	if err != nil {
		return fmt.Errorf("failed to convert back managed fields to API: %v", err)
	}
	accessor.SetManagedFields(encodedManagedFields)

	return nil
}


DecodeManagedFields

// DecodeManagedFields converts ManagedFields from the wire format (api format)
// to the format used by sigs.k8s.io/structured-merge-diff
func DecodeManagedFields(encodedManagedFields []metav1.ManagedFieldsEntry) (ManagedInterface, error) {
	managed := managedStruct{}
	managed.fields = make(fieldpath.ManagedFields, len(encodedManagedFields))
	managed.times = make(map[string]*metav1.Time, len(encodedManagedFields))

	for i, encodedVersionedSet := range encodedManagedFields {
		switch encodedVersionedSet.Operation {
		case metav1.ManagedFieldsOperationApply, metav1.ManagedFieldsOperationUpdate:
		default:
			return nil, fmt.Errorf("operation must be `Apply` or `Update`")
		}
		if len(encodedVersionedSet.APIVersion) < 1 {
			return nil, fmt.Errorf("apiVersion must not be empty")
		}
		switch encodedVersionedSet.FieldsType {
		case "FieldsV1":
			// Valid case.
		case "":
			return nil, fmt.Errorf("missing fieldsType in managed fields entry %d", i)
		default:
			return nil, fmt.Errorf("invalid fieldsType %q in managed fields entry %d", encodedVersionedSet.FieldsType, i)
		}
		manager, err := BuildManagerIdentifier(&encodedVersionedSet)
		if err != nil {
			return nil, fmt.Errorf("error decoding manager from %v: %v", encodedVersionedSet, err)
		}
		managed.fields[manager], err = decodeVersionedSet(&encodedVersionedSet)
		if err != nil {
			return nil, fmt.Errorf("error decoding versioned set from %v: %v", encodedVersionedSet, err)
		}
		managed.times[manager] = encodedVersionedSet.Time
	}
	return &managed, nil
}


BuildManagerIdentifier

// BuildManagerIdentifier creates a manager identifier string from a ManagedFieldsEntry
func BuildManagerIdentifier(encodedManager *metav1.ManagedFieldsEntry) (manager string, err error) {
	encodedManagerCopy := *encodedManager

	// Never include fields type in the manager identifier
	encodedManagerCopy.FieldsType = ""

	// Never include the fields in the manager identifier
	encodedManagerCopy.FieldsV1 = nil

	// Never include the time in the manager identifier
	encodedManagerCopy.Time = nil

	// For appliers, don't include the APIVersion in the manager identifier,
	// so it will always have the same manager identifier each time it applied.
	if encodedManager.Operation == metav1.ManagedFieldsOperationApply {
		encodedManagerCopy.APIVersion = ""
	}

	// Use the remaining fields to build the manager identifier
	b, err := json.Marshal(&encodedManagerCopy)
	if err != nil {
		return "", fmt.Errorf("error marshalling manager identifier: %v", err)
	}

	return string(b), nil
}


decodeVersionedSet

func decodeVersionedSet(encodedVersionedSet *metav1.ManagedFieldsEntry) (versionedSet fieldpath.VersionedSet, err error) {
	fields := EmptyFields
	if encodedVersionedSet.FieldsV1 != nil {
		fields = *encodedVersionedSet.FieldsV1
	}
	set, err := FieldsToSet(fields)
	if err != nil {
		return nil, fmt.Errorf("error decoding set: %v", err)
	}
	return fieldpath.NewVersionedSet(&set, fieldpath.APIVersion(encodedVersionedSet.APIVersion), encodedVersionedSet.Operation == metav1.ManagedFieldsOperationApply), nil
}


encodeManagedFields

// encodeManagedFields converts ManagedFields from the format used by
// sigs.k8s.io/structured-merge-diff to the wire format (api format)
func encodeManagedFields(managed ManagedInterface) (encodedManagedFields []metav1.ManagedFieldsEntry, err error) {
	if len(managed.Fields()) == 0 {
		return nil, nil
	}
	encodedManagedFields = []metav1.ManagedFieldsEntry{}
	for manager := range managed.Fields() {
		versionedSet := managed.Fields()[manager]
		v, err := encodeManagerVersionedSet(manager, versionedSet)
		if err != nil {
			return nil, fmt.Errorf("error encoding versioned set for %v: %v", manager, err)
		}
		if t, ok := managed.Times()[manager]; ok {
			v.Time = t
		}
		encodedManagedFields = append(encodedManagedFields, *v)
	}
	return sortEncodedManagedFields(encodedManagedFields)
}


sortEncodedManagedFields

func sortEncodedManagedFields(encodedManagedFields []metav1.ManagedFieldsEntry) (sortedManagedFields []metav1.ManagedFieldsEntry, err error) {
	sort.Slice(encodedManagedFields, func(i, j int) bool {
		p, q := encodedManagedFields[i], encodedManagedFields[j]

		if p.Operation != q.Operation {
			return p.Operation < q.Operation
		}

		pSeconds, qSeconds := int64(0), int64(0)
		if p.Time != nil {
			pSeconds = p.Time.Unix()
		}
		if q.Time != nil {
			qSeconds = q.Time.Unix()
		}
		if pSeconds != qSeconds {
			return pSeconds < qSeconds
		}

		if p.Manager != q.Manager {
			return p.Manager < q.Manager
		}

		if p.APIVersion != q.APIVersion {
			return p.APIVersion < q.APIVersion
		}
		return p.Subresource < q.Subresource
	})

	return encodedManagedFields, nil
}


encodeManagerVersionedSet

func encodeManagerVersionedSet(manager string, versionedSet fieldpath.VersionedSet) (encodedVersionedSet *metav1.ManagedFieldsEntry, err error) {
	encodedVersionedSet = &metav1.ManagedFieldsEntry{}

	// Get as many fields as we can from the manager identifier
	err = json.Unmarshal([]byte(manager), encodedVersionedSet)
	if err != nil {
		return nil, fmt.Errorf("error unmarshalling manager identifier %v: %v", manager, err)
	}

	// Get the APIVersion, Operation, and Fields from the VersionedSet
	encodedVersionedSet.APIVersion = string(versionedSet.APIVersion())
	if versionedSet.Applied() {
		encodedVersionedSet.Operation = metav1.ManagedFieldsOperationApply
	}
	encodedVersionedSet.FieldsType = "FieldsV1"
	fields, err := SetToFields(*versionedSet.Set())
	if err != nil {
		return nil, fmt.Errorf("error encoding set: %v", err)
	}
	encodedVersionedSet.FieldsV1 = &fields

	return encodedVersionedSet, nil
}


NewManagedFieldsUpdater

// NewManagedFieldsUpdater is responsible for updating the managedfields
// in the object, updating the time of the operation as necessary. For
// updates, it uses a hard-coded manager to detect if things have
// changed, and swaps back the correct manager after the operation is
// done.
func NewManagedFieldsUpdater(fieldManager Manager) Manager {
	return &managedFieldsUpdater{
		fieldManager: fieldManager,
	}
}


Update

// Update implements Manager.
func (f *managedFieldsUpdater) Update(liveObj, newObj runtime.Object, managed Managed, manager string) (runtime.Object, Managed, error) {
	self := "current-operation"
	object, managed, err := f.fieldManager.Update(liveObj, newObj, managed, self)
	if err != nil {
		return object, managed, err
	}

	// If the current operation took any fields from anything, it means the object changed,
	// so update the timestamp of the managedFieldsEntry and merge with any previous updates from the same manager
	if vs, ok := managed.Fields()[self]; ok {
		delete(managed.Fields(), self)

		if previous, ok := managed.Fields()[manager]; ok {
			managed.Fields()[manager] = fieldpath.NewVersionedSet(vs.Set().Union(previous.Set()), vs.APIVersion(), vs.Applied())
		} else {
			managed.Fields()[manager] = vs
		}

		managed.Times()[manager] = &metav1.Time{Time: time.Now().UTC()}
	}

	return object, managed, nil
}


Apply

// Apply implements Manager.
func (f *managedFieldsUpdater) Apply(liveObj, appliedObj runtime.Object, managed Managed, fieldManager string, force bool) (runtime.Object, Managed, error) {
	object, managed, err := f.fieldManager.Apply(liveObj, appliedObj, managed, fieldManager, force)
	if err != nil {
		return object, managed, err
	}
	if object != nil {
		managed.Times()[fieldManager] = &metav1.Time{Time: time.Now().UTC()}
	} else {
		object = liveObj.DeepCopyObject()
		RemoveObjectManagedFields(object)
	}
	return object, managed, nil
}


NewPathElement

// NewPathElement parses a serialized path element
func NewPathElement(s string) (fieldpath.PathElement, error) {
	split := strings.SplitN(s, Separator, 2)
	if len(split) < 2 {
		return fieldpath.PathElement{}, fmt.Errorf("missing colon: %v", s)
	}
	switch split[0] {
	case Field:
		return fieldpath.PathElement{
			FieldName: &split[1],
		}, nil
	case Value:
		val, err := value.FromJSON([]byte(split[1]))
		if err != nil {
			return fieldpath.PathElement{}, err
		}
		return fieldpath.PathElement{
			Value: &val,
		}, nil
	case Index:
		i, err := strconv.Atoi(split[1])
		if err != nil {
			return fieldpath.PathElement{}, err
		}
		return fieldpath.PathElement{
			Index: &i,
		}, nil
	case Key:
		kv := map[string]json.RawMessage{}
		err := json.Unmarshal([]byte(split[1]), &kv)
		if err != nil {
			return fieldpath.PathElement{}, err
		}
		fields := value.FieldList{}
		for k, v := range kv {
			b, err := json.Marshal(v)
			if err != nil {
				return fieldpath.PathElement{}, err
			}
			val, err := value.FromJSON(b)
			if err != nil {
				return fieldpath.PathElement{}, err
			}

			fields = append(fields, value.Field{
				Name:  k,
				Value: val,
			})
		}
		return fieldpath.PathElement{
			Key: &fields,
		}, nil
	default:
		// Ignore unknown key types
		return fieldpath.PathElement{}, nil
	}
}


PathElementString

// PathElementString serializes a path element
func PathElementString(pe fieldpath.PathElement) (string, error) {
	switch {
	case pe.FieldName != nil:
		return Field + Separator + *pe.FieldName, nil
	case pe.Key != nil:
		kv := map[string]json.RawMessage{}
		for _, k := range *pe.Key {
			b, err := value.ToJSON(k.Value)
			if err != nil {
				return "", err
			}
			m := json.RawMessage{}
			err = json.Unmarshal(b, &m)
			if err != nil {
				return "", err
			}
			kv[k.Name] = m
		}
		b, err := json.Marshal(kv)
		if err != nil {
			return "", err
		}
		return Key + ":" + string(b), nil
	case pe.Value != nil:
		b, err := value.ToJSON(*pe.Value)
		if err != nil {
			return "", err
		}
		return Value + ":" + string(b), nil
	case pe.Index != nil:
		return Index + ":" + strconv.Itoa(*pe.Index), nil
	default:
		return "", errors.New("Invalid type of path element")
	}
}


NewSkipNonAppliedManager

// 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 {
	return NewProbabilisticSkipNonAppliedManager(fieldManager, objectCreater, gvk, 0.0)
}


NewProbabilisticSkipNonAppliedManager

// 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{
		fieldManager:           fieldManager,
		objectCreater:          objectCreater,
		gvk:                    gvk,
		beforeApplyManagerName: "before-first-apply",
		probability:            p,
	}
}


Update

// Update implements Manager.
func (f *skipNonAppliedManager) Update(liveObj, newObj runtime.Object, managed Managed, manager string) (runtime.Object, Managed, error) {
	accessor, err := meta.Accessor(liveObj)
	if err != 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)
}


Apply

// Apply implements Manager.
func (f *skipNonAppliedManager) Apply(liveObj, appliedObj runtime.Object, managed Managed, fieldManager string, force bool) (runtime.Object, Managed, error) {
	if len(managed.Fields()) == 0 {
		emptyObj, err := f.objectCreater.New(f.gvk)
		if err != nil {
			return nil, nil, fmt.Errorf("failed to create empty object of type %v: %v", f.gvk, err)
		}
		liveObj, managed, err = f.fieldManager.Update(emptyObj, liveObj, managed, f.beforeApplyManagerName)
		if err != nil {
			return nil, nil, fmt.Errorf("failed to create manager for existing fields: %v", err)
		}
	}
	return f.fieldManager.Apply(liveObj, appliedObj, managed, fieldManager, force)
}


NewStripMetaManager

// NewStripMetaManager creates a new Manager that strips metadata and typemeta fields from the manager's fieldset.
func NewStripMetaManager(fieldManager Manager) Manager {
	return &stripMetaManager{
		fieldManager: fieldManager,
		stripSet: fieldpath.NewSet(
			fieldpath.MakePathOrDie("apiVersion"),
			fieldpath.MakePathOrDie("kind"),
			fieldpath.MakePathOrDie("metadata"),
			fieldpath.MakePathOrDie("metadata", "name"),
			fieldpath.MakePathOrDie("metadata", "namespace"),
			fieldpath.MakePathOrDie("metadata", "creationTimestamp"),
			fieldpath.MakePathOrDie("metadata", "selfLink"),
			fieldpath.MakePathOrDie("metadata", "uid"),
			fieldpath.MakePathOrDie("metadata", "clusterName"),
			fieldpath.MakePathOrDie("metadata", "generation"),
			fieldpath.MakePathOrDie("metadata", "managedFields"),
			fieldpath.MakePathOrDie("metadata", "resourceVersion"),
		),
	}
}


Update

// Update implements Manager.
func (f *stripMetaManager) Update(liveObj, newObj runtime.Object, managed Managed, manager string) (runtime.Object, Managed, error) {
	newObj, managed, err := f.fieldManager.Update(liveObj, newObj, managed, manager)
	if err != nil {
		return nil, nil, err
	}
	f.stripFields(managed.Fields(), manager)
	return newObj, managed, nil
}


Apply

// Apply implements Manager.
func (f *stripMetaManager) Apply(liveObj, appliedObj runtime.Object, managed Managed, manager string, force bool) (runtime.Object, Managed, error) {
	newObj, managed, err := f.fieldManager.Apply(liveObj, appliedObj, managed, manager, force)
	if err != nil {
		return nil, nil, err
	}
	f.stripFields(managed.Fields(), manager)
	return newObj, managed, nil
}


stripFields

// stripFields removes a predefined set of paths found in typed from managed
func (f *stripMetaManager) stripFields(managed fieldpath.ManagedFields, manager string) {
	vs, ok := managed[manager]
	if ok {
		if vs == nil {
			panic(fmt.Sprintf("Found unexpected nil manager which should never happen: %s", manager))
		}
		newSet := vs.Set().Difference(f.stripSet)
		if newSet.Empty() {
			delete(managed, manager)
		} else {
			managed[manager] = fieldpath.NewVersionedSet(newSet, vs.APIVersion(), vs.Applied())
		}
	}
}


NewStructuredMergeManager

// NewStructuredMergeManager creates a new Manager that merges apply requests
// and update managed fields for other types of requests.
func NewStructuredMergeManager(typeConverter TypeConverter, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, gv schema.GroupVersion, hub schema.GroupVersion, resetFields map[fieldpath.APIVersion]*fieldpath.Set) (Manager, error) {
	return &structuredMergeManager{
		typeConverter:   typeConverter,
		objectConverter: objectConverter,
		objectDefaulter: objectDefaulter,
		groupVersion:    gv,
		hubVersion:      hub,
		updater: merge.Updater{
			Converter:     newVersionConverter(typeConverter, objectConverter, hub), // This is the converter provided to SMD from k8s
			IgnoredFields: resetFields,
		},
	}, nil
}


NewCRDStructuredMergeManager

// NewCRDStructuredMergeManager creates a new Manager specifically for
// CRDs. This allows for the possibility of fields which are not defined
// in models, as well as having no models defined at all.
func NewCRDStructuredMergeManager(typeConverter TypeConverter, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, gv schema.GroupVersion, hub schema.GroupVersion, resetFields map[fieldpath.APIVersion]*fieldpath.Set) (_ Manager, err error) {
	return &structuredMergeManager{
		typeConverter:   typeConverter,
		objectConverter: objectConverter,
		objectDefaulter: objectDefaulter,
		groupVersion:    gv,
		hubVersion:      hub,
		updater: merge.Updater{
			Converter:     newCRDVersionConverter(typeConverter, objectConverter, hub),
			IgnoredFields: resetFields,
		},
	}, nil
}


objectGVKNN

func objectGVKNN(obj runtime.Object) string {
	name := "<unknown>"
	namespace := "<unknown>"
	if accessor, err := meta.Accessor(obj); err == nil {
		name = accessor.GetName()
		namespace = accessor.GetNamespace()
	}

	return fmt.Sprintf("%v/%v; %v", namespace, name, obj.GetObjectKind().GroupVersionKind())
}


Update

// Update implements Manager.
func (f *structuredMergeManager) Update(liveObj, newObj runtime.Object, managed Managed, manager string) (runtime.Object, Managed, error) {
	newObjVersioned, err := f.toVersioned(newObj)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to convert new object (%v) to proper version (%v): %v", objectGVKNN(newObj), f.groupVersion, err)
	}
	liveObjVersioned, err := f.toVersioned(liveObj)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to convert live object (%v) to proper version: %v", objectGVKNN(liveObj), err)
	}
	newObjTyped, err := f.typeConverter.ObjectToTyped(newObjVersioned)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to convert new object (%v) to smd typed: %v", objectGVKNN(newObjVersioned), err)
	}
	liveObjTyped, err := f.typeConverter.ObjectToTyped(liveObjVersioned)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to convert live object (%v) to smd typed: %v", objectGVKNN(liveObjVersioned), err)
	}
	apiVersion := fieldpath.APIVersion(f.groupVersion.String())

	// TODO(apelisse) use the first return value when unions are implemented
	_, managedFields, err := f.updater.Update(liveObjTyped, newObjTyped, apiVersion, managed.Fields(), manager)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to update ManagedFields (%v): %v", objectGVKNN(newObjVersioned), err)
	}
	managed = NewManaged(managedFields, managed.Times())

	return newObj, managed, nil
}


Apply

// Apply implements Manager.
func (f *structuredMergeManager) Apply(liveObj, patchObj runtime.Object, managed Managed, manager string, force bool) (runtime.Object, Managed, error) {
	// Check that the patch object has the same version as the live object
	if patchVersion := patchObj.GetObjectKind().GroupVersionKind().GroupVersion(); patchVersion != f.groupVersion {
		return nil, nil,
			errors.NewBadRequest(
				fmt.Sprintf("Incorrect version specified in apply patch. "+
					"Specified patch version: %s, expected: %s",
					patchVersion, f.groupVersion))
	}

	patchObjMeta, err := meta.Accessor(patchObj)
	if err != nil {
		return nil, nil, fmt.Errorf("couldn't get accessor: %v", err)
	}
	if patchObjMeta.GetManagedFields() != nil {
		return nil, nil, errors.NewBadRequest("metadata.managedFields must be nil")
	}

	liveObjVersioned, err := f.toVersioned(liveObj)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to convert live object (%v) to proper version: %v", objectGVKNN(liveObj), err)
	}

	patchObjTyped, err := f.typeConverter.ObjectToTyped(patchObj)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to create typed patch object (%v): %v", objectGVKNN(patchObj), err)
	}
	liveObjTyped, err := f.typeConverter.ObjectToTyped(liveObjVersioned)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to create typed live object (%v): %v", objectGVKNN(liveObjVersioned), err)
	}

	apiVersion := fieldpath.APIVersion(f.groupVersion.String())
	newObjTyped, managedFields, err := f.updater.Apply(liveObjTyped, patchObjTyped, apiVersion, managed.Fields(), manager, force)
	if err != nil {
		return nil, nil, err
	}
	managed = NewManaged(managedFields, managed.Times())

	if newObjTyped == nil {
		return nil, managed, nil
	}

	newObj, err := f.typeConverter.TypedToObject(newObjTyped)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to convert new typed object (%v) to object: %v", objectGVKNN(patchObj), err)
	}

	newObjVersioned, err := f.toVersioned(newObj)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to convert new object (%v) to proper version: %v", objectGVKNN(patchObj), err)
	}
	f.objectDefaulter.Default(newObjVersioned)

	newObjUnversioned, err := f.toUnversioned(newObjVersioned)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to convert to unversioned (%v): %v", objectGVKNN(patchObj), err)
	}
	return newObjUnversioned, managed, nil
}


toVersioned

func (f *structuredMergeManager) toVersioned(obj runtime.Object) (runtime.Object, error) {
	return f.objectConverter.ConvertToVersion(obj, f.groupVersion)
}


toUnversioned

func (f *structuredMergeManager) toUnversioned(obj runtime.Object) (runtime.Object, error) {
	return f.objectConverter.ConvertToVersion(obj, f.hubVersion)
}


NewTypeConverter

func NewTypeConverter(openapiSpec map[string]*spec.Schema, preserveUnknownFields bool) (TypeConverter, error) {
	typeSchema, err := schemaconv.ToSchemaFromOpenAPI(openapiSpec, preserveUnknownFields)
	if err != nil {
		return nil, fmt.Errorf("failed to convert models to schema: %v", err)
	}

	typeParser := typed.Parser{Schema: smdschema.Schema{Types: typeSchema.Types}}
	tr := indexModels(&typeParser, openapiSpec)

	return &typeConverter{parser: tr}, nil
}


ObjectToTyped

func (c *typeConverter) ObjectToTyped(obj runtime.Object) (*typed.TypedValue, error) {
	gvk := obj.GetObjectKind().GroupVersionKind()
	t := c.parser[gvk]
	if t == nil {
		return nil, NewNoCorrespondingTypeError(gvk)
	}
	switch o := obj.(type) {
	case *unstructured.Unstructured:
		return t.FromUnstructured(o.UnstructuredContent())
	default:
		return t.FromStructured(obj)
	}
}


TypedToObject

func (c *typeConverter) TypedToObject(value *typed.TypedValue) (runtime.Object, error) {
	return valueToObject(value.AsValue())
}


NewDeducedTypeConverter

// DeducedTypeConverter is a TypeConverter for CRDs that don't have a
// schema. It does implement the same interface though (and create the
// same types of objects), so that everything can still work the same.
// CRDs are merged with all their fields being "atomic" (lists
// included).
func NewDeducedTypeConverter() TypeConverter {
	return deducedTypeConverter{}
}


ObjectToTyped

// ObjectToTyped converts an object into a TypedValue with a "deduced type".
func (deducedTypeConverter) ObjectToTyped(obj runtime.Object) (*typed.TypedValue, error) {
	switch o := obj.(type) {
	case *unstructured.Unstructured:
		return typed.DeducedParseableType.FromUnstructured(o.UnstructuredContent())
	default:
		return typed.DeducedParseableType.FromStructured(obj)
	}
}


TypedToObject

// TypedToObject transforms the typed value into a runtime.Object. That
// is not specific to deduced type.
func (deducedTypeConverter) TypedToObject(value *typed.TypedValue) (runtime.Object, error) {
	return valueToObject(value.AsValue())
}


valueToObject

func valueToObject(val value.Value) (runtime.Object, error) {
	vu := val.Unstructured()
	switch o := vu.(type) {
	case map[string]interface{}:
		return &unstructured.Unstructured{Object: o}, nil
	default:
		return nil, fmt.Errorf("failed to convert value to unstructured for type %T", vu)
	}
}


indexModels

func indexModels(
	typeParser *typed.Parser,
	openAPISchemas map[string]*spec.Schema,
) map[schema.GroupVersionKind]*typed.ParseableType {
	tr := map[schema.GroupVersionKind]*typed.ParseableType{}
	for modelName, model := range openAPISchemas {
		gvkList := parseGroupVersionKind(model.Extensions)
		if len(gvkList) == 0 {
			continue
		}

		parsedType := typeParser.Type(modelName)
		for _, gvk := range gvkList {
			if len(gvk.Kind) > 0 {
				tr[schema.GroupVersionKind(gvk)] = &parsedType
			}
		}
	}
	return tr
}


parseGroupVersionKind

// Get and parse GroupVersionKind from the extension. Returns empty if it doesn't have one.
func parseGroupVersionKind(extensions map[string]interface{}) []schema.GroupVersionKind {
	gvkListResult := []schema.GroupVersionKind{}

	// Get the extensions
	gvkExtension, ok := extensions["x-kubernetes-group-version-kind"]
	if !ok {
		return []schema.GroupVersionKind{}
	}

	// gvk extension must be a list of at least 1 element.
	gvkList, ok := gvkExtension.([]interface{})
	if !ok {
		return []schema.GroupVersionKind{}
	}

	for _, gvk := range gvkList {
		var group, version, kind string

		// gvk extension list must be a map with group, version, and
		// kind fields
		if gvkMap, ok := gvk.(map[interface{}]interface{}); ok {
			group, ok = gvkMap["group"].(string)
			if !ok {
				continue
			}
			version, ok = gvkMap["version"].(string)
			if !ok {
				continue
			}
			kind, ok = gvkMap["kind"].(string)
			if !ok {
				continue
			}

		} else if gvkMap, ok := gvk.(map[string]interface{}); ok {
			group, ok = gvkMap["group"].(string)
			if !ok {
				continue
			}
			version, ok = gvkMap["version"].(string)
			if !ok {
				continue
			}
			kind, ok = gvkMap["kind"].(string)
			if !ok {
				continue
			}
		} else {
			continue
		}

		gvkListResult = append(gvkListResult, schema.GroupVersionKind{
			Group:   group,
			Version: version,
			Kind:    kind,
		})
	}

	return gvkListResult
}


newVersionConverter

// NewVersionConverter builds a VersionConverter from a TypeConverter and an ObjectConvertor.
func newVersionConverter(t TypeConverter, o runtime.ObjectConvertor, h schema.GroupVersion) merge.Converter {
	return &versionConverter{
		typeConverter:   t,
		objectConvertor: o,
		hubGetter: func(from schema.GroupVersion) schema.GroupVersion {
			return schema.GroupVersion{
				Group:   from.Group,
				Version: h.Version,
			}
		},
	}
}


newCRDVersionConverter

// NewCRDVersionConverter builds a VersionConverter for CRDs from a TypeConverter and an ObjectConvertor.
func newCRDVersionConverter(t TypeConverter, o runtime.ObjectConvertor, h schema.GroupVersion) merge.Converter {
	return &versionConverter{
		typeConverter:   t,
		objectConvertor: o,
		hubGetter: func(from schema.GroupVersion) schema.GroupVersion {
			return h
		},
	}
}


Convert

// Convert implements sigs.k8s.io/structured-merge-diff/merge.Converter
func (v *versionConverter) Convert(object *typed.TypedValue, version fieldpath.APIVersion) (*typed.TypedValue, error) {
	// Convert the smd typed value to a kubernetes object.
	objectToConvert, err := v.typeConverter.TypedToObject(object)
	if err != nil {
		return object, err
	}

	// Parse the target groupVersion.
	groupVersion, err := schema.ParseGroupVersion(string(version))
	if err != nil {
		return object, err
	}

	// If attempting to convert to the same version as we already have, just return it.
	fromVersion := objectToConvert.GetObjectKind().GroupVersionKind().GroupVersion()
	if fromVersion == groupVersion {
		return object, nil
	}

	// Convert to internal
	internalObject, err := v.objectConvertor.ConvertToVersion(objectToConvert, v.hubGetter(fromVersion))
	if err != nil {
		return object, err
	}

	// Convert the object into the target version
	convertedObject, err := v.objectConvertor.ConvertToVersion(internalObject, groupVersion)
	if err != nil {
		return object, err
	}

	// Convert the object back to a smd typed value and return it.
	return v.typeConverter.ObjectToTyped(convertedObject)
}


IsMissingVersionError

// IsMissingVersionError
func (v *versionConverter) IsMissingVersionError(err error) bool {
	return runtime.IsNotRegisteredError(err) || isNoCorrespondingTypeError(err)
}


NewNoCorrespondingTypeError

func NewNoCorrespondingTypeError(gvk schema.GroupVersionKind) error {
	return &noCorrespondingTypeErr{gvk: gvk}
}


Error

func (k *noCorrespondingTypeErr) Error() string {
	return fmt.Sprintf("no corresponding type for %v", k.gvk)
}


isNoCorrespondingTypeError

func isNoCorrespondingTypeError(err error) bool {
	if err == nil {
		return false
	}
	_, ok := err.(*noCorrespondingTypeErr)
	return ok
}


NewScaleHandler

// NewScaleHandler creates a new ScaleHandler
func NewScaleHandler(parentEntries []metav1.ManagedFieldsEntry, groupVersion schema.GroupVersion, mappings ResourcePathMappings) *ScaleHandler {
	return &ScaleHandler{
		parentEntries: parentEntries,
		groupVersion:  groupVersion,
		mappings:      mappings,
	}
}


ToSubresource

// ToSubresource filter the managed fields of the main resource and convert
// them so that they can be handled by scale.
// For the managed fields that have a replicas path it performs two changes:
//  1. APIVersion is changed to the APIVersion of the scale subresource
//  2. Replicas path of the main resource is transformed to the replicas path of
//     the scale subresource
func (h *ScaleHandler) ToSubresource() ([]metav1.ManagedFieldsEntry, error) {
	managed, err := internal.DecodeManagedFields(h.parentEntries)
	if err != nil {
		return nil, err
	}

	f := fieldpath.ManagedFields{}
	t := map[string]*metav1.Time{}
	for manager, versionedSet := range managed.Fields() {
		path, ok := h.mappings[string(versionedSet.APIVersion())]
		// Skip the entry if the APIVersion is unknown
		if !ok || path == nil {
			continue
		}

		if versionedSet.Set().Has(path) {
			newVersionedSet := fieldpath.NewVersionedSet(
				fieldpath.NewSet(replicasPathInScale),
				fieldpath.APIVersion(scaleGroupVersion.String()),
				versionedSet.Applied(),
			)

			f[manager] = newVersionedSet
			t[manager] = managed.Times()[manager]
		}
	}

	return managedFieldsEntries(internal.NewManaged(f, t))
}


ToParent

// ToParent merges `scaleEntries` with the entries of the main resource and
// transforms them accordingly
func (h *ScaleHandler) ToParent(scaleEntries []metav1.ManagedFieldsEntry) ([]metav1.ManagedFieldsEntry, error) {
	decodedParentEntries, err := internal.DecodeManagedFields(h.parentEntries)
	if err != nil {
		return nil, err
	}
	parentFields := decodedParentEntries.Fields()

	decodedScaleEntries, err := internal.DecodeManagedFields(scaleEntries)
	if err != nil {
		return nil, err
	}
	scaleFields := decodedScaleEntries.Fields()

	f := fieldpath.ManagedFields{}
	t := map[string]*metav1.Time{}

	for manager, versionedSet := range parentFields {
		// Get the main resource "replicas" path
		path, ok := h.mappings[string(versionedSet.APIVersion())]
		// Drop the entry if the APIVersion is unknown.
		if !ok {
			continue
		}

		// If the parent entry does not have the replicas path or it is nil, just
		// keep it as it is. The path is nil for Custom Resources without scale
		// subresource.
		if path == nil || !versionedSet.Set().Has(path) {
			f[manager] = versionedSet
			t[manager] = decodedParentEntries.Times()[manager]
			continue
		}

		if _, ok := scaleFields[manager]; !ok {
			// "Steal" the replicas path from the main resource entry
			newSet := versionedSet.Set().Difference(fieldpath.NewSet(path))

			if !newSet.Empty() {
				newVersionedSet := fieldpath.NewVersionedSet(
					newSet,
					versionedSet.APIVersion(),
					versionedSet.Applied(),
				)
				f[manager] = newVersionedSet
				t[manager] = decodedParentEntries.Times()[manager]
			}
		} else {
			// Field wasn't stolen, let's keep the entry as it is.
			f[manager] = versionedSet
			t[manager] = decodedParentEntries.Times()[manager]
			delete(scaleFields, manager)
		}
	}

	for manager, versionedSet := range scaleFields {
		if !versionedSet.Set().Has(replicasPathInScale) {
			continue
		}
		newVersionedSet := fieldpath.NewVersionedSet(
			fieldpath.NewSet(h.mappings[h.groupVersion.String()]),
			fieldpath.APIVersion(h.groupVersion.String()),
			versionedSet.Applied(),
		)
		f[manager] = newVersionedSet
		t[manager] = decodedParentEntries.Times()[manager]
	}

	return managedFieldsEntries(internal.NewManaged(f, t))
}


managedFieldsEntries

func managedFieldsEntries(entries internal.ManagedInterface) ([]metav1.ManagedFieldsEntry, error) {
	obj := &unstructured.Unstructured{Object: map[string]interface{}{}}
	if err := internal.EncodeObjectManagedFields(obj, entries); err != nil {
		return nil, err
	}
	accessor, err := meta.Accessor(obj)
	if err != nil {
		panic(fmt.Sprintf("couldn't get accessor: %v", err))
	}
	return accessor.GetManagedFields(), nil
}


NewDeducedTypeConverter

// NewDeducedTypeConverter creates a TypeConverter for CRDs that don't
// have a schema. It does implement the same interface though (and
// create the same types of objects), so that everything can still work
// the same. CRDs are merged with all their fields being "atomic" (lists
// included).
func NewDeducedTypeConverter() TypeConverter {
	return internal.NewDeducedTypeConverter()
}


NewTypeConverter

// NewTypeConverter builds a TypeConverter from a map of OpenAPIV3 schemas.
// This will automatically find the proper version of the object, and the
// corresponding schema information.
// The keys to the map must be consistent with the names
// used by Refs within the schemas.
// The schemas should conform to the Kubernetes Structural Schema OpenAPI
// restrictions found in docs:
// https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema
func NewTypeConverter(openapiSpec map[string]*spec.Schema, preserveUnknownFields bool) (TypeConverter, error) {
	return internal.NewTypeConverter(openapiSpec, preserveUnknownFields)
}


ErrNoMergeKey

func ErrNoMergeKey(m map[string]interface{}, k string) error {
	return fmt.Errorf("map: %v does not contain declared merge key: %s", m, k)
}


ErrBadArgType

func ErrBadArgType(expected, actual interface{}) error {
	return fmt.Errorf("expected a %s, but received a %s",
		reflect.TypeOf(expected),
		reflect.TypeOf(actual))
}


ErrBadArgKind

func ErrBadArgKind(expected, actual interface{}) error {
	var expectedKindString, actualKindString string
	if expected == nil {
		expectedKindString = "nil"
	} else {
		expectedKindString = reflect.TypeOf(expected).Kind().String()
	}
	if actual == nil {
		actualKindString = "nil"
	} else {
		actualKindString = reflect.TypeOf(actual).Kind().String()
	}
	return fmt.Errorf("expected a %s, but received a %s", expectedKindString, actualKindString)
}


ErrBadPatchType

func ErrBadPatchType(t interface{}, m map[string]interface{}) error {
	return fmt.Errorf("unknown patch type: %s in map: %v", t, m)
}


IsPreconditionFailed

// IsPreconditionFailed returns true if the provided error indicates
// a precondition failed.
func IsPreconditionFailed(err error) bool {
	_, ok := err.(ErrPreconditionFailed)
	return ok
}


NewErrPreconditionFailed

func NewErrPreconditionFailed(target map[string]interface{}) ErrPreconditionFailed {
	s := fmt.Sprintf("precondition failed for: %v", target)
	return ErrPreconditionFailed{s}
}


Error

func (err ErrPreconditionFailed) Error() string {
	return err.message
}


NewErrConflict

func NewErrConflict(patch, current string) ErrConflict {
	s := fmt.Sprintf("patch:\n%s\nconflicts with changes made from original to current:\n%s\n", patch, current)
	return ErrConflict{s}
}


Error

func (err ErrConflict) Error() string {
	return err.message
}


IsConflict

// IsConflict returns true if the provided error indicates
// a conflict between the patch and the current configuration.
func IsConflict(err error) bool {
	_, ok := err.(ErrConflict)
	return ok
}


RequireKeyUnchanged

// RequireKeyUnchanged returns a precondition function that fails if the provided key
// is present in the patch (indicating that its value has changed).
func RequireKeyUnchanged(key string) PreconditionFunc {
	return func(patch interface{}) bool {
		patchMap, ok := patch.(map[string]interface{})
		if !ok {
			return true
		}

		// The presence of key means that its value has been changed, so the test fails.
		_, ok = patchMap[key]
		return !ok
	}
}


RequireMetadataKeyUnchanged

// RequireMetadataKeyUnchanged creates a precondition function that fails
// if the metadata.key is present in the patch (indicating its value
// has changed).
func RequireMetadataKeyUnchanged(key string) PreconditionFunc {
	return func(patch interface{}) bool {
		patchMap, ok := patch.(map[string]interface{})
		if !ok {
			return true
		}
		patchMap1, ok := patchMap["metadata"]
		if !ok {
			return true
		}
		patchMap2, ok := patchMap1.(map[string]interface{})
		if !ok {
			return true
		}
		_, ok = patchMap2[key]
		return !ok
	}
}


ToYAMLOrError

func ToYAMLOrError(v interface{}) string {
	y, err := toYAML(v)
	if err != nil {
		return err.Error()
	}

	return y
}


toYAML

func toYAML(v interface{}) (string, error) {
	y, err := yaml.Marshal(v)
	if err != nil {
		return "", fmt.Errorf("yaml marshal failed:%v\n%v\n", err, spew.Sdump(v))
	}

	return string(y), nil
}


HasConflicts

// HasConflicts returns true if the left and right JSON interface objects overlap with
// different values in any key. All keys are required to be strings. Since patches of the
// same Type have congruent keys, this is valid for multiple patch types. This method
// supports JSON merge patch semantics.
//
// NOTE: Numbers with different types (e.g. int(0) vs int64(0)) will be detected as conflicts.
// Make sure the unmarshaling of left and right are consistent (e.g. use the same library).
func HasConflicts(left, right interface{}) (bool, error) {
	switch typedLeft := left.(type) {
	case map[string]interface{}:
		switch typedRight := right.(type) {
		case map[string]interface{}:
			for key, leftValue := range typedLeft {
				rightValue, ok := typedRight[key]
				if !ok {
					continue
				}
				if conflict, err := HasConflicts(leftValue, rightValue); err != nil || conflict {
					return conflict, err
				}
			}

			return false, nil
		default:
			return true, nil
		}
	case []interface{}:
		switch typedRight := right.(type) {
		case []interface{}:
			if len(typedLeft) != len(typedRight) {
				return true, nil
			}

			for i := range typedLeft {
				if conflict, err := HasConflicts(typedLeft[i], typedRight[i]); err != nil || conflict {
					return conflict, err
				}
			}

			return false, nil
		default:
			return true, nil
		}
	case string, float64, bool, int64, nil:
		return !reflect.DeepEqual(left, right), nil
	default:
		return true, fmt.Errorf("unknown type: %v", reflect.TypeOf(left))
	}
}


GetNameFromCallsite

// GetNameFromCallsite walks back through the call stack until we find a caller from outside of the ignoredPackages
// it returns back a shortpath/filename:line to aid in identification of this reflector when it starts logging
func GetNameFromCallsite(ignoredPackages ...string) string {
	name := "????"
	const maxStack = 10
	for i := 1; i < maxStack; i++ {
		_, file, line, ok := goruntime.Caller(i)
		if !ok {
			file, line, ok = extractStackCreator()
			if !ok {
				break
			}
			i += maxStack
		}
		if hasPackage(file, append(ignoredPackages, "/runtime/asm_")) {
			continue
		}

		file = trimPackagePrefix(file)
		name = fmt.Sprintf("%s:%d", file, line)
		break
	}
	return name
}


hasPackage

// hasPackage returns true if the file is in one of the ignored packages.
func hasPackage(file string, ignoredPackages []string) bool {
	for _, ignoredPackage := range ignoredPackages {
		if strings.Contains(file, ignoredPackage) {
			return true
		}
	}
	return false
}


trimPackagePrefix

// trimPackagePrefix reduces duplicate values off the front of a package name.
func trimPackagePrefix(file string) string {
	if l := strings.LastIndex(file, "/vendor/"); l >= 0 {
		return file[l+len("/vendor/"):]
	}
	if l := strings.LastIndex(file, "/src/"); l >= 0 {
		return file[l+5:]
	}
	if l := strings.LastIndex(file, "/pkg/"); l >= 0 {
		return file[l+1:]
	}
	return file
}


extractStackCreator

// extractStackCreator retrieves the goroutine file and line that launched this stack. Returns false
// if the creator cannot be located.
// TODO: Go does not expose this via runtime https://github.com/golang/go/issues/11440
func extractStackCreator() (string, int, bool) {
	stack := debug.Stack()
	matches := stackCreator.FindStringSubmatch(string(stack))
	if len(matches) != 4 {
		return "", 0, false
	}
	line, err := strconv.Atoi(matches[3])
	if err != nil {
		return "", 0, false
	}
	return matches[2], line, true
}


JoinPreservingTrailingSlash

// JoinPreservingTrailingSlash does a path.Join of the specified elements,
// preserving any trailing slash on the last non-empty segment
func JoinPreservingTrailingSlash(elem ...string) string {
	// do the basic path join
	result := path.Join(elem...)

	// find the last non-empty segment
	for i := len(elem) - 1; i >= 0; i-- {
		if len(elem[i]) > 0 {
			// if the last segment ended in a slash, ensure our result does as well
			if strings.HasSuffix(elem[i], "/") && !strings.HasSuffix(result, "/") {
				result += "/"
			}
			break
		}
	}

	return result
}


IsTimeout

// IsTimeout returns true if the given error is a network timeout error
func IsTimeout(err error) bool {
	var neterr net.Error
	if errors.As(err, &neterr) {
		return neterr != nil && neterr.Timeout()
	}
	return false
}


IsProbableEOF

// IsProbableEOF returns true if the given error resembles a connection termination
// scenario that would justify assuming that the watch is empty.
// These errors are what the Go http stack returns back to us which are general
// connection closure errors (strongly correlated) and callers that need to
// differentiate probable errors in connection behavior between normal "this is
// disconnected" should use the method.
func IsProbableEOF(err error) bool {
	if err == nil {
		return false
	}
	var uerr *url.Error
	if errors.As(err, &uerr) {
		err = uerr.Err
	}
	msg := err.Error()
	switch {
	case err == io.EOF:
		return true
	case err == io.ErrUnexpectedEOF:
		return true
	case msg == "http: can't write HTTP request on broken connection":
		return true
	case strings.Contains(msg, "http2: server sent GOAWAY and closed the connection"):
		return true
	case strings.Contains(msg, "connection reset by peer"):
		return true
	case strings.Contains(strings.ToLower(msg), "use of closed network connection"):
		return true
	}
	return false
}


SetOldTransportDefaults

// SetOldTransportDefaults applies the defaults from http.DefaultTransport
// for the Proxy, Dial, and TLSHandshakeTimeout fields if unset
func SetOldTransportDefaults(t *http.Transport) *http.Transport {
	if t.Proxy == nil || isDefault(t.Proxy) {
		// http.ProxyFromEnvironment doesn't respect CIDRs and that makes it impossible to exclude things like pod and service IPs from proxy settings
		// ProxierWithNoProxyCIDR allows CIDR rules in NO_PROXY
		t.Proxy = NewProxierWithNoProxyCIDR(http.ProxyFromEnvironment)
	}
	// If no custom dialer is set, use the default context dialer
	//lint:file-ignore SA1019 Keep supporting deprecated Dial method of custom transports
	if t.DialContext == nil && t.Dial == nil {
		t.DialContext = defaultTransport.DialContext
	}
	if t.TLSHandshakeTimeout == 0 {
		t.TLSHandshakeTimeout = defaultTransport.TLSHandshakeTimeout
	}
	if t.IdleConnTimeout == 0 {
		t.IdleConnTimeout = defaultTransport.IdleConnTimeout
	}
	return t
}


SetTransportDefaults

// SetTransportDefaults applies the defaults from http.DefaultTransport
// for the Proxy, Dial, and TLSHandshakeTimeout fields if unset
func SetTransportDefaults(t *http.Transport) *http.Transport {
	t = SetOldTransportDefaults(t)
	// Allow clients to disable http2 if needed.
	if s := os.Getenv("DISABLE_HTTP2"); len(s) > 0 {
		klog.Info("HTTP2 has been explicitly disabled")
	} else if allowsHTTP2(t) {
		if err := configureHTTP2Transport(t); err != nil {
			klog.Warningf("Transport failed http2 configuration: %v", err)
		}
	}
	return t
}


readIdleTimeoutSeconds

func readIdleTimeoutSeconds() int {
	ret := 30
	// User can set the readIdleTimeout to 0 to disable the HTTP/2
	// connection health check.
	if s := os.Getenv("HTTP2_READ_IDLE_TIMEOUT_SECONDS"); len(s) > 0 {
		i, err := strconv.Atoi(s)
		if err != nil {
			klog.Warningf("Illegal HTTP2_READ_IDLE_TIMEOUT_SECONDS(%q): %v."+
				" Default value %d is used", s, err, ret)
			return ret
		}
		ret = i
	}
	return ret
}


pingTimeoutSeconds

func pingTimeoutSeconds() int {
	ret := 15
	if s := os.Getenv("HTTP2_PING_TIMEOUT_SECONDS"); len(s) > 0 {
		i, err := strconv.Atoi(s)
		if err != nil {
			klog.Warningf("Illegal HTTP2_PING_TIMEOUT_SECONDS(%q): %v."+
				" Default value %d is used", s, err, ret)
			return ret
		}
		ret = i
	}
	return ret
}


func configureHTTP2Transport(t *http.Transport) error {
	t2, err := http2.ConfigureTransports(t)
	if err != nil {
		return err
	}
	// The following enables the HTTP/2 connection health check added in
	// https://github.com/golang/net/pull/55. The health check detects and
	// closes broken transport layer connections. Without the health check,
	// a broken connection can linger too long, e.g., a broken TCP
	// connection will be closed by the Linux kernel after 13 to 30 minutes
	// by default, which caused
	// https://github.com/kubernetes/client-go/issues/374 and
	// https://github.com/kubernetes/kubernetes/issues/87615.
	t2.ReadIdleTimeout = time.Duration(readIdleTimeoutSeconds()) * time.Second
	t2.PingTimeout = time.Duration(pingTimeoutSeconds()) * time.Second
	return nil
}


func allowsHTTP2(t *http.Transport) bool {
	if t.TLSClientConfig == nil || len(t.TLSClientConfig.NextProtos) == 0 {
		// the transport expressed no NextProto preference, allow
		return true
	}
	for _, p := range t.TLSClientConfig.NextProtos {
		if p == http2.NextProtoTLS {
			// the transport explicitly allowed http/2
			return true
		}
	}
	// the transport explicitly set NextProtos and excluded http/2
	return false
}


DialerFor

func DialerFor(transport http.RoundTripper) (DialFunc, error) {
	if transport == nil {
		return nil, nil
	}

	switch transport := transport.(type) {
	case *http.Transport:
		// transport.DialContext takes precedence over transport.Dial
		if transport.DialContext != nil {
			return transport.DialContext, nil
		}
		// adapt transport.Dial to the DialWithContext signature
		if transport.Dial != nil {
			return func(ctx context.Context, net, addr string) (net.Conn, error) {
				return transport.Dial(net, addr)
			}, nil
		}
		// otherwise return nil
		return nil, nil
	case RoundTripperWrapper:
		return DialerFor(transport.WrappedRoundTripper())
	default:
		return nil, fmt.Errorf("unknown transport type: %T", transport)
	}
}


CloseIdleConnectionsFor

// CloseIdleConnectionsFor close idles connections for the Transport.
// If the Transport is wrapped it iterates over the wrapped round trippers
// until it finds one that implements the CloseIdleConnections method.
// If the Transport does not have a CloseIdleConnections method
// then this function does nothing.
func CloseIdleConnectionsFor(transport http.RoundTripper) {
	if transport == nil {
		return
	}
	type closeIdler interface {
		CloseIdleConnections()
	}

	switch transport := transport.(type) {
	case closeIdler:
		transport.CloseIdleConnections()
	case RoundTripperWrapper:
		CloseIdleConnectionsFor(transport.WrappedRoundTripper())
	default:
		klog.Warningf("unknown transport type: %T", transport)
	}
}


TLSClientConfig

func TLSClientConfig(transport http.RoundTripper) (*tls.Config, error) {
	if transport == nil {
		return nil, nil
	}

	switch transport := transport.(type) {
	case *http.Transport:
		return transport.TLSClientConfig, nil
	case TLSClientConfigHolder:
		return transport.TLSClientConfig(), nil
	case RoundTripperWrapper:
		return TLSClientConfig(transport.WrappedRoundTripper())
	default:
		return nil, fmt.Errorf("unknown transport type: %T", transport)
	}
}


FormatURL

func FormatURL(scheme string, host string, port int, path string) *url.URL {
	return &url.URL{
		Scheme: scheme,
		Host:   net.JoinHostPort(host, strconv.Itoa(port)),
		Path:   path,
	}
}


GetHTTPClient

func GetHTTPClient(req *http.Request) string {
	if ua := req.UserAgent(); len(ua) != 0 {
		return ua
	}
	return "unknown"
}


SourceIPs

// SourceIPs splits the comma separated X-Forwarded-For header and joins it with
// the X-Real-Ip header and/or req.RemoteAddr, ignoring invalid IPs.
// The X-Real-Ip is omitted if it's already present in the X-Forwarded-For chain.
// The req.RemoteAddr is always the last IP in the returned list.
// It returns nil if all of these are empty or invalid.
func SourceIPs(req *http.Request) []net.IP {
	var srcIPs []net.IP

	hdr := req.Header
	// First check the X-Forwarded-For header for requests via proxy.
	hdrForwardedFor := hdr.Get("X-Forwarded-For")
	if hdrForwardedFor != "" {
		// X-Forwarded-For can be a csv of IPs in case of multiple proxies.
		// Use the first valid one.
		parts := strings.Split(hdrForwardedFor, ",")
		for _, part := range parts {
			ip := netutils.ParseIPSloppy(strings.TrimSpace(part))
			if ip != nil {
				srcIPs = append(srcIPs, ip)
			}
		}
	}

	// Try the X-Real-Ip header.
	hdrRealIp := hdr.Get("X-Real-Ip")
	if hdrRealIp != "" {
		ip := netutils.ParseIPSloppy(hdrRealIp)
		// Only append the X-Real-Ip if it's not already contained in the X-Forwarded-For chain.
		if ip != nil && !containsIP(srcIPs, ip) {
			srcIPs = append(srcIPs, ip)
		}
	}

	// Always include the request Remote Address as it cannot be easily spoofed.
	var remoteIP net.IP
	// Remote Address in Go's HTTP server is in the form host:port so we need to split that first.
	host, _, err := net.SplitHostPort(req.RemoteAddr)
	if err == nil {
		remoteIP = netutils.ParseIPSloppy(host)
	}
	// Fallback if Remote Address was just IP.
	if remoteIP == nil {
		remoteIP = netutils.ParseIPSloppy(req.RemoteAddr)
	}

	// Don't duplicate remote IP if it's already the last address in the chain.
	if remoteIP != nil && (len(srcIPs) == 0 || !remoteIP.Equal(srcIPs[len(srcIPs)-1])) {
		srcIPs = append(srcIPs, remoteIP)
	}

	return srcIPs
}


containsIP

// Checks whether the given IP address is contained in the list of IPs.
func containsIP(ips []net.IP, ip net.IP) bool {
	for _, v := range ips {
		if v.Equal(ip) {
			return true
		}
	}
	return false
}


GetClientIP

// Extracts and returns the clients IP from the given request.
// Looks at X-Forwarded-For header, X-Real-Ip header and request.RemoteAddr in that order.
// Returns nil if none of them are set or is set to an invalid value.
func GetClientIP(req *http.Request) net.IP {
	ips := SourceIPs(req)
	if len(ips) == 0 {
		return nil
	}
	return ips[0]
}


AppendForwardedForHeader

// Prepares the X-Forwarded-For header for another forwarding hop by appending the previous sender's
// IP address to the X-Forwarded-For chain.
func AppendForwardedForHeader(req *http.Request) {
	// Copied from net/http/httputil/reverseproxy.go:
	if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
		// If we aren't the first proxy retain prior
		// X-Forwarded-For information as a comma+space
		// separated list and fold multiple headers into one.
		if prior, ok := req.Header["X-Forwarded-For"]; ok {
			clientIP = strings.Join(prior, ", ") + ", " + clientIP
		}
		req.Header.Set("X-Forwarded-For", clientIP)
	}
}


isDefault

// isDefault checks to see if the transportProxierFunc is pointing to the default one
func isDefault(transportProxier func(*http.Request) (*url.URL, error)) bool {
	transportProxierPointer := fmt.Sprintf("%p", transportProxier)
	return transportProxierPointer == defaultProxyFuncPointer
}


NewProxierWithNoProxyCIDR

// NewProxierWithNoProxyCIDR constructs a Proxier function that respects CIDRs in NO_PROXY and delegates if
// no matching CIDRs are found
func NewProxierWithNoProxyCIDR(delegate func(req *http.Request) (*url.URL, error)) func(req *http.Request) (*url.URL, error) {
	// we wrap the default method, so we only need to perform our check if the NO_PROXY (or no_proxy) envvar has a CIDR in it
	noProxyEnv := os.Getenv("NO_PROXY")
	if noProxyEnv == "" {
		noProxyEnv = os.Getenv("no_proxy")
	}
	noProxyRules := strings.Split(noProxyEnv, ",")

	cidrs := []*net.IPNet{}
	for _, noProxyRule := range noProxyRules {
		_, cidr, _ := netutils.ParseCIDRSloppy(noProxyRule)
		if cidr != nil {
			cidrs = append(cidrs, cidr)
		}
	}

	if len(cidrs) == 0 {
		return delegate
	}

	return func(req *http.Request) (*url.URL, error) {
		ip := netutils.ParseIPSloppy(req.URL.Hostname())
		if ip == nil {
			return delegate(req)
		}

		for _, cidr := range cidrs {
			if cidr.Contains(ip) {
				return nil, nil
			}
		}

		return delegate(req)
	}
}


Dial

func (fn DialerFunc) Dial(req *http.Request) (net.Conn, error) {
	return fn(req)
}


CloneRequest

// CloneRequest creates a shallow copy of the request along with a deep copy of the Headers.
func CloneRequest(req *http.Request) *http.Request {
	r := new(http.Request)

	// shallow clone
	*r = *req

	// deep copy headers
	r.Header = CloneHeader(req.Header)

	return r
}


CloneHeader

// CloneHeader creates a deep copy of an http.Header.
func CloneHeader(in http.Header) http.Header {
	out := make(http.Header, len(in))
	for key, values := range in {
		newValues := make([]string, len(values))
		copy(newValues, values)
		out[key] = newValues
	}
	return out
}


ParseWarningHeaders

// ParseWarningHeaders extract RFC2616 14.46 warnings headers from the specified set of header values.
// Multiple comma-separated warnings per header are supported.
// If errors are encountered on a header, the remainder of that header are skipped and subsequent headers are parsed.
// Returns successfully parsed warnings and any errors encountered.
func ParseWarningHeaders(headers []string) ([]WarningHeader, []error) {
	var (
		results []WarningHeader
		errs    []error
	)
	for _, header := range headers {
		for len(header) > 0 {
			result, remainder, err := ParseWarningHeader(header)
			if err != nil {
				errs = append(errs, err)
				break
			}
			results = append(results, result)
			header = remainder
		}
	}
	return results, errs
}


ParseWarningHeader

// ParseWarningHeader extracts one RFC2616 14.46 warning from the specified header,
// returning an error if the header does not contain a correctly formatted warning.
// Any remaining content in the header is returned.
func ParseWarningHeader(header string) (result WarningHeader, remainder string, err error) {
	// https://tools.ietf.org/html/rfc2616#section-14.46
	//   updated by
	// https://tools.ietf.org/html/rfc7234#section-5.5
	//   https://tools.ietf.org/html/rfc7234#appendix-A
	//     Some requirements regarding production and processing of the Warning
	//     header fields have been relaxed, as it is not widely implemented.
	//     Furthermore, the Warning header field no longer uses RFC 2047
	//     encoding, nor does it allow multiple languages, as these aspects were
	//     not implemented.
	//
	// Format is one of:
	// warn-code warn-agent "warn-text"
	// warn-code warn-agent "warn-text" "warn-date"
	//
	// warn-code is a three digit number
	// warn-agent is unquoted and contains no spaces
	// warn-text is quoted with backslash escaping (RFC2047-encoded according to RFC2616, not encoded according to RFC7234)
	// warn-date is optional, quoted, and in HTTP-date format (no embedded or escaped quotes)
	//
	// additional warnings can optionally be included in the same header by comma-separating them:
	// warn-code warn-agent "warn-text" "warn-date"[, warn-code warn-agent "warn-text" "warn-date", ...]

	// tolerate leading whitespace
	header = strings.TrimSpace(header)

	parts := strings.SplitN(header, " ", 3)
	if len(parts) != 3 {
		return WarningHeader{}, "", errors.New("invalid warning header: fewer than 3 segments")
	}
	code, agent, textDateRemainder := parts[0], parts[1], parts[2]

	// verify code format
	if !codeMatcher.Match([]byte(code)) {
		return WarningHeader{}, "", errors.New("invalid warning header: code segment is not 3 digits between 100-299")
	}
	codeInt, _ := strconv.ParseInt(code, 10, 64)

	// verify agent presence
	if len(agent) == 0 {
		return WarningHeader{}, "", errors.New("invalid warning header: empty agent segment")
	}
	if !utf8.ValidString(agent) || hasAnyRunes(agent, unicode.IsControl) {
		return WarningHeader{}, "", errors.New("invalid warning header: invalid agent")
	}

	// verify textDateRemainder presence
	if len(textDateRemainder) == 0 {
		return WarningHeader{}, "", errors.New("invalid warning header: empty text segment")
	}

	// extract text
	text, dateAndRemainder, err := parseQuotedString(textDateRemainder)
	if err != nil {
		return WarningHeader{}, "", fmt.Errorf("invalid warning header: %v", err)
	}
	// tolerate RFC2047-encoded text from warnings produced according to RFC2616
	if decodedText, err := wordDecoder.DecodeHeader(text); err == nil {
		text = decodedText
	}
	if !utf8.ValidString(text) || hasAnyRunes(text, unicode.IsControl) {
		return WarningHeader{}, "", errors.New("invalid warning header: invalid text")
	}
	result = WarningHeader{Code: int(codeInt), Agent: agent, Text: text}

	if len(dateAndRemainder) > 0 {
		if dateAndRemainder[0] == '"' {
			// consume date
			foundEndQuote := false
			for i := 1; i < len(dateAndRemainder); i++ {
				if dateAndRemainder[i] == '"' {
					foundEndQuote = true
					remainder = strings.TrimSpace(dateAndRemainder[i+1:])
					break
				}
			}
			if !foundEndQuote {
				return WarningHeader{}, "", errors.New("invalid warning header: unterminated date segment")
			}
		} else {
			remainder = dateAndRemainder
		}
	}
	if len(remainder) > 0 {
		if remainder[0] == ',' {
			// consume comma if present
			remainder = strings.TrimSpace(remainder[1:])
		} else {
			return WarningHeader{}, "", errors.New("invalid warning header: unexpected token after warn-date")
		}
	}

	return result, remainder, nil
}


parseQuotedString

func parseQuotedString(quotedString string) (string, string, error) {
	if len(quotedString) == 0 {
		return "", "", errors.New("invalid quoted string: 0-length")
	}

	if quotedString[0] != '"' {
		return "", "", errors.New("invalid quoted string: missing initial quote")
	}

	quotedString = quotedString[1:]
	var remainder string
	escaping := false
	closedQuote := false
	result := &strings.Builder{}
loop:
	for i := 0; i < len(quotedString); i++ {
		b := quotedString[i]
		switch b {
		case '"':
			if escaping {
				result.WriteByte(b)
				escaping = false
			} else {
				closedQuote = true
				remainder = strings.TrimSpace(quotedString[i+1:])
				break loop
			}
		case '\\':
			if escaping {
				result.WriteByte(b)
				escaping = false
			} else {
				escaping = true
			}
		default:
			result.WriteByte(b)
			escaping = false
		}
	}

	if !closedQuote {
		return "", "", errors.New("invalid quoted string: missing closing quote")
	}
	return result.String(), remainder, nil
}


NewWarningHeader

func NewWarningHeader(code int, agent, text string) (string, error) {
	if code < 0 || code > 999 {
		return "", errors.New("code must be between 0 and 999")
	}
	if len(agent) == 0 {
		agent = "-"
	} else if !utf8.ValidString(agent) || strings.ContainsAny(agent, `\"`) || hasAnyRunes(agent, unicode.IsSpace, unicode.IsControl) {
		return "", errors.New("agent must be valid UTF-8 and must not contain spaces, quotes, backslashes, or control characters")
	}
	if !utf8.ValidString(text) || hasAnyRunes(text, unicode.IsControl) {
		return "", errors.New("text must be valid UTF-8 and must not contain control characters")
	}
	return fmt.Sprintf("%03d %s %s", code, agent, makeQuotedString(text)), nil
}


hasAnyRunes

func hasAnyRunes(s string, runeCheckers ...func(rune) bool) bool {
	for _, r := range s {
		for _, checker := range runeCheckers {
			if checker(r) {
				return true
			}
		}
	}
	return false
}


makeQuotedString

func makeQuotedString(s string) string {
	result := &bytes.Buffer{}
	// opening quote
	result.WriteRune('"')
	for _, c := range s {
		switch c {
		case '"', '\\':
			// escape " and \
			result.WriteRune('\\')
			result.WriteRune(c)
		default:
			// write everything else as-is
			result.WriteRune(c)
		}
	}
	// closing quote
	result.WriteRune('"')
	return result.String()
}


Error

func (e noRoutesError) Error() string {
	return e.message
}


IsNoRoutesError

// IsNoRoutesError checks if an error is of type noRoutesError
func IsNoRoutesError(err error) bool {
	if err == nil {
		return false
	}
	switch err.(type) {
	case noRoutesError:
		return true
	default:
		return false
	}
}


extract

func (rf RouteFile) extract() ([]Route, error) {
	file, err := os.Open(rf.name)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	return rf.parse(file)
}


// getIPv4DefaultRoutes obtains the IPv4 routes, and filters out non-default routes.
func getIPv4DefaultRoutes(input io.Reader) ([]Route, error) {
	routes := []Route{}
	scanner := bufio.NewReader(input)
	for {
		line, err := scanner.ReadString('\n')
		if err == io.EOF {
			break
		}
		//ignore the headers in the route info
		if strings.HasPrefix(line, "Iface") {
			continue
		}
		fields := strings.Fields(line)
		// Interested in fields:
		//  0 - interface name
		//  1 - destination address
		//  2 - gateway
		dest, err := parseIP(fields[1], familyIPv4)
		if err != nil {
			return nil, err
		}
		gw, err := parseIP(fields[2], familyIPv4)
		if err != nil {
			return nil, err
		}
		if !dest.Equal(net.IPv4zero) {
			continue
		}
		routes = append(routes, Route{
			Interface:   fields[0],
			Destination: dest,
			Gateway:     gw,
			Family:      familyIPv4,
		})
	}
	return routes, nil
}


func getIPv6DefaultRoutes(input io.Reader) ([]Route, error) {
	routes := []Route{}
	scanner := bufio.NewReader(input)
	for {
		line, err := scanner.ReadString('\n')
		if err == io.EOF {
			break
		}
		fields := strings.Fields(line)
		// Interested in fields:
		//  0 - destination address
		//  4 - gateway
		//  9 - interface name
		dest, err := parseIP(fields[0], familyIPv6)
		if err != nil {
			return nil, err
		}
		gw, err := parseIP(fields[4], familyIPv6)
		if err != nil {
			return nil, err
		}
		if !dest.Equal(net.IPv6zero) {
			continue
		}
		if gw.Equal(net.IPv6zero) {
			continue // loopback
		}
		routes = append(routes, Route{
			Interface:   fields[9],
			Destination: dest,
			Gateway:     gw,
			Family:      familyIPv6,
		})
	}
	return routes, nil
}


parseIP

// parseIP takes the hex IP address string from route file and converts it
// to a net.IP address. For IPv4, the value must be converted to big endian.
func parseIP(str string, family AddressFamily) (net.IP, error) {
	if str == "" {
		return nil, fmt.Errorf("input is nil")
	}
	bytes, err := hex.DecodeString(str)
	if err != nil {
		return nil, err
	}
	if family == familyIPv4 {
		if len(bytes) != net.IPv4len {
			return nil, fmt.Errorf("invalid IPv4 address in route")
		}
		return net.IP([]byte{bytes[3], bytes[2], bytes[1], bytes[0]}), nil
	}
	// Must be IPv6
	if len(bytes) != net.IPv6len {
		return nil, fmt.Errorf("invalid IPv6 address in route")
	}
	return net.IP(bytes), nil
}


isInterfaceUp

func isInterfaceUp(intf *net.Interface) bool {
	if intf == nil {
		return false
	}
	if intf.Flags&net.FlagUp != 0 {
		klog.V(4).Infof("Interface %v is up", intf.Name)
		return true
	}
	return false
}


isLoopbackOrPointToPoint

func isLoopbackOrPointToPoint(intf *net.Interface) bool {
	return intf.Flags&(net.FlagLoopback|net.FlagPointToPoint) != 0
}


getMatchingGlobalIP

// getMatchingGlobalIP returns the first valid global unicast address of the given
// 'family' from the list of 'addrs'.
func getMatchingGlobalIP(addrs []net.Addr, family AddressFamily) (net.IP, error) {
	if len(addrs) > 0 {
		for i := range addrs {
			klog.V(4).Infof("Checking addr  %s.", addrs[i].String())
			ip, _, err := netutils.ParseCIDRSloppy(addrs[i].String())
			if err != nil {
				return nil, err
			}
			if memberOf(ip, family) {
				if ip.IsGlobalUnicast() {
					klog.V(4).Infof("IP found %v", ip)
					return ip, nil
				} else {
					klog.V(4).Infof("Non-global unicast address found %v", ip)
				}
			} else {
				klog.V(4).Infof("%v is not an IPv%d address", ip, int(family))
			}

		}
	}
	return nil, nil
}


getIPFromInterface

// getIPFromInterface gets the IPs on an interface and returns a global unicast address, if any. The
// interface must be up, the IP must in the family requested, and the IP must be a global unicast address.
func getIPFromInterface(intfName string, forFamily AddressFamily, nw networkInterfacer) (net.IP, error) {
	intf, err := nw.InterfaceByName(intfName)
	if err != nil {
		return nil, err
	}
	if isInterfaceUp(intf) {
		addrs, err := nw.Addrs(intf)
		if err != nil {
			return nil, err
		}
		klog.V(4).Infof("Interface %q has %d addresses :%v.", intfName, len(addrs), addrs)
		matchingIP, err := getMatchingGlobalIP(addrs, forFamily)
		if err != nil {
			return nil, err
		}
		if matchingIP != nil {
			klog.V(4).Infof("Found valid IPv%d address %v for interface %q.", int(forFamily), matchingIP, intfName)
			return matchingIP, nil
		}
	}
	return nil, nil
}


getIPFromLoopbackInterface

// getIPFromLoopbackInterface gets the IPs on a loopback interface and returns a global unicast address, if any.
// The loopback interface must be up, the IP must in the family requested, and the IP must be a global unicast address.
func getIPFromLoopbackInterface(forFamily AddressFamily, nw networkInterfacer) (net.IP, error) {
	intfs, err := nw.Interfaces()
	if err != nil {
		return nil, err
	}
	for _, intf := range intfs {
		if !isInterfaceUp(&intf) {
			continue
		}
		if intf.Flags&(net.FlagLoopback) != 0 {
			addrs, err := nw.Addrs(&intf)
			if err != nil {
				return nil, err
			}
			klog.V(4).Infof("Interface %q has %d addresses :%v.", intf.Name, len(addrs), addrs)
			matchingIP, err := getMatchingGlobalIP(addrs, forFamily)
			if err != nil {
				return nil, err
			}
			if matchingIP != nil {
				klog.V(4).Infof("Found valid IPv%d address %v for interface %q.", int(forFamily), matchingIP, intf.Name)
				return matchingIP, nil
			}
		}
	}
	return nil, nil
}


memberOf

// memberOf tells if the IP is of the desired family. Used for checking interface addresses.
func memberOf(ip net.IP, family AddressFamily) bool {
	if ip.To4() != nil {
		return family == familyIPv4
	} else {
		return family == familyIPv6
	}
}


chooseIPFromHostInterfaces

// chooseIPFromHostInterfaces looks at all system interfaces, trying to find one that is up that
// has a global unicast address (non-loopback, non-link local, non-point2point), and returns the IP.
// addressFamilies determines whether it prefers IPv4 or IPv6
func chooseIPFromHostInterfaces(nw networkInterfacer, addressFamilies AddressFamilyPreference) (net.IP, error) {
	intfs, err := nw.Interfaces()
	if err != nil {
		return nil, err
	}
	if len(intfs) == 0 {
		return nil, fmt.Errorf("no interfaces found on host.")
	}
	for _, family := range addressFamilies {
		klog.V(4).Infof("Looking for system interface with a global IPv%d address", uint(family))
		for _, intf := range intfs {
			if !isInterfaceUp(&intf) {
				klog.V(4).Infof("Skipping: down interface %q", intf.Name)
				continue
			}
			if isLoopbackOrPointToPoint(&intf) {
				klog.V(4).Infof("Skipping: LB or P2P interface %q", intf.Name)
				continue
			}
			addrs, err := nw.Addrs(&intf)
			if err != nil {
				return nil, err
			}
			if len(addrs) == 0 {
				klog.V(4).Infof("Skipping: no addresses on interface %q", intf.Name)
				continue
			}
			for _, addr := range addrs {
				ip, _, err := netutils.ParseCIDRSloppy(addr.String())
				if err != nil {
					return nil, fmt.Errorf("unable to parse CIDR for interface %q: %s", intf.Name, err)
				}
				if !memberOf(ip, family) {
					klog.V(4).Infof("Skipping: no address family match for %q on interface %q.", ip, intf.Name)
					continue
				}
				// TODO: Decide if should open up to allow IPv6 LLAs in future.
				if !ip.IsGlobalUnicast() {
					klog.V(4).Infof("Skipping: non-global address %q on interface %q.", ip, intf.Name)
					continue
				}
				klog.V(4).Infof("Found global unicast address %q on interface %q.", ip, intf.Name)
				return ip, nil
			}
		}
	}
	return nil, fmt.Errorf("no acceptable interface with global unicast address found on host")
}


ChooseHostInterface

// ChooseHostInterface is a method used fetch an IP for a daemon.
// If there is no routing info file, it will choose a global IP from the system
// interfaces. Otherwise, it will use IPv4 and IPv6 route information to return the
// IP of the interface with a gateway on it (with priority given to IPv4). For a node
// with no internet connection, it returns error.
func ChooseHostInterface() (net.IP, error) {
	return chooseHostInterface(preferIPv4)
}


chooseHostInterface

func chooseHostInterface(addressFamilies AddressFamilyPreference) (net.IP, error) {
	var nw networkInterfacer = networkInterface{}
	if _, err := os.Stat(ipv4RouteFile); os.IsNotExist(err) {
		return chooseIPFromHostInterfaces(nw, addressFamilies)
	}
	routes, err := getAllDefaultRoutes()
	if err != nil {
		return nil, err
	}
	return chooseHostInterfaceFromRoute(routes, nw, addressFamilies)
}


InterfaceByName

func (_ networkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
	return net.InterfaceByName(intfName)
}


Addrs

func (_ networkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
	return intf.Addrs()
}


Interfaces

func (_ networkInterface) Interfaces() ([]net.Interface, error) {
	return net.Interfaces()
}


getAllDefaultRoutes

// getAllDefaultRoutes obtains IPv4 and IPv6 default routes on the node. If unable
// to read the IPv4 routing info file, we return an error. If unable to read the IPv6
// routing info file (which is optional), we'll just use the IPv4 route information.
// Using all the routing info, if no default routes are found, an error is returned.
func getAllDefaultRoutes() ([]Route, error) {
	routes, err := v4File.extract()
	if err != nil {
		return nil, err
	}
	v6Routes, _ := v6File.extract()
	routes = append(routes, v6Routes...)
	if len(routes) == 0 {
		return nil, noRoutesError{
			message: fmt.Sprintf("no default routes found in %q or %q", v4File.name, v6File.name),
		}
	}
	return routes, nil
}


chooseHostInterfaceFromRoute

// chooseHostInterfaceFromRoute cycles through each default route provided, looking for a
// global IP address from the interface for the route. If there are routes but no global
// address is obtained from the interfaces, it checks if the loopback interface has a global address.
// addressFamilies determines whether it prefers IPv4 or IPv6
func chooseHostInterfaceFromRoute(routes []Route, nw networkInterfacer, addressFamilies AddressFamilyPreference) (net.IP, error) {
	for _, family := range addressFamilies {
		klog.V(4).Infof("Looking for default routes with IPv%d addresses", uint(family))
		for _, route := range routes {
			if route.Family != family {
				continue
			}
			klog.V(4).Infof("Default route transits interface %q", route.Interface)
			finalIP, err := getIPFromInterface(route.Interface, family, nw)
			if err != nil {
				return nil, err
			}
			if finalIP != nil {
				klog.V(4).Infof("Found active IP %v ", finalIP)
				return finalIP, nil
			}
			// In case of network setups where default routes are present, but network
			// interfaces use only link-local addresses (e.g. as described in RFC5549).
			// the global IP is assigned to the loopback interface, and we should use it
			loopbackIP, err := getIPFromLoopbackInterface(family, nw)
			if err != nil {
				return nil, err
			}
			if loopbackIP != nil {
				klog.V(4).Infof("Found active IP %v on Loopback interface", loopbackIP)
				return loopbackIP, nil
			}
		}
	}
	klog.V(4).Infof("No active IP found by looking at default routes")
	return nil, fmt.Errorf("unable to select an IP from default routes.")
}


ResolveBindAddress

// ResolveBindAddress returns the IP address of a daemon, based on the given bindAddress:
// If bindAddress is unset, it returns the host's default IP, as with ChooseHostInterface().
// If bindAddress is unspecified or loopback, it returns the default IP of the same
// address family as bindAddress.
// Otherwise, it just returns bindAddress.
func ResolveBindAddress(bindAddress net.IP) (net.IP, error) {
	addressFamilies := preferIPv4
	if bindAddress != nil && memberOf(bindAddress, familyIPv6) {
		addressFamilies = preferIPv6
	}

	if bindAddress == nil || bindAddress.IsUnspecified() || bindAddress.IsLoopback() {
		hostIP, err := chooseHostInterface(addressFamilies)
		if err != nil {
			return nil, err
		}
		bindAddress = hostIP
	}
	return bindAddress, nil
}


ChooseBindAddressForInterface

// ChooseBindAddressForInterface choose a global IP for a specific interface, with priority given to IPv4.
// This is required in case of network setups where default routes are present, but network
// interfaces use only link-local addresses (e.g. as described in RFC5549).
// e.g when using BGP to announce a host IP over link-local ip addresses and this ip address is attached to the lo interface.
func ChooseBindAddressForInterface(intfName string) (net.IP, error) {
	var nw networkInterfacer = networkInterface{}
	for _, family := range preferIPv4 {
		ip, err := getIPFromInterface(intfName, family, nw)
		if err != nil {
			return nil, err
		}
		if ip != nil {
			return ip, nil
		}
	}
	return nil, fmt.Errorf("unable to select an IP from %s network interface", intfName)
}


Contains

// Contains tests whether a given port falls within the PortRange.
func (pr *PortRange) Contains(p int) bool {
	return (p >= pr.Base) && ((p - pr.Base) < pr.Size)
}


String

// String converts the PortRange to a string representation, which can be
// parsed by PortRange.Set or ParsePortRange.
func (pr PortRange) String() string {
	if pr.Size == 0 {
		return ""
	}
	return fmt.Sprintf("%d-%d", pr.Base, pr.Base+pr.Size-1)
}


Set

// Set parses a string of the form "value", "min-max", or "min+offset", inclusive at both ends, and
// sets the PortRange from it.  This is part of the flag.Value and pflag.Value
// interfaces.
func (pr *PortRange) Set(value string) error {
	const (
		SinglePortNotation = 1 << iota
		HyphenNotation
		PlusNotation
	)

	value = strings.TrimSpace(value)
	hyphenIndex := strings.Index(value, "-")
	plusIndex := strings.Index(value, "+")

	if value == "" {
		pr.Base = 0
		pr.Size = 0
		return nil
	}

	var err error
	var low, high int
	var notation int

	if plusIndex == -1 && hyphenIndex == -1 {
		notation |= SinglePortNotation
	}
	if hyphenIndex != -1 {
		notation |= HyphenNotation
	}
	if plusIndex != -1 {
		notation |= PlusNotation
	}

	switch notation {
	case SinglePortNotation:
		var port int
		port, err = strconv.Atoi(value)
		if err != nil {
			return err
		}
		low = port
		high = port
	case HyphenNotation:
		low, err = strconv.Atoi(value[:hyphenIndex])
		if err != nil {
			return err
		}
		high, err = strconv.Atoi(value[hyphenIndex+1:])
		if err != nil {
			return err
		}
	case PlusNotation:
		var offset int
		low, err = strconv.Atoi(value[:plusIndex])
		if err != nil {
			return err
		}
		offset, err = strconv.Atoi(value[plusIndex+1:])
		if err != nil {
			return err
		}
		high = low + offset
	default:
		return fmt.Errorf("unable to parse port range: %s", value)
	}

	if low > 65535 || high > 65535 {
		return fmt.Errorf("the port range cannot be greater than 65535: %s", value)
	}

	if high < low {
		return fmt.Errorf("end port cannot be less than start port: %s", value)
	}

	pr.Base = low
	pr.Size = 1 + high - low
	return nil
}


Type

// Type returns a descriptive string about this type.  This is part of the
// pflag.Value interface.
func (*PortRange) Type() string {
	return "portRange"
}


ParsePortRange

// ParsePortRange parses a string of the form "min-max", inclusive at both
// ends, and initializes a new PortRange from it.
func ParsePortRange(value string) (*PortRange, error) {
	pr := &PortRange{}
	err := pr.Set(value)
	if err != nil {
		return nil, err
	}
	return pr, nil
}


ParsePortRangeOrDie

func ParsePortRangeOrDie(value string) *PortRange {
	pr, err := ParsePortRange(value)
	if err != nil {
		panic(fmt.Sprintf("couldn't parse port range %q: %v", value, err))
	}
	return pr
}