feat: remove module/rollout config key

This commit is contained in:
2025-11-18 15:37:21 +08:00
parent dcd85a9f41
commit 347eb3adc5
36 changed files with 167 additions and 566 deletions

View File

@@ -41,7 +41,6 @@ func TestAPKProxyCachesIndexAndPackages(t *testing.T) {
Name: "apk",
Domain: "apk.hub.local",
Type: "apk",
Module: "apk",
Upstream: stub.URL,
},
},

View File

@@ -41,7 +41,6 @@ func TestAptPackagesCachedWithoutRevalidate(t *testing.T) {
Name: "apt",
Domain: "apt.hub.local",
Type: "debian",
Module: "debian",
Upstream: stub.URL,
},
},

View File

@@ -36,7 +36,6 @@ func TestAptUpdateCachesIndexes(t *testing.T) {
Name: "apt",
Domain: "apt.hub.local",
Type: "debian",
Module: "debian",
Upstream: stub.URL,
},
},

View File

@@ -44,7 +44,6 @@ func TestCacheFlowWithConditionalRequest(t *testing.T) {
Name: "docker",
Domain: "docker.hub.local",
Type: "docker",
Module: "docker",
Upstream: upstream.URL,
},
},
@@ -146,7 +145,6 @@ func TestDockerManifestHeadDoesNotOverwriteCache(t *testing.T) {
Name: "docker",
Domain: "docker.hub.local",
Type: "docker",
Module: "docker",
Upstream: upstream.URL,
},
},

View File

@@ -35,7 +35,6 @@ func TestCacheStrategyOverrides(t *testing.T) {
Name: "npm-ttl",
Domain: "ttl.npm.local",
Type: "npm",
Module: "npm",
Upstream: stub.URL,
CacheTTL: config.Duration(ttl),
},
@@ -111,7 +110,6 @@ func TestCacheStrategyOverrides(t *testing.T) {
Name: "npm-novalidation",
Domain: "novalidation.npm.local",
Type: "npm",
Module: "npm",
Upstream: stub.URL,
CacheTTL: config.Duration(ttl),
ValidationMode: string(hubmodule.ValidationModeNever),

View File

@@ -1,118 +0,0 @@
package integration
import (
"io"
"net/http/httptest"
"testing"
"time"
"github.com/gofiber/fiber/v3"
"github.com/sirupsen/logrus"
"github.com/any-hub/any-hub/internal/config"
"github.com/any-hub/any-hub/internal/hubmodule"
"github.com/any-hub/any-hub/internal/hubmodule/legacy"
"github.com/any-hub/any-hub/internal/server"
)
func TestLegacyAdapterRolloutToggle(t *testing.T) {
const moduleKey = "rollout-toggle-test"
_ = hubmodule.Register(hubmodule.ModuleMetadata{Key: moduleKey})
logger := logrus.New()
logger.SetOutput(io.Discard)
baseHub := config.HubConfig{
Name: "dual-mode",
Domain: "dual.local",
Type: "docker",
Upstream: "https://registry.npmjs.org",
Module: moduleKey,
}
testCases := []struct {
name string
rolloutFlag string
expectKey string
expectFlag legacy.RolloutFlag
}{
{
name: "force legacy",
rolloutFlag: "legacy-only",
expectKey: hubmodule.DefaultModuleKey(),
expectFlag: legacy.RolloutLegacyOnly,
},
{
name: "dual mode",
rolloutFlag: "dual",
expectKey: moduleKey,
expectFlag: legacy.RolloutDual,
},
{
name: "full modular",
rolloutFlag: "modular",
expectKey: moduleKey,
expectFlag: legacy.RolloutModular,
},
{
name: "rollback to legacy",
rolloutFlag: "legacy-only",
expectKey: hubmodule.DefaultModuleKey(),
expectFlag: legacy.RolloutLegacyOnly,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
cfg := &config.Config{
Global: config.GlobalConfig{
ListenPort: 6100,
CacheTTL: config.Duration(time.Minute),
},
Hubs: []config.HubConfig{
func() config.HubConfig {
h := baseHub
h.Rollout = tc.rolloutFlag
return h
}(),
},
}
registry, err := server.NewHubRegistry(cfg)
if err != nil {
t.Fatalf("failed to build registry: %v", err)
}
recorder := &routeRecorder{}
app := mustNewApp(t, cfg.Global.ListenPort, logger, registry, recorder)
req := httptest.NewRequest("GET", "http://dual.local/v2/", nil)
req.Host = "dual.local"
resp, err := app.Test(req)
if err != nil {
t.Fatalf("request failed: %v", err)
}
if resp.StatusCode != fiber.StatusNoContent {
t.Fatalf("unexpected status: %d", resp.StatusCode)
}
if recorder.moduleKey != tc.expectKey {
t.Fatalf("expected module %s, got %s", tc.expectKey, recorder.moduleKey)
}
if recorder.rolloutFlag != tc.expectFlag {
t.Fatalf("expected rollout flag %s, got %s", tc.expectFlag, recorder.rolloutFlag)
}
})
}
}
type routeRecorder struct {
moduleKey string
rolloutFlag legacy.RolloutFlag
}
func (r *routeRecorder) Handle(c fiber.Ctx, route *server.HubRoute) error {
r.moduleKey = route.ModuleKey
r.rolloutFlag = route.RolloutFlag
return c.SendStatus(fiber.StatusNoContent)
}

