package apps import ( "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/sqlite" "github.com/rosti-cz/node-api/detector" ) // AppsProcessor encapsulates functions for apps manipulation // This handles only the database part but not containers type AppsProcessor struct { DB *gorm.DB } func (a *AppsProcessor) Init() { a.DB.AutoMigrate(Label{}) a.DB.AutoMigrate(App{}) } // Get returns one app func (a *AppsProcessor) Get(name string) (App, error) { var app App err := a.DB.Preload("Labels").Where("name = ?", name).First(&app).Error if err != nil { return app, err } return app, nil } // List returns all apps located on this node func (a *AppsProcessor) List() (Apps, error) { var apps Apps err := a.DB.Preload("Labels").Find(&apps).Error if err != nil { return nil, err } return apps, nil } // New creates new record about application in the database func (a *AppsProcessor) New(name string, SSHPort int, HTTPPort int, image string, CPU int, memory int) error { app := App{ Name: name, SSHPort: SSHPort, HTTPPort: HTTPPort, Image: image, CPU: CPU, Memory: memory, } validationErrors := app.Validate() if len(validationErrors) != 0 { return ValidationError{ Errors: validationErrors, } } if err := a.DB.Create(&app).Error; err != nil { return err } return nil } // Update changes value about app in the database func (a *AppsProcessor) Update(name string, SSHPort int, HTTPPort int, image string, CPU int, memory int, env map[string]string) (*App, error) { var app App err := a.DB.Where("name = ?", name).First(&app).Error if err != nil { return &app, err } // Update affected fields if image != "" { app.Image = image } if CPU != 0 { app.CPU = CPU } if memory != 0 { app.Memory = memory } // SSH port and HTTP port cannot be turned off when they are once set if SSHPort != 0 { app.SSHPort = SSHPort } // SSH port and HTTP port cannot be turned off when they are once set if HTTPPort != 0 { app.HTTPPort = HTTPPort } if len(env) != 0 { app.SetEnv(env) } validationErrors := app.Validate() if len(validationErrors) != 0 { return &app, ValidationError{ Errors: validationErrors, } } // Apply the changes err = a.DB.Save(&app).Error return &app, err } // UpdateResources updates various metrics saved in the database func (a *AppsProcessor) UpdateResources(name string, state string, OOMKilled bool, CPUUsage float64, memory int, diskUsageBytes int, diskUsageInodes int, flags detector.Flags) error { err := a.DB.Model(&App{}).Where("name = ?", name).Updates(App{ State: state, OOMKilled: OOMKilled, CPUUsage: CPUUsage, MemoryUsage: memory, DiskUsageBytes: diskUsageBytes, DiskUsageInodes: diskUsageInodes, Flags: flags.String(), }).Error return err } // UpdateState sets container's state func (a *AppsProcessor) UpdateState(name string, state string, OOMKilled bool) error { err := a.DB.Model(&App{}).Where("name = ?", name).Updates(App{ State: state, OOMKilled: OOMKilled, }).Error return err } // Delete removes records about one app from the database func (a *AppsProcessor) Delete(name string) error { app, err := a.Get(name) if err != nil { return err } err = a.DB.Where("app_id = ?", app.ID).Delete(&Label{}).Error if err != nil { return err } err = a.DB.Where("id = ?", app.ID).Delete(App{}).Error return err } // AddLabel adds label to existing application func (a *AppsProcessor) AddLabel(appName string, label string) error { var app App err := a.DB.Where("name = ?", appName).First(&app).Error if err != nil { return err } // Check if there is such label already var count int err = a.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 a.DB.Create(&Label{AppID: app.ID, Value: label}).Error } // RemoveLabel removes label from existing application func (a *AppsProcessor) RemoveLabel(appName string, label string) error { var app App err := a.DB.Where("name = ?", appName).First(&app).Error if err != nil { return err } return a.DB.Where("value = ? AND app_id = ?", label, app.ID).Delete(&Label{}).Error }