Skip to content

Support mux patterns in VW framework - #4543

Merged
kcp-ci-bot merged 17 commits into
kcp-dev:mainfrom
ntnn:vw-path-pattern
Nov 4, 2026
Merged

kcp-ci-bot merged 17 commits into
kcp-dev:mainfrom
ntnn:vw-path-pattern

Conversation

@ntnn

@ntnn ntnn commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

Summary

I saw the virtualWorkspaceClusterOffsets and became sad.
So I did something to not be sad.
Also adding some e2e tests for this since we only have unit tests to cover the case of a clusters APIExport.

What Type of PR Is This?

/kind cleanup

Related Issue(s)

Fixes #

Release Notes

BREAKING: The virtual-workspace-framework now requires at least one mux pattern to be set instead of parsing request URLs by hand

@kcp-ci-bot kcp-ci-bot added release-note-none Denotes a PR that doesn't merit a release note. kind/cleanup Categorizes issue or PR as related to cleaning up code, process, or technical debt. dco-signoff: yes Indicates the PR's author has signed the DCO. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Nov 3, 2026
ntnn added 11 commits November 3, 2026 19:21
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
@kcp-ci-bot kcp-ci-bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 3, 2026
…PIExport

Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
@ntnn

ntnn commented Nov 3, 2026

Copy link
Copy Markdown
Member Author

@mjudeikis-bot review this, be nitpicky around the vw-framework API for external users

@mjudeikis-bot mjudeikis-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly looks good as a cleanup, but there is one regression in the front-proxy and two framework-API concerns.

Not anchored

  • Breaking change for external VW implementers: RootPathResolverFunc/RootPathResolver.ResolveRootPath changes signature (arguments swapped and PathMatch replaces urlPath). This is intentional per the PR, but it has no release note (release-note-none), and the staging repo is consumed externally. Please add a release note describing the migration (Patterns + new resolver signature). Conflicting or duplicate patterns across VWs now panic at startup; worth stating in architecture.md.
  • Behaviour shift worth documenting: previously the first VW (in registration order) that accepted any path won; now the most specific mux pattern wins first and registration order only applies within an identical pattern string.

Checked

  • Read beyond the diff: pkg/server/proxy/lookup.go (WithClusterResolver, newMappingHandler, extractClusterFromPath), pkg/virtual/options/options.go (how VWs are composed), the full server.go/config.go/types.go in the framework, and all seven builders' resolvers.
  • Correctness: resolvers traced for admin, apiexport, replication, apiresourceschema (consumer/cluster mismatch check kept), initializing/terminating (three VWs sharing one pattern keep order), migrating. No other issue found. Findings above: front-proxy regression (verified with a throwaway test on this head), mux path-cleaning redirect (verified with a throwaway test), empty Patterns (traced).
  • Concurrency: mux built once at handler-chain build; n/a for races.
  • kcp specifics: the cluster is now resolved before the resolver runs; invalid cluster segments fall to the delegate, as before. Wildcard * handled.
  • API/storage: no API types/codegen touched. Security: no authorizer changes; the apiresourceschema cluster mismatch check preserved.
  • Tests: new unit tests in server_test.go and the builders cover the mux; the removed proxy tests are what would fail without the revert.
  • Commands: go build ./... OK; go vet ./pkg/virtual/... ./pkg/server/proxy/... clean; go test ./pkg/virtual/... ./pkg/server/proxy/... pass; go test ./... in the framework staging module passes. I did not run the e2e tests (they need a full kcp environment, and the proxy regression is already confirmed at unit level).

Comment thread pkg/server/proxy/lookup.go Resolved
@kcp-ci-bot

Copy link
Copy Markdown
Contributor

@mjudeikis-bot: changing LGTM is restricted to collaborators

Details

In response to this:

Mostly looks good as a cleanup, but there is one regression in the front-proxy and two framework-API concerns.

Not anchored

  • Breaking change for external VW implementers: RootPathResolverFunc/RootPathResolver.ResolveRootPath changes signature (arguments swapped and PathMatch replaces urlPath). This is intentional per the PR, but it has no release note (release-note-none), and the staging repo is consumed externally. Please add a release note describing the migration (Patterns + new resolver signature). Conflicting or duplicate patterns across VWs now panic at startup; worth stating in architecture.md.
  • Behaviour shift worth documenting: previously the first VW (in registration order) that accepted any path won; now the most specific mux pattern wins first and registration order only applies within an identical pattern string.

