Skip to content

[deckhouse-cli] Push CLI plugins to the registry root above the edition - #451

Draft
Glitchy-Sheep wants to merge 2 commits into
mainfrom
fix/mirror-push-plugins-root
Draft

[deckhouse-cli] Push CLI plugins to the registry root above the edition#451
Glitchy-Sheep wants to merge 2 commits into
mainfrom
fix/mirror-push-plugins-root

Conversation

@Glitchy-Sheep

@Glitchy-Sheep Glitchy-Sheep commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Summary

d8 CLI plugins belong one level above the edition segment of the push target. Pull already reads them there, and the in-cluster registry-packages-proxy will look for them there. Push was the only side that put them somewhere else.

Problem

  • Push glues every bundle path onto the target as the user typed it
  • Users push to a target that ends with an edition, for example REGISTRY/dkp/ee
  • So plugins landed at REGISTRY/dkp/ee/deckhouse-cli/plugins
  • The proxy cuts the edition off the cluster imagesRepo and reads REGISTRY/dkp/deckhouse-cli/plugins
  • d8 plugins install <name> in an air-gapped cluster did not find the plugin
  • The catalog tags moved with the images, so nothing was listed at the path the proxy uses

Fix

  • Push now takes the registry host plus the target path and works out two roots on its own
  • The deckhouse-cli/ part of the bundle goes to the target minus its trailing edition segment
  • Plugin images and catalog discovery tags move together
  • A target without an edition, like registry.company.com/deckhouse, is used as is
  • Platform, modules, packages, installer and security databases stay under the target as before
  • The root is picked by the bundle path, not by the final registry path, so --modules-path-suffix cannot move modules above the edition
  • The push log names the plugins path before the first write there
  • A denied write above the target now says which repository was refused, which target it sits above and which edition was cut off

Before / After

Before: d8 mirror push ./bundle REGISTRY/dkp/ee wrote plugins to REGISTRY/dkp/ee/deckhouse-cli/plugins, where the cluster never looks.

After: the same command writes them to REGISTRY/dkp/deckhouse-cli/plugins, and d8 plugins install finds them.

Tests

  • TestPluginsRootPath - the root rule itself, including the targets where nothing is cut
  • TestPushService_PluginsGoToRootAboveEdition - seven target shapes: with edition, se-plus, trailing slash, no edition, nested path, edition not at the end
  • TestPushService_PluginLayoutIsNotPlatform - a bundle with only a plugin is not counted as platform
  • TestPushService_ModulesPathSuffixIntoPluginsNamespace - --modules-path-suffix deckhouse-cli keeps modules under the target
  • TestPushService_PluginsRootDenied, TestPushService_PluginsRootDenied_LayoutPush - a refused write above the target keeps the HTTP status and names the paths
  • TestDiagnose_PluginsRootDenied, TestDiagnose_PluginsRootNonAuthFallsThrough - the 401/403 diagnostic names the paths, other errors keep their own category
  • TestPullE2E_RoundTrip_PullThenPushPlugins - pull, pack, push: plugins land at the root, modules stay under the edition

Checked by hand against two local registries: the same bundle pushed by the old and the new binary, then d8 cr catalog, d8 cr ls and d8 cr digest on both.

Also in this PR

A second, small fix in the same area: the 403 diagnostic for d8 dist plugins named the wrong ClusterRole.

  • Plugins are downloaded over /v1/images/, which kube-rbac-proxy authorizes through the deployments/cli-binary subresource
  • That subresource is granted by d8:registry-packages-proxy:cli-download
  • The advice named packages-download, which covers /v1/packages/ and is never called by the CLI, so following it left the user with the same 403
  • The same block told the user to wait about 5 minutes and retry with a fresh token. A denial is cached for about 30 seconds and the old token keeps working, so both halves were wrong. Fixed in the d8 dist copy of the diagnostic too
  • TestDiagnose in internal/plugins/cmd/errdetect now pins cli-download

The mapping comes from modules/039-registry-packages-proxy/templates/deployment.yaml in deckhouse.

Notes

  • This needs to ship before the proxy patch (deckhouse#22324) lands in DKP
  • cse is not an edition here, while the proxy patch treats it as one. CSE mirrors keep plugins under deckhouse/cse for now
  • The pre-push access check still covers the target only. A missing grant on <root>/deckhouse-cli shows up at the first plugin write, after the rest of the bundle is uploaded

d8 CLI artifacts are published once for all editions, at the registry root
above the edition segment. Pull already reads plugins from there, and the
in-cluster registry-packages-proxy looks them up there by cutting the edition
off the cluster's imagesRepo. Push was the only side gluing every bundle
segment onto the target as typed, so a push to REGISTRY/dkp/ee left plugins at
REGISTRY/dkp/ee/deckhouse-cli/plugins while the cluster looked one level up:
d8 plugins install could not find them in an air-gapped registry.

Push now writes the deckhouse-cli/ part of the bundle, images and the catalog
discovery tags alike, to the target minus its trailing edition segment. A
target without an edition is used as is. Platform, modules, packages,
installer and security databases stay under the target as before.

The push log names the plugins path before the first write there, and a
denied write above the target no longer surfaces as a bare 401/403: the
diagnostic says which repository was refused, which target it sits above and
which edition was cut off.

Signed-off-by: Roman Berezkin <roman.berezkin@flant.com>
@Glitchy-Sheep Glitchy-Sheep changed the title [mirror] Push CLI plugins to the registry root above the edition [deckhouse-cli] Push CLI plugins to the registry root above the edition Aug 21, 2026
…s-proxy

Plugins are downloaded over /v1/images/, and kube-rbac-proxy authorizes that
whole prefix through the deployments/cli-binary subresource, granted by the
ClusterRole d8:registry-packages-proxy:cli-download. The 403 diagnostic named
packages-download instead. That role covers /v1/packages/, which the CLI never
calls, so a user who followed the advice bound the role and still got 403.

The same suggestion told the user to wait about 5 minutes and retry with a
fresh token. kube-rbac-proxy caches a denial for about 30 seconds, and the
existing token keeps working, so both halves of that hint were wrong. The
d8 dist copy of the diagnostic carried the same wrong hint and is fixed too.

Signed-off-by: Roman Berezkin <roman.berezkin@flant.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant