Skip to content

Commit

Permalink
further changes to support multiple providers:
Browse files Browse the repository at this point in the history
- moves all `init()` functions to `main.go` by making each package's
  `init()` public (`Init()`) so they can be run in a specific order
- uses a new `RegisterProviderCommand` to add provider versions of each
  comand as a subcommand to cani's command.  this currently requires the
  passing of a provider name for all calls but easily allows for each
  provider to define their own settings and not clash with each other
- adds a `utils.CloneCommand()` funciton to clone a cobra command, which
  providers can use to create and modify the commands as needed
- converts `recommendations.Print()` method to a provider-specific
  method: `root.D.PrintRecommendations(cmd, args, recommendations)`
- changes some variable names from `bootstrapCmd` to `caniCmd` to better
  distinguish cani vs. provider
- moves additional cray-sauce like cabinet vlans out of the `cmd`
  package and into the `csm` package where it belongs
- updates `provider.ProviderCommands` interface for all
  currently-supported commands
- adjusts test to call `csm`, which will begin to adjust tests for
  multiple providers
- adjusts help fixtures as needed
- converts some CSM `DEBUG` statements to `TRACE` since development will
  be minimal on CSM and less of that info is relevant to multiple
  providers
- changes some `cmd.Name()` conditionals to `cmd.Parent().Name()`
  since the provider command is a sub command
- updated `makeprovider` command for changes (some stupid changes, but
  they meet the immediate need)

Signed-off-by: Jacob Salmela <jacob.salmela@hpe.com>
  • Loading branch information
