Add possibility to prepare /srv from an archive
All checks were successful
Unittests / unittests (push) Successful in 18s
Unittests / deploy-dev (push) Successful in 1m13s

This commit is contained in:
Adam Štrauch 2023-12-08 19:01:07 +01:00
parent 0ad979b240
commit 9564118f40
Signed by: cx
GPG Key ID: 7262DAFE292BCE20
3 changed files with 78 additions and 4 deletions

View File

@ -111,6 +111,7 @@ type App struct {
Tech string `json:"tech"`
TechVersion string `json:"tech_version"`
Password string `json:"password"`
ArchiveURL string `json:"archive_url"` // Archive with content of /srv
} `json:"setup,omitempty" gorm:"-"`
}

View File

@ -57,7 +57,7 @@ func (c *Container) getDriver() *Driver {
}
// volumeHostPath each container has one volume mounted into it,
func (c *Container) volumeHostPath() string {
func (c *Container) VolumeHostPath() string {
return path.Join(c.AppsPath, c.App.Name)
}
@ -132,7 +132,7 @@ func (c *Container) Status() (ContainerStatus, error) {
// DiskUsage returns number of bytes and inodes used by the container in it's mounted volume
func (c *Container) DiskUsage() (int, int, error) {
return du(c.volumeHostPath())
return du(c.VolumeHostPath())
}
// ResourceUsage returns amount of memory in B and CPU in % that the app occupies
@ -153,7 +153,7 @@ func (c *Container) Create() error {
_, err := driver.Create(
c.App.Name,
c.App.Image,
c.volumeHostPath(),
c.VolumeHostPath(),
c.App.HTTPPort,
c.App.SSHPort,
c.App.CPU,
@ -586,7 +586,7 @@ func (c *Container) GetTechs() (apps.AppTechs, error) {
// Returns info about active technology
func (c *Container) GetActiveTech() (*TechInfo, error) {
info, err := getTechAndVersion(path.Join(c.volumeHostPath(), "bin", "primary_tech"))
info, err := getTechAndVersion(path.Join(c.VolumeHostPath(), "bin", "primary_tech"))
if err != nil {
return info, err
}

View File

@ -3,7 +3,11 @@ package glue
import (
"errors"
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
"strings"
"time"
@ -200,6 +204,64 @@ func (p *Processor) Get(noUpdate bool) (apps.App, error) {
return app, nil
}
// Takes URL with an tar archive and prepares container's volume from it.
func (p *Processor) volumeFromURL(url string, container *docker.Container) error {
// Validation, check if url ends with tar.zstd
if !strings.HasSuffix(url, ".tar.zstd") {
return fmt.Errorf("archive has to end with .tar.zstd")
}
volumePath := container.VolumeHostPath()
// Prepare volume path
err := os.MkdirAll(volumePath, 0755)
if err != nil {
return fmt.Errorf("failed to create volume path: %v", err)
}
// Download the archive
log.Printf("%s: downloading archive from %s\n", container.App.Name, url)
f, err := os.Create(volumePath + "/archive.tar.zstd")
if err != nil {
return fmt.Errorf("failed to create archive file: %v", err)
}
defer f.Close()
resp, err := http.Get(url)
if err != nil {
return fmt.Errorf("failed to download archive: %v", err)
}
defer resp.Body.Close()
n, err := io.Copy(f, resp.Body)
if err != nil {
return fmt.Errorf("failed to download archive: %v", err)
}
log.Printf("downloaded %d bytes\n", n)
// Extract the archive
log.Printf("%s: extracting archive\n", container.App.Name)
// Call tar xf archive.tar.zstd -C /volume
cmd := exec.Command("tar", "-I", "zstd", "-xf", "archive.tar.zstd", "-C", volumePath)
err = cmd.Run()
if err != nil {
log.Printf("%s: failed to extract archive: %v", container.App.Name, err)
return err
}
// Remove archive
log.Printf("%s: removing archive\n", container.App.Name)
err = os.Remove(volumePath + "/archive.tar.zstd")
if err != nil {
return fmt.Errorf("failed to remove archive: %v", err)
}
log.Printf("%s: volume preparing done\n", container.App.Name)
return nil
}
// Create creates a single app in the system
func (p *Processor) Create(appTemplate apps.App) error {
if appTemplate.EnvRaw == nil {
@ -219,6 +281,17 @@ func (p *Processor) Create(appTemplate apps.App) error {
AppsPath: p.AppsPath,
}
if len(appTemplate.Snapshot) > 0 && len(appTemplate.Setup.ArchiveURL) > 0 {
return fmt.Errorf("snapshot and archive_url cannot be used together")
}
if len(appTemplate.Setup.ArchiveURL) > 0 {
err = p.volumeFromURL(appTemplate.Setup.ArchiveURL, &container)
if err != nil {
return fmt.Errorf("failed to prepare volume: %v", err)
}
}
err = container.Create()
if err != nil {
return err