cmd: add synthetic command validate-interfaces

The command is injected when running xcaddy with one of Caddy's commands, though `validate-interfaces` does not exist in Caddy itself. This is useful for [guest modules](https://caddyserver.com/docs/extending-caddy) developers to validate their implementation meets the expectation of the host module.
This commit is contained in:
Mohammed Al Sahaf 2023-12-14 23:35:37 +03:00
parent 18eadf4260
commit 971664d22f
No known key found for this signature in database
3 changed files with 44 additions and 4 deletions

View file

@ -45,6 +45,15 @@ type Builder struct {
Debug bool `json:"debug,omitempty"` Debug bool `json:"debug,omitempty"`
BuildFlags string `json:"build_flags,omitempty"` BuildFlags string `json:"build_flags,omitempty"`
ModFlags string `json:"mod_flags,omitempty"` ModFlags string `json:"mod_flags,omitempty"`
// Experimental: Inject extra imports into the build. These
// imports are to add Go modules that may be needed in the
// Prequels.
ExtraImports []string
// Experimental: Inject extra code before running Caddy's `main`.
// If any of the prequels requires an import, it's you responsibility
// to add the import to the ExtraImports slice.
Prequels []string
} }
// Build builds Caddy at the configured version with the // Build builds Caddy at the configured version with the

View file

@ -223,6 +223,8 @@ func runDev(ctx context.Context, args []string) error {
SkipBuild: skipBuild, SkipBuild: skipBuild,
SkipCleanup: skipCleanup, SkipCleanup: skipCleanup,
Debug: buildDebugOutput, Debug: buildDebugOutput,
ExtraImports: []string{`caddy "github.com/caddyserver/caddy/v2"`, `"fmt"`, `"github.com/spf13/cobra"`},
Prequels: []string{interfaceValidationCommand},
} }
err = builder.Build(ctx, binOutput) err = builder.Build(ctx, binOutput)
if err != nil { if err != nil {
@ -439,3 +441,22 @@ func goModule() *debug.Module {
} }
return mod return mod
} }
const interfaceValidationCommand = `
caddycmd.RegisterCommand(caddycmd.Command{
Name: "validate-interfaces",
Short: "Validate that all modules conform to their namespaces",
CobraFunc: func(cmd *cobra.Command) {
cmd.RunE = caddycmd.WrapCommandFuncForCobra(func(f caddycmd.Flags) (int, error) {
for _, v := range caddy.Modules() {
mod, _ := caddy.GetModule(v)
if ok, err := caddy.ConformsToNamespace(mod.New(), mod.ID.Namespace()); !ok {
return caddy.ExitCodeFailedStartup, fmt.Errorf("module %s does not conform to its namespace: %v", mod.ID, err)
}
}
fmt.Println("All modules conform to their namespaces.")
return caddy.ExitCodeSuccess, nil
})
},
})
`

View file

@ -51,7 +51,9 @@ func (b Builder) newEnvironment(ctx context.Context) (*environment, error) {
// create the context for the main module template // create the context for the main module template
tplCtx := goModTemplateContext{ tplCtx := goModTemplateContext{
CaddyModule: caddyModulePath, CaddyModule: caddyModulePath,
ExtraImports: b.ExtraImports,
Prequels: b.Prequels,
} }
for _, p := range b.Plugins { for _, p := range b.Plugins {
tplCtx.Plugins = append(tplCtx.Plugins, p.PackagePath) tplCtx.Plugins = append(tplCtx.Plugins, p.PackagePath)
@ -86,7 +88,7 @@ func (b Builder) newEnvironment(ctx context.Context) (*environment, error) {
// write the main module file to temporary folder // write the main module file to temporary folder
mainPath := filepath.Join(tempFolder, "main.go") mainPath := filepath.Join(tempFolder, "main.go")
log.Printf("[INFO] Writing main module: %s\n%s", mainPath, buf.Bytes()) log.Printf("[INFO] Writing main module: %s\n%s", mainPath, buf.Bytes())
err = os.WriteFile(mainPath, buf.Bytes(), 0644) err = os.WriteFile(mainPath, buf.Bytes(), 0o644)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -317,8 +319,10 @@ func (env environment) execGoGet(ctx context.Context, modulePath, moduleVersion,
} }
type goModTemplateContext struct { type goModTemplateContext struct {
CaddyModule string CaddyModule string
Plugins []string Plugins []string
ExtraImports []string
Prequels []string
} }
const mainModuleTemplate = `package main const mainModuleTemplate = `package main
@ -331,9 +335,15 @@ import (
{{- range .Plugins}} {{- range .Plugins}}
_ "{{.}}" _ "{{.}}"
{{- end}} {{- end}}
{{- range .ExtraImports}}
{{.}}
{{- end}}
) )
func main() { func main() {
{{- range .Prequels}}
{{.}}
{{- end}}
caddycmd.Main() caddycmd.Main()
} }
` `