Rest of the endpoints finished
This commit is contained in:
		
							parent
							
								
									0181236e23
								
							
						
					
					
						commit
						4f9dac7f5c
					
				
					 5 changed files with 208 additions and 39 deletions
				
			
		
							
								
								
									
										32
									
								
								api.http
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								api.http
									
									
									
									
									
								
							|  | @ -3,8 +3,8 @@ Content-type: application/json | ||||||
| 
 | 
 | ||||||
| { | { | ||||||
|     "name": "test_1234", |     "name": "test_1234", | ||||||
|     "ssh_port": 10000, |     "ssh_port": 46500, | ||||||
|     "http_port": 10001, |     "http_port": 46501, | ||||||
|     "image": "docker.io/rosti/runtime:2020.04-1", |     "image": "docker.io/rosti/runtime:2020.04-1", | ||||||
|     "cpu": 100, |     "cpu": 100, | ||||||
|     "memory": 128000 |     "memory": 128000 | ||||||
|  | @ -16,8 +16,8 @@ PUT http://localhost:1323/v1/apps/test_1234 | ||||||
| Content-type: application/json | Content-type: application/json | ||||||
| 
 | 
 | ||||||
| { | { | ||||||
|     "ssh_port": 36500, |     "ssh_port": 46500, | ||||||
|     "http_port": 36501 |     "http_port": 46501 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -25,3 +25,27 @@ Content-type: application/json | ||||||
| 
 | 
 | ||||||
| PUT http://localhost:1323/v1/apps/test_1234/start | PUT http://localhost:1323/v1/apps/test_1234/start | ||||||
| Content-type: application/json | Content-type: application/json | ||||||
|  | 
 | ||||||
|  | ### | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | PUT http://localhost:1323/v1/apps/test_1234/stop | ||||||
|  | Content-type: application/json | ||||||
|  | 
 | ||||||
|  | ### | ||||||
|  | 
 | ||||||
|  | DELETE http://localhost:1323/v1/apps/test_1234 | ||||||
|  | Content-type: application/json | ||||||
|  | 
 | ||||||
|  | ### | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | GET http://localhost:1323/v1/apps/test_1234/stats | ||||||
|  | Content-type: application/json | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ### | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | GET http://localhost:1323/v1/apps | ||||||
|  | Content-type: application/json | ||||||
|  |  | ||||||
|  | @ -23,6 +23,13 @@ type Label struct { | ||||||
| 	Value string `json:"value"` | 	Value string `json:"value"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // AppState contains info about runnint application, it's not saved in the database
 | ||||||
|  | type AppState struct { | ||||||
|  | 	State       string `json:"state"` | ||||||
|  | 	CPUUsage    int    `json:"cpu_usage"` | ||||||
|  | 	MemoryUsage int    `json:"memory_usage"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // App keeps info about hosted application
 | // App keeps info about hosted application
 | ||||||
| type App struct { | type App struct { | ||||||
| 	gorm.Model | 	gorm.Model | ||||||
|  | @ -34,6 +41,8 @@ type App struct { | ||||||
| 	CPU      int    `json:"cpu"`    // percentage, 200 means two CPU
 | 	CPU      int    `json:"cpu"`    // percentage, 200 means two CPU
 | ||||||
| 	Memory   int    `json:"memory"` // Limit in MB
 | 	Memory   int    `json:"memory"` // Limit in MB
 | ||||||
| 	// Labels   []Label `json:"labels"` // username:cx or user_id:1
 | 	// Labels   []Label `json:"labels"` // username:cx or user_id:1
 | ||||||
|  | 
 | ||||||
|  | 	State AppState `json:"state" gorm:"-"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Validate do basic checks of the struct values
 | // Validate do basic checks of the struct values
 | ||||||
|  |  | ||||||
|  | @ -7,7 +7,6 @@ import ( | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"log" | 	"log" | ||||||
| 	"os" | 	"os" | ||||||
| 	"strconv" |  | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | @ -25,7 +24,7 @@ const dockerTimeout = 10 | ||||||
| const dockerSock = "unix:///var/run/docker.sock" | const dockerSock = "unix:///var/run/docker.sock" | ||||||
| 
 | 
 | ||||||
| // DOCKER_API_VERSION set API version of Docker, 1.40 belongs to Docker 19.03.11
 | // DOCKER_API_VERSION set API version of Docker, 1.40 belongs to Docker 19.03.11
 | ||||||
| const dockerAPIVersion = "1.40" | const dockerAPIVersion = "1.24" | ||||||
| 
 | 
 | ||||||
| // Driver keeps everything for connection to Docker
 | // Driver keeps everything for connection to Docker
 | ||||||
| type Driver struct{} | type Driver struct{} | ||||||
|  | @ -76,8 +75,10 @@ func (d *Driver) Status(name string) (string, error) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	containerID, err := d.nameToID(name) | 	containerID, err := d.nameToID(name) | ||||||
|  | 	if err != nil && err.Error() == "no container found" { | ||||||
|  | 		return "no-container", err | ||||||
|  | 	} | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		status = "no-container" |  | ||||||
| 		return status, err | 		return status, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -117,7 +118,9 @@ func (d *Driver) Stats(name string) (float64, int, error) { | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return 0.0, 0, err | 		return 0.0, 0, err | ||||||
| 	} | 	} | ||||||
| 	log.Println(data) | 	// It returns one JSON:
 | ||||||
|  | 	// {"read":"2020-07-11T20:42:31.486726241Z","preread":"2020-07-11T20:42:30.484048602Z","pids_stats":{"current":7},"blkio_stats":{"io_service_bytes_recursive":[{"major":253,"minor":0,"op":"Read","value":0},{"major":253,"minor":0,"op":"Write","value":20480},{"major":253,"minor":0,"op":"Sync","value":12288},{"major":253,"minor":0,"op":"Async","value":8192},{"major":253,"minor":0,"op":"Discard","value":0},{"major":253,"minor":0,"op":"Total","value":20480}],"io_serviced_recursive":[{"major":253,"minor":0,"op":"Read","value":0},{"major":253,"minor":0,"op":"Write","value":5},{"major":253,"minor":0,"op":"Sync","value":3},{"major":253,"minor":0,"op":"Async","value":2},{"major":253,"minor":0,"op":"Discard","value":0},{"major":253,"minor":0,"op":"Total","value":5}],"io_queue_recursive":[],"io_service_time_recursive":[],"io_wait_time_recursive":[],"io_merged_recursive":[],"io_time_recursive":[],"sectors_recursive":[]},"num_procs":0,"storage_stats":{},"cpu_stats":{"cpu_usage":{"total_usage":758392753,"percpu_usage":[302688474,0,11507116,124238500,222136766,5656446,3009320,0,19406386,1397028,6201423,62151294,0,0,0,0],"usage_in_kernelmode":100000000,"usage_in_usermode":640000000},"system_cpu_usage":119385810000000,"online_cpus":12,"throttling_data":{"periods":21,"throttled_periods":1,"throttled_time":2995938}},"precpu_stats":{"cpu_usage":{"total_usage":758282347,"percpu_usage":[302688474,0,11507116,124238500,222026360,5656446,3009320,0,19406386,1397028,6201423,62151294,0,0,0,0],"usage_in_kernelmode":100000000,"usage_in_usermode":640000000},"system_cpu_usage":119373720000000,"online_cpus":12,"throttling_data":{"periods":21,"throttled_periods":1,"throttled_time":2995938}},"memory_stats":{"usage":21626880,"max_usage":22630400,"stats":{"active_anon":15949824,"active_file":0,"cache":0,"dirty":0,"hierarchical_memory_limit":144179200,"hierarchical_memsw_limit":288358400,"inactive_anon":0,"inactive_file":0,"mapped_file":0,"pgfault":13167,"pgmajfault":0,"pgpgin":7293,"pgpgout":3406,"rss":15900672,"rss_huge":0,"total_active_anon":15949824,"total_active_file":0,"total_cache":0,"total_dirty":0,"total_inactive_anon":0,"total_inactive_file":0,"total_mapped_file":0,"total_pgfault":13167,"total_pgmajfault":0,"total_pgpgin":7293,"total_pgpgout":3406,"total_rss":15900672,"total_rss_huge":0,"total_unevictable":0,"total_writeback":0,"unevictable":0,"writeback":0},"limit":144179200},"name":"/test_1234","id":"576878d645efecc8e5e2a57b88351f7b5c551e3fc72dc8473fd965d10dfddbec","networks":{"eth0":{"rx_bytes":6150,"rx_packets":37,"rx_errors":0,"rx_dropped":0,"tx_bytes":0,"tx_packets":0,"tx_errors":0,"tx_dropped":0}}}
 | ||||||
|  | 	log.Println(string(data)) | ||||||
| 
 | 
 | ||||||
| 	return 0.0, 0, nil | 	return 0.0, 0, nil | ||||||
| } | } | ||||||
|  | @ -248,24 +251,26 @@ func (d *Driver) Create(name string, image string, volumePath string, HTTPPort i | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	portmaps := make(nat.PortMap, 1) | 	portmaps := nat.PortMap{} | ||||||
| 
 | 
 | ||||||
| 	portbindingsHTTP := make([]nat.PortBinding, 1) | 	// portbindingsHTTP := make([]nat.PortBinding, 1)
 | ||||||
| 	portbindingsHTTP[0] = nat.PortBinding{ | 	// portbindingsHTTP[0] = nat.PortBinding{
 | ||||||
| 		HostPort: strconv.Itoa(HTTPPort) + "/tcp", | 	// 	HostIP:   "0.0.0.0",
 | ||||||
| 	} | 	// 	HostPort: strconv.Itoa(HTTPPort) + "/tcp",
 | ||||||
| 	portmaps["8000/tcp"] = portbindingsHTTP | 	// }
 | ||||||
|  | 	// portmaps["8000/tcp"] = portbindingsHTTP
 | ||||||
| 
 | 
 | ||||||
| 	if SSHPort != 0 { | 	// if SSHPort != 0 {
 | ||||||
| 		portbindingsSSH := make([]nat.PortBinding, 1) | 	// 	portbindingsSSH := make([]nat.PortBinding, 1)
 | ||||||
| 		portbindingsSSH[0] = nat.PortBinding{ | 	// 	portbindingsSSH[0] = nat.PortBinding{
 | ||||||
| 			HostPort: strconv.Itoa(SSHPort) + "/tcp", | 	// 		HostIP:   "0.0.0.0",
 | ||||||
| 		} | 	// 		HostPort: strconv.Itoa(SSHPort) + "/tcp",
 | ||||||
| 		portmaps["22/tcp"] = portbindingsSSH | 	// 	}
 | ||||||
| 	} | 	// 	portmaps["22/tcp"] = portbindingsSSH
 | ||||||
|  | 	// }
 | ||||||
| 
 | 
 | ||||||
| 	createdContainer, err := cli.ContainerCreate( | 	createdContainer, err := cli.ContainerCreate( | ||||||
| 		context.TODO(), | 		context.Background(), | ||||||
| 		&container.Config{ | 		&container.Config{ | ||||||
| 			Hostname: name, | 			Hostname: name, | ||||||
| 			Env:      []string{}, | 			Env:      []string{}, | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| package docker | package docker | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"log" | ||||||
| 	"path" | 	"path" | ||||||
| 
 | 
 | ||||||
| 	"github.com/rosti-cz/apps-api/apps" | 	"github.com/rosti-cz/apps-api/apps" | ||||||
|  | @ -8,7 +9,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| // Container extends App struct from App
 | // Container extends App struct from App
 | ||||||
| type Container struct { | type Container struct { | ||||||
| 	App apps.App `json:"app"` | 	App *apps.App `json:"app"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *Container) getDriver() *Driver { | func (c *Container) getDriver() *Driver { | ||||||
|  | @ -21,8 +22,26 @@ func (c *Container) volumeHostPath() string { | ||||||
| 	return path.Join("/srv", c.App.Name) | 	return path.Join("/srv", c.App.Name) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // GetApp app object with populated state fields
 | ||||||
|  | func (c *Container) GetApp() (*apps.App, error) { | ||||||
|  | 	status, err := c.Status() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	state := apps.AppState{ | ||||||
|  | 		State:       status, | ||||||
|  | 		CPUUsage:    0, | ||||||
|  | 		MemoryUsage: 0, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	c.App.State = state | ||||||
|  | 
 | ||||||
|  | 	return c.App, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Status returns state of the container
 | // Status returns state of the container
 | ||||||
| // Possible values: running, stopped, data-only, unknown
 | // Possible values: running, stopped, no-container, unknown
 | ||||||
| func (c *Container) Status() (string, error) { | func (c *Container) Status() (string, error) { | ||||||
| 	status := "unknown" | 	status := "unknown" | ||||||
| 
 | 
 | ||||||
|  | @ -32,15 +51,14 @@ func (c *Container) Status() (string, error) { | ||||||
| 
 | 
 | ||||||
| 	driver := c.getDriver() | 	driver := c.getDriver() | ||||||
| 	containerStatus, err := driver.Status(c.App.Name) | 	containerStatus, err := driver.Status(c.App.Name) | ||||||
|  | 	if err != nil && err.Error() == "no container found" { | ||||||
|  | 		return "no-container", nil | ||||||
|  | 	} | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return status, err | 		return status, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if containerStatus == "no-container" { | 	status = containerStatus | ||||||
| 		status = "data-only" |  | ||||||
| 	} else { |  | ||||||
| 		status = containerStatus |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	return status, nil | 	return status, nil | ||||||
| } | } | ||||||
|  | @ -121,6 +139,9 @@ func (c *Container) Delete() error { | ||||||
| 
 | 
 | ||||||
| 	volumePath := path.Join("/srv", c.App.Name) | 	volumePath := path.Join("/srv", c.App.Name) | ||||||
| 	err = removeDirectory(volumePath) | 	err = removeDirectory(volumePath) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Println(err) | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	return err | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										128
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								main.go
									
									
									
									
									
								
							|  | @ -1,6 +1,7 @@ | ||||||
| package main | package main | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"log" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 
 | 
 | ||||||
| 	"github.com/labstack/echo" | 	"github.com/labstack/echo" | ||||||
|  | @ -25,13 +26,25 @@ func main() { | ||||||
| 
 | 
 | ||||||
| 	// Returns list of apps
 | 	// Returns list of apps
 | ||||||
| 	e.GET("/v1/apps", func(c echo.Context) error { | 	e.GET("/v1/apps", func(c echo.Context) error { | ||||||
| 		apps, err := apps.List() | 		applications, err := apps.List() | ||||||
| 
 | 
 | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return c.JSON(http.StatusOK, apps) | 		populatedApps := []*apps.App{} | ||||||
|  | 		for _, app := range *applications { | ||||||
|  | 			container := docker.Container{ | ||||||
|  | 				App: &app, | ||||||
|  | 			} | ||||||
|  | 			populatedApp, err := container.GetApp() | ||||||
|  | 			if err != nil { | ||||||
|  | 				return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
|  | 			} | ||||||
|  | 			populatedApps = append(populatedApps, populatedApp) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return c.JSON(http.StatusOK, populatedApps) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	// Returns one app
 | 	// Returns one app
 | ||||||
|  | @ -43,6 +56,14 @@ func main() { | ||||||
| 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		container := docker.Container{ | ||||||
|  | 			App: app, | ||||||
|  | 		} | ||||||
|  | 		_, err = container.GetApp() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		return c.JSON(http.StatusOK, app) | 		return c.JSON(http.StatusOK, app) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
|  | @ -63,7 +84,7 @@ func main() { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		container := docker.Container{ | 		container := docker.Container{ | ||||||
| 			App: app, | 			App: &app, | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		err = container.Create() | 		err = container.Create() | ||||||
|  | @ -100,7 +121,7 @@ func main() { | ||||||
| 		app = *appPointer | 		app = *appPointer | ||||||
| 
 | 
 | ||||||
| 		container := docker.Container{ | 		container := docker.Container{ | ||||||
| 			App: app, | 			App: &app, | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		err = container.Destroy() | 		err = container.Destroy() | ||||||
|  | @ -123,7 +144,23 @@ func main() { | ||||||
| 
 | 
 | ||||||
| 	// Stop existing app
 | 	// Stop existing app
 | ||||||
| 	e.PUT("/v1/apps/:name/stop", func(c echo.Context) error { | 	e.PUT("/v1/apps/:name/stop", func(c echo.Context) error { | ||||||
| 		return c.JSON(http.StatusOK, map[string]string{}) | 		name := c.Param("name") | ||||||
|  | 
 | ||||||
|  | 		app, err := apps.Get(name) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		container := docker.Container{ | ||||||
|  | 			App: app, | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = container.Stop() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return c.JSON(http.StatusOK, Message{Message: "ok"}) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	// Start existing app
 | 	// Start existing app
 | ||||||
|  | @ -136,7 +173,7 @@ func main() { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		container := docker.Container{ | 		container := docker.Container{ | ||||||
| 			App: *app, | 			App: app, | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		err = container.Start() | 		err = container.Start() | ||||||
|  | @ -149,19 +186,92 @@ func main() { | ||||||
| 
 | 
 | ||||||
| 	// Stop existing app
 | 	// Stop existing app
 | ||||||
| 	e.PUT("/v1/apps/:name/restart", func(c echo.Context) error { | 	e.PUT("/v1/apps/:name/restart", func(c echo.Context) error { | ||||||
| 		return c.JSON(http.StatusOK, map[string]string{}) | 		name := c.Param("name") | ||||||
|  | 
 | ||||||
|  | 		app, err := apps.Get(name) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		container := docker.Container{ | ||||||
|  | 			App: app, | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = container.Restart() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return c.JSON(http.StatusOK, Message{Message: "ok"}) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	// Stats for existing app
 | ||||||
|  | 	e.GET("/v1/apps/:name/stats", func(c echo.Context) error { | ||||||
|  | 		name := c.Param("name") | ||||||
|  | 
 | ||||||
|  | 		app, err := apps.Get(name) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		container := docker.Container{ | ||||||
|  | 			App: app, | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		cpu, memory, err := container.ResourceUsage() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
|  | 		} | ||||||
|  | 		log.Println("DEBUG", cpu, memory) | ||||||
|  | 
 | ||||||
|  | 		return c.JSON(http.StatusOK, Message{Message: "ok"}) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	// Rebuilds existing app, it keeps the data but created the container again
 | 	// Rebuilds existing app, it keeps the data but created the container again
 | ||||||
| 	e.PUT("/v1/apps/:name/rebuild", func(c echo.Context) error { | 	e.PUT("/v1/apps/:name/rebuild", func(c echo.Context) error { | ||||||
| 		return c.JSON(http.StatusOK, map[string]string{}) | 		name := c.Param("name") | ||||||
|  | 
 | ||||||
|  | 		app, err := apps.Get(name) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		container := docker.Container{ | ||||||
|  | 			App: app, | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = container.Destroy() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = container.Create() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return c.JSON(http.StatusOK, Message{Message: "ok"}) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	// Delete one app
 | 	// Delete one app
 | ||||||
| 	e.DELETE("/v1/apps/:name", func(c echo.Context) error { | 	e.DELETE("/v1/apps/:name", func(c echo.Context) error { | ||||||
| 		name := c.Param("name") | 		name := c.Param("name") | ||||||
| 
 | 
 | ||||||
| 		err := apps.Delete(name) | 		app, err := apps.Get(name) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		container := docker.Container{ | ||||||
|  | 			App: app, | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = container.Delete() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = apps.Delete(name) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | 			return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue