From 60f99d52b0373031f7b0c8a4eefcece356fa847a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C5=A0trauch?= Date: Thu, 23 Jul 2020 23:50:20 +0200 Subject: [PATCH] Various fixes * UI: abbility to start container in exited state * Fix all Where() method usages * Container state is updated every list and get operation --- api.http | 8 ++++---- apps/main.go | 37 +++++++++++++++++++++++++++++-------- main.go | 15 +++++++++++++++ stats.go | 37 ++++++++++++++++++++++++++++++++++++- ui/index.html | 8 +++++++- 5 files changed, 91 insertions(+), 14 deletions(-) diff --git a/api.http b/api.http index e27c693..5278f08 100644 --- a/api.http +++ b/api.http @@ -2,9 +2,9 @@ POST http://localhost:1323/v1/apps Content-type: application/json { - "name": "test_1234", - "ssh_port": 46500, - "http_port": 46501, + "name": "test_1235", + "ssh_port": 46502, + "http_port": 46503, "image": "docker.io/rosti/runtime:2020.04-1", "cpu": 100, "memory": 128 @@ -63,7 +63,7 @@ Content-type: application/json # Get -GET http://localhost:1323/v1/apps/test_1234 +GET http://localhost:1323/v1/apps/test_1235 Content-type: application/json diff --git a/apps/main.go b/apps/main.go index eba8183..64059ca 100644 --- a/apps/main.go +++ b/apps/main.go @@ -16,7 +16,7 @@ func Get(name string) (*App, error) { db := common.GetDBConnection() - err := db.Preload("Labels").First(&app).Where("name = ?", name).Error + err := db.Preload("Labels").Where("name = ?", name).First(&app).Error if err != nil { return nil, err } @@ -71,7 +71,7 @@ func Update(name string, SSHPort int, HTTPPort int, image string, CPU int, memor db := common.GetDBConnection() - err := db.First(&app).Where("name = ?", name).Error + err := db.Where("name = ?", name).First(&app).Error if err != nil { return &app, err } @@ -115,13 +115,23 @@ func Update(name string, SSHPort int, HTTPPort int, image string, CPU int, memor func UpdateState(name string, state string, CPUUsage float64, memory int, diskUsageBytes int, diskUsageInodes int) error { db := common.GetDBConnection() - err := db.Model(&App{}).Updates(App{ + err := db.Model(&App{}).Where("name = ?", name).Updates(App{ State: state, CPUUsage: CPUUsage, MemoryUsage: memory, DiskUsageBytes: diskUsageBytes, DiskUsageInodes: diskUsageInodes, - }).Where("name = ?", name).Error + }).Error + return err +} + +// UpdateContainerState sets container's state +func UpdateContainerState(name string, state string) error { + db := common.GetDBConnection() + + err := db.Model(&App{}).Where("name = ?", name).Updates(App{ + State: state, + }).Error return err } @@ -129,7 +139,18 @@ func UpdateState(name string, state string, CPUUsage float64, memory int, diskUs func Delete(name string) error { db := common.GetDBConnection() - err := db.Delete(App{}).Where("name = ?", name).Error + app, err := Get(name) + if err != nil { + return err + } + + err = db.Where("app_id = ?", app.ID).Delete(&Label{}).Error + if err != nil { + return err + } + + err = db.Where("id = ?", app.ID).Delete(App{}).Error + return err } @@ -139,7 +160,7 @@ func AddLabel(appName string, label string) error { db := common.GetDBConnection() - err := db.First(&app).Where("name = ?", appName).Error + err := db.Where("name = ?", appName).First(&app).Error if err != nil { return err } @@ -165,10 +186,10 @@ func RemoveLabel(appName string, label string) error { db := common.GetDBConnection() - err := db.First(&app).Where("name = ?", appName).Error + err := db.Where("name = ?", appName).First(&app).Error if err != nil { return err } - return db.Delete(&Label{}).Where("label = ? AND app_id = ?", label, app.ID).Error + return db.Where("label = ? AND app_id = ?", label, app.ID).Delete(&Label{}).Error } diff --git a/main.go b/main.go index f9d4790..8cb14ee 100644 --- a/main.go +++ b/main.go @@ -56,6 +56,11 @@ func main() { return c.Render(http.StatusOK, "index.html", "") }) e.GET("/v1/apps", func(c echo.Context) error { + err := gatherContainersStates() + if err != nil { + return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) + } + applications, err := apps.List() if err != nil { @@ -74,6 +79,16 @@ func main() { return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) } + err = updateContainerState(app) + if err != nil { + return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) + } + + app, err = apps.Get(name) + if err != nil { + return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent) + } + return c.JSON(http.StatusOK, app) }) diff --git a/stats.go b/stats.go index 646afe3..fe17ceb 100644 --- a/stats.go +++ b/stats.go @@ -7,6 +7,24 @@ import ( "github.com/rosti-cz/node-api/docker" ) +// Updates only container's state +func updateContainerState(app *apps.App) error { + container := docker.Container{ + App: app, + } + state, err := container.Status() + if err != nil { + return err + } + + err = apps.UpdateContainerState( + app.Name, + state, + ) + return err +} + +// Updates info about all containers func updateContainerStats(app *apps.App) error { container := docker.Container{ App: app, @@ -24,7 +42,7 @@ func updateContainerStats(app *apps.App) error { state.DiskUsageBytes, state.DiskUsageInodes, ) - return nil + return err } // gatherContainersStats gathers information about containers and saves it into the database @@ -43,3 +61,20 @@ func gatherContainersStats() error { return nil } + +// gatherContainersStates refreshes all container's state +func gatherContainersStates() error { + appList, err := apps.List() + if err != nil { + return err + } + + for _, app := range *appList { + err := updateContainerState(&app) + if err != nil { + log.Println("STATE ERROR:", err.Error()) + } + } + + return nil +} diff --git a/ui/index.html b/ui/index.html index 40650df..ecf3431 100644 --- a/ui/index.html +++ b/ui/index.html @@ -82,7 +82,7 @@ {( label.value )} - + @@ -122,6 +122,12 @@ hasError: () => { return this.api_status_code >= 400 && this.api_status_code < 505 }, + refresh: () => { + fetch('/v1/apps').then(response => response.json()) + .then(data => this.apps = data); + fetch('/v1/node').then(response => response.json()) + .then(data => this.node = data); + }, start: (id) => { app.api_response = "working" fetch('/v1/apps/'+id+'/start', {method: 'PUT'})