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
|
|
|
|
2022-02-03 00:31:47 +00:00
|
|
|
"github.com/rosti-cz/node-api/detector"
|
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 {
|
2022-02-03 00:31:47 +00:00
|
|
|
State string `json:"state"`
|
2022-10-04 17:54:26 +00:00
|
|
|
OOMKilled bool `json:"oom_killed"`
|
2022-02-03 00:31:47 +00:00
|
|
|
CPUUsage float64 `json:"cpu_usage"` // in percents
|
|
|
|
MemoryUsage int `json:"memory_usage"` // in MB
|
|
|
|
DiskUsageBytes int `json:"disk_usage_bytes"`
|
|
|
|
DiskUsageInodes int `json:"disk_usage_inodes"`
|
|
|
|
Flags detector.Flags `json:"flags"`
|
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
|
|
|
|
2022-02-07 16:00:16 +00:00
|
|
|
// ####################################################
|
|
|
|
// This part is used in app template
|
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"`
|
2023-01-28 10:46:59 +00:00
|
|
|
// Port of the application inside the container. Default is 0 which means default by the image.
|
|
|
|
// But it has to be between 1024 and 65536 with exception of 8000.
|
|
|
|
AppPort int `json:"app_port"`
|
2020-07-30 20:46:09 +00:00
|
|
|
// 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
|
2022-02-07 16:00:16 +00:00
|
|
|
// ####################################################
|
2020-07-30 20:46:09 +00:00
|
|
|
|
|
|
|
// Current status of the application (underlaying container)
|
|
|
|
State string `json:"state"`
|
2022-10-04 17:54:26 +00:00
|
|
|
// True if the current container has been killed by OOM killer
|
|
|
|
OOMKilled bool `json:"oom_killed"`
|
2020-07-30 20:46:09 +00:00
|
|
|
// 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"`
|
2022-02-03 00:31:47 +00:00
|
|
|
// Flags from detector of problems in the container
|
2022-02-05 01:22:53 +00:00
|
|
|
Flags string `json:"flags"` // flags are separated by comma
|
2021-10-31 00:29:58 +00:00
|
|
|
|
2021-12-20 03:53:22 +00:00
|
|
|
// this is gathered in docker package and has to be assembled externally
|
|
|
|
Techs AppTechs `json:"techs,omitempty" gorm:"-"` // list of available technologies in the image
|
|
|
|
PrimaryTech AppTech `json:"primary_tech,omitempty" gorm:"-"` // Technology that was selected as primary in the environment
|
|
|
|
|
2021-10-31 00:29:58 +00:00
|
|
|
// This is not store in the database but used in create request when the app suppose to be created from an existing snapshot
|
|
|
|
Snapshot string `json:"snapshot" gorm:"-"`
|
2020-07-09 22:27:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Validate do basic checks of the struct values
|
|
|
|
func (a *App) Validate() []string {
|
|
|
|
var errors []string
|
|
|
|
|
2020-08-29 13:12:29 +00:00
|
|
|
nameRegExp := regexp.MustCompile(`^[a-z0-9_\-]{3,48}$`)
|
2020-07-09 22:27:23 +00:00
|
|
|
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")
|
|
|
|
}
|
|
|
|
|
2023-01-28 10:46:59 +00:00
|
|
|
if a.AppPort != 0 && ((a.AppPort < 1024 && a.AppPort > 65536) || a.AppPort == 8000) {
|
|
|
|
errors = append(errors, "App port has to be between 1024 and 65536 with exception of 8000")
|
|
|
|
}
|
|
|
|
|
2020-07-09 22:27:23 +00:00
|
|
|
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
|
|
|
}
|
2021-12-20 03:53:22 +00:00
|
|
|
|
|
|
|
// AppTechs is list of technologies available in the app
|
|
|
|
type AppTechs []AppTech
|
|
|
|
|
|
|
|
// AppTech holds info about one technology in the app
|
|
|
|
type AppTech struct {
|
2021-12-22 00:29:56 +00:00
|
|
|
Name string `json:"name"`
|
|
|
|
Version string `json:"version"`
|
2021-12-20 03:53:22 +00:00
|
|
|
}
|