2020-07-09 22:27:23 +00:00
|
|
|
package docker
|
|
|
|
|
|
|
|
import (
|
2020-07-11 21:14:45 +00:00
|
|
|
"log"
|
2020-07-09 22:27:23 +00:00
|
|
|
"path"
|
|
|
|
|
2020-07-13 22:01:42 +00:00
|
|
|
"github.com/rosti-cz/node-api/apps"
|
2020-07-09 22:27:23 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Container extends App struct from App
|
|
|
|
type Container struct {
|
2020-07-11 21:14:45 +00:00
|
|
|
App *apps.App `json:"app"`
|
2020-07-11 11:04:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Container) getDriver() *Driver {
|
|
|
|
driver := &Driver{}
|
|
|
|
return driver
|
2020-07-09 22:27:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// volumeHostPath each container has one volume mounted into it,
|
|
|
|
func (c *Container) volumeHostPath() string {
|
|
|
|
return path.Join("/srv", c.App.Name)
|
|
|
|
}
|
|
|
|
|
2020-07-25 22:34:16 +00:00
|
|
|
// GetRawResourceStats returns RAW CPU and memory usage directly from Docker API
|
|
|
|
func (c *Container) GetRawResourceStats() (int64, int, error) {
|
|
|
|
driver := c.getDriver()
|
|
|
|
cpu, memory, err := driver.RawStats(c.App.Name)
|
|
|
|
return cpu, memory, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetState returns app state object with populated state fields
|
2020-07-16 17:05:38 +00:00
|
|
|
func (c *Container) GetState() (*apps.AppState, error) {
|
2020-07-11 21:14:45 +00:00
|
|
|
status, err := c.Status()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-07-15 21:32:28 +00:00
|
|
|
cpu, memory, err := c.ResourceUsage()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2020-07-11 21:14:45 +00:00
|
|
|
}
|
|
|
|
|
2020-07-15 21:32:28 +00:00
|
|
|
bytes, inodes, err := c.DiskUsage()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
state := apps.AppState{
|
|
|
|
State: status,
|
|
|
|
CPUUsage: cpu,
|
|
|
|
MemoryUsage: memory,
|
|
|
|
DiskUsageBytes: bytes,
|
2020-07-16 17:05:38 +00:00
|
|
|
DiskUsageInodes: inodes,
|
2020-07-15 21:32:28 +00:00
|
|
|
}
|
2020-07-11 21:14:45 +00:00
|
|
|
|
2020-07-15 21:32:28 +00:00
|
|
|
return &state, nil
|
2020-07-11 21:14:45 +00:00
|
|
|
}
|
|
|
|
|
2020-07-09 22:27:23 +00:00
|
|
|
// Status returns state of the container
|
2020-07-11 21:14:45 +00:00
|
|
|
// Possible values: running, stopped, no-container, unknown
|
2020-07-09 22:27:23 +00:00
|
|
|
func (c *Container) Status() (string, error) {
|
2020-07-11 11:04:37 +00:00
|
|
|
status := "unknown"
|
|
|
|
|
|
|
|
// if _, err := os.Stat(path.Join("/srv", c.App.Name)); !os.IsNotExist(err) {
|
|
|
|
// status = "data-only"
|
|
|
|
// }
|
|
|
|
|
|
|
|
driver := c.getDriver()
|
|
|
|
containerStatus, err := driver.Status(c.App.Name)
|
2020-07-11 21:14:45 +00:00
|
|
|
if err != nil && err.Error() == "no container found" {
|
|
|
|
return "no-container", nil
|
|
|
|
}
|
2020-07-11 11:04:37 +00:00
|
|
|
if err != nil {
|
|
|
|
return status, err
|
|
|
|
}
|
|
|
|
|
2020-07-11 21:14:45 +00:00
|
|
|
status = containerStatus
|
2020-07-11 11:04:37 +00:00
|
|
|
|
|
|
|
return status, nil
|
2020-07-09 22:27:23 +00:00
|
|
|
}
|
|
|
|
|
2020-07-25 22:34:16 +00:00
|
|
|
// DiskUsage returns number of bytes and inodes used by the container in it's mounted volume
|
2020-07-11 11:04:37 +00:00
|
|
|
func (c *Container) DiskUsage() (int, int, error) {
|
2020-07-09 22:27:23 +00:00
|
|
|
return du(c.volumeHostPath())
|
|
|
|
}
|
|
|
|
|
2020-07-16 21:24:09 +00:00
|
|
|
// ResourceUsage returns amount of memory in B and CPU in % that the app occupies
|
2020-07-11 11:04:37 +00:00
|
|
|
func (c *Container) ResourceUsage() (float64, int, error) {
|
|
|
|
driver := c.getDriver()
|
|
|
|
|
|
|
|
cpu, memory, err := driver.Stats(c.App.Name)
|
|
|
|
if err != nil {
|
|
|
|
return 0.0, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return cpu, memory, nil
|
|
|
|
}
|
|
|
|
|
2020-07-09 22:27:23 +00:00
|
|
|
// Create creates the container
|
|
|
|
func (c *Container) Create() error {
|
2020-07-11 11:04:37 +00:00
|
|
|
driver := c.getDriver()
|
|
|
|
_, err := driver.Create(
|
|
|
|
c.App.Name,
|
|
|
|
c.App.Image,
|
|
|
|
c.volumeHostPath(),
|
|
|
|
c.App.HTTPPort,
|
|
|
|
c.App.SSHPort,
|
|
|
|
c.App.CPU,
|
|
|
|
c.App.Memory,
|
|
|
|
[]string{},
|
|
|
|
)
|
|
|
|
|
|
|
|
return err
|
2020-07-09 22:27:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Start starts the container
|
|
|
|
func (c *Container) Start() error {
|
2020-07-11 11:04:37 +00:00
|
|
|
driver := c.getDriver()
|
|
|
|
|
|
|
|
return driver.Start(c.App.Name)
|
2020-07-09 22:27:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Stop stops the container
|
|
|
|
func (c *Container) Stop() error {
|
2020-07-11 11:04:37 +00:00
|
|
|
driver := c.getDriver()
|
|
|
|
|
|
|
|
return driver.Stop(c.App.Name)
|
2020-07-09 22:27:23 +00:00
|
|
|
}
|
|
|
|
|
2020-07-11 11:04:37 +00:00
|
|
|
// Restart restarts the container
|
|
|
|
func (c *Container) Restart() error {
|
|
|
|
driver := c.getDriver()
|
|
|
|
|
|
|
|
err := driver.Stop(c.App.Name)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return driver.Start(c.App.Name)
|
2020-07-09 22:27:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Destroy removes the container but keeps the data so it can be created again
|
|
|
|
func (c *Container) Destroy() error {
|
2020-07-11 11:04:37 +00:00
|
|
|
driver := c.getDriver()
|
|
|
|
|
|
|
|
return driver.Remove(c.App.Name)
|
2020-07-09 22:27:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Delete removes both data and the container
|
|
|
|
func (c *Container) Delete() error {
|
2020-07-11 11:04:37 +00:00
|
|
|
err := c.Destroy()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
volumePath := path.Join("/srv", c.App.Name)
|
|
|
|
err = removeDirectory(volumePath)
|
2020-07-11 21:14:45 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
}
|
2020-07-11 11:04:37 +00:00
|
|
|
|
2020-07-11 21:14:45 +00:00
|
|
|
return nil
|
2020-07-09 22:27:23 +00:00
|
|
|
}
|