Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lima-vm
GitHub Repository: lima-vm/lima
Path: blob/master/cmd/limactl/prune.go
2614 views
1
// SPDX-FileCopyrightText: Copyright The Lima Authors
2
// SPDX-License-Identifier: Apache-2.0
3
4
package main
5
6
import (
7
"context"
8
"maps"
9
"os"
10
11
"github.com/sirupsen/logrus"
12
"github.com/spf13/cobra"
13
14
"github.com/lima-vm/lima/v2/pkg/downloader"
15
"github.com/lima-vm/lima/v2/pkg/driverutil"
16
"github.com/lima-vm/lima/v2/pkg/limatmpl"
17
"github.com/lima-vm/lima/v2/pkg/limatype"
18
"github.com/lima-vm/lima/v2/pkg/limayaml"
19
"github.com/lima-vm/lima/v2/pkg/store"
20
"github.com/lima-vm/lima/v2/pkg/templatestore"
21
)
22
23
func newPruneCommand() *cobra.Command {
24
pruneCommand := &cobra.Command{
25
Use: "prune",
26
Short: "Prune garbage objects",
27
Args: WrapArgsError(cobra.NoArgs),
28
RunE: pruneAction,
29
ValidArgsFunction: cobra.NoFileCompletions,
30
GroupID: advancedCommand,
31
}
32
pruneCommand.Flags().Bool("keep-referred", false, "Keep objects that are referred by some instances or templates")
33
return pruneCommand
34
}
35
36
func pruneAction(cmd *cobra.Command, _ []string) error {
37
ctx := cmd.Context()
38
keepReferred, err := cmd.Flags().GetBool("keep-referred")
39
if err != nil {
40
return err
41
}
42
opt := downloader.WithCache()
43
if !keepReferred {
44
return downloader.RemoveAllCacheDir(opt)
45
}
46
47
// Prune downloads that are not used by any instances or templates
48
cacheEntries, err := downloader.CacheEntries(opt)
49
if err != nil {
50
return err
51
}
52
knownLocations, err := knownLocations(ctx)
53
if err != nil {
54
return err
55
}
56
for cacheKey, cachePath := range cacheEntries {
57
if file, exists := knownLocations[cacheKey]; exists {
58
logrus.Debugf("Keep %q caching %q", cacheKey, file.Location)
59
} else {
60
logrus.Debug("Deleting ", cacheKey)
61
if err := os.RemoveAll(cachePath); err != nil {
62
logrus.Warnf("Failed to delete %q: %v", cacheKey, err)
63
return err
64
}
65
}
66
}
67
return nil
68
}
69
70
func knownLocations(ctx context.Context) (map[string]limatype.File, error) {
71
locations := make(map[string]limatype.File)
72
73
// Collect locations from instances
74
instances, err := store.Instances()
75
if err != nil {
76
return nil, err
77
}
78
for _, instanceName := range instances {
79
instance, err := store.Inspect(ctx, instanceName)
80
if err != nil {
81
return nil, err
82
}
83
if instance.Errors != nil {
84
logrus.Warnf("skipping instance %q because it has errors: %v", instanceName, instance.Errors)
85
continue
86
}
87
maps.Copy(locations, locationsFromLimaYAML(instance.Config))
88
}
89
90
// Collect locations from templates
91
templates, err := templatestore.Templates()
92
if err != nil {
93
return nil, err
94
}
95
for _, t := range templates {
96
tmpl, err := limatmpl.Read(ctx, "", t.Location)
97
if err != nil {
98
return nil, err
99
}
100
if err := tmpl.Embed(ctx, true, true); err != nil {
101
return nil, err
102
}
103
y, err := limayaml.Load(ctx, tmpl.Bytes, tmpl.Name)
104
if err != nil {
105
return nil, err
106
}
107
if err := driverutil.ResolveVMType(ctx, y, t.Name); err != nil {
108
logrus.Warnf("failed to resolve vmType for %q: %v", t.Name, err)
109
}
110
maps.Copy(locations, locationsFromLimaYAML(y))
111
}
112
return locations, nil
113
}
114
115
func locationsFromLimaYAML(y *limatype.LimaYAML) map[string]limatype.File {
116
locations := make(map[string]limatype.File)
117
for _, f := range y.Images {
118
locations[downloader.CacheKey(f.Location)] = f.File
119
if f.Kernel != nil {
120
locations[downloader.CacheKey(f.Kernel.Location)] = f.Kernel.File
121
}
122
if f.Initrd != nil {
123
locations[downloader.CacheKey(f.Initrd.Location)] = *f.Initrd
124
}
125
}
126
for _, f := range y.Containerd.Archives {
127
locations[downloader.CacheKey(f.Location)] = f
128
}
129
for _, f := range y.Firmware.Images {
130
locations[downloader.CacheKey(f.Location)] = f.File
131
}
132
return locations
133
}
134
135