mirror of
https://github.com/yusing/godoxy.git
synced 2026-03-23 17:41:05 +01:00
Decouple the types package from the internal/proxmox package by defining a standalone ProxmoxConfig struct. This reduces circular dependencies and allows the types package to define its own configuration structures without importing the proxmox package. The route validation logic now converts between types.ProxmoxConfig and proxmox.NodeConfig where needed for internal operations.
149 lines
4.3 KiB
Go
149 lines
4.3 KiB
Go
package types
|
|
|
|
import (
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
gperr "github.com/yusing/goutils/errs"
|
|
)
|
|
|
|
type (
|
|
IdlewatcherProviderConfig struct {
|
|
Proxmox *ProxmoxConfig `json:"proxmox,omitempty"`
|
|
Docker *DockerConfig `json:"docker,omitempty"`
|
|
} // @name IdlewatcherProviderConfig
|
|
IdlewatcherConfigBase struct {
|
|
// 0: no idle watcher.
|
|
// Positive: idle watcher with idle timeout.
|
|
// Negative: idle watcher as a dependency. IdleTimeout time.Duration `json:"idle_timeout" json_ext:"duration"`
|
|
IdleTimeout time.Duration `json:"idle_timeout"`
|
|
WakeTimeout time.Duration `json:"wake_timeout"`
|
|
StopTimeout time.Duration `json:"stop_timeout"`
|
|
StopMethod ContainerStopMethod `json:"stop_method"`
|
|
StopSignal ContainerSignal `json:"stop_signal,omitempty"`
|
|
} // @name IdlewatcherConfigBase
|
|
IdlewatcherConfig struct {
|
|
IdlewatcherProviderConfig
|
|
IdlewatcherConfigBase
|
|
|
|
StartEndpoint string `json:"start_endpoint,omitempty"` // Optional path that must be hit to start container
|
|
DependsOn []string `json:"depends_on,omitempty"`
|
|
NoLoadingPage bool `json:"no_loading_page,omitempty"`
|
|
|
|
valErr gperr.Error
|
|
} // @name IdlewatcherConfig
|
|
ContainerStopMethod string // @name ContainerStopMethod
|
|
ContainerSignal string // @name ContainerSignal
|
|
|
|
DockerConfig struct {
|
|
DockerCfg DockerProviderConfig `json:"docker_cfg" validate:"required"`
|
|
ContainerID string `json:"container_id" validate:"required"`
|
|
ContainerName string `json:"container_name" validate:"required"`
|
|
} // @name DockerConfig
|
|
ProxmoxConfig struct {
|
|
Node string `json:"node" validate:"required"`
|
|
VMID int `json:"vmid" validate:"required"`
|
|
} // @name ProxmoxNodeConfig
|
|
)
|
|
|
|
const (
|
|
ContainerWakeTimeoutDefault = 30 * time.Second
|
|
ContainerStopTimeoutDefault = 1 * time.Minute
|
|
|
|
ContainerStopMethodPause ContainerStopMethod = "pause"
|
|
ContainerStopMethodStop ContainerStopMethod = "stop"
|
|
ContainerStopMethodKill ContainerStopMethod = "kill"
|
|
)
|
|
|
|
func (c *IdlewatcherConfig) Key() string {
|
|
if c.Docker != nil {
|
|
return c.Docker.ContainerID
|
|
}
|
|
return c.Proxmox.Node + ":" + strconv.Itoa(c.Proxmox.VMID)
|
|
}
|
|
|
|
func (c *IdlewatcherConfig) ContainerName() string {
|
|
if c.Docker != nil {
|
|
return c.Docker.ContainerName
|
|
}
|
|
return "lxc-" + strconv.Itoa(c.Proxmox.VMID)
|
|
}
|
|
|
|
func (c *IdlewatcherConfig) Validate() gperr.Error {
|
|
if c.IdleTimeout == 0 { // zero idle timeout means no idle watcher
|
|
c.valErr = nil
|
|
return nil
|
|
}
|
|
|
|
var errs gperr.Builder
|
|
errs.AddRange(
|
|
c.validateProvider(),
|
|
c.validateTimeouts(),
|
|
c.validateStopMethod(),
|
|
c.validateStopSignal(),
|
|
c.validateStartEndpoint(),
|
|
)
|
|
c.valErr = errs.Error()
|
|
return c.valErr
|
|
}
|
|
|
|
func (c *IdlewatcherConfig) ValErr() gperr.Error {
|
|
return c.valErr
|
|
}
|
|
|
|
func (c *IdlewatcherConfig) validateProvider() error {
|
|
if c.Docker == nil && c.Proxmox == nil {
|
|
return gperr.New("missing idlewatcher provider config")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *IdlewatcherConfig) validateTimeouts() error { //nolint:unparam
|
|
if c.WakeTimeout == 0 {
|
|
c.WakeTimeout = ContainerWakeTimeoutDefault
|
|
}
|
|
if c.StopTimeout == 0 {
|
|
c.StopTimeout = ContainerStopTimeoutDefault
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *IdlewatcherConfig) validateStopMethod() error {
|
|
switch c.StopMethod {
|
|
case "":
|
|
c.StopMethod = ContainerStopMethodStop
|
|
return nil
|
|
case ContainerStopMethodPause, ContainerStopMethodStop, ContainerStopMethodKill:
|
|
return nil
|
|
default:
|
|
return gperr.New("invalid stop method").Subject(string(c.StopMethod))
|
|
}
|
|
}
|
|
|
|
func (c *IdlewatcherConfig) validateStopSignal() error {
|
|
switch c.StopSignal {
|
|
case "", "SIGINT", "SIGTERM", "SIGQUIT", "SIGHUP", "INT", "TERM", "QUIT", "HUP":
|
|
return nil
|
|
default:
|
|
return gperr.New("invalid stop signal").Subject(string(c.StopSignal))
|
|
}
|
|
}
|
|
|
|
func (c *IdlewatcherConfig) validateStartEndpoint() error {
|
|
if c.StartEndpoint == "" {
|
|
return nil
|
|
}
|
|
// checks needed as of Go 1.6 because of change https://github.com/golang/go/commit/617c93ce740c3c3cc28cdd1a0d712be183d0b328#diff-6c2d018290e298803c0c9419d8739885L195
|
|
// emulate browser and strip the '#' suffix prior to validation. see issue-#237
|
|
if i := strings.Index(c.StartEndpoint, "#"); i > -1 {
|
|
c.StartEndpoint = c.StartEndpoint[:i]
|
|
}
|
|
if len(c.StartEndpoint) == 0 {
|
|
return gperr.New("start endpoint must not be empty if defined")
|
|
}
|
|
_, err := url.ParseRequestURI(c.StartEndpoint)
|
|
return err
|
|
}
|