-
Notifications
You must be signed in to change notification settings - Fork 0
/
pull.go
83 lines (78 loc) · 2.74 KB
/
pull.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package composectl
import (
"encoding/json"
"fmt"
"github.com/containerd/containerd/content/local"
"github.com/containerd/containerd/platforms"
"github.com/foundriesio/composeapp/pkg/compose"
v1 "github.com/foundriesio/composeapp/pkg/compose/v1"
"github.com/spf13/cobra"
"os"
"path"
)
var (
pullCmd = &cobra.Command{
Use: "pull <ref> [<ref>]",
Short: "",
Long: ``,
Args: cobra.MinimumNArgs(1),
Run: pullApps,
}
pullUsageWatermark *uint
pullSrcStorePath *string
pullPrintUsageStat *bool
exitCodeInsufficientSpace int = 100
)
func init() {
rootCmd.AddCommand(pullCmd)
pullUsageWatermark = pullCmd.Flags().UintP("storage-usage-watermark", "u", 80, "The maximum allowed storage usage in percentage")
pullSrcStorePath = pullCmd.Flags().StringP("source-store-path", "l", "", "A path to the source store root directory")
pullPrintUsageStat = pullCmd.Flags().BoolP("print-usage-stat", "p", false, "A flag to enable/disable usage statistic output to stderr")
}
func pullApps(cmd *cobra.Command, args []string) {
if len(args) > 1 {
fmt.Printf("Pulling %d apps to %s\n", len(args), config.StoreRoot)
} else {
fmt.Printf("Pulling %s to %s\n", args[0], config.StoreRoot)
}
cr, ui, apps := checkApps(cmd.Context(), args, *pullUsageWatermark, *pullSrcStorePath, false)
if len(cr.MissingBlobs) > 0 {
ui.Print()
if ui.Required > ui.Available {
if *pullPrintUsageStat {
if b, err := json.Marshal(ui); err == nil {
fmt.Fprintln(os.Stderr, string(b))
}
}
DieNotNilWithCode(fmt.Errorf("not enough storage available"), exitCodeInsufficientSpace)
}
cr.print()
fmt.Println("Pulling app blobs...")
// copying missing blobs
// TODO: move to a separate function:
// 1) Copy in multiple goroutines/workers (configurable)
// 2) Generic status reporting mechanism
authorizer := compose.NewRegistryAuthorizer(config.DockerCfg)
resolver := compose.NewResolver(authorizer)
ls, err := local.NewStore(config.StoreRoot)
DieNotNil(err)
for _, b := range cr.MissingBlobs {
fmt.Printf(" [%-15s] %s %15d ... ", b.Type, b.Descriptor.Digest.Encoded(), b.Descriptor.Size)
var copyErr error
if len(*pullSrcStorePath) > 0 {
blobPath := path.Join(*pullSrcStorePath, "blobs/sha256", b.Descriptor.Digest.Encoded())
copyErr = compose.CopyLocalBlob(cmd.Context(), blobPath, b.Descriptor.URLs[0], *b.Descriptor, ls, true)
} else {
copyErr = compose.CopyBlob(cmd.Context(), resolver, b.Descriptor.URLs[0], *b.Descriptor, ls, true)
}
DieNotNil(copyErr)
fmt.Println("ok")
}
}
cs, err := v1.NewAppStore(config.StoreRoot, config.Platform)
DieNotNil(err)
for _, app := range apps {
err = v1.MakeAkliteHappy(cmd.Context(), cs, app, platforms.OnlyStrict(config.Platform))
DieNotNil(err)
}
}