mirror of
https://github.com/kairos-io/provider-kairos.git
synced 2025-08-10 11:51:52 +00:00
This PR extracts the registration command into a `kairos-register` binary of its own. The old sub command is kept so users can see a deprecation notice and adapt for a future release when it's removed. The version number is shared between binaries. ⚠️ I'm not entirely sure about the gorelease, and would benefit from a couple of extra 👀 on this, thanks! relates to kairos-io/kairos#1211 --------- Signed-off-by: Mauro Morales <mauro.morales@spectrocloud.com> Signed-off-by: Mauro Morales <contact@mauromorales.com> Signed-off-by: Itxaka <itxaka.garcia@spectrocloud.com> Signed-off-by: GitHub <noreply@github.com> Co-authored-by: Dimitris Karakasilis <dimitris@karakasilis.me> Co-authored-by: Itxaka <itxaka.garcia@spectrocloud.com> Co-authored-by: ci-robbot [bot] <105103991+ci-robbot@users.noreply.github.com> Co-authored-by: mudler <mudler@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
144 lines
3.8 KiB
Go
144 lines
3.8 KiB
Go
package cli
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/urfave/cli/v2"
|
|
|
|
nodepair "github.com/mudler/go-nodepair"
|
|
qr "github.com/mudler/go-nodepair/qrcode"
|
|
)
|
|
|
|
// RegisterCMD is only used temporarily to avoid duplication while the kairosctl sub-command is deprecated.
|
|
func RegisterCMD(toolName string) *cli.Command {
|
|
subCommandName := "register"
|
|
fullName := fmt.Sprintf("%s %s", toolName, subCommandName)
|
|
usage := "Registers and bootstraps a node"
|
|
description := fmt.Sprintf(`
|
|
Bootstraps a node which is started in pairing mode. It can send over a configuration file used to install the kairos node.
|
|
|
|
For example:
|
|
$ %s --config config.yaml --device /dev/sda ~/Downloads/screenshot.png
|
|
|
|
will decode the QR code from ~/Downloads/screenshot.png and bootstrap the node remotely.
|
|
|
|
If the image is omitted, a screenshot will be taken and used to decode the QR code.
|
|
|
|
See also https://kairos.io/docs/getting-started/ for documentation.
|
|
`, fullName)
|
|
if toolName != "kairosctl" {
|
|
usage += " (WARNING: this command will be deprecated in the next release, use the kairosctl binary instead)"
|
|
description = "\t\tWARNING: This command will be deprecated in the next release. Please use the new kairosctl binary to register your nodes.\n" + description
|
|
}
|
|
|
|
return &cli.Command{
|
|
Name: subCommandName,
|
|
UsageText: fmt.Sprintf("%s --reboot --device /dev/sda /image/snapshot.png", fullName),
|
|
Usage: usage,
|
|
Description: description,
|
|
ArgsUsage: "Register optionally accepts an image. If nothing is passed will take a screenshot of the screen and try to decode the QR code",
|
|
Flags: []cli.Flag{
|
|
&cli.StringFlag{
|
|
Name: "config",
|
|
Usage: "Kairos YAML configuration file",
|
|
Required: true,
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "device",
|
|
Usage: "Device used for the installation target",
|
|
},
|
|
&cli.BoolFlag{
|
|
Name: "reboot",
|
|
Usage: "Reboot node after installation",
|
|
},
|
|
&cli.BoolFlag{
|
|
Name: "poweroff",
|
|
Usage: "Shutdown node after installation",
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "log-level",
|
|
Usage: "Set log level",
|
|
},
|
|
},
|
|
Action: func(c *cli.Context) error {
|
|
var ref string
|
|
if c.Args().Len() == 1 {
|
|
ref = c.Args().First()
|
|
}
|
|
|
|
return register(c.String("log-level"), ref, c.String("config"), c.String("device"), c.Bool("reboot"), c.Bool("poweroff"))
|
|
},
|
|
}
|
|
}
|
|
|
|
// isDirectory determines if a file represented
|
|
// by `path` is a directory or not.
|
|
func isDirectory(path string) (bool, error) {
|
|
fileInfo, err := os.Stat(path)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return fileInfo.IsDir(), err
|
|
}
|
|
|
|
func isReadable(fileName string) bool {
|
|
file, err := os.Open(fileName)
|
|
if err != nil {
|
|
if os.IsPermission(err) {
|
|
return false
|
|
}
|
|
}
|
|
file.Close()
|
|
return true
|
|
}
|
|
|
|
func register(loglevel, arg, configFile, device string, reboot, poweroff bool) error {
|
|
b, _ := os.ReadFile(configFile)
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
if arg != "" {
|
|
isDir, err := isDirectory(arg)
|
|
if err == nil && isDir {
|
|
return fmt.Errorf("Cannot register with a directory, please pass a file.") //nolint:revive // This is a message printed to the user.
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
if !isReadable(arg) {
|
|
return fmt.Errorf("Cannot register with a file that is not readable.") //nolint:revive // This is a message printed to the user.
|
|
}
|
|
}
|
|
// dmesg -D to suppress tty ev
|
|
fmt.Println("Sending registration payload, please wait")
|
|
|
|
config := map[string]string{
|
|
"device": device,
|
|
"cc": string(b),
|
|
}
|
|
|
|
if reboot {
|
|
config["reboot"] = ""
|
|
}
|
|
|
|
if poweroff {
|
|
config["poweroff"] = ""
|
|
}
|
|
|
|
err := nodepair.Send(
|
|
ctx,
|
|
config,
|
|
nodepair.WithReader(qr.Reader),
|
|
nodepair.WithToken(arg),
|
|
nodepair.WithLogLevel(loglevel),
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Println("Payload sent, installation will start on the machine briefly")
|
|
return nil
|
|
}
|