Don't crash when passing in an environment variable that isn't a string value

This commit is contained in:
Dane Everitt 2020-07-02 20:32:17 -07:00
parent e5b844d2c4
commit 65809b5731
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53
3 changed files with 37 additions and 36 deletions

View File

@ -34,7 +34,7 @@ func New(data []byte) (*Installer, error) {
Suspended: false, Suspended: false,
State: server.ProcessOfflineState, State: server.ProcessOfflineState,
Invocation: getString(data, "invocation"), Invocation: getString(data, "invocation"),
EnvVars: make(map[string]string), EnvVars: make(server.EnvironmentVariables),
Build: server.BuildSettings{ Build: server.BuildSettings{
MemoryLimit: getInt(data, "build", "memory"), MemoryLimit: getInt(data, "build", "memory"),
Swap: getInt(data, "build", "swap"), Swap: getInt(data, "build", "swap"),
@ -55,7 +55,7 @@ func New(data []byte) (*Installer, error) {
if b, _, _, err := jsonparser.Get(data, "environment"); err != nil { if b, _, _, err := jsonparser.Get(data, "environment"); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStack(err)
} else { } else {
s.EnvVars = make(map[string]string) s.EnvVars = make(server.EnvironmentVariables)
if err := json.Unmarshal(b, &s.EnvVars); err != nil { if err := json.Unmarshal(b, &s.EnvVars); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStack(err)
} }

View File

@ -653,7 +653,7 @@ func (d *DockerEnvironment) Create() error {
ExposedPorts: d.exposedPorts(), ExposedPorts: d.exposedPorts(),
Image: d.Server.Container.Image, Image: d.Server.Container.Image,
Env: d.environmentVariables(), Env: d.Server.GetEnvironmentVariables(),
Labels: map[string]string{ Labels: map[string]string{
"Service": "Pterodactyl", "Service": "Pterodactyl",
@ -804,36 +804,6 @@ func (d *DockerEnvironment) parseLogToStrings(b []byte) ([]string, error) {
return out, nil 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 // Converts the server allocation mappings into a format that can be understood
// by Docker. // by Docker.
func (d *DockerEnvironment) portBindings() nat.PortMap { func (d *DockerEnvironment) portBindings() nat.PortMap {

View File

@ -13,6 +13,7 @@ import (
"golang.org/x/sync/semaphore" "golang.org/x/sync/semaphore"
"math" "math"
"os" "os"
"strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -24,6 +25,36 @@ func GetServers() *Collection {
return servers 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. // High level definition for a server instance being controlled by Wings.
type Server struct { type Server struct {
// The unique identifier for the server that should be used when referencing // 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 // An array of environment variables that should be passed along to the running
// server process. // server process.
EnvVars map[string]string `json:"environment" yaml:"environment"` EnvVars EnvironmentVariables `json:"environment" yaml:"environment"`
Archiver Archiver `json:"-" yaml:"-"` Archiver Archiver `json:"-" yaml:"-"`
CrashDetection CrashDetection `json:"crash_detection" yaml:"crash_detection"` CrashDetection CrashDetection `json:"crash_detection" yaml:"crash_detection"`
@ -287,14 +318,14 @@ func (s *Server) GetEnvironmentVariables() []string {
} }
eloop: eloop:
for k, v := range s.EnvVars { for k := range s.EnvVars {
for _, e := range out { for _, e := range out {
if strings.HasPrefix(e, strings.ToUpper(k)) { if strings.HasPrefix(e, strings.ToUpper(k)) {
continue eloop 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 return out