Skip to content

Commit 05c7ceb

Browse files
committed
update: add option to prune all unused images on complete
Add --prune-all-images to update complete. When used together with --prune, the complete flow can remove all container images not used by any container, instead of pruning only images related to apps being uninstalled. Propagate image prune mode through update completion and allow image pruning even when no apps are being removed. Signed-off-by: Mike Sul <mike.sul@foundries.io>
1 parent 4d1cd04 commit 05c7ceb

3 files changed

Lines changed: 60 additions & 41 deletions

File tree

cmd/composectl/cmd/update/complete.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
package updatectl
22

33
import (
4+
"github.com/foundriesio/composeapp/pkg/compose"
45
v1 "github.com/foundriesio/composeapp/pkg/compose/v1"
56
"github.com/foundriesio/composeapp/pkg/update"
67
"github.com/spf13/cobra"
78
)
89

910
type (
1011
completeOptions struct {
11-
Prune bool
12+
Prune bool
13+
PruneAllImages bool
1214
}
1315
)
1416

@@ -25,7 +27,10 @@ This will mark the update as successful after checking whether the update apps a
2527
opts := completeOptions{}
2628

2729
completeCmd.Flags().BoolVar(&opts.Prune, "prune", false,
28-
"Uninstall and remove the apps that are not included in the update.")
30+
"Uninstall and remove the apps that are not included in the update and images referenced by those apps")
31+
completeCmd.Flags().BoolVar(&opts.PruneAllImages, "prune-all-images", false,
32+
"Remove all unused images, even those that are not associated with the apps being uninstalled and pruned by the update complete process."+
33+
" This option is only effective when --prune is also specified.")
2934
completeCmd.Run = func(cmd *cobra.Command, args []string) {
3035
completeUpdateCmd(cmd, args, &opts)
3136
}
@@ -42,7 +47,11 @@ func completeUpdateCmd(cmd *cobra.Command, args []string, opts *completeOptions)
4247

4348
var options []update.CompleteOpt
4449
if opts.Prune {
45-
options = append(options, update.CompleteWithPruning())
50+
imagePruneType := compose.PruneTypeOnlyAppImages
51+
if opts.PruneAllImages {
52+
imagePruneType = compose.PruneTypeAllUnusedImages
53+
}
54+
options = append(options, update.CompleteWithPruning(imagePruneType))
4655
}
4756
err = updateCtl.Complete(cmd.Context(), options...)
4857
ExitIfNotNil(err)

pkg/compose/uninstall.go

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -41,47 +41,52 @@ func WithImagePruning(pruneType ...PruneType) UninstallOpt {
4141
}
4242

4343
func UninstallApps(ctx context.Context, cfg *Config, appRefs []string, options ...UninstallOpt) error {
44-
if len(appRefs) == 0 {
45-
return nil
46-
}
4744
opts := &UninstallOpts{}
4845
for _, o := range options {
4946
o(opts)
5047
}
51-
status, err := CheckAppsStatus(ctx, cfg, appRefs)
52-
if err != nil {
53-
return err
54-
}
55-
if status.AreRunning() {
56-
return ErrUninstallRunningApps
48+
if len(appRefs) == 0 && (!opts.Prune || opts.PruneType != PruneTypeAllUnusedImages) {
49+
return nil
5750
}
5851

59-
store, err := cfg.AppStoreFactory()
60-
if err != nil {
61-
return err
62-
}
63-
appInStoreRefs, err := store.ListApps(ctx)
64-
if err != nil {
65-
return err
66-
}
67-
appsInStore := make(map[string]int)
68-
for _, ref := range appInStoreRefs {
69-
appsInStore[ref.Name] += 1
70-
}
71-
for _, app := range status.Apps {
72-
if appsInStore[app.Name()] > 1 {
73-
// Multiple versions of the same app exist in the store.
74-
// If the version being removed is not installed, another version may still be
75-
// installed and using the same compose directory. In that case, keep the app
76-
// compose directory; otherwise we could remove compose files needed by the
77-
// other installed version.
78-
if _, isNotInstalled := status.NotInstalledCompose[app.Ref().Digest]; isNotInstalled {
79-
continue
80-
}
52+
var err error
53+
var status *AppsStatus
54+
if len(appRefs) > 0 {
55+
status, err = CheckAppsStatus(ctx, cfg, appRefs)
56+
if err != nil {
57+
return err
8158
}
82-
if err = os.RemoveAll(cfg.GetAppComposeDir(app.Name())); err != nil {
59+
if status.AreRunning() {
60+
return ErrUninstallRunningApps
61+
}
62+
63+
store, err := cfg.AppStoreFactory()
64+
if err != nil {
8365
return err
8466
}
67+
appInStoreRefs, err := store.ListApps(ctx)
68+
if err != nil {
69+
return err
70+
}
71+
appsInStore := make(map[string]int)
72+
for _, ref := range appInStoreRefs {
73+
appsInStore[ref.Name] += 1
74+
}
75+
for _, app := range status.Apps {
76+
if appsInStore[app.Name()] > 1 {
77+
// Multiple versions of the same app exist in the store.
78+
// If the version being removed is not installed, another version may still be
79+
// installed and using the same compose directory. In that case, keep the app
80+
// compose directory; otherwise we could remove compose files needed by the
81+
// other installed version.
82+
if _, isNotInstalled := status.NotInstalledCompose[app.Ref().Digest]; isNotInstalled {
83+
continue
84+
}
85+
}
86+
if err = os.RemoveAll(cfg.GetAppComposeDir(app.Name())); err != nil {
87+
return err
88+
}
89+
}
8590
}
8691

8792
if opts.Prune {

pkg/update/complete.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,20 @@ import (
1111

1212
type (
1313
CompleteOpts struct {
14-
Prune bool
15-
Force bool
14+
Prune bool
15+
ImagePruneType compose.PruneType
16+
Force bool
1617
}
1718
CompleteOpt func(*CompleteOpts)
1819
)
1920

20-
func CompleteWithPruning() CompleteOpt {
21+
func CompleteWithPruning(imagePruneType ...compose.PruneType) CompleteOpt {
2122
return func(opts *CompleteOpts) {
2223
opts.Prune = true
24+
opts.ImagePruneType = compose.PruneTypeOnlyAppImages
25+
if len(imagePruneType) > 0 {
26+
opts.ImagePruneType = imagePruneType[0]
27+
}
2328
}
2429
}
2530

@@ -93,10 +98,10 @@ func (u *runnerImpl) complete(ctx context.Context, options ...CompleteOpt) error
9398
appsToPrune = append(appsToPrune, app.Ref().String())
9499
}
95100
}
101+
if err := compose.UninstallApps(ctx, u.config, appsToPrune, compose.WithImagePruning(opts.ImagePruneType)); err != nil {
102+
return err
103+
}
96104
if len(appsToPrune) > 0 {
97-
if err := compose.UninstallApps(ctx, u.config, appsToPrune, compose.WithImagePruning()); err != nil {
98-
return err
99-
}
100105
if err := compose.RemoveApps(ctx, u.config, appsToPrune, compose.WithCheckStatus(false)); err != nil {
101106
return err
102107
}

0 commit comments

Comments
 (0)