package main import ( "fmt" "os" "github.com/distribution/distribution/v3/registry" _ "github.com/distribution/distribution/v3/registry/auth/token" _ "github.com/distribution/distribution/v3/registry/storage/driver/inmemory" "github.com/spf13/cobra" "atcr.io/pkg/appview" // Register our custom middleware _ "atcr.io/pkg/appview/middleware" // Register built-in themes _ "atcr.io/themes/seamark" ) var configFile string var serveCmd = &cobra.Command{ Use: "serve", Short: "Start the ATCR registry server", Long: `Start the ATCR registry server with authentication endpoints. Configuration is loaded in layers: defaults -> YAML file -> environment variables. Use --config to specify a YAML configuration file. Environment variables always override file values.`, Args: cobra.NoArgs, RunE: serveRegistry, } var configCmd = &cobra.Command{ Use: "config", Short: "Configuration management commands", } var configInitCmd = &cobra.Command{ Use: "init [path]", Short: "Generate an example configuration file", Long: `Generate an example YAML configuration file with all available options. If path is provided, writes to that file. Otherwise writes to stdout.`, Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { yamlBytes, err := appview.ExampleYAML() if err != nil { return fmt.Errorf("failed to generate example config: %w", err) } if len(args) == 1 { if err := os.WriteFile(args[0], yamlBytes, 0644); err != nil { return fmt.Errorf("failed to write config file: %w", err) } fmt.Fprintf(os.Stderr, "Wrote example config to %s\n", args[0]) return nil } fmt.Print(string(yamlBytes)) return nil }, } func init() { serveCmd.Flags().StringVarP(&configFile, "config", "c", "", "path to YAML configuration file") configCmd.AddCommand(configInitCmd) // Replace the default serve command with our custom one for i, cmd := range registry.RootCmd.Commands() { if cmd.Name() == "serve" { registry.RootCmd.Commands()[i] = serveCmd break } } registry.RootCmd.AddCommand(configCmd) } func serveRegistry(cmd *cobra.Command, args []string) error { cfg, err := appview.LoadConfig(configFile) if err != nil { return fmt.Errorf("failed to load config: %w", err) } branding, err := appview.LookupTheme(cfg.UI.Theme) if err != nil { return err } server, err := appview.NewAppViewServer(cfg, branding) if err != nil { return fmt.Errorf("failed to initialize server: %w", err) } return server.Serve() } func main() { // The serve command is registered above via init() // Just execute the root command if err := registry.RootCmd.Execute(); err != nil { os.Exit(1) } }