Skip to content

cub variant create

cub variant create

Create a variant by cloning a space and its units

Synopsis

Create a variant of an upstream space by cloning the space and all of its units into a new downstream space.

This is a convenience command that combines two bulk operations: 1. Clone the upstream space (like "cub space create" in bulk mode), setting the new space's "Variant" label to . 2. Clone every unit from the upstream space into the new space (like "cub unit create" in bulk mode), linking each clone to its upstream unit.

The first argument is the variant name, which becomes the value of the "Variant" label on the new space. The second argument is the slug (or UUID) of the upstream space to clone from. The upstream space is expected to have labels such as Component, Layer, Owner, Stage, Environment, Region, and Variant, and may have a "TargetID" annotation referencing the default target for the space, but none of these are required.

The new space's labels are inherited from the upstream space, with "Variant" overridden to . Use --stage, --environment, and --region to add or change the "Stage", "Environment", and "Region" labels, since some values (like Region) commonly differ between variants. The other well-known labels (Component, Layer, Owner) are inherited and can be overridden with --variant-labels.

The new space's slug defaults to -, derived from the cloned space's Component and Variant labels — the same convention as "cub variant upload" and "cub helm install". When the cloned space would have no Component label, the server instead derives the slug from the upstream space's slug and the variant name. Use --space-pattern to override: a Go template evaluated over the cloned space's labels (and .SourceEntitySlug for the upstream slug), for example "template:{{.Labels.Component}}-{{.Labels.Variant}}".

The following are copied from the upstream space to the new space: WhereTrigger, TriggerFilterID, Permissions, and DeleteGates.

Metadata flags are split by what they target, space vs. unit (mirroring "install upload"): --space-annotation / --space-delete-gate set on the new space, merged onto the values copied from the upstream space. --unit-annotation / --unit-delete-gate / set on every cloned unit, merged onto each clone's --unit-destroy-gate copied values. Destroy gates are unit-only (spaces have no destroy gates). Use --unit-delete-gate critical to protect a prod variant's units. --wait wait for the cloned units' triggers to finish (default true); pass --wait=false to return as soon as the clone is queued.

To automatically customize the cloned units, create PostClone triggers and select them via the upstream space's WhereTrigger or TriggerFilterID so that they are copied to the downstream space and run during the clone. Trigger arguments can reference space metadata in Go templates, such as "template:{{.SpaceLabels.Region}}" or "template:{{.SpaceAnnotations.host}}" — set the latter with --space-annotation. Any other changes can be made after the clone completes.

Links between units of the cloned space are copied into the new space and retargeted at the clones. Links pointing out of it are not, unless --include-outgoing-links-where selects them: a copied outgoing link keeps the original unit as its to-unit, so the variant reads from the same producer the upstream reads from.

A variant is normally downstream of its upstream space: changes flow from the upstream units into the clones, through the UpgradeUnit links this command creates ("cub variant promote"). --syncback additionally creates a MergeUnits link the other way, from each upstream unit back to its clone, which makes the variant usable as a draft: clone the space, change the clones, review them, then merge the changes back into the upstream units with

cub unit update --patch --space --where "..." \ --resolve "Link:ToSpaceID = ''"

The syncback links live in the upstream space and are named for the clone they take changes from ("syncback--"), so an upstream space can have several drafts open at once.

When --target points at a cub-cluster Argo target (an OCI target carrying the confighub.com/argo-apps-space annotation that "cub cluster up" stamps), this command also creates the Argo CD Application that makes the new deployment live: a Kubernetes/YAML unit named after the new space, added to the cluster's apps space and pulling the new space's OCI Release. The apps space's Release is republished so the cluster's root app-of-apps picks it up on its next sync. This is a no-op for ordinary targets; use --no-argo-app to skip it. Publish the deployment's own release ("cub release publish ") to make its configuration go live.

