2020-07-08 22:09:19 +00:00
|
|
|
package apps
|
|
|
|
|
2020-07-09 22:27:23 +00:00
|
|
|
import (
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
2020-07-16 17:05:38 +00:00
|
|
|
"time"
|
2020-07-09 22:27:23 +00:00
|
|
|
|
2020-07-11 11:04:37 +00:00
|
|
|
// This is line from GORM documentation that imports database dialect
|
|
|
|
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
2020-07-09 22:27:23 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// ValidationError is error that holds multiple validation error messages
|
|
|
|
type ValidationError struct {
|
2020-07-30 20:46:09 +00:00
|
|
|
// List of validation errors
|
|
|
|
// Example: ["phone number is too short", "email address is wrongly formated"]
|
2020-07-09 22:27:23 +00:00
|
|
|
Errors []string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v ValidationError) Error() string {
|
|
|
|
return strings.Join(v.Errors, "\n")
|
|
|
|
}
|
2020-07-08 22:09:19 +00:00
|
|
|
|
|
|
|
// Label holds metadata about the application
|
|
|
|
type Label struct {
|
2020-07-30 20:46:09 +00:00
|
|
|
// Value of the label
|
|
|
|
// Example: userid:1
|
|
|
|
// Required: true
|
2020-07-08 22:09:19 +00:00
|
|
|
Value string `json:"value"`
|
2020-07-16 21:24:09 +00:00
|
|
|
AppID uint `json:"-" gorm:"not null"`
|
2020-07-08 22:09:19 +00:00
|
|
|
}
|
|
|
|
|
2020-07-11 21:14:45 +00:00
|
|
|
// AppState contains info about runnint application, it's not saved in the database
|
|
|
|
type AppState struct {
|
2020-07-15 21:32:28 +00:00
|
|
|
State string `json:"state"`
|
|
|
|
CPUUsage float64 `json:"cpu_usage"` // in percents
|
|
|
|
MemoryUsage int `json:"memory_usage"` // in MB
|
|
|
|
DiskUsageBytes int `json:"disk_usage_bytes"`
|
2020-07-16 17:05:38 +00:00
|
|
|
DiskUsageInodes int `json:"disk_usage_inodes"`
|
2020-07-11 21:14:45 +00:00
|
|
|
}
|
|
|
|
|
2020-07-30 20:46:09 +00:00
|
|
|
// Apps is list of applications
|
|
|
|
type Apps []App
|
|
|
|
|
2020-07-08 22:09:19 +00:00
|
|
|
// App keeps info about hosted application
|
|
|
|
type App struct {
|
2020-07-30 20:46:09 +00:00
|
|
|
// ID of the applicaton
|
|
|
|
// Unique: true
|
|
|
|
ID uint `gorm:"primary_key" json:"id"`
|
|
|
|
// Datetime of creation
|
|
|
|
CreatedAt time.Time `json:"created_at"`
|
|
|
|
// Datetime of last update
|
|
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
|
|
// Datetime of deletion
|
2020-07-16 17:05:38 +00:00
|
|
|
DeletedAt *time.Time `sql:"index" json:"deleted_at"`
|
2020-07-08 22:09:19 +00:00
|
|
|
|
2020-07-30 20:46:09 +00:00
|
|
|
// Name of the application
|
|
|
|
// Example: test_1234
|
|
|
|
Name string `json:"name" gorm:"unique,index,not_null"`
|
|
|
|
// SSH port where the application will be available
|
|
|
|
// Unique: true
|
|
|
|
// Example: 10001
|
|
|
|
SSHPort int `json:"ssh_port"`
|
|
|
|
// HTTP port where the application will be available
|
|
|
|
// Unique: true
|
|
|
|
// Example: 10002
|
|
|
|
HTTPPort int `json:"http_port"`
|
|
|
|
// Runtime image
|
|
|
|
Image string `json:"image"`
|
|
|
|
// Number of CPUs ticks assigned, 100 means one CPU, 200 are two
|
|
|
|
CPU int `json:"cpu"` // percentage, 200 means two CPU
|
|
|
|
// Memory limit in MB
|
|
|
|
Memory int `json:"memory"` // Limit in MB
|
|
|
|
// Custom labels
|
|
|
|
Labels []Label `json:"labels" gorm:"foreignkey:AppID"` // username:cx or user_id:1
|
|
|
|
|
|
|
|
// Current status of the application (underlaying container)
|
|
|
|
State string `json:"state"`
|
|
|
|
// CPU usage in percents
|
|
|
|
CPUUsage float64 `json:"cpu_usage"` // in percents
|
|
|
|
// Memory usage in bytes
|
|
|
|
MemoryUsage int `json:"memory_usage"` // in B
|
|
|
|
// Disk usage in bytes
|
|
|
|
DiskUsageBytes int `json:"disk_usage_bytes"`
|
|
|
|
// Disk usage in inodes
|
|
|
|
DiskUsageInodes int `json:"disk_usage_inodes"`
|
2020-07-09 22:27:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Validate do basic checks of the struct values
|
|
|
|
func (a *App) Validate() []string {
|
|
|
|
var errors []string
|
|
|
|
|
|
|
|
nameRegExp := regexp.MustCompile(`^[a-z0-9_]{3,48}$`)
|
|
|
|
if !nameRegExp.MatchString(a.Name) {
|
|
|
|
errors = append(errors, "name can contain only characters, numbers and underscores and has to be between 3 and 48 characters")
|
|
|
|
}
|
|
|
|
|
|
|
|
if a.SSHPort < 0 && a.SSHPort > 65536 {
|
|
|
|
errors = append(errors, "SSH port has to be between 0 and 65536, where 0 means disabled")
|
|
|
|
}
|
|
|
|
|
|
|
|
if a.HTTPPort < 1 && a.HTTPPort > 65536 {
|
|
|
|
errors = append(errors, "HTTP port has to be between 1 and 65536")
|
|
|
|
}
|
|
|
|
|
|
|
|
if a.Image == "" {
|
|
|
|
errors = append(errors, "image cannot be empty")
|
|
|
|
}
|
|
|
|
|
|
|
|
if a.CPU < 10 && a.CPU > 800 {
|
|
|
|
errors = append(errors, "CPU value has be between 10 and 800")
|
|
|
|
}
|
|
|
|
|
|
|
|
if a.Memory < 32 && a.Memory > 16384 {
|
|
|
|
errors = append(errors, "Memory value has be between 32 and 16384")
|
|
|
|
}
|
2020-07-08 22:09:19 +00:00
|
|
|
|
2020-07-09 22:27:23 +00:00
|
|
|
return errors
|
2020-07-08 22:09:19 +00:00
|
|
|
}
|