Skip to content

cub unit conflicts

cub unit conflicts

Show, apply, or dismiss a unit's outstanding merge conflicts

Synopsis

Work with the parts of the last merge's patch that were not applied.

A merge reports a conflict for every change it could not make: a path the downstream owns (Subtracted), a path the downstream protects (ProtectedPath), a path that could not be located in this unit (UnresolvedPath), and each downstream change displaced by an upstream deletion (DeleteShadowed). The merged data is correct as it stands -- a conflict says what the source wanted to change and couldn't.

Guarded is one of those, for a value the source wanted to write at a path carrying a guard -- a recorded reason its value is what it is -- that the merge was not cleared for. The conflict names the guard, so the report says which reason stopped it rather than only that something did.

GuardWithheld is the other half, and is about a guard rather than a value: the source changed the guards at a path and this merge was not cleared for the guards this unit already has there, so the guard change did not propagate. Reported because a base that adds a policy exception and a variant that silently does not receive it is exactly the failure guards exist to prevent, and the data merging cleanly would otherwise hide it. Applying one writes the guard change rather than any configuration data.

ExclusiveWithheld is one of those, for a change that could not be made because this unit owns a field mutually exclusive with it -- the source switched a volume to a secret and this unit had already chosen an emptyDir. Applying it performs the switch. ExclusiveCleared reports the opposite: the source's change applied and a value this unit had was removed to make room for it, because keeping both is a resource that will not apply. It carries the removed value.

The conflicts stay on the unit until they are dealt with, so a merge that dropped half its patch is still visible afterwards rather than only in the response of the request that ran it. The next merge replaces them with its own, and a merge that lands cleanly clears them.

With no flags this lists the outstanding conflicts, and the dismissals recorded with --permanent. --apply replays the changes they withheld, with every path eligible so nothing filters them out a second time. --dismiss drops them without touching the configuration data. Both act on every outstanding conflict unless --reason, --path, --resource, --resource-type, or --guard narrows the selection, and both take --dry-run, which reports what the request would do and writes nothing.

--resource names a resource by its whole name (prod/web, or /web for a cluster-scoped resource) or a name it had before a rename. A name without a namespace (web) is a filter instead, selecting the resource of that name in every namespace; --permanent and --undismiss refuse one that matches more than one resource. --resource-type tells apart resources that share a name, as a Deployment and a Service named for their app do; it matches the type in any API version. --path names an element of a list by its position in this unit (spec.data.0.secretKey), by merge key (spec.template.spec.containers.?name=main.image), or as the conflict shows it, and * stands for any one list element or map key (spec.data.*.secretKey). --guard, repeatable, names a guard as key or key=value, and selects a Guarded or GuardWithheld conflict when it names every guard the conflict lists.

--dismiss --permanent also records the selection on the unit, so that a later merge reporting a conflict it covers leaves that conflict dismissed rather than outstanding: for a value this unit overrides on purpose, or a guard that is meant to withhold what the upstream sends. Each recorded dismissal is about one resource and one reason, so --permanent needs --resource and --reason, and --guard for a Guarded or GuardWithheld conflict to dismiss only what those guards withheld. Without --path it covers every path of the resource. The merge's revision keeps the conflicts it reported, and a revision of its own records their dismissal. --undismiss removes recorded dismissals of a --resource, for --reason and --guard, or for every reason without them: without --path, the one on the resource as a whole; with --path '', every one; with a path, the one recorded at that path, a pattern such as containers..image included.

Applying changes the configuration data, so the unit goes through the same trigger pass as any other change and may pick up a ValidationError. --wait, on by default, waits for that pass to finish before returning.

Examples:

  # What did the last merge fail to apply?
  cub unit conflicts my-unit

  # What would taking the upstream's value do to this unit?
  cub unit conflicts my-unit --apply --dry-run -o mutations

  # Apply the upstream changes that were withheld because this unit owns the path
  cub unit conflicts my-unit --apply --reason Subtracted

  # Accept the current state and stop reporting them
  cub unit conflicts my-unit --dismiss

  # Dismiss the conflict at one path of the Service, not of the Deployment of the same name
  cub unit conflicts my-unit --dismiss --resource prod/web --resource-type v1/Service \
    --path metadata.labels.tier

  # The same, naming the resource without its namespace and the element by position
  cub unit conflicts my-unit --dismiss --resource app --path spec.data.0.secretKey

  # Stop reporting the upstream's replica count: this unit sets its own
  cub unit conflicts my-unit --dismiss --permanent --resource web --reason Subtracted \
    --path spec.replicas

  # Stop reporting values withheld only by the platform team's guard, at any element
  cub unit conflicts my-unit --dismiss --permanent --resource web --reason Guarded \
    --guard owner=platform --path 'spec.template.spec.containers.*.image'

  # Report the replica count again
  cub unit conflicts my-unit --undismiss --resource web --path spec.replicas

  # Remove every dismissal recorded on the resource
  cub unit conflicts my-unit --undismiss --resource web --path '*'

  # Which units in the space merged with paths the patch could not locate?
  cub unit list --where "Conflicts.*.Reason = 'UnresolvedPath'"
cub unit conflicts <unit-slug> [--apply | --dismiss [--permanent] | --undismiss] [--reason REASON] [--path PATH] [--resource NAME] [--resource-type TYPE] [--guard KEY[=VALUE]]... [flags]

Options

      --apply                  apply the changes the selected conflicts withheld
      --dismiss                drop the selected conflicts without changing the configuration data
      --dry-run                dry run mode: report what --apply or --dismiss would do without writing anything
      --guard stringArray      select conflicts withheld only by these guards, as key or key=value (repeatable)
  -h, --help                   help for conflicts
  -o, --output string          Output format. One of: json, yaml, name, wide, mutations, jq=<expr>, yq=<expr>, custom-columns=<spec>
      --path string            select conflicts at this path; a list element by position or merge key, * for any one element or key
      --permanent              with --dismiss, also dismiss what the selection covers whenever a later merge reports it
      --quiet                  No default output.
      --reason string          select conflicts with this reason: Subtracted, DeleteShadowed, ProtectedPath, UnresolvedPath, ExclusiveWithheld, ExclusiveCleared, Guarded, GuardWithheld, or ReplayFailed
      --resource string        select conflicts on this resource, by its whole name (namespace/name); a name without a namespace selects that name in every namespace
      --resource-type string   select conflicts on resources of this type, such as apps/v1/Deployment, in any API version
      --timeout string         completion timeout as a duration with units, such as 10s or 2m (default "10m0s")
      --undismiss              remove dismissals recorded with --permanent, so the conflicts they covered are reported again
      --verbose                Detailed output, additive with default output
      --wait                   wait for completion (default true)

Options inherited from parent commands

      --component string   the Component of --variant, when that names the variant alone; --variant <component>/<variant> says the same in one flag
      --context string     The context to use for this command
      --debug              Debug output
      --space string       space to operate in, by slug or UUID. Omitted, a list or bulk operation spans the organization and a single entity is named as <space>/<slug>; "*" means the same as omitting it
      --variant string     variant to operate in, as <component>/<variant>, or as <variant> with --component: the space naming that Component whose Variant label is <variant>. The same scope as --space, named by what it is rather than by the space's slug; the two cannot be combined

SEE ALSO