Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lima-vm
GitHub Repository: lima-vm/lima
Path: blob/master/cmd/limactl/clone.go
2609 views
1
// SPDX-FileCopyrightText: Copyright The Lima Authors
2
// SPDX-License-Identifier: Apache-2.0
3
4
package main
5
6
import (
7
"errors"
8
"fmt"
9
"os"
10
"path/filepath"
11
12
"github.com/spf13/cobra"
13
14
"github.com/lima-vm/lima/v2/cmd/limactl/editflags"
15
"github.com/lima-vm/lima/v2/pkg/driverutil"
16
"github.com/lima-vm/lima/v2/pkg/instance"
17
"github.com/lima-vm/lima/v2/pkg/limatype/filenames"
18
"github.com/lima-vm/lima/v2/pkg/limayaml"
19
"github.com/lima-vm/lima/v2/pkg/networks/reconcile"
20
"github.com/lima-vm/lima/v2/pkg/store"
21
"github.com/lima-vm/lima/v2/pkg/yqutil"
22
)
23
24
func newCloneCommand() *cobra.Command {
25
cloneCommand := &cobra.Command{
26
Use: "clone OLDINST NEWINST",
27
Short: "Clone an instance of Lima",
28
Long: `Clone an instance of Lima.
29
30
Not to be confused with 'limactl copy' ('limactl cp').
31
`,
32
Args: WrapArgsError(cobra.ExactArgs(2)),
33
RunE: cloneOrRenameAction,
34
ValidArgsFunction: cloneBashComplete,
35
GroupID: advancedCommand,
36
}
37
cloneCommand.Flags().Bool("start", false, "Start the instance after cloning")
38
editflags.RegisterEdit(cloneCommand, "[limactl edit] ")
39
return cloneCommand
40
}
41
42
func newRenameCommand() *cobra.Command {
43
renameCommand := &cobra.Command{
44
Use: "rename OLDINST NEWINST",
45
// No "mv" alias, to avoid confusion with a theoretical equivalent of `limactl cp` but s/cp/mv/.
46
Short: "Rename an instance of Lima",
47
Args: WrapArgsError(cobra.ExactArgs(2)),
48
RunE: cloneOrRenameAction,
49
ValidArgsFunction: cloneBashComplete,
50
GroupID: advancedCommand,
51
}
52
renameCommand.Flags().Bool("start", false, "Start the instance after renaming")
53
editflags.RegisterEdit(renameCommand, "[limactl edit] ")
54
return renameCommand
55
}
56
57
func cloneOrRenameAction(cmd *cobra.Command, args []string) error {
58
rename := cmd.Name() == "rename"
59
ctx := cmd.Context()
60
flags := cmd.Flags()
61
tty, err := flags.GetBool("tty")
62
if err != nil {
63
return err
64
}
65
66
oldInstName, newInstName := args[0], args[1]
67
oldInst, err := store.Inspect(ctx, oldInstName)
68
if err != nil {
69
if errors.Is(err, os.ErrNotExist) {
70
return fmt.Errorf("instance %q not found", oldInstName)
71
}
72
return err
73
}
74
75
newInst, err := instance.CloneOrRename(ctx, oldInst, newInstName, rename)
76
if err != nil {
77
return err
78
}
79
80
yqExprs, err := editflags.YQExpressions(flags, false)
81
if err != nil {
82
return err
83
}
84
if len(yqExprs) > 0 {
85
// TODO: reduce duplicated codes across cloneAction and editAction
86
yq := yqutil.Join(yqExprs)
87
filePath := filepath.Join(newInst.Dir, filenames.LimaYAML)
88
yContent, err := os.ReadFile(filePath)
89
if err != nil {
90
return err
91
}
92
yBytes, err := yqutil.EvaluateExpression(yq, yContent)
93
if err != nil {
94
return err
95
}
96
y, err := limayaml.LoadWithWarnings(ctx, yBytes, filePath)
97
if err != nil {
98
return err
99
}
100
if err := driverutil.ResolveVMType(ctx, y, filePath); err != nil {
101
return fmt.Errorf("failed to resolve vm for %q: %w", filePath, err)
102
}
103
if err := limayaml.Validate(y, true); err != nil {
104
return saveRejectedYAML(yBytes, err)
105
}
106
if err := limayaml.ValidateAgainstLatestConfig(ctx, yBytes, yContent); err != nil {
107
return saveRejectedYAML(yBytes, err)
108
}
109
if err := os.WriteFile(filePath, yBytes, 0o644); err != nil {
110
return err
111
}
112
newInst, err = store.Inspect(ctx, newInst.Name)
113
if err != nil {
114
return err
115
}
116
}
117
118
start, err := flags.GetBool("start")
119
if err != nil {
120
return err
121
}
122
123
if tty && !flags.Changed("start") {
124
start, err = askWhetherToStart(cmd)
125
if err != nil {
126
return err
127
}
128
}
129
if !start {
130
return nil
131
}
132
err = reconcile.Reconcile(ctx, newInst.Name)
133
if err != nil {
134
return err
135
}
136
return instance.Start(ctx, newInst, false, false)
137
}
138
139
func cloneBashComplete(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
140
return bashCompleteInstanceNames(cmd)
141
}
142
143