refactor: Make --context cli flag a global option (#174)

* Make `--context` flag a global option and remove duplication

* Remove unused dns showOptions struct

* First pass of refactoring "active context" determination and validation

* Undo some refactoring in cli.go to keep diff more focused
This commit is contained in:
Justin Bradford
2025-11-19 20:30:32 +10:00
committed by GitHub
parent 1d413734d8
commit 939645e144
27 changed files with 55 additions and 175 deletions
-2
View File
@@ -74,8 +74,6 @@ to cluster machines or --push-registry to upload them to external registries.`,
"Use --machine to specify which machines. (default is all machines)")
cmd.Flags().BoolVar(&opts.PushRegistry, "push-registry", false,
"Upload the built images to external registries (e.g., Docker Hub) after building.")
cmd.Flags().StringVarP(&opts.Context, "context", "c", "",
"Name of the cluster context. (default is the current context)")
return cmd
}
+1 -6
View File
@@ -14,7 +14,6 @@ import (
type configOptions struct {
machine string
noColor bool
context string
}
func NewConfigCommand() *cobra.Command {
@@ -34,16 +33,12 @@ func NewConfigCommand() *cobra.Command {
"Name or ID of the machine to get the configuration from. (default is connected machine)")
cmd.Flags().BoolVar(&opts.noColor, "no-color", false,
"Disable syntax highlighting for the output.")
cmd.Flags().StringVarP(
&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)",
)
return cmd
}
func runConfig(ctx context.Context, uncli *cli.CLI, opts configOptions) error {
clusterClient, err := uncli.ConnectCluster(ctx, opts.context)
clusterClient, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+1 -6
View File
@@ -22,7 +22,6 @@ type deployOptions struct {
caddyfile string
image string
machines []string
context string
}
func NewDeployCommand() *cobra.Command {
@@ -46,10 +45,6 @@ func NewDeployCommand() *cobra.Command {
cmd.Flags().StringSliceVarP(&opts.machines, "machine", "m", nil,
"Machine names or IDs to deploy to. Can be specified multiple times or as a comma-separated "+
"list. (default is all machines)")
cmd.Flags().StringVarP(
&opts.context, "context", "c", "",
"Name of the cluster context to deploy to. (default is the current context)",
)
return cmd
}
@@ -64,7 +59,7 @@ func runDeploy(ctx context.Context, uncli *cli.CLI, opts deployOptions) error {
caddyfile = strings.TrimSpace(string(data))
}
clusterClient, err := uncli.ConnectCluster(ctx, opts.context)
clusterClient, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+1 -5
View File
@@ -26,8 +26,6 @@ type deployOptions struct {
noBuild bool
recreate bool
yes bool
context string
}
// NewDeployCommand creates a new command to deploy services from a Compose file.
@@ -51,8 +49,6 @@ func NewDeployCommand() *cobra.Command {
"Can be specified multiple times. Format: --build-arg VAR=VALUE")
cmd.Flags().BoolVar(&opts.BuildServicesOptions.Pull, "build-pull", false,
"Always attempt to pull newer versions of base images before building service images.")
cmd.Flags().StringVarP(&opts.context, "context", "c", "",
"Name of the cluster context to deploy to (default is the current context)")
cmd.Flags().StringSliceVarP(&opts.files, "file", "f", nil,
"One or more Compose files to deploy services from. (default compose.yaml)")
cmd.Flags().BoolVar(&opts.noBuild, "no-build", false,
@@ -108,7 +104,7 @@ func runDeploy(ctx context.Context, uncli *cli.CLI, opts deployOptions) error {
fmt.Println()
}
clusterClient, err := uncli.ConnectCluster(ctx, opts.context)
clusterClient, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+3 -14
View File
@@ -12,32 +12,21 @@ import (
"google.golang.org/protobuf/types/known/emptypb"
)
type releaseOptions struct {
context string
}
func NewReleaseCommand() *cobra.Command {
opts := releaseOptions{}
cmd := &cobra.Command{
Use: "release",
Short: "Release the reserved cluster domain.",
RunE: func(cmd *cobra.Command, args []string) error {
uncli := cmd.Context().Value("cli").(*cli.CLI)
return release(cmd.Context(), uncli, opts)
return release(cmd.Context(), uncli)
},
}
cmd.Flags().StringVarP(
&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)",
)
return cmd
}
func release(ctx context.Context, uncli *cli.CLI, opts releaseOptions) error {
client, err := uncli.ConnectCluster(ctx, opts.context)
func release(ctx context.Context, uncli *cli.CLI) error {
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+1 -6
View File
@@ -19,7 +19,6 @@ const DefaultUncloudDNSAPIEndpoint = "https://dns.uncloud.run/v1"
type reserveOptions struct {
endpoint string
context string
}
func NewReserveCommand() *cobra.Command {
@@ -36,16 +35,12 @@ func NewReserveCommand() *cobra.Command {
cmd.Flags().StringVar(&opts.endpoint, "endpoint", DefaultUncloudDNSAPIEndpoint,
"API endpoint for the Uncloud DNS service.")
cmd.Flags().StringVarP(
&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)",
)
return cmd
}
func reserve(ctx context.Context, uncli *cli.CLI, opts reserveOptions) error {
clusterClient, err := uncli.ConnectCluster(ctx, opts.context)
clusterClient, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+3 -14
View File
@@ -10,32 +10,21 @@ import (
"github.com/spf13/cobra"
)
type showOptions struct {
context string
}
func NewShowCommand() *cobra.Command {
opts := showOptions{}
cmd := &cobra.Command{
Use: "show",
Short: "Print the cluster domain name.",
RunE: func(cmd *cobra.Command, args []string) error {
uncli := cmd.Context().Value("cli").(*cli.CLI)
return show(cmd.Context(), uncli, opts)
return show(cmd.Context(), uncli)
},
}
cmd.Flags().StringVarP(
&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)",
)
return cmd
}
func show(ctx context.Context, uncli *cli.CLI, opts showOptions) error {
clusterClient, err := uncli.ConnectCluster(ctx, opts.context)
func show(ctx context.Context, uncli *cli.CLI) error {
clusterClient, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+1 -6
View File
@@ -22,7 +22,6 @@ import (
type listOptions struct {
machines []string
nameFilter string
context string
}
func NewListCommand() *cobra.Command {
@@ -60,10 +59,6 @@ func NewListCommand() *cobra.Command {
cmd.Flags().StringSliceVarP(&opts.machines, "machine", "m", nil,
"Filter images by machine name or ID. Can be specified multiple times or as a comma-separated list. "+
"(default is include all machines)")
cmd.Flags().StringVarP(
&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)",
)
return cmd
}
@@ -82,7 +77,7 @@ type imageRow struct {
}
func list(ctx context.Context, uncli *cli.CLI, opts listOptions) error {
clusterClient, err := uncli.ConnectCluster(ctx, opts.context)
clusterClient, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+1 -6
View File
@@ -15,7 +15,6 @@ type pushOptions struct {
image string
machines []string
platform string
context string
}
func NewPushCommand() *cobra.Command {
@@ -54,16 +53,12 @@ The image is uploaded to all cluster machines (default) or the specified machine
"Push a specific platform of a multi-platform image (e.g., linux/amd64, linux/arm64).\n"+
"Local Docker must be configured to use containerd image store to support multi-platform images.",
)
cmd.Flags().StringVarP(
&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)",
)
return cmd
}
func push(ctx context.Context, uncli *cli.CLI, opts pushOptions) error {
clusterClient, err := uncli.ConnectCluster(ctx, opts.context)
clusterClient, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
-6
View File
@@ -26,7 +26,6 @@ type addOptions struct {
noInstall bool
publicIP string
sshKey string
context string
version string
}
@@ -89,10 +88,6 @@ Connection methods:
&opts.version, "version", "latest",
"Version of the Uncloud daemon to install on the machine.",
)
cmd.Flags().StringVarP(
&opts.context, "context", "c", "",
"Name of the cluster context to add the machine to. (default is the current context)",
)
return cmd
}
@@ -113,7 +108,6 @@ func add(ctx context.Context, uncli *cli.CLI, remoteMachine *cli.RemoteMachine,
}
clusterClient, machineClient, err := uncli.AddMachine(ctx, cli.AddMachineOptions{
Context: opts.context,
MachineName: opts.name,
PublicIP: publicIP,
RemoteMachine: remoteMachine,
+3 -8
View File
@@ -14,25 +14,20 @@ import (
)
func NewListCommand() *cobra.Command {
var contextName string
cmd := &cobra.Command{
Use: "ls",
Aliases: []string{"list"},
Short: "List machines in a cluster.",
RunE: func(cmd *cobra.Command, args []string) error {
uncli := cmd.Context().Value("cli").(*cli.CLI)
return list(cmd.Context(), uncli, contextName)
return list(cmd.Context(), uncli)
},
}
cmd.Flags().StringVarP(
&contextName, "context", "c", "",
"Name of the cluster context. (default is the current context)",
)
return cmd
}
func list(ctx context.Context, uncli *cli.CLI, clusterName string) error {
client, err := uncli.ConnectCluster(ctx, clusterName)
func list(ctx context.Context, uncli *cli.CLI) error {
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+3 -8
View File
@@ -9,7 +9,6 @@ import (
)
func NewRenameCommand() *cobra.Command {
var contextName string
cmd := &cobra.Command{
Use: "rename OLD_NAME NEW_NAME",
Short: "Rename a machine in the cluster.",
@@ -20,18 +19,14 @@ configuration including network settings, public IP, and cluster membership.`,
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
uncli := cmd.Context().Value("cli").(*cli.CLI)
return rename(cmd.Context(), uncli, contextName, args[0], args[1])
return rename(cmd.Context(), uncli, args[0], args[1])
},
}
cmd.Flags().StringVarP(
&contextName, "context", "c", "",
"Name of the cluster context. (default is the current context)",
)
return cmd
}
func rename(ctx context.Context, uncli *cli.CLI, contextName, oldName, newName string) error {
client, err := uncli.ConnectCluster(ctx, contextName)
func rename(ctx context.Context, uncli *cli.CLI, oldName, newName string) error {
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return err
}
+1 -4
View File
@@ -22,7 +22,6 @@ import (
type removeOptions struct {
noReset bool
yes bool
context string
}
func NewRmCommand() *cobra.Command {
@@ -39,8 +38,6 @@ func NewRmCommand() *cobra.Command {
},
}
cmd.Flags().StringVarP(&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)")
cmd.Flags().BoolVarP(&opts.yes, "yes", "y", false,
"Do not prompt for confirmation before removing the machine.")
cmd.Flags().BoolVar(&opts.noReset, "no-reset", false,
@@ -51,7 +48,7 @@ func NewRmCommand() *cobra.Command {
func remove(ctx context.Context, uncli *cli.CLI, nameOrID string, opts removeOptions) error {
// TODO: automatically choose a connection to the machine that is not being removed.
client, err := uncli.ConnectCluster(ctx, opts.context)
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+1 -6
View File
@@ -13,7 +13,6 @@ import (
type updateOptions struct {
name string
publicIP string
context string
}
func NewUpdateCommand() *cobra.Command {
@@ -43,10 +42,6 @@ At least one flag must be specified to perform an update operation.`,
&opts.publicIP, "public-ip", "",
fmt.Sprintf("Public IP address of the machine for ingress configuration. Use '%s' or '' to remove the public IP.", PublicIPNone),
)
cmd.Flags().StringVarP(
&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)",
)
return cmd
}
@@ -57,7 +52,7 @@ func update(ctx context.Context, uncli *cli.CLI, cmd *cobra.Command, opts update
return fmt.Errorf("at least one update flag must be specified (--name, --public-ip)")
}
client, err := uncli.ConnectCluster(ctx, opts.context)
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return err
}
+5 -2
View File
@@ -24,6 +24,7 @@ import (
type globalOptions struct {
configPath string
connect string
context string
}
func main() {
@@ -39,6 +40,7 @@ func main() {
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
cli.BindEnvToFlag(cmd, "connect", "UNCLOUD_CONNECT")
cli.BindEnvToFlag(cmd, "uncloud-config", "UNCLOUD_CONFIG")
cli.BindEnvToFlag(cmd, "context", "UNCLOUD_CONTEXT")
var conn *config.MachineConnection
if opts.connect != "" {
@@ -67,7 +69,7 @@ func main() {
}
configPath := fs.ExpandHomeDir(opts.configPath)
uncli, err := cli.New(configPath, conn)
uncli, err := cli.New(configPath, conn, opts.context)
if err != nil {
return fmt.Errorf("initialise CLI: %w", err)
}
@@ -82,7 +84,8 @@ func main() {
cmd.PersistentFlags().StringVar(&opts.configPath, "uncloud-config", "~/.config/uncloud/config.yaml",
"Path to the Uncloud configuration file. [$UNCLOUD_CONFIG]")
_ = cmd.MarkPersistentFlagFilename("uncloud-config", "yaml", "yml")
// TODO: make --context a global flag and pass it as a value of the command context.
cmd.PersistentFlags().StringVarP(&opts.context, "context", "c", "",
"Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]")
cmd.AddCommand(
NewDeployCommand(),
+1 -5
View File
@@ -15,7 +15,6 @@ type execCliOptions struct {
detach bool
interactive bool
noTty bool
context string
containerId string
}
@@ -69,9 +68,6 @@ If the service has multiple replicas and no container ID is specified, the comma
execCmd.Flags().BoolP("tty", "t", false, "Allocate a pseudo-TTY")
execCmd.Flags().MarkHidden("tty")
execCmd.Flags().StringVarP(&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)")
// Common flags
execCmd.Flags().StringVar(&opts.containerId, "container", "",
"ID of the container to exec into. Accepts full ID or a unique prefix "+
@@ -95,7 +91,7 @@ func runExec(ctx context.Context, uncli *cli.CLI, serviceName string, command []
}
}
client, err := uncli.ConnectClusterWithOptions(ctx, opts.context, cli.ConnectOptions{
client, err := uncli.ConnectClusterWithOptions(ctx, cli.ConnectOptions{
ShowProgress: false,
})
if err != nil {
+1 -6
View File
@@ -15,7 +15,6 @@ import (
type inspectOptions struct {
service string
context string
}
func NewInspectCommand() *cobra.Command {
@@ -30,15 +29,11 @@ func NewInspectCommand() *cobra.Command {
return inspect(cmd.Context(), uncli, opts)
},
}
cmd.Flags().StringVarP(
&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)",
)
return cmd
}
func inspect(ctx context.Context, uncli *cli.CLI, opts inspectOptions) error {
client, err := uncli.ConnectCluster(ctx, opts.context)
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+3 -8
View File
@@ -12,25 +12,20 @@ import (
)
func NewListCommand() *cobra.Command {
var contextName string
cmd := &cobra.Command{
Use: "ls",
Aliases: []string{"list"},
Short: "List services.",
RunE: func(cmd *cobra.Command, args []string) error {
uncli := cmd.Context().Value("cli").(*cli.CLI)
return list(cmd.Context(), uncli, contextName)
return list(cmd.Context(), uncli)
},
}
cmd.Flags().StringVarP(
&contextName, "context", "c", "",
"Name of the cluster context. (default is the current context)",
)
return cmd
}
func list(ctx context.Context, uncli *cli.CLI, contextName string) error {
client, err := uncli.ConnectCluster(ctx, contextName)
func list(ctx context.Context, uncli *cli.CLI) error {
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+1 -6
View File
@@ -11,7 +11,6 @@ import (
type rmOptions struct {
services []string
context string
}
func NewRmCommand() *cobra.Command {
@@ -27,15 +26,11 @@ func NewRmCommand() *cobra.Command {
return rm(cmd.Context(), uncli, opts)
},
}
cmd.Flags().StringVarP(
&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)",
)
return cmd
}
func rm(ctx context.Context, uncli *cli.CLI, opts rmOptions) error {
client, err := uncli.ConnectCluster(ctx, opts.context)
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+1 -8
View File
@@ -34,8 +34,6 @@ type runOptions struct {
replicas uint
user string
volumes []string
context string
}
func NewRunCommand() *cobra.Command {
@@ -112,11 +110,6 @@ func NewRunCommand() *cobra.Command {
" -v /data/uploads:/app/uploads Bind mount /data/uploads host directory to /app/uploads in container\n"+
" -v /host/path:/container/path:ro Bind mount a host directory or file as read-only")
cmd.Flags().StringVarP(
&opts.context, "context", "c", "",
"Name of the cluster context to run the service in. (default is the current context)",
)
return cmd
}
@@ -126,7 +119,7 @@ func run(ctx context.Context, uncli *cli.CLI, opts runOptions) error {
return err
}
clusterClient, err := uncli.ConnectCluster(ctx, opts.context)
clusterClient, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+1 -7
View File
@@ -15,7 +15,6 @@ import (
type scaleOptions struct {
service string
replicas uint
context string
}
func NewScaleCommand() *cobra.Command {
@@ -39,11 +38,6 @@ func NewScaleCommand() *cobra.Command {
},
}
cmd.Flags().StringVarP(
&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)",
)
return cmd
}
@@ -57,7 +51,7 @@ func scale(ctx context.Context, uncli *cli.CLI, opts scaleOptions) error {
)
}
clusterClient, err := uncli.ConnectCluster(ctx, opts.context)
clusterClient, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+1 -4
View File
@@ -19,7 +19,6 @@ type createOptions struct {
driverOpts []string
labels []string
machine string
context string
}
func NewCreateCommand() *cobra.Command {
@@ -50,14 +49,12 @@ func NewCreateCommand() *cobra.Command {
"Labels to assign to the volume in the form of 'key=value' pairs. Can be specified multiple times.")
cmd.Flags().StringVarP(&opts.machine, "machine", "m", "",
"Name or ID of the machine to create the volume on.")
cmd.Flags().StringVarP(&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)")
return cmd
}
func create(ctx context.Context, uncli *cli.CLI, name string, opts createOptions) error {
client, err := uncli.ConnectCluster(ctx, opts.context)
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+1 -4
View File
@@ -13,7 +13,6 @@ import (
type inspectOptions struct {
machine string
context string
}
func NewInspectCommand() *cobra.Command {
@@ -32,14 +31,12 @@ func NewInspectCommand() *cobra.Command {
cmd.Flags().StringVarP(&opts.machine, "machine", "m", "",
"Name or ID of the machine where the volume is located. "+
"If not specified, the volume will be searched across all machines.")
cmd.Flags().StringVarP(&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)")
return cmd
}
func inspect(ctx context.Context, uncli *cli.CLI, name string, opts inspectOptions) error {
client, err := uncli.ConnectCluster(ctx, opts.context)
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+1 -5
View File
@@ -16,7 +16,6 @@ import (
type listOptions struct {
machines []string
quiet bool
context string
}
func NewListCommand() *cobra.Command {
@@ -38,14 +37,11 @@ func NewListCommand() *cobra.Command {
cmd.Flags().BoolVarP(&opts.quiet, "quiet", "q", false,
"Only display volume names.")
cmd.Flags().StringVarP(&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)")
return cmd
}
func list(ctx context.Context, uncli *cli.CLI, opts listOptions) error {
client, err := uncli.ConnectCluster(ctx, opts.context)
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+1 -5
View File
@@ -14,7 +14,6 @@ type removeOptions struct {
force bool
machines []string
yes bool
context string
}
func NewRemoveCommand() *cobra.Command {
@@ -41,14 +40,11 @@ func NewRemoveCommand() *cobra.Command {
cmd.Flags().BoolVarP(&opts.yes, "yes", "y", false,
"Do not prompt for confirmation before removing the volume(s).")
cmd.Flags().StringVarP(&opts.context, "context", "c", "",
"Name of the cluster context. (default is the current context)")
return cmd
}
func remove(ctx context.Context, uncli *cli.CLI, names []string, opts removeOptions) error {
client, err := uncli.ConnectCluster(ctx, opts.context)
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+1 -3
View File
@@ -40,8 +40,6 @@ type BuildServicesOptions struct {
PushRegistry bool
// Cluster-specific options (only used if PushCluster is true).
// Context is the name of the cluster context.
Context string
// Machines is a list of machine names or IDs to push the image to. If empty, images are pushed to all machines.
Machines []string
}
@@ -95,7 +93,7 @@ func (cli *CLI) BuildServices(ctx context.Context, project *composetypes.Project
// Add a line break after the build output.
fmt.Fprintln(cli.ProgressOut())
clusterClient, err := cli.ConnectCluster(ctx, opts.Context)
clusterClient, err := cli.ConnectCluster(ctx)
if err != nil {
return fmt.Errorf("connect to cluster: %w", err)
}
+17 -15
View File
@@ -28,14 +28,16 @@ const (
)
type CLI struct {
Config *config.Config
conn *config.MachineConnection
Config *config.Config
conn *config.MachineConnection
contextOverride string
}
// New creates a new CLI instance with the given config path or remote machine connection.
// If the connection is provided, the config is ignored for all operations which is useful for interacting with
// a cluster without creating a config.
func New(configPath string, conn *config.MachineConnection) (*CLI, error) {
// If a non-empty context name is given, it will override the current default.
func New(configPath string, conn *config.MachineConnection, contextName string) (*CLI, error) {
if conn != nil {
return &CLI{conn: conn}, nil
}
@@ -46,7 +48,8 @@ func New(configPath string, conn *config.MachineConnection) (*CLI, error) {
}
return &CLI{
Config: cfg,
Config: cfg,
contextOverride: contextName,
}, nil
}
@@ -68,19 +71,20 @@ func (cli *CLI) SetCurrentContext(name string) error {
return cli.Config.Save()
}
// ConnectCluster connects to a cluster using the given context name or the current context if not specified.
// ConnectCluster connects to a cluster using the context override or the current context if not specified.
// If the CLI was initialised with a machine connection, the config is ignored and the connection is used instead.
func (cli *CLI) ConnectCluster(ctx context.Context, contextName string) (*client.Client, error) {
return cli.ConnectClusterWithOptions(ctx, contextName, ConnectOptions{
func (cli *CLI) ConnectCluster(ctx context.Context) (*client.Client, error) {
return cli.ConnectClusterWithOptions(ctx, ConnectOptions{
// Default to showing progress for CLI usage.
ShowProgress: true,
})
}
// ConnectClusterWithOptions connects to a cluster using the given context name and options.
// ConnectClusterWithOptions connects to a cluster with the given options.
// If the CLI was initialised with a machine connection, the config is ignored and the connection is used instead.
// If the CLI has an override context, it is used instead of the current default.
// Options are useful when using the CLI as a library where you may want to disable visual feedback.
func (cli *CLI) ConnectClusterWithOptions(ctx context.Context, contextName string, opts ConnectOptions) (*client.Client, error) {
func (cli *CLI) ConnectClusterWithOptions(ctx context.Context, opts ConnectOptions) (*client.Client, error) {
if cli.conn != nil {
return ConnectCluster(ctx, *cli.conn, opts)
}
@@ -92,6 +96,8 @@ func (cli *CLI) ConnectClusterWithOptions(ctx context.Context, contextName strin
cli.Config.Path(),
)
}
contextName := cli.contextOverride
if contextName == "" {
// If the cluster is not specified, use the current cluster if set.
if cli.Config.CurrentContext == "" {
@@ -269,7 +275,6 @@ func (cli *CLI) newContextName(name string) (string, error) {
}
type AddMachineOptions struct {
Context string
MachineName string
PublicIP *netip.Addr
RemoteMachine *RemoteMachine
@@ -282,11 +287,11 @@ type AddMachineOptions struct {
// cluster. The machine client is connected to the new machine and can be used to interact with it.
// Both client should be closed after use by the caller.
func (cli *CLI) AddMachine(ctx context.Context, opts AddMachineOptions) (*client.Client, *client.Client, error) {
contextName := opts.Context
contextName := cli.contextOverride
if contextName == "" {
contextName = cli.Config.CurrentContext
}
c, err := cli.ConnectCluster(ctx, contextName)
c, err := cli.ConnectCluster(ctx)
if err != nil {
return nil, nil, fmt.Errorf("connect to cluster (context '%s'): %w", contextName, err)
}
@@ -407,9 +412,6 @@ func (cli *CLI) AddMachine(ctx context.Context, opts AddMachineOptions) (*client
} else {
connCfg.SSH = config.NewSSHDestination(opts.RemoteMachine.User, opts.RemoteMachine.Host, opts.RemoteMachine.Port)
}
if contextName == "" {
contextName = cli.Config.CurrentContext
}
cli.Config.Contexts[contextName].Connections = append(cli.Config.Contexts[contextName].Connections, connCfg)
if err = cli.Config.Save(); err != nil {
return nil, nil, fmt.Errorf("save config: %w", err)