Skip to content

Latest commit

 

History

History
65 lines (48 loc) · 3.3 KB

legacy.md

File metadata and controls

65 lines (48 loc) · 3.3 KB

Deprecation notice

This page documents the legacy method for matching objects, which is now deprecated. Please use the the patch package.

The legacy version was last available with the 0.1.1 version.

Supported Objects

  • ClusterRole
  • ClusterRoleBindings
  • ConfigMap
  • CustomResourceDefinition
  • DaemonSet
  • Deployment
  • HorizontalPodAutoScaler
  • MutatingWebhook
  • Role
  • RoleBinding
  • Pod
  • PersistentVolumeClaim
  • Service
  • ServiceAccount
  • Unstructured
  • Node

How to use it

objectMatcher := objectmatch.New(logf.NewDelegatingLogger(logf.NullLogger{}))
objectMatcher.Match(e.ObjectOld, e.ObjectNew)

The idea

There are existing libraries in the wild that can calculate a patch by giving them two different objects. If the patch is empty the two objects match and we are ready, right? Well not quite. JSON Merge Patch, defined by rfc7396 replaces lists completely which is not always what we need. Kubernetes defines and uses a modified version called strategic merge patch.

Strategic Merge Patch extends the JSON Merge Patch format by adding explicit directives for deleting, replacing, ordering and merging lists. It uses the go struct tag of the API objects to determine what lists should be merged and which ones should not. Worth to note it's not tied to Kubernetes objects only, so we can use this for matching custom go structs as well.

Caveats

Defaults and version compatibility

As outlined previously Kubernetes objects are amended with different default values when submitted. For example PodSpec.RestartPolicy will be set to "Always" when ommitted from the object, so we will have a mismatch when we try to compare it later. This library uses the same functions to set the default values on the local objects before matching so that they won't differ.

Since the defaults functions are defined in the main kubernetes repo, there is a higher chance that objects decorated using these functions will be incompatible when comparing them with objects coming from different server versions. Also since the library depends on the kubernetes repo it is more tightly coupled to it's version.

To preserve compatibility between the client and server versions .circleci/config.yml contains jobs that run the integration test suite against Kubernetes versions from 1.10 to 1.14. The library itself is known and tested to be working with operators depending on Kubernetes client version 1.12 and 1.13.

Generated values

There are values that are generated by the API Server dynamically. To workaround this the library removes null fields from the patch as long as it's not inside a list. (In case of lists, even if we remove null fields we would still left with setElementOrder directives) This works as long as we don't set/unset complete fields on the objects conditionally, because in that case we would miss to detect a change to unset something.

In case a field gets removed from somewhere inside a list we have to explicitly tell to ignore it. One example is NodePort in Service objects, see service.go. Another example is Volume and VolumeMount generated automatically for the service account token, see pod.go.