Checked

  • Read beyond the diff: pkg/server/proxy/lookup.go (WithClusterResolver, newMappingHandler, extractClusterFromPath), pkg/virtual/options/options.go (how VWs are composed), the full server.go/config.go/types.go in the framework, and all seven builders' resolvers.
  • Correctness: resolvers traced for admin, apiexport, replication, apiresourceschema (consumer/cluster mismatch check kept), initializing/terminating (three VWs sharing one pattern keep order), migrating. No other issue found. Findings above: front-proxy regression (verified with a throwaway test on this head), mux path-cleaning redirect (verified with a throwaway test), empty Patterns (traced).
  • Concurrency: mux built once at handler-chain build; n/a for races.
  • kcp specifics: the cluster is now resolved before the resolver runs; invalid cluster segments fall to the delegate, as before. Wildcard * handled.
  • API/storage: no API types/codegen touched. Security: no authorizer changes; the apiresourceschema cluster mismatch check preserved.
  • Tests: new unit tests in server_test.go and the builders cover the mux; the removed proxy tests are what would fail without the revert.
  • Commands: go build ./... OK; go vet ./pkg/virtual/... ./pkg/server/proxy/... clean; go test ./pkg/virtual/... ./pkg/server/proxy/... pass; go test ./... in the framework staging module passes. I did not run the e2e tests (they need a full kcp environment, and the proxy regression is already confirmed at unit level).

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

ntnn added 3 commits November 3, 2026 22:05
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
@ntnn

ntnn commented Nov 3, 2026

Copy link
Copy Markdown
Member Author

/test pull-kcp-test-e2e

@kcp-ci-bot kcp-ci-bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed release-note-none Denotes a PR that doesn't merit a release note. labels Nov 4, 2026
// When it returns `true`, it will also set the VirtualWorkspace name in the request context,
// as well as the prefix that should be removed from the request URL Path before forwarding
// the request to the given VirtualWorkspace delegated APIServer.
type RootPathResolverFunc func(urlPath string, context context.Context) (accepted bool, prefixToStrip string, completedContext context.Context)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could also leave this as is without a breaking change. Would be more wiring probably.
Question is how many people are using the vw-framework to implement VWs and if they shouldn't be migrating to a mux pattern instead of parsing themselves anyway.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it's not removed; just signature changes:

func (r RootPathResolverFunc) ResolveRootPath(ctx context.Context, match PathMatch) (accepted bool, prefixToStrip string, completedContext context.Context) {
	return r(ctx, match)
}

so we should be ok

@mjudeikis mjudeikis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mostly missing docs

Comment on lines +49 to +58
const (
sliceClusterWildcard = "sliceCluster"
sliceNameWildcard = "sliceName"
)

// pathPattern returns the mux pattern of the virtual workspace below rootPathPrefix.
func pathPattern(rootPathPrefix string) string {
return path.Join(rootPathPrefix, "{sliceCluster}/{sliceName}/clusters/{cluster}")
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get bit of godocs on ththese? what these sliceClusterX means?

@ntnn ntnn Nov 4, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I just followed what the virtualWorkspaceClusterOffsets map did:

// /services/replication/<slice cluster>/<slice name>/clusters/<cluster>/...

require.Equal(t, tc.expectedLogicalPath, logicalPath, "LogicalPath should match expected value")
})
require.Equal(t,
"/services/replication/{sliceCluster}/{sliceName}/clusters/{cluster}",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above. This reads strange sliceCluster and later clusters...

Comment on lines +37 to +45
// PathMatch is a request path matched against a virtual workspace pattern.
type PathMatch struct {
// Path is the full request path.
Path string
// Trail is the kube-like API path after the pattern, "" if none.
Trail string

value func(name string) string
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this is breaking change, lets add bit more extensive godocs what is path, how it could looks like (example), and trails itself. Smth user can read and understand how to use this new pathmatcher

// When it returns `true`, it will also set the VirtualWorkspace name in the request context,
// as well as the prefix that should be removed from the request URL Path before forwarding
// the request to the given VirtualWorkspace delegated APIServer.
type RootPathResolverFunc func(urlPath string, context context.Context) (accepted bool, prefixToStrip string, completedContext context.Context)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it's not removed; just signature changes:

func (r RootPathResolverFunc) ResolveRootPath(ctx context.Context, match PathMatch) (accepted bool, prefixToStrip string, completedContext context.Context) {
	return r(ctx, match)
}

so we should be ok

ntnn added 2 commits November 4, 2026 08:53
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>
Signed-off-by: Nelo-T. Wallus <git@ntnn.de>
Signed-off-by: Nelo-T. Wallus <n.wallus@sap.com>

@mjudeikis mjudeikis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm
/approve

@kcp-ci-bot kcp-ci-bot added the lgtm Indicates that a PR is ready to be merged. label Nov 4, 2026
@kcp-ci-bot

Copy link
Copy Markdown
Contributor

LGTM label has been added.

DetailsGit tree hash: 87e39fb54ae0b26b41b67f8c98f7087651f6cc06

@kcp-ci-bot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: mjudeikis

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kcp-ci-bot kcp-ci-bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Nov 4, 2026
@kcp-ci-bot
kcp-ci-bot merged commit c0d6984 into kcp-dev:main Nov 4, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. dco-signoff: yes Indicates the PR's author has signed the DCO. kind/cleanup Categorizes issue or PR as related to cleaning up code, process, or technical debt. lgtm Indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants