From 65809b5731e8f2ef39117bd9514b0333fb72fc3c Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 2 Jul 2020 20:32:17 -0700 Subject: [PATCH] Don't crash when passing in an environment variable that isn't a string value --- installer/installer.go | 4 ++-- server/environment_docker.go | 32 +------------------------------ server/server.go | 37 +++++++++++++++++++++++++++++++++--- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/installer/installer.go b/installer/installer.go index b2fdf09..37ce0cb 100644 --- a/installer/installer.go +++ b/installer/installer.go @@ -34,7 +34,7 @@ func New(data []byte) (*Installer, error) { Suspended: false, State: server.ProcessOfflineState, Invocation: getString(data, "invocation"), - EnvVars: make(map[string]string), + EnvVars: make(server.EnvironmentVariables), Build: server.BuildSettings{ MemoryLimit: getInt(data, "build", "memory"), Swap: getInt(data, "build", "swap"), @@ -55,7 +55,7 @@ func New(data []byte) (*Installer, error) { if b, _, _, err := jsonparser.Get(data, "environment"); err != nil { return nil, errors.WithStack(err) } else { - s.EnvVars = make(map[string]string) + s.EnvVars = make(server.EnvironmentVariables) if err := json.Unmarshal(b, &s.EnvVars); err != nil { return nil, errors.WithStack(err) } diff --git a/server/environment_docker.go b/server/environment_docker.go index afe0b70..14597e6 100644 --- a/server/environment_docker.go +++ b/server/environment_docker.go @@ -653,7 +653,7 @@ func (d *DockerEnvironment) Create() error { ExposedPorts: d.exposedPorts(), Image: d.Server.Container.Image, - Env: d.environmentVariables(), + Env: d.Server.GetEnvironmentVariables(), Labels: map[string]string{ "Service": "Pterodactyl", @@ -804,36 +804,6 @@ func (d *DockerEnvironment) parseLogToStrings(b []byte) ([]string, error) { return out, nil } -// Returns the environment variables for a server in KEY="VALUE" form. -func (d *DockerEnvironment) environmentVariables() []string { - zone, _ := time.Now().In(time.Local).Zone() - - var out = []string{ - fmt.Sprintf("TZ=%s", zone), - fmt.Sprintf("STARTUP=%s", d.Server.Invocation), - fmt.Sprintf("SERVER_MEMORY=%d", d.Server.Build.MemoryLimit), - fmt.Sprintf("SERVER_IP=%s", d.Server.Allocations.DefaultMapping.Ip), - fmt.Sprintf("SERVER_PORT=%d", d.Server.Allocations.DefaultMapping.Port), - } - -eloop: - for k, v := range d.Server.EnvVars { - for _, e := range out { - if strings.HasPrefix(e, strings.ToUpper(k)) { - continue eloop - } - } - - out = append(out, fmt.Sprintf("%s=%s", strings.ToUpper(k), v)) - } - - return out -} - -func (d *DockerEnvironment) volumes() map[string]struct{} { - return nil -} - // Converts the server allocation mappings into a format that can be understood // by Docker. func (d *DockerEnvironment) portBindings() nat.PortMap { diff --git a/server/server.go b/server/server.go index 5389841..7b7792c 100644 --- a/server/server.go +++ b/server/server.go @@ -13,6 +13,7 @@ import ( "golang.org/x/sync/semaphore" "math" "os" + "strconv" "strings" "sync" "time" @@ -24,6 +25,36 @@ func GetServers() *Collection { return servers } +type EnvironmentVariables map[string]interface{} + +// Ugly hacky function to handle environment variables that get passed through as not-a-string +// from the Panel. Ideally we'd just say only pass strings, but that is a fragile idea and if a +// string wasn't passed through you'd cause a crash or the server to become unavailable. For now +// try to handle the most likely values from the JSON and hope for the best. +func (ev EnvironmentVariables) Get(key string) string { + val, ok := ev[key] + if !ok { + return "" + } + + switch val.(type) { + case int: + return strconv.Itoa(val.(int)) + case int32: + return strconv.FormatInt(val.(int64), 10) + case int64: + return strconv.FormatInt(val.(int64), 10) + case float32: + return fmt.Sprintf("%f", val.(float32)) + case float64: + return fmt.Sprintf("%f", val.(float64)) + case bool: + return strconv.FormatBool(val.(bool)) + } + + return val.(string) +} + // High level definition for a server instance being controlled by Wings. type Server struct { // The unique identifier for the server that should be used when referencing @@ -43,7 +74,7 @@ type Server struct { // An array of environment variables that should be passed along to the running // server process. - EnvVars map[string]string `json:"environment" yaml:"environment"` + EnvVars EnvironmentVariables `json:"environment" yaml:"environment"` Archiver Archiver `json:"-" yaml:"-"` CrashDetection CrashDetection `json:"crash_detection" yaml:"crash_detection"` @@ -287,14 +318,14 @@ func (s *Server) GetEnvironmentVariables() []string { } eloop: - for k, v := range s.EnvVars { + for k := range s.EnvVars { for _, e := range out { if strings.HasPrefix(e, strings.ToUpper(k)) { continue eloop } } - out = append(out, fmt.Sprintf("%s=%s", strings.ToUpper(k), v)) + out = append(out, fmt.Sprintf("%s=%s", strings.ToUpper(k), s.EnvVars.Get(k))) } return out