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"` Tech string `json:"tech"`
TechVersion string `json:"tech_version"` TechVersion string `json:"tech_version"`
Password string `json:"password"` Password string `json:"password"`
ArchiveURL string `json:"archive_url"` // Archive with content of /srv
} `json:"setup,omitempty" gorm:"-"` } `json:"setup,omitempty" gorm:"-"`
} }

View File

@ -57,7 +57,7 @@ func (c *Container) getDriver() *Driver {
} }
// volumeHostPath each container has one volume mounted into it, // 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) 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 // DiskUsage returns number of bytes and inodes used by the container in it's mounted volume
func (c *Container) DiskUsage() (int, int, error) { 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 // 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( _, err := driver.Create(
c.App.Name, c.App.Name,
c.App.Image, c.App.Image,
c.volumeHostPath(), c.VolumeHostPath(),
c.App.HTTPPort, c.App.HTTPPort,
c.App.SSHPort, c.App.SSHPort,
c.App.CPU, c.App.CPU,
@ -586,7 +586,7 @@ func (c *Container) GetTechs() (apps.AppTechs, error) {
// Returns info about active technology // Returns info about active technology
func (c *Container) GetActiveTech() (*TechInfo, error) { 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 { if err != nil {
return info, err return info, err
} }

View File

@ -3,7 +3,11 @@ package glue
import ( import (
"errors" "errors"
"fmt" "fmt"
"io"
"log" "log"
"net/http"
"os"
"os/exec"
"strings" "strings"
"time" "time"
@ -200,6 +204,64 @@ func (p *Processor) Get(noUpdate bool) (apps.App, error) {
return app, nil 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 // Create creates a single app in the system
func (p *Processor) Create(appTemplate apps.App) error { func (p *Processor) Create(appTemplate apps.App) error {
if appTemplate.EnvRaw == nil { if appTemplate.EnvRaw == nil {
@ -219,6 +281,17 @@ func (p *Processor) Create(appTemplate apps.App) error {
AppsPath: p.AppsPath, 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() err = container.Create()
if err != nil { if err != nil {
return err return err