jacobsalmela committed Jan 8, 2024
1 parent fa9db40 commit 129e3c9
Show file tree
Hide file tree
Showing 48 changed files with 571 additions and 446 deletions.
5 changes: 3 additions & 2 deletions cmd/blade/add_blade.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ import (

// AddBladeCmd represents the blade add command
var AddBladeCmd = &cobra.Command{
Use: "blade",
Use: "blade PROVIDER",
Short: "Add blades to the inventory.",
Long: `Add blades to the inventory.`,
PreRunE: validHardware, // Hardware can only be valid if defined in the hardware library
RunE: addBlade, // Add a blade when this sub-command is called
Args: cobra.ExactArgs(1),
RunE: addBlade, // Add a blade when this sub-command is called
}

// addBlade adds a blade to the inventory
Expand Down
19 changes: 18 additions & 1 deletion cmd/blade/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@
package blade

import (
"os"

root "github.com/Cray-HPE/cani/cmd"
"github.com/Cray-HPE/cani/internal/domain"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
)

var (
Expand All @@ -40,7 +45,8 @@ var (
sortBy string
)

func init() {
func Init() {
log.Trace().Msgf("%+v", "github.com/Cray-HPE/cani/cmd/blade.init")
// Add blade variants to root commands
root.AddCmd.AddCommand(AddBladeCmd)
root.ListCmd.AddCommand(ListBladeCmd)
Expand All @@ -63,4 +69,15 @@ func init() {
RemoveBladeCmd.Flags().BoolVarP(&recursion, "recursive", "R", false, "Recursively delete child hardware")
ListBladeCmd.Flags().StringVarP(&format, "format", "f", "pretty", "Format output")
ListBladeCmd.Flags().StringVarP(&sortBy, "sort", "s", "location", "Sort by a specific key")

// Register all provider commands during init()
for _, p := range domain.GetProviders() {
for _, c := range []*cobra.Command{AddBladeCmd, ListBladeCmd} {
err := root.RegisterProviderCommand(p, c)
if err != nil {
log.Error().Msgf("Unable to get command '%s %s' from provider %s ", c.Parent().Name(), c.Name(), p.Slug())
os.Exit(1)
}
}
}
}
4 changes: 2 additions & 2 deletions cmd/blade/list_blade.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ import (

// ListBladeCmd represents the blade list command
var ListBladeCmd = &cobra.Command{
Use: "blade",
Use: "blade PROVIDER",
Short: "List blades in the inventory.",
Long: `List blades in the inventory.`,
Args: cobra.ArbitraryArgs,
Args: cobra.ExactArgs(1),
RunE: listBlade,
}

Expand Down
2 changes: 0 additions & 2 deletions cmd/blade/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,11 @@ import (
"os"

root "github.com/Cray-HPE/cani/cmd"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
)

// validHardware checks that the hardware type is valid by comparing it against the list of hardware types
func validHardware(cmd *cobra.Command, args []string) (err error) {
log.Debug().Msgf("Validating hardware %+v", root.D)
if cmd.Flags().Changed("list-supported-types") {
cmd.SetOut(os.Stdout)
for _, hw := range root.BladeTypes {
Expand Down
9 changes: 4 additions & 5 deletions cmd/cabinet/add_cabinet.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ import (

// AddCabinetCmd represents the cabinet add command
var AddCabinetCmd = &cobra.Command{
Use: "cabinet",
Use: "cabinet PROVIDER",
Short: "Add cabinets to the inventory.",
Long: `Add cabinets to the inventory.`,
PreRunE: validHardware, // Hardware can only be valid if defined in the hardware library
RunE: addCabinet, // Add a cabinet when this sub-command is called
Args: cobra.ExactArgs(1),
RunE: addCabinet,
}

// addCabinet adds a cabinet to the inventory
Expand Down Expand Up @@ -75,7 +76,7 @@ func addCabinet(cmd *cobra.Command, args []string) (err error) {
}

// log the provider recommendations to the screen
recommendations.Print()
root.D.PrintRecommendations(cmd, args, recommendations)
}

// Add the cabinet to the inventory using domain methods
Expand All @@ -98,8 +99,6 @@ func addCabinet(cmd *cobra.Command, args []string) (err error) {
var filtered = make(map[uuid.UUID]inventory.Hardware, 0)
for _, result := range result.AddedHardware {
if result.Hardware.Type == hardwaretypes.Cabinet {
log.Debug().Msgf("%s added at %s with parent %s (%s)", result.Hardware.Type, result.Location.String(), hardwaretypes.System, result.Hardware.Parent)
log.Info().Str("status", "SUCCESS").Msgf("%s %d was successfully staged to be added to the system", hardwaretypes.Cabinet, recommendations.CabinetOrdinal)
filtered[result.Hardware.ID] = result.Hardware
}
}
Expand Down
36 changes: 17 additions & 19 deletions cmd/cabinet/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,20 @@ import (
"os"

root "github.com/Cray-HPE/cani/cmd"
"github.com/Cray-HPE/cani/internal/domain"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
)

var (
cabinetNumber int
auto bool
accept bool
format string
sortBy string
ProviderAddCabinetCmd = &cobra.Command{}
ProviderListCabinetCmd = &cobra.Command{}
auto bool
accept bool
format string
sortBy string
)

func init() {
var err error
func Init() {
log.Trace().Msgf("%+v", "github.com/Cray-HPE/cani/cmd/cabinet.init")

// Add subcommands to root commands
root.AddCmd.AddCommand(AddCabinetCmd)
Expand All @@ -53,22 +51,22 @@ func init() {

// Common 'add cabinet' flags and then merge with provider-specified command
AddCabinetCmd.Flags().BoolP("list-supported-types", "L", false, "List supported hardware types.")
AddCabinetCmd.Flags().IntVar(&cabinetNumber, "cabinet", 1001, "Cabinet number.")
AddCabinetCmd.Flags().BoolVar(&auto, "auto", false, "Automatically recommend and assign required flags.")
AddCabinetCmd.MarkFlagsMutuallyExclusive("auto")
AddCabinetCmd.Flags().BoolVarP(&accept, "accept", "y", false, "Automatically accept recommended values.")
err = root.MergeProviderCommand(AddCabinetCmd)
if err != nil {
log.Error().Msgf("%+v", err)
os.Exit(1)
}

// Common 'list cabinet' flags and then merge with provider-specified command
ListCabinetCmd.Flags().StringVarP(&format, "format", "f", "pretty", "Format out output")
ListCabinetCmd.Flags().StringVarP(&sortBy, "sort", "s", "location", "Sort by a specific key")
err = root.MergeProviderCommand(ListCabinetCmd)
if err != nil {
log.Error().Msgf("%+v", err)
os.Exit(1)

// Register all provider commands during init()
for _, p := range domain.GetProviders() {
for _, c := range []*cobra.Command{AddCabinetCmd, ListCabinetCmd} {
err := root.RegisterProviderCommand(p, c)
if err != nil {
log.Error().Msgf("Unable to get command '%s %s' from provider %s ", c.Parent().Name(), c.Name(), p.Slug())
os.Exit(1)
}
}
}
}
4 changes: 2 additions & 2 deletions cmd/cabinet/list_cabinet.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ import (

// ListCabinetCmd represents the cabinet list command
var ListCabinetCmd = &cobra.Command{
Use: "cabinet",
Use: "cabinet PROVIDER",
Short: "List cabinets in the inventory.",
Long: `List cabinets in the inventory.`,
Args: cobra.ArbitraryArgs,
Args: cobra.ExactArgs(1),
RunE: listCabinet,
}

Expand Down
28 changes: 0 additions & 28 deletions cmd/cabinet/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,33 +72,5 @@ func validHardware(cmd *cobra.Command, args []string) (err error) {
}
}

err = validFlagCombos(cmd, args)
if err != nil {
return err
}

return nil
}

// validFlagCombos has additional flag logic to account for overiding required flags with the --auto flag
func validFlagCombos(cmd *cobra.Command, args []string) error {
cabinetSet := cmd.Flags().Changed("cabinet")
vlanIdSet := cmd.Flags().Changed("vlan-id")
autoSet := cmd.Flags().Changed("auto")
// if auto is set, the values are recommended and the required flags are bypassed
if autoSet {
return nil
} else {
if !cabinetSet && !vlanIdSet {
return errors.New("required flag(s) \"cabinet\", \"vlan-id\" not set")
}
if cabinetSet && !vlanIdSet {
return errors.New("required flag(s) \"vlan-id\" not set")
}
if !cabinetSet && vlanIdSet {
return errors.New("required flag(s) \"cabinet\" not set")
}
}

return nil
}
4 changes: 3 additions & 1 deletion cmd/cdu/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ package cdu

import (
root "github.com/Cray-HPE/cani/cmd"
"github.com/rs/zerolog/log"
)

var (
hwType string
supportedHw []string
)

func init() {
func Init() {
log.Trace().Msgf("%+v", "github.com/Cray-HPE/cani/cmd/cdu.init")
// Add variants to root commands
root.AddCmd.AddCommand(AddCduCmd)
root.ListCmd.AddCommand(ListCduCmd)
Expand Down
4 changes: 3 additions & 1 deletion cmd/chassis/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ package chassis

import (
root "github.com/Cray-HPE/cani/cmd"
"github.com/rs/zerolog/log"
)

var (
Expand All @@ -36,7 +37,8 @@ var (
sortBy string
)

func init() {
func Init() {
log.Trace().Msgf("%+v", "github.com/Cray-HPE/cani/cmd/chassis.init")
// Add variants to root commands
root.AddCmd.AddCommand(AddChassisCmd)
root.ListCmd.AddCommand(ListChassisCmd)
Expand Down
40 changes: 31 additions & 9 deletions cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ import (
"gopkg.in/yaml.v3"
)

func Init() {
log.Trace().Msgf("%+v", "github.com/Cray-HPE/cani/cmd/config.init")
}

// Config is the top-level config struct that is written/read to/from a file
type Config struct {
Session *Session `yaml:"session"`
Expand Down Expand Up @@ -145,16 +149,34 @@ func WriteConfig(path string, cfg *Config) error {
return nil
}

// AvailableDomains returns a slice of available domains read from the config
func (c *Config) AvailableDomains() (map[string]*domain.Domain, error) {
domains := make(map[string]*domain.Domain, 0)

func (c *Config) ActiveProvider() (activeDomain *domain.Domain, err error) {
// Find an active session
activeDomains := []*domain.Domain{}
activeProviders := []string{}
for p, d := range c.Session.Domains {
log.Info().Msgf("Found an available domain: %+v", p)
_, exists := domains[p]
if !exists {
domains[p] = d
if d.Active {
log.Debug().Msgf("Provider '%s' is ACTIVE", p)
activeDomains = append(activeDomains, d)
activeProviders = append(activeProviders, p)
} else {
log.Debug().Msgf("Provider '%s' is inactive", p)
}
}
return domains, nil

// Check that only one session is active
if len(activeProviders) > 1 {
for _, p := range activeProviders {
err := fmt.Errorf("currently active: %v", p)
log.Error().Msgf("%v", err)
}

return nil, fmt.Errorf("only one session may be active at a time")
}
if len(activeDomains) == 0 {
log.Info().Msgf("No active domains")
return nil, nil
}
activeDomain = activeDomains[0]

return activeDomain, nil
}
3 changes: 2 additions & 1 deletion cmd/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ var (

// ExportCmd represents the export command
var ExportCmd = &cobra.Command{
Use: "export",
Use: "export PROVIDER",
Short: "Export assets from the inventory.",
Long: `Export assets from the inventory.`,
Args: cobra.ExactArgs(1),
RunE: export,
}

Expand Down
3 changes: 2 additions & 1 deletion cmd/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ var (

// ImportCmd represents the import command
var ImportCmd = &cobra.Command{
Use: "import [FILE]",
Use: "import PROVIDER [FILE]",
Short: "Import assets into the inventory.",
Long: `Import assets into the inventory.`,
Args: cobra.ExactArgs(1),
RunE: importCmd,
}

Expand Down
Loading

0 comments on commit 129e3c9

Please sign in to comment.