Deleting referenced entities
ConfigHub doesn't delete an entity while something outside the delete still references it: a Unit that targets a Target, a Space whose release Target it is, a Unit cloned from another Unit, a Revision a Tag marks. The delete is refused, and the error names each referrer by Space and slug, and the field that holds the reference. This is the rule a relational database applies with ON DELETE RESTRICT. It differs from Kubernetes, where deleting an object that another names, such as a ConfigMap a Pod mounts, succeeds and leaves the reference dangling.
$ cub target delete --space cluster release
Failed: HTTP 409: Cannot delete Target cluster/release: it is still referenced by 1 Space and 1 Unit. Remove those references first, or detach them as part of the delete.
Metadata:
Space app: ReleaseTargetID references Target cluster/release
Unit app/ns: TargetID references Target cluster/release
There are three ways forward:
- Remove the references, for example with
cub space update --release-target - appandcub unit set-target --space app ns -. - Delete the referrers in the same request. A bulk delete, with
--whereor a list of slugs, removes entities that reference one another in whatever order it lists them, and a recursive Space delete removes everything in the Space along with it. What references them from within the request doesn't count. - Pass
--detachto remove the references as part of the delete. The referrers stay. Detaching needs permission to edit every referrer. If you don't have it for any of them, nothing is changed and the delete is refused. Referrers in Spaces you can't view are counted but not named.
Detaching never happens without --detach.
What --detach removes
| Deleting | What references it | With --detach |
|---|---|---|
| Target | Units that target it, Spaces whose release Target it is, Releases published for it | The Units and Spaces are left without a Target, and the Releases without the Target they were published for |
| Worker | Targets that name it | The Targets are left without a worker, and so are their Units |
| Unit | Links to it from other Units, including a clone's link to the Unit it was cloned from | The Links are deleted; a clone is left without an upstream Unit |
| Tag | The Revisions it marks | The marks are removed |
| ChangeSet | Revisions made in it, Units open in it, and the Revisions its Tags mark | The Revisions and Units are taken out of it, and the marks removed |
| ChangeOrder | The Revisions it and its Tags mark: those of the Units its changes were made in and promoted to | The marks are removed |
| Release | The Revisions it bundled and its Tag marks | The marks are removed |
Deleting a ChangeOrder or a Release therefore needs --detach in practice: each marks the Revisions it covers. So does discarding a draft made with cub variant create --syncback: its syncback Links, in the upstream Space, link to the draft's Units, and --detach deletes them.
A few references refuse the delete even with --detach, since removing them would change what the referrer does:
- A Filter that a Space, Target, Trigger, View or ChangeOrder uses.
- An Invocation that a Trigger, Link or ChangeOrder runs.
- A Worker that a Trigger or Invocation runs on.
- A Space that a Filter selects from.
- A Tag that a ChangeSet, ChangeOrder or Release names as a boundary. A Tag one of them made is deleted with it; one it adopted stays.
What a delete takes with it
Deleting a Unit deletes its Revisions, Resources and the Links from it. Deleting a ChangeSet, ChangeOrder or Release deletes the Tags it made. Deleting a Space with --recursive deletes everything in it, and checks what outside the Space references what it contains before it deletes anything. --detach then applies to everything the delete reaches.
--recursive-force skips Delete Gates, and nothing else: it doesn't remove references.