Labels done
This commit is contained in:
parent
31cdc6ef42
commit
753bd452fb
9
api.http
9
api.http
@ -74,3 +74,12 @@ Content-type: application/json
|
|||||||
GET http://localhost:1323/v1/apps
|
GET http://localhost:1323/v1/apps
|
||||||
Content-type: application/json
|
Content-type: application/json
|
||||||
Authorization: Token 333ff32b-6c9e-4794-adab-c289447e66b0
|
Authorization: Token 333ff32b-6c9e-4794-adab-c289447e66b0
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
POST http://localhost:1323/v1/apps/test_1234/labels
|
||||||
|
Content-type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"Value": "userid:cx"
|
||||||
|
}
|
||||||
|
44
apps/main.go
44
apps/main.go
@ -16,7 +16,7 @@ func Get(name string) (*App, error) {
|
|||||||
|
|
||||||
db := common.GetDBConnection()
|
db := common.GetDBConnection()
|
||||||
|
|
||||||
err := db.First(&app).Where("name = ?", name).Error
|
err := db.Preload("Labels").First(&app).Where("name = ?", name).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ func List() (*[]App, error) {
|
|||||||
|
|
||||||
db := common.GetDBConnection()
|
db := common.GetDBConnection()
|
||||||
|
|
||||||
err := db.Find(&apps).Error
|
err := db.Preload("Labels").Find(&apps).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -132,3 +132,43 @@ func Delete(name string) error {
|
|||||||
err := db.Delete(App{}).Where("name = ?", name).Error
|
err := db.Delete(App{}).Where("name = ?", name).Error
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddLabel adds label to existing application
|
||||||
|
func AddLabel(appName string, label string) error {
|
||||||
|
var app App
|
||||||
|
|
||||||
|
db := common.GetDBConnection()
|
||||||
|
|
||||||
|
err := db.First(&app).Where("name = ?", appName).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there is such label already
|
||||||
|
var count int
|
||||||
|
err = db.Model(&Label{}).Where("value = ? AND app_id = ?", label, app.ID).Count(&count).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if count > 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// And create the label
|
||||||
|
return db.Create(&Label{AppID: app.ID, Value: label}).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveLabel removes label from existing application
|
||||||
|
func RemoveLabel(appName string, label string) error {
|
||||||
|
var app App
|
||||||
|
|
||||||
|
db := common.GetDBConnection()
|
||||||
|
|
||||||
|
err := db.First(&app).Where("name = ?", appName).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.Delete(&Label{}).Where("label = ? AND app_id = ?", label, app.ID).Error
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@ func (v ValidationError) Error() string {
|
|||||||
// Label holds metadata about the application
|
// Label holds metadata about the application
|
||||||
type Label struct {
|
type Label struct {
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
|
AppID uint `json:"-" gorm:"not null"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppState contains info about runnint application, it's not saved in the database
|
// AppState contains info about runnint application, it's not saved in the database
|
||||||
@ -39,13 +40,13 @@ type App struct {
|
|||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
DeletedAt *time.Time `sql:"index" json:"deleted_at"`
|
DeletedAt *time.Time `sql:"index" json:"deleted_at"`
|
||||||
|
|
||||||
Name string `json:"name" gorm:"primary_key"`
|
Name string `json:"name" gorm:"unique,index,not_null"`
|
||||||
SSHPort int `json:"ssh_port"`
|
SSHPort int `json:"ssh_port"`
|
||||||
HTTPPort int `json:"http_port"`
|
HTTPPort int `json:"http_port"`
|
||||||
Image string `json:"image"`
|
Image string `json:"image"`
|
||||||
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" gorm:"foreignkey:AppID"` // username:cx or user_id:1
|
||||||
|
|
||||||
State string `json:"state"`
|
State string `json:"state"`
|
||||||
CPUUsage float64 `json:"cpu_usage"` // in percents
|
CPUUsage float64 `json:"cpu_usage"` // in percents
|
||||||
|
@ -17,13 +17,12 @@ func du(path string) (int, int, error) {
|
|||||||
// Occupied space
|
// Occupied space
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
var errOut bytes.Buffer
|
var errOut bytes.Buffer
|
||||||
command := exec.Command("/usr/bin/du", "-m", "-s", path)
|
command := exec.Command("/usr/bin/du", "-b", "-s", path)
|
||||||
command.Stdout = &out
|
command.Stdout = &out
|
||||||
command.Stderr = &errOut
|
command.Stderr = &errOut
|
||||||
err := command.Run()
|
err := command.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(errOut.String())
|
log.Println(errOut.String())
|
||||||
log.Println("/usr/bin/du -m -s " + path)
|
|
||||||
return space, inodes, err
|
return space, inodes, err
|
||||||
}
|
}
|
||||||
fields := strings.Fields(strings.TrimSpace(out.String()))
|
fields := strings.Fields(strings.TrimSpace(out.String()))
|
||||||
@ -44,7 +43,6 @@ func du(path string) (int, int, error) {
|
|||||||
err = command.Run()
|
err = command.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(errOut.String())
|
log.Println(errOut.String())
|
||||||
log.Println("/usr/bin/du --inodes -s " + path)
|
|
||||||
return space, inodes, err
|
return space, inodes, err
|
||||||
}
|
}
|
||||||
fields = strings.Fields(strings.TrimSpace(out.String()))
|
fields = strings.Fields(strings.TrimSpace(out.String()))
|
||||||
|
@ -78,7 +78,7 @@ func (c *Container) DiskUsage() (int, int, error) {
|
|||||||
return du(c.volumeHostPath())
|
return du(c.volumeHostPath())
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResourceUsage returns amount of memory in MB and CPU in % that the app occupies
|
// ResourceUsage returns amount of memory in B and CPU in % that the app occupies
|
||||||
func (c *Container) ResourceUsage() (float64, int, error) {
|
func (c *Container) ResourceUsage() (float64, int, error) {
|
||||||
driver := c.getDriver()
|
driver := c.getDriver()
|
||||||
|
|
||||||
|
31
main.go
31
main.go
@ -255,6 +255,37 @@ func main() {
|
|||||||
return c.JSON(http.StatusOK, Message{Message: "ok"})
|
return c.JSON(http.StatusOK, Message{Message: "ok"})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Adds new label
|
||||||
|
e.POST("/v1/apps/:name/labels", func(c echo.Context) error {
|
||||||
|
name := c.Param("name")
|
||||||
|
label := apps.Label{}
|
||||||
|
|
||||||
|
err := c.Bind(&label)
|
||||||
|
if err != nil {
|
||||||
|
return c.JSONPretty(http.StatusBadRequest, Message{Message: err.Error()}, JSONIndent)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = apps.AddLabel(name, label.Value)
|
||||||
|
if err != nil {
|
||||||
|
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusOK, Message{Message: "ok"})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Removes existing label
|
||||||
|
e.DELETE("/v1/apps/:name/labels/:label", func(c echo.Context) error {
|
||||||
|
name := c.Param("name")
|
||||||
|
label := c.Param("name")
|
||||||
|
|
||||||
|
err := apps.RemoveLabel(name, label)
|
||||||
|
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")
|
||||||
|
@ -69,11 +69,13 @@
|
|||||||
<td><strong>{( app.name )}</strong></td>
|
<td><strong>{( app.name )}</strong></td>
|
||||||
<td>{( app.state.state )}</td>
|
<td>{( app.state.state )}</td>
|
||||||
<td>{( app.image.replace("docker.io/", "") )}</td>
|
<td>{( app.image.replace("docker.io/", "") )}</td>
|
||||||
<td>- / {( app.cpu )} %</td>
|
<td>{( app.cpu_usage )} % / {( app.cpu )} %</td>
|
||||||
<td>- / {( app.memory )} MB</td>
|
<td>{( app.memory_usage )} MB / {( app.memory )} MB</td>
|
||||||
<td>- GB</td>
|
<td>{( (app.disk_usage_bytes / 1000 / 1000 / 1000).toFixed(2) )} GB</td>
|
||||||
<td>-</td>
|
<td>{( app.disk_usage_inodes )}</td>
|
||||||
<td>-</td>
|
<td>
|
||||||
|
<span v-for="label in app.labels" class="label label-info">{( label.value )}</span>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-success btn-sm" v-on:click="start(app.name)" v-if="['stopped'].includes(app.state.state)">Start</button>
|
<button class="btn btn-success btn-sm" v-on:click="start(app.name)" v-if="['stopped'].includes(app.state.state)">Start</button>
|
||||||
<button class="btn btn-warning btn-sm" v-on:click="stop(app.name)" v-if="['running'].includes(app.state.state)">Stop</button>
|
<button class="btn btn-warning btn-sm" v-on:click="stop(app.name)" v-if="['running'].includes(app.state.state)">Stop</button>
|
||||||
|
Loading…
Reference in New Issue
Block a user