diff --git a/cache/cache.go b/cache/cache.go new file mode 100644 index 0000000..33aab4d --- /dev/null +++ b/cache/cache.go @@ -0,0 +1,64 @@ +// Copyright 2023 Mikhail Klementev. All rights reserved. +// Use of this source code is governed by a AGPLv3 license +// (or later) that can be found in the LICENSE file. + +package cache + +import ( + "fmt" + "io/ioutil" + "net/url" + "os" + "os/exec" + + "github.com/cavaliergopher/grab/v3" + "github.com/rs/zerolog/log" + + "code.dumpstack.io/tools/out-of-tree/config" +) + +var URL string + +func unpackTar(archive, destination string) (err error) { + // NOTE: If you're change anything in tar command please check also + // BSD tar (or if you're using macOS, do not forget to check GNU Tar) + // Also make sure that sparse files are extracting correctly + cmd := exec.Command("tar", "-Sxf", archive) + cmd.Dir = destination + "/" + + log.Debug().Msgf("%v", cmd) + + rawOutput, err := cmd.CombinedOutput() + if err != nil { + err = fmt.Errorf("%v: %s", err, rawOutput) + return + } + + return +} + +func DownloadQemuImage(path, file string) (err error) { + tmp, err := ioutil.TempDir(config.Dir("tmp"), "out-of-tree_") + if err != nil { + return + } + defer os.RemoveAll(tmp) + + fileurl, err := url.JoinPath(URL, file+".tar.gz") + if err != nil { + return + } + + resp, err := grab.Get(tmp, fileurl) + if err != nil { + err = fmt.Errorf("Cannot download %s. It looks like you need "+ + "to generate it manually and place it "+ + "to ~/.out-of-tree/images/. "+ + "Check documentation for additional information.", + fileurl) + return + } + + err = unpackTar(resp.Filename, path) + return +} diff --git a/cache/cache_test.go b/cache/cache_test.go new file mode 100644 index 0000000..be11fbd --- /dev/null +++ b/cache/cache_test.go @@ -0,0 +1,31 @@ +package cache + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + "code.dumpstack.io/tools/out-of-tree/fs" +) + +func TestDownloadQemuImage(t *testing.T) { + + tmp, err := ioutil.TempDir("", "out-of-tree_") + if err != nil { + return + } + defer os.RemoveAll(tmp) + + URL = "https://out-of-tree.fra1.digitaloceanspaces.com/1.0.0/" + file := "out_of_tree_ubuntu_12__04.img" + + err = DownloadQemuImage(tmp, file) + if err != nil { + t.Fatal(err) + } + + if !fs.PathExists(filepath.Join(tmp, file)) { + t.Fatalf("%s does not exist", file) + } +} diff --git a/main.go b/main.go index ffc8cb8..b537788 100644 --- a/main.go +++ b/main.go @@ -22,6 +22,7 @@ import ( "github.com/alecthomas/kong" + "code.dumpstack.io/tools/out-of-tree/cache" "code.dumpstack.io/tools/out-of-tree/config" "code.dumpstack.io/tools/out-of-tree/container" "code.dumpstack.io/tools/out-of-tree/fs" @@ -31,6 +32,8 @@ type Globals struct { Config config.OutOfTree `help:"path to out-of-tree configuration" default:"~/.out-of-tree/out-of-tree.toml"` WorkDir string `help:"path to work directory" default:"./" type:"path"` + + CacheURL string `default:"https://out-of-tree.fra1.digitaloceanspaces.com/1.0.0/" hidden:""` } type CLI struct { @@ -192,6 +195,8 @@ func main() { } container.Runtime = cli.ContainerRuntime + cache.URL = cli.Globals.CacheURL + err = ctx.Run(&cli.Globals) ctx.FatalIfErrorf(err) }