Adam Štrauch
779d9ba95a
All checks were successful
continuous-integration/drone/push Build is passing
157 lines
5.1 KiB
Go
157 lines
5.1 KiB
Go
package apps
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/rosti-cz/node-api/detector"
|
|
)
|
|
|
|
// ValidationError is error that holds multiple validation error messages
|
|
type ValidationError struct {
|
|
// List of validation errors
|
|
// Example: ["phone number is too short", "email address is wrongly formated"]
|
|
Errors []string
|
|
}
|
|
|
|
func (v ValidationError) Error() string {
|
|
return strings.Join(v.Errors, "\n")
|
|
}
|
|
|
|
// Label holds metadata about the application
|
|
type Label struct {
|
|
// Value of the label
|
|
// Example: userid:1
|
|
// Required: true
|
|
Value string `json:"value"`
|
|
AppID uint `json:"-" gorm:"not null"`
|
|
}
|
|
|
|
// AppState contains info about runnint application, it's not saved in the database
|
|
type AppState struct {
|
|
State string `json:"state"`
|
|
OOMKilled bool `json:"oom_killed"`
|
|
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"`
|
|
}
|
|
|
|
// Apps is list of applications
|
|
type Apps []App
|
|
|
|
// App keeps info about hosted application
|
|
type App struct {
|
|
// 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
|
|
DeletedAt *time.Time `sql:"index" json:"deleted_at"`
|
|
|
|
// ####################################################
|
|
// This part is used in app template
|
|
// 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"`
|
|
// 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"`
|
|
// 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"`
|
|
// True if the current container has been killed by OOM killer
|
|
OOMKilled bool `json:"oom_killed"`
|
|
// 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"`
|
|
// Flags from detector of problems in the container
|
|
Flags string `json:"flags"` // flags are separated by comma
|
|
|
|
// 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
|
|
|
|
// 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:"-"`
|
|
|
|
// Fields to setup during creating of the app, this is not stored in the database
|
|
Setup struct {
|
|
SSHKeys string `json:"ssh_keys"`
|
|
Tech string `json:"tech"`
|
|
TechVersion string `json:"tech_version"`
|
|
Password string `json:"password"`
|
|
} `json:"setup,omitempty" gorm:"-"`
|
|
}
|
|
|
|
// 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.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")
|
|
}
|
|
|
|
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")
|
|
}
|
|
|
|
return errors
|
|
}
|
|
|
|
// AppTechs is list of technologies available in the app
|
|
type AppTechs []AppTech
|
|
|
|
// AppTech holds info about one technology in the app
|
|
type AppTech struct {
|
|
Name string `json:"name"`
|
|
Version string `json:"version"`
|
|
}
|