Examples:

  # Clone a space into a "test" variant. With Component=website inherited and Variant overridden to
  # "test", the default slug is "website-test".
  cub variant create test website-prod

  # Clone into a regional staging variant, overriding the Environment and Region labels.
  cub variant create staging website-prod --environment Staging --region us-east2

  # Clone into a canary variant of production, overriding the Stage label.
  cub variant create canary website-prod --stage Canary --environment Prod

  # Point the cloned units at a target and stamp the new space's TargetID annotation.
  # For an OCI target, this also sets the new space's release target, so the variant
  # can be published with "cub release publish" without further setup.
  cub variant create test website-prod --target website-test/cluster

  # Deploy to a "cub cluster up" cluster: clones the base, retargets it, and creates
  # the Argo CD Application so the cluster picks up the deployment (skip with --no-argo-app).
  cub variant create dev cubbychat-base --target dev/target --namespace cubbychat

  # Clone a space as a draft to change and review, with links to merge the changes back.
  cub variant create draft website-prod --syncback

  # Carry the units' links to producers in other spaces into the variant, so its units read
  # from the same ones.
  cub variant create prod website-base --include-outgoing-links-where "UpdateType = 'TransformPaths'"

  # Set a space annotation a PostClone trigger reads, and protect the prod clones with a delete gate.
  cub variant create prod website-base \
    --space-annotation host=website.prod.example.com \
    --unit-delete-gate critical --unit-destroy-gate critical
cub variant create <variant-name> <upstream-space> [flags]

Options

      --allow-exists                          Allow creation of resources that already exist
      --environment string                    set the "Environment" label on the new space (example: "Prod")
  -h, --help                                  help for create
      --include-outgoing-links-where string   where expression selecting which of the upstream units' links to units in other spaces to copy onto the clones; each copy keeps the original unit as its to-unit, so the variant reads from the same producers. Links within the cloned space are always copied and retargeted at the clones
      --namespace string                      run set-namespace with this value on the cloned Kubernetes/YAML units, replacing the placeholder namespace from the upstream (e.g. a base uploaded with --namespace confighubplaceholder)
      --no-argo-app                           skip auto-creating the Argo CD Application when --target is a cub-cluster Argo target
  -o, --output string                         Output format. One of: json, yaml, name, wide, mutations, jq=<expr>, yq=<expr>, custom-columns=<spec>
      --quiet                                 No default output.
      --region string                         set the "Region" label on the new space (example: "us-east2")
      --space-annotation strings              annotation key=value to set on the new space (repeatable); merged onto the annotations copied from the upstream space. PostClone trigger args can read these via {{.SpaceAnnotations.<key>}}. "TargetID" is reserved (use --target)
      --space-delete-gate strings             delete gate key[=true] to set on the new space (repeatable); merged onto the delete gates copied from the upstream space
      --space-pattern string                  a pattern string for the new space's slug, prefix 'template:' to use a Go template with .SourceEntitySlug for the upstream slug and .Labels for the cloned space's labels; defaults to 'template:{{.Labels.Component}}-{{.Labels.Variant}}' when the cloned space has a Component label
      --stage string                          set the "Stage" label on the new space (example: "Canary")
      --syncback                              also link each cloned unit back to its upstream unit, with a MergeUnits link in the upstream space, so changes made in the variant can be merged back into the upstream units (see the draft workflow in the long help)
      --target string                         target for the cloned units, in <target-slug> or <space-slug>/<target-slug> form; also sets the TargetID annotation on the new space, and for an OCI target the new space's ReleaseTargetID (required by 'cub release publish')
      --timeout string                        completion timeout as a duration with units, such as 10s or 2m (default "10m0s")
      --unit-annotation strings               annotation key=value to set on every cloned unit (repeatable); merged onto each unit's copied annotations
      --unit-delete-gate strings              delete gate key[=true] to set on every cloned unit (repeatable); e.g. --unit-delete-gate critical to protect a prod variant
      --unit-destroy-gate strings             destroy gate key[=true] to set on every cloned unit (repeatable); destroy gates are unit-only (spaces have no destroy gates)
      --variant-labels strings                additional variant labels for the new space in the format key1=value1,key2=value2 (the Variant label is always set from <variant-name>)
      --verbose                               Detailed output, additive with default output
      --wait                                  wait for completion (default true)

Options inherited from parent commands

      --context string   The context to use for this command
      --debug            Debug output

SEE ALSO