Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lima-vm
GitHub Repository: lima-vm/lima
Path: blob/master/cmd/limactl/clone.go
1645 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
networks "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: cloneAction,
34
ValidArgsFunction: cloneBashComplete,
35
GroupID: advancedCommand,
36
}
37
editflags.RegisterEdit(cloneCommand, "[limactl edit] ")
38
return cloneCommand
39
}
40
41
func cloneAction(cmd *cobra.Command, args []string) error {
42
ctx := cmd.Context()
43
flags := cmd.Flags()
44
tty, err := flags.GetBool("tty")
45
if err != nil {
46
return err
47
}
48
49
oldInstName, newInstName := args[0], args[1]
50
oldInst, err := store.Inspect(ctx, oldInstName)
51
if err != nil {
52
if errors.Is(err, os.ErrNotExist) {
53
return fmt.Errorf("instance %q not found", oldInstName)
54
}
55
return err
56
}
57
58
newInst, err := instance.Clone(ctx, oldInst, newInstName)
59
if err != nil {
60
return err
61
}
62
63
yqExprs, err := editflags.YQExpressions(flags, false)
64
if err != nil {
65
return err
66
}
67
if len(yqExprs) > 0 {
68
// TODO: reduce duplicated codes across cloneAction and editAction
69
yq := yqutil.Join(yqExprs)
70
filePath := filepath.Join(newInst.Dir, filenames.LimaYAML)
71
yContent, err := os.ReadFile(filePath)
72
if err != nil {
73
return err
74
}
75
yBytes, err := yqutil.EvaluateExpression(yq, yContent)
76
if err != nil {
77
return err
78
}
79
y, err := limayaml.LoadWithWarnings(ctx, yBytes, filePath)
80
if err != nil {
81
return err
82
}
83
if err := driverutil.ResolveVMType(ctx, y, filePath); err != nil {
84
return fmt.Errorf("failed to resolve vm for %q: %w", filePath, err)
85
}
86
if err := limayaml.Validate(y, true); err != nil {
87
return saveRejectedYAML(yBytes, err)
88
}
89
if err := limayaml.ValidateAgainstLatestConfig(ctx, yBytes, yContent); err != nil {
90
return saveRejectedYAML(yBytes, err)
91
}
92
if err := os.WriteFile(filePath, yBytes, 0o644); err != nil {
93
return err
94
}
95
newInst, err = store.Inspect(ctx, newInst.Name)
96
if err != nil {
97
return err
98
}
99
}
100
101
if !tty {
102
// use "start" to start it
103
return nil
104
}
105
startNow, err := askWhetherToStart()
106
if err != nil {
107
return err
108
}
109
if !startNow {
110
return nil
111
}
112
err = networks.Reconcile(ctx, newInst.Name)
113
if err != nil {
114
return err
115
}
116
return instance.Start(ctx, newInst, "", false, false)
117
}
118
119
func cloneBashComplete(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
120
return bashCompleteInstanceNames(cmd)
121
}
122
123