package main import ( "context" "errors" "flag" "fmt" "io/fs" "os" "git.faercol.me/faercol/http-boot-config/config/logger" "git.faercol.me/faercol/http-boot-config/config/prober" "git.faercol.me/faercol/http-boot-config/config/remote" "github.com/google/uuid" ) type action int const ( actionList action = iota actionGetRemote actionUnknown ) type cliArgs struct { debug bool colour bool action action id uuid.UUID remoteAddr string prettyPrint bool } var defaultArgs cliArgs = cliArgs{ debug: false, colour: true, action: actionUnknown, } func parseArgs() (cliArgs, error) { args := defaultArgs var firstArg int listFlagSet := flag.NewFlagSet("list", flag.ExitOnError) getRemoteFlagSet := flag.NewFlagSet("get-remote", flag.ExitOnError) uuidFlag := getRemoteFlagSet.String("uuid", "", "Client UUID") remoteFlag := getRemoteFlagSet.String("remote-host", "http://localhost:5000", "Address for the remote boot server") jsonFlag := getRemoteFlagSet.Bool("json", false, "Display the result in JSON format") debugFlag := flag.Bool("debug", false, "Display debug logs") noColourFlag := flag.Bool("no-colour", false, "Disable colour logs") for i, v := range os.Args { switch v { case "list": args.action = actionList case "get-remote": args.action = actionGetRemote default: continue } firstArg = i + 1 } switch args.action { case actionList: listFlagSet.Parse(os.Args[firstArg:]) case actionGetRemote: getRemoteFlagSet.Parse(os.Args[firstArg:]) parsedID, err := uuid.Parse(*uuidFlag) if err != nil { return args, fmt.Errorf("invalid format for uuid %q", *uuidFlag) } args.id = parsedID args.remoteAddr = *remoteFlag args.prettyPrint = !*jsonFlag default: flag.Parse() return cliArgs{}, errors.New("missing an action") } flag.Parse() args.debug = *debugFlag args.colour = !*noColourFlag return args, nil } func displayAppList(l *logger.SimpleLogger) { l.Info("Checking EFI directory for available boot images...") apps, err := prober.GetEFIApps(l) if err != nil { if errors.Is(err, fs.ErrPermission) { l.Fatal("Permission error, try to run the command as sudo") } l.Fatalf("Failed to check EFI directory: %s", err.Error()) } l.Info("Found the following EFI applications:") for _, a := range apps { prefix := " " if a.Active { prefix = "*" } l.Infof("\t- %s[%d] %s: %s", prefix, a.ID, a.Name, a.Path) } } func getRemoteConfig(l *logger.SimpleLogger, host string, id uuid.UUID, pretty bool) { l.Info("Getting config from remote server...") if pretty { if err := remote.DisplayRemoteConfigPretty(context.Background(), host, id, l); err != nil { l.Fatal(err.Error()) } } else { if err := remote.DisplayRemoteConfigJSON(context.Background(), host, id, l); err != nil { l.Fatal(err.Error()) } } } func main() { args, err := parseArgs() if err != nil { l := logger.New(true, false) l.Fatalf("Invalid command: %s", err.Error()) } l := logger.New(args.colour, args.debug) fmt.Print("") switch args.action { case actionList: displayAppList(l) case actionGetRemote: getRemoteConfig(l, args.remoteAddr, args.id, args.prettyPrint) default: l.Fatal("Unknown action") } }