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.
This commit is contained in:
James Shubin
2024-04-16 14:10:20 -04:00
parent bc4b5d96b0
commit 68ee163eb1
4 changed files with 35 additions and 25 deletions

View File

@@ -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
}

View File

@@ -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

View File

@@ -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?

View File

@@ -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)