incus-mirror/cmd/incus/admin_init.go
Benjamin Somers 1d967dc872
incus: Modify argument order in flag helpers
This allows making default values optional where needed.

Signed-off-by: Benjamin Somers <benjamin.somers@imt-atlantique.fr>
2026-07-29 22:51:05 -04:00

159 lines
4.7 KiB
Go

//go:build linux
package main
import (
"errors"
"fmt"
"github.com/spf13/cobra"
incus "github.com/lxc/incus/v7/client"
"github.com/lxc/incus/v7/cmd/incus/color"
u "github.com/lxc/incus/v7/cmd/incus/usage"
"github.com/lxc/incus/v7/internal/i18n"
"github.com/lxc/incus/v7/internal/ports"
"github.com/lxc/incus/v7/shared/api"
cli "github.com/lxc/incus/v7/shared/cmd"
)
type cmdAdminInit struct {
global *cmdGlobal
flagAuto bool
flagMinimal bool
flagPreseed bool
flagDump bool
flagNetworkAddress string
flagNetworkPort int
flagStorageBackend string
flagStorageDevice string
flagStorageLoopSize int
flagStoragePool string
}
var cmdAdminInitUsage = u.Usage{u.Sequence(u.Flag("preseed"), u.Placeholder(i18n.G("preseed.yaml")).Optional()).Optional()}
func (c *cmdAdminInit) command() *cobra.Command {
cmd := &cobra.Command{}
cmd.Use = cli.U("init", cmdAdminInitUsage...)
cmd.Short = i18n.G("Configure the daemon")
cmd.Long = cli.FormatSection(color.DescriptionPrefix, i18n.G(`Configure the daemon`))
cmd.Example = ` init --minimal
init --auto [--network-address=IP] [--network-port=8443] [--storage-backend=dir]
[--storage-create-device=DEVICE] [--storage-create-loop=SIZE]
[--storage-pool=POOL]
init --preseed [preseed.yaml]
init --dump
`
cmd.RunE = c.run
cli.AddBoolFlag(cmd.Flags(), &c.flagAuto, "auto", i18n.G("Automatic (non-interactive) mode"))
cli.AddBoolFlag(cmd.Flags(), &c.flagMinimal, "minimal", i18n.G("Minimal configuration (non-interactive)"))
cli.AddBoolFlag(cmd.Flags(), &c.flagPreseed, "preseed", i18n.G("Pre-seed mode, expects YAML config from stdin"))
cli.AddBoolFlag(cmd.Flags(), &c.flagDump, "dump", i18n.G("Dump YAML config to stdout"))
cli.AddStringFlag(cmd.Flags(), &c.flagNetworkAddress, "network-address", "", "", i18n.G("Address to bind to (default: none)"))
cli.AddIntFlag(cmd.Flags(), &c.flagNetworkPort, "network-port", fmt.Sprintf(i18n.G("Port to bind to (default: %d)"), ports.HTTPSDefaultPort), -1)
cli.AddStringFlag(cmd.Flags(), &c.flagStorageBackend, "storage-backend", "", "", i18n.G("Storage backend to use (btrfs, dir, lvm or zfs, default: dir)"))
cli.AddStringFlag(cmd.Flags(), &c.flagStorageDevice, "storage-create-device", "", "", i18n.G("Setup device based storage using DEVICE"))
cli.AddIntFlag(cmd.Flags(), &c.flagStorageLoopSize, "storage-create-loop", i18n.G("Setup loop based storage with SIZE in GiB"), -1)
cli.AddStringFlag(cmd.Flags(), &c.flagStoragePool, "storage-pool", "", "", i18n.G("Storage pool to use or create"))
return cmd
}
func (c *cmdAdminInit) run(cmd *cobra.Command, args []string) error {
parsed, err := c.global.Parse(cmdAdminInitUsage, cmd, args)
if err != nil {
return err
}
// Quick checks.
if c.flagAuto && c.flagPreseed {
return errors.New(i18n.G("Can't use --auto and --preseed together"))
}
if c.flagMinimal && c.flagPreseed {
return errors.New(i18n.G("Can't use --minimal and --preseed together"))
}
if c.flagMinimal && c.flagAuto {
return errors.New(i18n.G("Can't use --minimal and --auto together"))
}
if !c.flagAuto && (c.flagNetworkAddress != "" || c.flagNetworkPort != -1 ||
c.flagStorageBackend != "" || c.flagStorageDevice != "" ||
c.flagStorageLoopSize != -1 || c.flagStoragePool != "") {
return errors.New(i18n.G("Configuration flags require --auto"))
}
if c.flagDump && (c.flagAuto || c.flagMinimal ||
c.flagPreseed || c.flagNetworkAddress != "" ||
c.flagNetworkPort != -1 || c.flagStorageBackend != "" ||
c.flagStorageDevice != "" || c.flagStorageLoopSize != -1 ||
c.flagStoragePool != "") {
return errors.New(i18n.G("Can't use --dump with other flags"))
}
// Connect to the daemon
d, err := incus.ConnectIncusUnix("", nil)
if err != nil {
return fmt.Errorf(i18n.G("Failed to connect to local daemon: %w"), err)
}
server, _, err := d.GetServer()
if err != nil {
return fmt.Errorf(i18n.G("Failed to connect to get server info: %w"), err)
}
// Dump mode
if c.flagDump {
err := c.runDump(d)
if err != nil {
return err
}
return nil
}
// Prepare the input data
var config *api.InitPreseed
switch {
case c.flagPreseed:
config, err = c.runPreseed(parsed[0].List[1])
if err != nil {
return err
}
case c.flagAuto || c.flagMinimal:
config, err = c.runAuto(d, server)
if err != nil {
return err
}
default:
config, err = c.runInteractive(cmd, d, server)
if err != nil {
return err
}
}
err = fillClusterConfig(config)
if err != nil {
return err
}
if config.Cluster != nil && config.Cluster.ClusterAddress != "" && config.Cluster.ServerAddress != "" {
err = updateCluster(d, config)
if err != nil {
return err
}
return nil
}
return d.ApplyServerPreseed(*config)
}