Add possibility to prepare /srv from an archive
This commit is contained in:
		
							parent
							
								
									0ad979b240
								
							
						
					
					
						commit
						9564118f40
					
				
					 3 changed files with 78 additions and 4 deletions
				
			
		|  | @ -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:"-"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
							
								
								
									
										73
									
								
								glue/main.go
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								glue/main.go
									
									
									
									
									
								
							|  | @ -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 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue