2022-07-04 20:39:34 +00:00
package main
import (
2023-01-05 13:15:05 +00:00
"context"
2023-04-20 07:57:58 +00:00
"encoding/json"
2023-09-14 12:53:27 +00:00
"errors"
2022-07-04 20:39:34 +00:00
"fmt"
2023-06-14 12:44:22 +00:00
"os"
2023-06-07 09:28:37 +00:00
"path/filepath"
2023-06-05 13:19:39 +00:00
"regexp"
2023-06-14 12:44:22 +00:00
"runtime"
2023-04-20 07:57:58 +00:00
"strings"
2022-07-04 20:39:34 +00:00
2023-09-14 12:35:44 +00:00
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
2023-07-10 12:39:48 +00:00
"github.com/kairos-io/kairos-agent/v2/internal/agent"
"github.com/kairos-io/kairos-agent/v2/internal/bus"
"github.com/kairos-io/kairos-agent/v2/internal/common"
"github.com/kairos-io/kairos-agent/v2/internal/webui"
2023-07-25 13:21:34 +00:00
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
2023-07-10 12:39:48 +00:00
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
2023-03-18 09:27:18 +00:00
"github.com/kairos-io/kairos-sdk/bundles"
2023-06-14 12:44:22 +00:00
"github.com/kairos-io/kairos-sdk/collector"
2023-03-18 09:27:18 +00:00
"github.com/kairos-io/kairos-sdk/machine"
2023-05-26 10:36:22 +00:00
"github.com/kairos-io/kairos-sdk/schema"
2023-03-15 14:45:00 +00:00
"github.com/kairos-io/kairos-sdk/state"
2023-06-14 12:44:22 +00:00
"github.com/sirupsen/logrus"
2022-07-04 20:39:34 +00:00
2023-04-20 07:57:58 +00:00
"github.com/Masterminds/semver/v3"
2023-06-21 07:42:11 +00:00
"github.com/spf13/viper"
2023-01-24 23:39:51 +00:00
"github.com/urfave/cli/v2"
2023-04-20 07:57:58 +00:00
"gopkg.in/yaml.v3"
2022-07-04 20:39:34 +00:00
)
2022-10-24 11:13:23 +00:00
var configScanDir = [ ] string { "/oem" , "/usr/local/cloud-config" , "/run/initramfs/live" }
2023-04-20 07:57:58 +00:00
// ReleasesToOutput gets a semver.Collection and outputs it in the given format
// Only used here.
func ReleasesToOutput ( rels semver . Collection , output string ) [ ] string {
// Set them back to their original version number with the v in front
var stringRels [ ] string
for _ , v := range rels {
stringRels = append ( stringRels , v . Original ( ) )
}
switch strings . ToLower ( output ) {
case "yaml" :
d , _ := yaml . Marshal ( stringRels )
return [ ] string { string ( d ) }
case "json" :
d , _ := json . Marshal ( stringRels )
return [ ] string { string ( d ) }
default :
return stringRels
}
}
2023-01-24 23:39:51 +00:00
var cmds = [ ] * cli . Command {
2022-07-04 20:39:34 +00:00
{
Name : "upgrade" ,
Flags : [ ] cli . Flag {
& cli . BoolFlag {
Name : "force" ,
Usage : "Force an upgrade" ,
} ,
& cli . StringFlag {
Name : "image" ,
2023-06-05 13:19:39 +00:00
Usage : "[DEPRECATED] Specify a full image reference, e.g.: quay.io/some/image:tag" ,
} ,
& cli . StringFlag {
Name : "source" ,
Usage : "Source for upgrade. Composed of `type:address`. Accepts `file:`,`dir:` or `oci:` for the type of source.\nFor example `file:/var/share/myimage.tar`, `dir:/tmp/extracted` or `oci:repo/image:tag`" ,
2022-07-04 20:39:34 +00:00
} ,
2023-04-21 10:32:28 +00:00
& cli . BoolFlag { Name : "pre" , Usage : "Include pre-releases (rc, beta, alpha)" } ,
2023-08-07 14:11:13 +00:00
& cli . BoolFlag { Name : "recovery" , Usage : "Upgrade recovery" } ,
2022-07-04 20:39:34 +00:00
} ,
Description : `
2023-08-07 14:11:13 +00:00
Manually upgrade a kairos node Active image . Does not upgrade passive or recovery images .
2022-07-04 20:39:34 +00:00
By default takes no arguments , defaulting to latest available release , to specify a version , pass it as argument :
2022-09-17 16:43:51 +00:00
$ kairos upgrade v1 .20 ... .
2022-07-04 20:39:34 +00:00
2022-09-17 16:43:51 +00:00
To retrieve all the available versions , use "kairos upgrade list-releases"
2022-07-04 20:39:34 +00:00
2022-09-17 16:43:51 +00:00
$ kairos upgrade list - releases
2022-07-04 20:39:34 +00:00
2023-01-19 21:16:13 +00:00
See https : //kairos.io/docs/upgrade/manual/ for documentation.
2022-07-04 20:39:34 +00:00
` ,
2023-01-24 23:39:51 +00:00
Subcommands : [ ] * cli . Command {
2022-07-04 20:39:34 +00:00
{
Flags : [ ] cli . Flag {
& cli . StringFlag {
Name : "output" ,
Usage : "Output format (json|yaml|terminal)" ,
} ,
2023-04-21 10:32:28 +00:00
& cli . BoolFlag { Name : "pre" , Usage : "Include pre-releases (rc, beta, alpha)" } ,
2022-07-04 20:39:34 +00:00
} ,
Name : "list-releases" ,
Description : ` List all available releases versions ` ,
Action : func ( c * cli . Context ) error {
2023-04-21 10:32:28 +00:00
releases := agent . ListReleases ( c . Bool ( "pre" ) )
2023-04-20 07:57:58 +00:00
list := ReleasesToOutput ( releases , c . String ( "output" ) )
2023-01-19 21:16:13 +00:00
for _ , i := range list {
fmt . Println ( i )
2022-07-04 20:39:34 +00:00
}
return nil
} ,
} ,
} ,
2023-06-05 13:19:39 +00:00
Before : func ( c * cli . Context ) error {
2023-09-26 14:09:24 +00:00
if err := validateSource ( c . String ( "source" ) ) ; err != nil {
return err
2023-06-05 13:19:39 +00:00
}
2023-09-14 12:53:27 +00:00
return checkRoot ( )
2023-06-05 13:19:39 +00:00
} ,
2022-07-04 20:39:34 +00:00
Action : func ( c * cli . Context ) error {
var v string
2023-01-24 23:39:51 +00:00
if c . Args ( ) . Len ( ) == 1 {
v = c . Args ( ) . First ( )
2022-07-04 20:39:34 +00:00
}
2023-03-24 13:00:33 +00:00
2023-06-05 13:19:39 +00:00
image := c . String ( "image" )
source := c . String ( "source" )
if image != "" {
fmt . Println ( "--image flag is deprecated, please use --source" )
// override source with image for now until we drop it
source = fmt . Sprintf ( "oci:%s" , image )
}
2023-03-24 13:00:33 +00:00
return agent . Upgrade (
2023-07-20 13:53:48 +00:00
v , source , c . Bool ( "force" ) ,
2023-03-24 13:00:33 +00:00
c . Bool ( "strict-validation" ) , configScanDir ,
2023-08-07 14:11:13 +00:00
c . Bool ( "pre" ) , c . Bool ( "recovery" ) ,
2023-03-24 13:00:33 +00:00
)
2022-07-04 20:39:34 +00:00
} ,
} ,
2022-08-09 06:01:54 +00:00
{
Name : "notify" ,
Usage : "notify <event> <config dir>..." ,
UsageText : "emits the given event with a generic event payload" ,
Description : `
Sends a generic event payload with the configuration found in the scanned directories .
` ,
Aliases : [ ] string { } ,
Flags : [ ] cli . Flag { } ,
Action : func ( c * cli . Context ) error {
dirs := [ ] string { "/oem" , "/usr/local/cloud-config" }
2023-01-24 23:39:51 +00:00
if c . Args ( ) . Len ( ) > 1 {
dirs = c . Args ( ) . Slice ( ) [ 1 : ]
2022-08-09 06:01:54 +00:00
}
2023-01-24 23:39:51 +00:00
return agent . Notify ( c . Args ( ) . First ( ) , dirs )
2022-08-09 06:01:54 +00:00
} ,
} ,
2022-07-04 20:39:34 +00:00
{
Name : "start" ,
2022-09-17 16:43:51 +00:00
Usage : "Starts the kairos agent" ,
2022-07-04 20:39:34 +00:00
UsageText : "starts the agent" ,
Description : `
2022-09-17 16:43:51 +00:00
Starts the kairos agent which automatically bootstrap and advertize to the kairos network .
2022-07-04 20:39:34 +00:00
` ,
Aliases : [ ] string { "s" } ,
Flags : [ ] cli . Flag {
2022-08-08 08:15:15 +00:00
& cli . BoolFlag {
Name : "restart" ,
} ,
2022-07-04 20:39:34 +00:00
& cli . BoolFlag {
Name : "force" ,
} ,
& cli . StringFlag {
Name : "api" ,
Value : "http://127.0.0.1:8080" ,
} ,
} ,
Action : func ( c * cli . Context ) error {
dirs := [ ] string { "/oem" , "/usr/local/cloud-config" }
2023-01-24 23:39:51 +00:00
if c . Args ( ) . Present ( ) {
dirs = c . Args ( ) . Slice ( )
2022-07-04 20:39:34 +00:00
}
2022-08-08 08:15:15 +00:00
opts := [ ] agent . Option {
agent . WithAPI ( c . String ( "api" ) ) ,
agent . WithDirectory ( dirs ... ) ,
}
if c . Bool ( "force" ) {
opts = append ( opts , agent . ForceAgent )
}
if c . Bool ( "restart" ) {
opts = append ( opts , agent . RestartAgent )
}
return agent . Run ( opts ... )
2022-07-04 20:39:34 +00:00
} ,
} ,
2022-07-13 22:23:47 +00:00
{
Name : "install-bundle" ,
2022-09-17 16:43:51 +00:00
Usage : "Installs a kairos bundle" ,
2022-07-13 22:23:47 +00:00
Description : `
2022-09-17 16:43:51 +00:00
Manually installs a kairos bundle .
2022-07-13 22:23:47 +00:00
2022-09-17 16:43:51 +00:00
E . g . kairos - agent install - bundle container : quay . io / kairos / kairos ...
2022-07-13 22:23:47 +00:00
` ,
Aliases : [ ] string { "i" } ,
Flags : [ ] cli . Flag {
& cli . StringFlag {
2023-01-24 23:39:51 +00:00
Name : "repository" ,
EnvVars : [ ] string { "REPOSITORY" } ,
Value : "docker://quay.io/kairos/packages" ,
2022-07-13 22:23:47 +00:00
} ,
2023-05-18 10:10:09 +00:00
& cli . StringFlag {
Name : "root-path" ,
Value : "/" ,
} ,
2023-04-14 15:33:02 +00:00
& cli . BoolFlag {
Name : "local-file" ,
EnvVars : [ ] string { "LOCAL_FILE" } ,
} ,
2022-07-13 22:23:47 +00:00
} ,
UsageText : "Install a bundle manually in the node" ,
2023-09-14 12:53:27 +00:00
Before : func ( c * cli . Context ) error {
return checkRoot ( )
} ,
2022-07-13 22:23:47 +00:00
Action : func ( c * cli . Context ) error {
2023-01-24 23:39:51 +00:00
if c . Args ( ) . Len ( ) != 1 {
2022-07-13 22:23:47 +00:00
return fmt . Errorf ( "bundle name required" )
}
2023-05-18 10:10:09 +00:00
return bundles . RunBundles ( [ ] bundles . BundleOption { bundles . WithRootFS ( c . String ( "root-path" ) ) , bundles . WithRepository ( c . String ( "repository" ) ) , bundles . WithTarget ( c . Args ( ) . First ( ) ) , bundles . WithLocalFile ( c . Bool ( "local-file" ) ) } )
2022-07-13 22:23:47 +00:00
} ,
} ,
2022-07-04 20:39:34 +00:00
{
Name : "uuid" ,
Usage : "Prints the local UUID" ,
Description : "Print node uuid" ,
Aliases : [ ] string { "u" } ,
Action : func ( c * cli . Context ) error {
fmt . Print ( machine . UUID ( ) )
return nil
} ,
} ,
2023-01-05 13:15:05 +00:00
{
Name : "webui" ,
Usage : "Starts the webui" ,
Description : "Starts the webui installer" ,
Aliases : [ ] string { "w" } ,
Action : func ( c * cli . Context ) error {
return webui . Start ( context . Background ( ) )
//return nil
} ,
} ,
2022-12-19 16:01:57 +00:00
{
Name : "config" ,
Usage : "get machine configuration" ,
Description : "Print machine state information, e.g. `state get uuid` returns the machine uuid" ,
Aliases : [ ] string { "c" } ,
Action : func ( c * cli . Context ) error {
runtime , err := state . NewRuntime ( )
if err != nil {
return err
}
fmt . Print ( runtime )
return err
} ,
2023-01-24 23:39:51 +00:00
Subcommands : [ ] * cli . Command {
2022-12-19 16:01:57 +00:00
{
Name : "show" ,
Usage : "Shows the machine configuration" ,
Description : "Show the runtime configuration of the machine. It will scan the machine for all the configuration and will return the config file processed and found." ,
Aliases : [ ] string { "s" } ,
Action : func ( c * cli . Context ) error {
2023-07-25 13:21:34 +00:00
config , err := agentConfig . Scan ( collector . Directories ( configScanDir ... ) , collector . NoLogs )
2022-12-19 16:01:57 +00:00
if err != nil {
return err
}
2022-10-23 18:22:32 +00:00
2023-03-29 14:25:38 +00:00
configStr , err := config . String ( )
if err != nil {
return err
}
fmt . Printf ( "%s" , configStr )
2022-12-19 16:01:57 +00:00
return nil
} ,
} ,
{
Name : "get" ,
Usage : "Get specific data from the configuration" ,
UsageText : `
Use it to retrieve configuration programmatically from the CLI :
$ kairos - agent config get k3s . enabled
true
or
$ kairos - agent config get k3s
enabled : true ` ,
Description : "It allows to navigate the YAML config file by searching with 'yq' style keywords as `config get k3s` to retrieve the k3s config block" ,
Aliases : [ ] string { "g" } ,
Action : func ( c * cli . Context ) error {
2023-07-25 13:21:34 +00:00
config , err := agentConfig . Scan ( collector . Directories ( configScanDir ... ) , collector . NoLogs , collector . StrictValidation ( c . Bool ( "strict-validation" ) ) )
2022-12-19 16:01:57 +00:00
if err != nil {
return err
}
res , err := config . Query ( c . Args ( ) . First ( ) )
if err != nil {
return err
}
fmt . Printf ( "%s" , res )
return nil
} ,
} ,
} ,
} ,
2022-10-23 18:22:32 +00:00
{
Name : "state" ,
Usage : "get machine state" ,
2022-10-24 06:34:49 +00:00
Description : "Print machine state information, e.g. `state get uuid` returns the machine uuid" ,
2022-10-23 18:22:32 +00:00
Aliases : [ ] string { "s" } ,
Action : func ( c * cli . Context ) error {
runtime , err := state . NewRuntime ( )
if err != nil {
return err
}
fmt . Print ( runtime )
return err
} ,
2023-01-24 23:39:51 +00:00
Subcommands : [ ] * cli . Command {
2022-10-23 18:22:32 +00:00
{
Name : "apply" ,
Usage : "Applies a machine state" ,
2022-10-24 06:34:49 +00:00
Description : "Applies machine configuration in runtimes" ,
2022-10-23 18:22:32 +00:00
Aliases : [ ] string { "a" } ,
Action : func ( c * cli . Context ) error {
// TODO
return nil
} ,
} ,
{
Name : "get" ,
Usage : "get specific " ,
Description : "query state data" ,
Aliases : [ ] string { "g" } ,
Action : func ( c * cli . Context ) error {
runtime , err := state . NewRuntime ( )
if err != nil {
return err
}
res , err := runtime . Query ( c . Args ( ) . First ( ) )
fmt . Print ( res )
return err
} ,
} ,
} ,
} ,
2022-07-04 20:39:34 +00:00
{
Name : "interactive-install" ,
Description : `
2022-09-17 16:43:51 +00:00
Starts kairos in interactive mode install .
2022-07-04 20:39:34 +00:00
2022-08-12 13:49:41 +00:00
It will ask prompt for several questions and perform an install depending on the providers available in the system .
2022-07-04 20:39:34 +00:00
2022-09-17 22:11:45 +00:00
See also https : //kairos.io/installation/interactive_install/ for documentation.
2022-07-04 20:39:34 +00:00
2022-08-12 13:49:41 +00:00
This command is meant to be used from the boot GRUB menu , but can be also started manually ` ,
2022-07-04 20:39:34 +00:00
Flags : [ ] cli . Flag {
& cli . BoolFlag {
Name : "shell" ,
} ,
2023-09-26 14:09:24 +00:00
& cli . StringFlag {
Name : "source" ,
Usage : "Source for upgrade. Composed of `type:address`. Accepts `file:`,`dir:` or `oci:` for the type of source.\nFor example `file:/var/share/myimage.tar`, `dir:/tmp/extracted` or `oci:repo/image:tag`" ,
} ,
2022-07-04 20:39:34 +00:00
} ,
Usage : "Starts interactive installation" ,
2023-09-14 12:53:27 +00:00
Before : func ( c * cli . Context ) error {
2023-09-26 14:09:24 +00:00
if err := validateSource ( c . String ( "source" ) ) ; err != nil {
return err
}
2023-09-14 12:53:27 +00:00
return checkRoot ( )
} ,
2022-07-04 20:39:34 +00:00
Action : func ( c * cli . Context ) error {
2023-09-26 14:09:24 +00:00
source := c . String ( "source" )
return agent . InteractiveInstall ( c . Bool ( "debug" ) , c . Bool ( "shell" ) , source )
2022-07-04 20:39:34 +00:00
} ,
} ,
2022-09-10 13:01:03 +00:00
{
Name : "manual-install" ,
Usage : "Starts the manual installation" ,
Description : `
` ,
Aliases : [ ] string { "m" } ,
Flags : [ ] cli . Flag {
& cli . StringFlag {
Name : "device" ,
} ,
& cli . BoolFlag {
Name : "poweroff" ,
} ,
& cli . BoolFlag {
Name : "reboot" ,
} ,
2023-09-26 14:09:24 +00:00
& cli . StringFlag {
Name : "source" ,
Usage : "Source for upgrade. Composed of `type:address`. Accepts `file:`,`dir:` or `oci:` for the type of source.\nFor example `file:/var/share/myimage.tar`, `dir:/tmp/extracted` or `oci:repo/image:tag`" ,
} ,
2022-09-10 13:01:03 +00:00
} ,
2023-09-14 12:53:27 +00:00
Before : func ( c * cli . Context ) error {
2023-09-26 14:09:24 +00:00
if err := validateSource ( c . String ( "source" ) ) ; err != nil {
return err
}
2023-09-14 12:53:27 +00:00
return checkRoot ( )
} ,
2022-09-10 13:01:03 +00:00
Action : func ( c * cli . Context ) error {
if c . NArg ( ) == 0 {
return fmt . Errorf ( "expect one argument. the config file - if you don't have it, use the interactive-install" )
}
config := c . Args ( ) . First ( )
2023-09-26 14:09:24 +00:00
source := c . String ( "source" )
return agent . ManualInstall ( config , source , c . String ( "device" ) , c . Bool ( "reboot" ) , c . Bool ( "poweroff" ) , c . Bool ( "strict-validation" ) )
2022-09-10 13:01:03 +00:00
} ,
} ,
2022-07-04 20:39:34 +00:00
{
Name : "install" ,
2022-09-17 16:43:51 +00:00
Usage : "Starts the kairos pairing installation" ,
2022-07-04 20:39:34 +00:00
Description : `
2022-09-17 16:43:51 +00:00
Starts kairos in pairing mode .
2022-07-04 20:39:34 +00:00
2022-09-17 16:43:51 +00:00
It will print out a QR code which can be used with "kairos register" to send over a configuration and bootstraping a kairos node .
2022-07-04 20:39:34 +00:00
2023-03-06 18:16:19 +00:00
See also https : //kairos.io/docs/installation/qrcode/ for documentation.
2022-07-04 20:39:34 +00:00
This command is meant to be used from the boot GRUB menu , but can be started manually ` ,
Aliases : [ ] string { "i" } ,
2023-09-14 12:53:27 +00:00
Before : func ( c * cli . Context ) error {
2023-09-26 14:09:24 +00:00
if err := validateSource ( c . String ( "source" ) ) ; err != nil {
return err
}
2023-09-14 12:53:27 +00:00
return checkRoot ( )
} ,
2023-09-26 14:09:24 +00:00
Flags : [ ] cli . Flag {
& cli . StringFlag {
Name : "source" ,
Usage : "Source for upgrade. Composed of `type:address`. Accepts `file:`,`dir:` or `oci:` for the type of source.\nFor example `file:/var/share/myimage.tar`, `dir:/tmp/extracted` or `oci:repo/image:tag`" ,
} ,
} ,
2022-07-04 20:39:34 +00:00
Action : func ( c * cli . Context ) error {
2023-09-26 14:09:24 +00:00
source := c . String ( "source" )
return agent . Install ( source , configScanDir ... )
2022-07-04 20:39:34 +00:00
} ,
} ,
{
Name : "recovery" ,
Aliases : [ ] string { "r" } ,
2022-07-18 22:02:49 +00:00
Action : func ( c * cli . Context ) error {
return agent . Recovery ( )
} ,
2022-09-17 16:43:51 +00:00
Usage : "Starts kairos recovery mode" ,
2022-07-04 20:39:34 +00:00
Description : `
2022-09-17 16:43:51 +00:00
Starts kairos recovery mode .
2022-07-04 20:39:34 +00:00
2022-09-17 16:43:51 +00:00
In recovery mode a QR code will be printed out on the screen which should be used in conjunction with "kairos bridge" . Pass by the QR code as snapshot
to the bridge to connect over the machine which runs the "kairos recovery" command .
2022-07-04 20:39:34 +00:00
2022-09-17 22:11:45 +00:00
See also https : //kairos.io/after_install/recovery_mode/ for documentation.
2022-07-04 20:39:34 +00:00
This command is meant to be used from the boot GRUB menu , but can likely be used standalone ` ,
} ,
{
2022-07-18 22:02:49 +00:00
Name : "reset" ,
2023-08-04 18:39:22 +00:00
Flags : [ ] cli . Flag {
& cli . BoolFlag {
Name : "reboot" ,
Usage : "Enable automated reboot after reset. Has precedence over any config in the system." ,
} ,
& cli . BoolFlag {
Name : "unattended" ,
Usage : "Do not wait for user input and provide ttys after reset. Also sets the fast mode (do not wait 60 seconds before reset)" ,
} ,
} ,
2023-09-14 12:53:27 +00:00
Before : func ( c * cli . Context ) error {
return checkRoot ( )
} ,
2022-07-18 22:02:49 +00:00
Action : func ( c * cli . Context ) error {
2023-08-04 18:39:22 +00:00
reboot := c . Bool ( "reboot" )
unattended := c . Bool ( "unattended" )
2023-07-20 13:53:48 +00:00
2023-08-04 18:39:22 +00:00
return agent . Reset ( reboot , unattended , configScanDir ... )
2022-07-18 22:02:49 +00:00
} ,
2022-09-17 16:43:51 +00:00
Usage : "Starts kairos reset mode" ,
2022-07-04 20:39:34 +00:00
Description : `
2022-09-17 16:43:51 +00:00
Starts kairos reset mode , it will nuke completely the node data and restart fresh .
2022-07-04 20:39:34 +00:00
Attention ! this will delete any persistent data on the node . It is equivalent to re - init the node right after the installation .
In reset mode a the node will automatically reset
2022-09-17 22:11:45 +00:00
See also https : //kairos.io/after_install/reset_mode/ for documentation.
2022-07-04 20:39:34 +00:00
This command is meant to be used from the boot GRUB menu , but can likely be used standalone ` ,
} ,
2023-02-14 15:15:13 +00:00
{
Name : "validate" ,
Action : func ( c * cli . Context ) error {
config := c . Args ( ) . First ( )
2023-05-26 10:36:22 +00:00
return schema . Validate ( config )
2023-02-14 15:15:13 +00:00
} ,
Usage : "Validates a cloud config file" ,
Description : `
The validate command expects a configuration file as its only argument . Local files and URLs are accepted .
` ,
} ,
{
Name : "print-schema" ,
2023-05-11 11:30:17 +00:00
Flags : [ ] cli . Flag {
& cli . StringFlag {
Name : "version" ,
Usage : "Print the current schema but with another version number, instead of using the agent version number." ,
} ,
} ,
2023-02-14 15:15:13 +00:00
Action : func ( c * cli . Context ) error {
2023-05-11 11:30:17 +00:00
var version string
if c . String ( "version" ) != "" {
version = c . String ( "version" )
} else {
version = common . VERSION
}
2023-02-14 15:15:13 +00:00
2023-05-26 10:36:22 +00:00
json , err := schema . JSONSchema ( version )
2023-02-14 15:15:13 +00:00
if err != nil {
return err
}
fmt . Println ( json )
return nil
} ,
Usage : "Print out Kairos' Cloud Configuration JSON Schema" ,
Description : ` Prints out Kairos' Cloud Configuration JSON Schema ` ,
} ,
2023-05-16 16:06:49 +00:00
{
Name : "run-stage" ,
Description : "Run stage from cloud-init" ,
Usage : "Run stage from cloud-init" ,
UsageText : "run-stage STAGE" ,
Flags : [ ] cli . Flag {
& cli . BoolFlag {
Name : "strict" ,
Usage : "Enable strict mode. Fails and exits on stage errors" ,
} ,
2023-05-18 14:23:18 +00:00
& cli . StringSliceFlag {
Name : "cloud-init-paths" ,
Usage : "Extra paths to add to the run stage" ,
} ,
2023-05-16 16:06:49 +00:00
} ,
Before : func ( c * cli . Context ) error {
if c . Args ( ) . Len ( ) != 1 {
cli . HelpPrinter ( c . App . Writer , "Stage to run missing\n\n" , c . Command )
_ = cli . ShowSubcommandHelp ( c )
return fmt . Errorf ( "" )
}
2023-09-14 12:53:27 +00:00
return checkRoot ( )
2023-05-16 16:06:49 +00:00
} ,
Action : func ( c * cli . Context ) error {
stage := c . Args ( ) . First ( )
2023-07-25 13:21:34 +00:00
config , err := agentConfig . Scan ( collector . Directories ( configScanDir ... ) , collector . NoLogs )
config . Strict = c . Bool ( "strict" )
2023-05-16 16:06:49 +00:00
2023-05-18 14:23:18 +00:00
if len ( c . StringSlice ( "cloud-init-paths" ) ) > 0 {
2023-07-25 13:21:34 +00:00
config . CloudInitPaths = append ( config . CloudInitPaths , c . StringSlice ( "cloud-init-paths" ) ... )
2023-05-18 14:23:18 +00:00
}
2023-05-24 08:39:17 +00:00
if c . Bool ( "debug" ) {
2023-07-25 13:21:34 +00:00
config . Logger . SetLevel ( logrus . DebugLevel )
2023-05-24 08:39:17 +00:00
}
2023-05-18 14:23:18 +00:00
2023-05-16 16:06:49 +00:00
if err != nil {
2023-07-25 13:21:34 +00:00
config . Logger . Errorf ( "Error reading config: %s\n" , err )
2023-05-16 16:06:49 +00:00
}
2023-07-25 13:21:34 +00:00
return utils . RunStage ( config , stage )
2023-05-16 16:06:49 +00:00
} ,
} ,
2023-05-16 14:06:49 +00:00
{
Name : "pull-image" ,
Description : "Pull remote image to local file" ,
2023-05-16 16:06:49 +00:00
Usage : "Pull remote image to local file" ,
2023-05-16 14:06:49 +00:00
UsageText : "pull-image [-l] IMAGE TARGET" ,
Flags : [ ] cli . Flag {
& cli . StringFlag {
Name : "platform" ,
Usage : "Platform/arch to pull image from" ,
Value : fmt . Sprintf ( "%s/%s" , runtime . GOOS , runtime . GOARCH ) ,
} ,
} ,
Before : func ( c * cli . Context ) error {
if c . Args ( ) . Len ( ) != 2 {
cli . HelpPrinter ( c . App . Writer , "Either Image or target argument missing\n\n" , c . Command )
_ = cli . ShowSubcommandHelp ( c )
return fmt . Errorf ( "" )
}
2023-09-14 12:53:27 +00:00
return checkRoot ( )
2023-05-16 14:06:49 +00:00
} ,
Action : func ( c * cli . Context ) error {
image := c . Args ( ) . Get ( 0 )
destination , err := filepath . Abs ( c . Args ( ) . Get ( 1 ) )
if err != nil {
return fmt . Errorf ( "invalid path %s" , destination )
}
2023-07-25 13:21:34 +00:00
config , err := agentConfig . Scan ( collector . Directories ( configScanDir ... ) , collector . NoLogs )
2023-07-20 13:53:48 +00:00
if err != nil {
return err
}
2023-07-25 13:21:34 +00:00
config . Logger . Infof ( "Starting download and extraction for image %s to %s\n" , image , destination )
2023-05-16 14:06:49 +00:00
e := v1 . OCIImageExtractor { }
2023-06-21 07:39:59 +00:00
if err = e . ExtractImage ( image , destination , c . String ( "platform" ) ) ; err != nil {
2023-05-16 14:06:49 +00:00
return err
}
2023-07-25 13:21:34 +00:00
config . Logger . Infof ( "Image %s downloaded and extracted to %s correctly\n" , image , destination )
2023-05-16 14:06:49 +00:00
return nil
} ,
} ,
2023-06-05 10:40:23 +00:00
{
Name : "version" ,
Description : "Print kairos-agent version" ,
Usage : "Print kairos-agent version" ,
Flags : [ ] cli . Flag {
& cli . BoolFlag {
Name : "long" ,
Usage : "Print long version info" ,
Aliases : [ ] string { "l" } ,
} ,
} ,
Action : func ( c * cli . Context ) error {
if c . Bool ( "long" ) {
fmt . Printf ( "%+v\n" , common . Get ( ) )
} else {
fmt . Println ( common . VERSION )
}
return nil
} ,
} ,
2022-07-04 20:39:34 +00:00
}
func main ( ) {
bus . Manager . Initialize ( )
app := & cli . App {
2023-02-14 15:15:13 +00:00
Flags : [ ] cli . Flag {
& cli . BoolFlag {
Name : "strict-validation" ,
Usage : "Fail instead of warn on validation errors." ,
EnvVars : [ ] string { "STRICT_VALIDATIONS" } ,
} ,
2023-05-24 08:39:17 +00:00
& cli . BoolFlag {
Name : "debug" ,
Usage : "enable debug output" ,
EnvVars : [ ] string { "KAIROS_AGENT_DEBUG" } ,
} ,
2023-02-14 15:15:13 +00:00
} ,
2022-09-17 16:43:51 +00:00
Name : "kairos-agent" ,
2023-01-16 18:24:11 +00:00
Version : common . VERSION ,
2023-01-24 23:39:51 +00:00
Authors : [ ] * cli . Author {
{
Name : "Ettore Di Giacinto" ,
} ,
} ,
Usage : "kairos agent start" ,
2022-07-04 20:39:34 +00:00
Description : `
2022-09-17 16:43:51 +00:00
The kairos agent is a component to abstract away node ops , providing a common feature - set across kairos variants .
2022-07-04 20:39:34 +00:00
` ,
UsageText : ` ` ,
2022-09-17 16:43:51 +00:00
Copyright : "kairos authors" ,
2023-06-21 07:42:11 +00:00
Before : func ( c * cli . Context ) error {
// Set debug from here already, so it's loaded by the ReadConfigRun
viper . Set ( "debug" , c . Bool ( "debug" ) )
return nil
} ,
2022-08-11 11:31:00 +00:00
Commands : cmds ,
2022-07-04 20:39:34 +00:00
}
err := app . Run ( os . Args )
if err != nil {
fmt . Println ( err )
os . Exit ( 1 )
}
}
2023-09-14 12:53:27 +00:00
func checkRoot ( ) error {
if os . Geteuid ( ) != 0 {
return errors . New ( "this command requires root privileges" )
}
return nil
}
2023-09-26 14:09:24 +00:00
func validateSource ( source string ) error {
if source == "" {
return nil
}
r , err := regexp . Compile ( ` ^oci:|dir:|file: ` )
if err != nil {
return err
}
if ! r . MatchString ( source ) {
return fmt . Errorf ( "source %s does not match any of oci:, dir: or file: " , source )
}
return nil
}