Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@ current-bench.txt
benchmark-results.txt
benchstat-output.txt
.worktrees
cmd/wfctl/.wfctl.yaml
100 changes: 100 additions & 0 deletions cmd/wfctl/type_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,18 @@ func KnownModuleTypes() map[string]ModuleTypeInfo {
Stateful: false,
ConfigKeys: []string{"secret", "algorithm", "privateKey", "tokenExpiry", "issuer", "clients"},
},
"auth.token-blacklist": {
Type: "auth.token-blacklist",
Plugin: "auth",
Stateful: false,
ConfigKeys: []string{"ttl"},
},
"security.field-protection": {
Type: "security.field-protection",
Plugin: "auth",
Stateful: false,
ConfigKeys: []string{"fields", "algorithm", "keyRef"},
},

// messaging plugin
"messaging.broker": {
Expand Down Expand Up @@ -513,6 +525,94 @@ func KnownModuleTypes() map[string]ModuleTypeInfo {
Stateful: false,
ConfigKeys: []string{"account", "provider", "name", "region", "image", "instances", "http_port", "envs"},
},
"platform.do_database": {
Type: "platform.do_database",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"account", "provider", "engine", "size", "region", "nodes"},
},
"platform.kubernetes": {
Type: "platform.kubernetes",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"account", "cluster", "namespace", "kubeconfig"},
},
"platform.ecs": {
Type: "platform.ecs",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"account", "cluster", "region"},
},
"platform.dns": {
Type: "platform.dns",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"account", "provider", "domain"},
},
"platform.networking": {
Type: "platform.networking",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"account", "provider", "vpc"},
},
"platform.apigateway": {
Type: "platform.apigateway",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"account", "provider", "name", "region"},
},
"platform.autoscaling": {
Type: "platform.autoscaling",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"account", "provider", "resource"},
},
"platform.region": {
Type: "platform.region",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"provider", "region", "primary"},
},
"iac.state": {
Type: "iac.state",
Plugin: "platform",
Stateful: true,
ConfigKeys: []string{"backend", "path"},
},
"app.container": {
Type: "app.container",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"image", "registry", "port", "envs"},
},
"argo.workflows": {
Type: "argo.workflows",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"namespace", "kubeconfig", "server_addr"},
},

// actors plugin
"actor.system": {
Type: "actor.system",
Plugin: "actors",
Stateful: false,
ConfigKeys: []string{"maxWorkers", "mailboxSize"},
},
"actor.pool": {
Type: "actor.pool",
Plugin: "actors",
Stateful: false,
ConfigKeys: []string{"system", "workers", "handler"},
},

// scanner plugin
"security.scanner": {
Type: "security.scanner",
Plugin: "scanner",
Stateful: false,
ConfigKeys: []string{"trivy", "semgrep", "snyk"},
},
}
// Include any types registered dynamically (e.g. from external plugins loaded via LoadPluginTypesFromDir).
for _, t := range schema.KnownModuleTypes() {
Expand Down
25 changes: 25 additions & 0 deletions cmd/wfctl/type_registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,28 @@ func TestKnownStepTypesCoverAllPlugins(t *testing.T) {
}
}
}

// TestKnownModuleTypesCoverAllPlugins ensures KnownModuleTypes() is in sync with all module
// types registered by the built-in plugins. Any module type registered by a DefaultPlugin
// that is not listed in KnownModuleTypes() will cause this test to fail, preventing silent
// omissions from being introduced in the future (e.g. the auth.m2m missing-type regression).
func TestKnownModuleTypesCoverAllPlugins(t *testing.T) {
// Collect all module types registered by DefaultPlugins via the PluginLoader.
capReg := capability.NewRegistry()
schemaReg := schema.NewModuleSchemaRegistry()
loader := plugin.NewPluginLoader(capReg, schemaReg)
for _, p := range all.DefaultPlugins() {
if err := loader.LoadPlugin(p); err != nil {
t.Fatalf("LoadPlugin(%q) error: %v", p.Name(), err)
}
}

pluginModules := loader.ModuleFactories()
known := KnownModuleTypes()

for modType := range pluginModules {
if _, ok := known[modType]; !ok {
t.Errorf("module type %q is registered by a built-in plugin but missing from KnownModuleTypes()", modType)
}
}
}
32 changes: 32 additions & 0 deletions consistency_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package workflow
import (
"testing"

"github.com/GoCodeAlone/workflow/capability"
"github.com/GoCodeAlone/workflow/module"
"github.com/GoCodeAlone/workflow/plugin"
"github.com/GoCodeAlone/workflow/plugins/all"
"github.com/GoCodeAlone/workflow/schema"
)
Expand Down Expand Up @@ -59,4 +61,34 @@ func TestRegistryConsistency(t *testing.T) {
t.Errorf("expected at least 40 engine step types, got %d", len(engineTypes))
}
})

t.Run("schema KnownModuleTypes covers all built-in plugin module types", func(t *testing.T) {
// This is the contract test: every module type registered by a DefaultPlugin
// must appear in schema.KnownModuleTypes() so that wfctl validate does not
// report false "unknown module type" errors.
capReg := capability.NewRegistry()
schemaReg := schema.NewModuleSchemaRegistry()
loader := plugin.NewPluginLoader(capReg, schemaReg)
for _, p := range all.DefaultPlugins() {
if err := loader.LoadPlugin(p); err != nil {
t.Fatalf("LoadPlugin(%q) error: %v", p.Name(), err)
}
}

known := make(map[string]bool)
for _, mt := range schema.KnownModuleTypes() {
known[mt] = true
}

for modType := range loader.ModuleFactories() {
if !known[modType] {
t.Errorf("module type %q is registered by a built-in plugin but missing from schema.KnownModuleTypes() — add it to coreModuleTypes in schema/schema.go", modType)
}
}
for stepType := range loader.StepFactories() {
if !known[stepType] {
t.Errorf("step type %q is registered by a built-in plugin but missing from schema.KnownModuleTypes() — add it to coreModuleTypes in schema/schema.go", stepType)
}
}
})
}
Loading
Loading