mirror of
https://github.com/yusing/godoxy.git
synced 2026-03-20 00:03:53 +01:00
This is a large-scale refactoring across the codebase that replaces the custom `gperr.Error` type with Go's standard `error` interface. The changes include: - Replacing `gperr.Error` return types with `error` in function signatures - Using `errors.New()` and `fmt.Errorf()` instead of `gperr.New()` and `gperr.Errorf()` - Using `%w` format verb for error wrapping instead of `.With()` method - Replacing `gperr.Subject()` calls with `gperr.PrependSubject()` - Converting error logging from `gperr.Log*()` functions to zerolog's `.Err().Msg()` pattern - Update NewLogger to handle multiline error message - Updating `goutils` submodule to latest commit This refactoring aligns with Go idioms and removes the dependency on custom error handling abstractions in favor of standard library patterns.
157 lines
4.5 KiB
Go
157 lines
4.5 KiB
Go
package types
|
|
|
|
import (
|
|
"errors"
|
|
"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"`
|
|
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 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 IdlewatcherDockerConfig
|
|
ProxmoxConfig struct {
|
|
Node string `json:"node" validate:"required"`
|
|
VMID int `json:"vmid" validate:"required"`
|
|
} // @name IdlewatcherProxmoxNodeConfig
|
|
)
|
|
|
|
const (
|
|
ContainerWakeTimeoutDefault = 30 * time.Second
|
|
ContainerStopTimeoutDefault = 1 * time.Minute
|
|
|
|
ContainerStopMethodPause ContainerStopMethod = "pause"
|
|
ContainerStopMethodStop ContainerStopMethod = "stop"
|
|
ContainerStopMethodKill ContainerStopMethod = "kill"
|
|
)
|
|
|
|
var (
|
|
ErrMissingProviderConfig = errors.New("missing idlewatcher provider config")
|
|
ErrInvalidStopMethod = errors.New("invalid stop method")
|
|
ErrInvalidStopSignal = errors.New("invalid stop signal")
|
|
ErrEmptyStartEndpoint = errors.New("start endpoint must not be empty if defined")
|
|
)
|
|
|
|
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() 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() error {
|
|
return c.valErr
|
|
}
|
|
|
|
func (c *IdlewatcherConfig) validateProvider() error {
|
|
if c.Docker == nil && c.Proxmox == nil {
|
|
return ErrMissingProviderConfig
|
|
}
|
|
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.PrependSubject(ErrInvalidStopMethod, 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.PrependSubject(ErrInvalidStopSignal, 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 ErrEmptyStartEndpoint
|
|
}
|
|
_, err := url.ParseRequestURI(c.StartEndpoint)
|
|
return err
|
|
}
|