View File

@@ -13,7 +13,6 @@ import (
"github.com/any-hub/any-hub/internal/config"
"github.com/any-hub/any-hub/internal/hubmodule"
"github.com/any-hub/any-hub/internal/hubmodule/legacy"
"github.com/any-hub/any-hub/internal/proxy/hooks"
"github.com/any-hub/any-hub/internal/server"
"github.com/any-hub/any-hub/internal/server/routes"
@@ -37,21 +36,17 @@ func TestModuleDiagnosticsEndpoints(t *testing.T) {
CacheTTL: config.Duration(30 * time.Minute),
},
Hubs: []config.HubConfig{
{
Name: "legacy-hub",
Domain: "legacy.local",
Type: "docker",
Upstream: "https://registry-1.docker.io",
Module: hubmodule.DefaultModuleKey(),
Rollout: string(legacy.RolloutLegacyOnly),
},
{
Name: "modern-hub",
Domain: "modern.local",
Type: "npm",
Upstream: "https://registry.npmjs.org",
Module: moduleKey,
Rollout: "dual",
},
{
Name: "docker-hub",
Domain: "docker.local",
Type: "docker",
Upstream: "https://registry-1.docker.io",
},
},
}
@@ -77,12 +72,10 @@ func TestModuleDiagnosticsEndpoints(t *testing.T) {
var payload struct {
Modules []map[string]any `json:"modules"`
Hubs []struct {
HubName string `json:"hub_name"`
ModuleKey string `json:"module_key"`
Rollout string `json:"rollout_flag"`
Domain string `json:"domain"`
Port int `json:"port"`
LegacyOnly bool `json:"legacy_only"`
HubName string `json:"hub_name"`
ModuleKey string `json:"module_key"`
Domain string `json:"domain"`
Port int `json:"port"`
} `json:"hubs"`
}
body, _ := io.ReadAll(resp.Body)
@@ -111,22 +104,13 @@ func TestModuleDiagnosticsEndpoints(t *testing.T) {
}
for _, hub := range payload.Hubs {
switch hub.HubName {
case "legacy-hub":
if hub.ModuleKey != hubmodule.DefaultModuleKey() {
t.Fatalf("legacy hub should expose legacy module, got %s", hub.ModuleKey)
}
if !hub.LegacyOnly {
t.Fatalf("legacy hub should be marked legacy_only")
}
case "modern-hub":
if hub.ModuleKey != moduleKey {
t.Fatalf("modern hub should expose %s, got %s", moduleKey, hub.ModuleKey)
if hub.ModuleKey != "npm" {
t.Fatalf("modern hub should expose npm, got %s", hub.ModuleKey)
}
if hub.Rollout != "dual" {
t.Fatalf("modern hub rollout flag should be dual, got %s", hub.Rollout)
}
if hub.LegacyOnly {
t.Fatalf("modern hub should not be marked legacy_only")
case "docker-hub":
if hub.ModuleKey != "docker" {
t.Fatalf("docker hub should expose docker, got %s", hub.ModuleKey)
}
default:
t.Fatalf("unexpected hub %s", hub.HubName)

View File

@@ -1,107 +1,100 @@
package integration
import (
"io"
"net/http/httptest"
"testing"
"io"
"net/http/httptest"
"testing"
"github.com/gofiber/fiber/v3"
"github.com/sirupsen/logrus"
"github.com/gofiber/fiber/v3"
"github.com/sirupsen/logrus"
"github.com/any-hub/any-hub/internal/config"
"github.com/any-hub/any-hub/internal/hubmodule"
"github.com/any-hub/any-hub/internal/server"
"github.com/any-hub/any-hub/internal/config"
"github.com/any-hub/any-hub/internal/server"
)
func TestModuleRoutingIsolation(t *testing.T) {
_ = hubmodule.Register(hubmodule.ModuleMetadata{Key: "module-routing-test"})
cfg := &config.Config{
Global: config.GlobalConfig{
ListenPort: 6000,
CacheTTL: config.Duration(3600),
},
Hubs: []config.HubConfig{
{
Name: "docker-hub",
Domain: "legacy.hub.local",
Type: "docker",
Upstream: "https://registry-1.docker.io",
},
{
Name: "npm-hub",
Domain: "test.hub.local",
Type: "npm",
Upstream: "https://registry.example.com",
},
},
}
cfg := &config.Config{
Global: config.GlobalConfig{
ListenPort: 6000,
CacheTTL: config.Duration(3600),
},
Hubs: []config.HubConfig{
{
Name: "legacy",
Domain: "legacy.hub.local",
Type: "docker",
Module: "legacy",
Upstream: "https://registry-1.docker.io",
},
{
Name: "test",
Domain: "test.hub.local",
Type: "npm",
Module: "module-routing-test",
Upstream: "https://registry.example.com",
},
},
}
registry, err := server.NewHubRegistry(cfg)
if err != nil {
t.Fatalf("failed to create registry: %v", err)
}
registry, err := server.NewHubRegistry(cfg)
if err != nil {
t.Fatalf("failed to create registry: %v", err)
}
logger := logrus.New()
logger.SetOutput(io.Discard)
logger := logrus.New()
logger.SetOutput(io.Discard)
recorder := &moduleRecorder{}
app := mustNewApp(t, cfg.Global.ListenPort, logger, registry, recorder)
recorder := &moduleRecorder{}
app := mustNewApp(t, cfg.Global.ListenPort, logger, registry, recorder)
legacyReq := httptest.NewRequest("GET", "http://legacy.hub.local/v2/", nil)
legacyReq.Host = "legacy.hub.local"
legacyReq.Header.Set("Host", "legacy.hub.local")
resp, err := app.Test(legacyReq)
if err != nil {
t.Fatalf("legacy request failed: %v", err)
}
if resp.StatusCode != fiber.StatusNoContent {
t.Fatalf("legacy hub should return 204, got %d", resp.StatusCode)
}
if recorder.moduleKey != "docker" {
t.Fatalf("expected docker module, got %s", recorder.moduleKey)
}
legacyReq := httptest.NewRequest("GET", "http://legacy.hub.local/v2/", nil)
legacyReq.Host = "legacy.hub.local"
legacyReq.Header.Set("Host", "legacy.hub.local")
resp, err := app.Test(legacyReq)
if err != nil {
t.Fatalf("legacy request failed: %v", err)
}
if resp.StatusCode != fiber.StatusNoContent {
t.Fatalf("legacy hub should return 204, got %d", resp.StatusCode)
}
if recorder.moduleKey != "legacy" {
t.Fatalf("expected legacy module, got %s", recorder.moduleKey)
}
testReq := httptest.NewRequest("GET", "http://test.hub.local/v2/", nil)
testReq.Host = "test.hub.local"
testReq.Header.Set("Host", "test.hub.local")
resp2, err := app.Test(testReq)
if err != nil {
t.Fatalf("test request failed: %v", err)
}
if resp2.StatusCode != fiber.StatusNoContent {
t.Fatalf("test hub should return 204, got %d", resp2.StatusCode)
}
if recorder.moduleKey != "module-routing-test" {
t.Fatalf("expected module-routing-test module, got %s", recorder.moduleKey)
}
testReq := httptest.NewRequest("GET", "http://test.hub.local/v2/", nil)
testReq.Host = "test.hub.local"
testReq.Header.Set("Host", "test.hub.local")
resp2, err := app.Test(testReq)
if err != nil {
t.Fatalf("test request failed: %v", err)
}
if resp2.StatusCode != fiber.StatusNoContent {
t.Fatalf("test hub should return 204, got %d", resp2.StatusCode)
}
if recorder.moduleKey != "npm" {
t.Fatalf("expected npm module, got %s", recorder.moduleKey)
}
}
func mustNewApp(t *testing.T, port int, logger *logrus.Logger, registry *server.HubRegistry, handler server.ProxyHandler) *fiber.App {
t.Helper()
app, err := server.NewApp(server.AppOptions{
Logger: logger,
Registry: registry,
Proxy: handler,
ListenPort: port,
})
if err != nil {
t.Fatalf("failed to create app: %v", err)
}
return app
t.Helper()
app, err := server.NewApp(server.AppOptions{
Logger: logger,
Registry: registry,
Proxy: handler,
ListenPort: port,
})
if err != nil {
t.Fatalf("failed to create app: %v", err)
}
return app
}
type moduleRecorder struct {
routeName string
moduleKey string
rollout string
routeName string
moduleKey string
}
func (p *moduleRecorder) Handle(c fiber.Ctx, route *server.HubRoute) error {
p.routeName = route.Config.Name
p.moduleKey = route.ModuleKey
p.rollout = string(route.RolloutFlag)
return c.SendStatus(fiber.StatusNoContent)
p.routeName = route.Config.Name
p.moduleKey = route.ModuleKey
return c.SendStatus(fiber.StatusNoContent)
}