Conversation
73f547f to
7cdd1be
Compare
7cdd1be to
8f91c85
Compare
Upstream gates sync.toHost.namespaces behind pro.GetNamespaceMapper and
pro.GetWithSyncedNamespacesTranslator, which return a license error in the
OSS binary. Following the same model as vCluster Pro, this links replacement
implementations in from a separate package instead of editing core:
- pkg/linkpool/namespaces registers the overrides in init(): a translator
that syncs mapped virtual namespaces to their own host namespace with raw
object names and falls back to single-namespace rewriting in the control
plane namespace for unmapped ones, and a Namespace mapper that resolves
through the configured mappings (exact, single-wildcard patterns, ${name}),
returns the control plane namespace for unmapped virtual namespaces so
lookups such as the kube-dns service keep working, and treats matching
host namespaces as managed so they are imported unless another vCluster's
marker label owns them. mappingsOnly is not enforced and logs a warning.
- cmd/vcluster-linkpool is the upstream main with that package imported; the
Dockerfile takes MAIN as a build arg (default unchanged) to build it.
Core changes, all small:
- namespace syncer implements ObjectExcluder so virtual namespaces that
resolve to the vCluster's own host namespace are never synced as
namespaces, and the host namespace itself is never touched
- namespace syncer marks a host namespace it did not create as imported when
adopting it, so deleting the virtual namespace never deletes it
- the Service create filter waits up to 10s for a host namespace the
namespace syncer is still creating, instead of failing a kubectl apply
that creates a namespace and a service together
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
8f91c85 to
8303b72
Compare
|
Live test on vcluster-test (image
Known gap outside this repo: pods in mapped host namespaces sit outside the tenant CiliumNetworkPolicy (keyed on the control-plane namespace), so in-pod DNS to the vcluster coredns times out and they get default-pool IPs. Needs a chart follow-up (policy keyed on |
With mappingsOnly, virtual namespaces outside the mappings get no host namespace and their objects get no host name, so nothing of theirs is synced. The translator hook does not receive the flag, so the mapper, which sees the full config and is built before any controller starts, passes it to the translator. Each rejected namespace is logged once. kube-system must be mapped when mappingsOnly is set, otherwise the kube-dns lookup fails for every pod. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…Only With mappingsOnly no tenant object belongs in the control plane namespace, so the translator stops reporting it as targeted. The mapping store verifies every mapping against IsTargetedNamespace when it loads at leader start, so mappings recorded before namespace sync was enabled (kube-root-ca.crt, coredns, services pinned to the control plane namespace) are dropped and the objects re-translate into their mapped host namespace. This is what makes an in-place switch to namespace sync possible without resetting etcd; the old host copies are left untouched for manual cleanup. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Two more commits from the in-place switch of vcluster-test to
Images: |
The mapping store is created and loaded inside initControllerContext and verifies each stored mapping against translate.Default at that point. The namespace mapper, which used to hand mappingsOnly to the translator, is only built afterwards, so stale control plane mappings still passed verification. pro.LicenseInit runs right after the translator is built and receives the full config, so set the flag there; the mapper keeps setting it as well for the plugin process. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
|
The store verified only the top-level mapping when loading from the backend; references recorded under it (e.g. a pod's configmaps) were added to the name maps unverified. References into a host namespace that is no longer a sync target kept pinning those objects to stale host names after namespace sync was enabled. Filter references with the same verify function on load and on backend updates. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
|
Upstream gates sync.toHost.*.patches / sync.fromHost.*.patches behind
pro.ApplyPatchesHostObject / pro.ApplyPatchesVirtualObject. This adds
pkg/linkpool/patches, registered from init() like the namespaces package:
- path: JSONPath subset over the object's unstructured form: dotted and
quoted fields, [N], [*], [?(@.field=='x')] / != / existence filters. A
missing path is skipped; a missing final field in an existing map counts
as a match with an undefined value so expressions can add fields.
- expression / reverseExpression: JavaScript via goja with `value` and
`context` {vObject, hostObject, path}; undefined or null removes the
field. Host objects get the forward expression, virtual objects the
reverse one, swapped when the syncer passes reverseExpressions (fromHost
resources).
- reference: rewrites the referenced name (and namespace via namespacePath)
through the registered mapper for the kind, falling back to the
translator's short host name and recording the mapping; the reverse
direction uses the mapper or the mapping store.
- labels: translates a plain label map or a metav1.LabelSelector the same
way pod selectors are translated.
go.mod: add github.com/dop251/goja. Upstream also requires
github.com/loft-sh/e2e-framework, whose repository is gone, which made any
module graph change impossible; it is now replaced by hack/e2e-framework, a
copy of the already vendored packages (e2e tests only).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Dependencies: |
What
Upstream gates
sync.toHost.namespacesbehindpro.GetNamespaceMapper/pro.GetWithSyncedNamespacesTranslator,which return a license error in the OSS binary. vCluster Pro is not a plugin either: it is a separate binary that
overrides those hook variables. This does the same, so core stays almost untouched.
pkg/linkpool/namespacesregisters the overrides ininit():fall back to single-namespace rewriting in the control-plane namespace (documented Pro default).
${name}); returnsthe control-plane namespace for unmapped virtual namespaces so lookups such as the kube-dns service keep working;
treats matching host namespaces as managed so they are imported, unless another vCluster's marker label owns
them. Deterministic, so not wrapped in the store recorder.
mappingsOnlyis not enforced and logs a warning.cmd/vcluster-linkpool/main.gois the upstream main with that package imported. The Dockerfile takesMAINas abuild arg (default unchanged); build with
--build-arg MAIN=cmd/vcluster-linkpool/main.go.Core changes, all small:
ObjectExcluder: virtual namespaces that resolve to the vCluster's own host namespaceare never synced as namespaces, and the host namespace itself is never touched.
namespace never deletes a pre-existing host namespace.
failing a
kubectl applythat creates a namespace and a service in one go (seen on vcluster-test).Not included: the Pro Importer (bulk import of pre-existing workloads inside a mapped host namespace) is still the
no-op stub. Only the Namespace object itself is imported.
Testing
go build ./...andgo test ./pkg/...pass. Unit tests cover the mapping helpers, translator and mapper; themapper test goes through
resources.CreateNamespacesMapperso the hook override is exercised.Live test on vcluster-test via linkpoolio/infra-argocd-deployments (
team-*mapping); the node-proxy plugin must bebuilt against this branch too (linkpoolio/vcluster-node-proxy#2) because the SDK re-runs config init in the plugin.
🤖 Generated with Claude Code