From 68ee163eb107abf6094d4ba0f6033a7e5b6b546e Mon Sep 17 00:00:00 2001 From: James Shubin Date: Tue, 16 Apr 2024 14:10:20 -0400 Subject: [PATCH] entry, lang: core: embedded: provisioner: Allow more than one entry This changes the entry API slightly to allow for more than one entry registered, which makes building, testing and user tooling easier. --- entry/entry.go | 48 +++++++++++-------- lang/core/embedded/provisioner.go | 2 +- lang/core/embedded/provisioner/provisioner.go | 4 +- main.go | 6 ++- 4 files changed, 35 insertions(+), 25 deletions(-) diff --git a/entry/entry.go b/entry/entry.go index 33a0bef9..f12b5228 100644 --- a/entry/entry.go +++ b/entry/entry.go @@ -45,27 +45,27 @@ import ( "github.com/alexflint/go-arg" ) -// registeredData is the single "registered" entry point that we built with. You -// cannot have more than one currently. -// TODO: In the future we could have more than one registered and each could -// appear under a top-level "embedded" subcommand if we decided not to have a -// "default" singleton registered. -var registeredData *Data +// registeredData is the map of "registered" entry points that we built with. +// You can have more than one registered. Each will appear under the top-level +// binary name as a subcommand. +var registeredData = make(map[string]*Data) // must initialize -// Register takes input data and stores it for lookup by the top-level main -// function. Register is commonly called in the init() method of the module that -// defined it, which happens at program startup. Build flags should be used to -// determine which Register gets to run. Only one entry can be registered at a -// time. There is no matching Unregister function at this time. -func Register(data *Data) { - if registeredData != nil { - panic("an entry is already registered") +// Register takes a data struct and stores a reference to it in our entry system +// along with a name. Future lookups to that name will pull out that data. +// Register is commonly called in the init() method of the module that defined +// it, which happens at program startup. Build flags should be used to determine +// which Register functions should run. Multiple entry data struct can be +// registered at a time. There is no matching Unregister function at this time. +func Register(name string, data *Data) { + if _, exists := registeredData[name]; exists { + panic(fmt.Sprintf("an entry named %s is already registered", name)) } + if err := data.Validate(); err != nil { panic(err) } - registeredData = data + registeredData[name] = data } // Data is what a prospective standalone entry program must specify to our API. @@ -128,15 +128,21 @@ func (obj *Data) Validate() error { return nil } -// Lookup returns the runner that implements the complex plumbing to kick off -// the run. If one has not been registered, then this will error. -func Lookup() (*Runner, error) { - if registeredData == nil { - return nil, fmt.Errorf("could not find a registered entry") +// Lookup takes a name and returns the runner that implements the complex +// plumbing to kick off the run. If one has not been registered under that name, +// then this will error. +func Lookup(name string) (*Runner, error) { + data, exists := registeredData[name] + if !exists { + return nil, fmt.Errorf("could not lookup entry named: %s", name) + } + + if data == nil { + return nil, fmt.Errorf("registered entry data was nil") } return &Runner{ - data: registeredData, // *Data + data: data, // *Data }, nil } diff --git a/lang/core/embedded/provisioner.go b/lang/core/embedded/provisioner.go index 4b7ce07f..daa4f0cf 100644 --- a/lang/core/embedded/provisioner.go +++ b/lang/core/embedded/provisioner.go @@ -27,7 +27,7 @@ // additional permission if he deems it necessary to achieve the goals of this // additional permission. -//go:build embedded_provisioner +//go:build !noembedded_provisioner package coreembedded diff --git a/lang/core/embedded/provisioner/provisioner.go b/lang/core/embedded/provisioner/provisioner.go index dda14d66..b194e269 100644 --- a/lang/core/embedded/provisioner/provisioner.go +++ b/lang/core/embedded/provisioner/provisioner.go @@ -27,7 +27,7 @@ // additional permission if he deems it necessary to achieve the goals of this // additional permission. -//go:build embedded_provisioner +//go:build !noembedded_provisioner package coreprovisioner @@ -434,7 +434,7 @@ func init() { localArgs: a.(*localArgs), // force the correct type } - entry.Register(&entry.Data{ + entry.Register(ModuleName, &entry.Data{ Program: ModuleName, Version: Version, // TODO: get from git? diff --git a/main.go b/main.go index cc9ab879..819a1cc1 100644 --- a/main.go +++ b/main.go @@ -91,8 +91,12 @@ func main() { Args: os.Args, } + name := "" + if len(data.Args) > 1 { + name = data.Args[1] + } // is there an alternate entry point for the cli? - if cli, err := entry.Lookup(); err == nil && len(data.Args) > 1 && cli.Name() == data.Args[1] { + if cli, err := entry.Lookup(name); err == nil && cli.Name() == name { data.Args = data.Args[1:] // pop off "argv[0]" if err := cli.CLI(context.Background(), data); err != nil { fmt.Println(err)