Compare commits

..

1 Commits

Author SHA1 Message Date
Dane Everitt
893cf9f7e2 Bump for release 2020-05-17 18:26:06 -07:00
35 changed files with 278 additions and 512 deletions

View File

@@ -7,6 +7,4 @@ compress:
cross-build: clean build compress
clean:
rm -rf build/wings_*
.PHONY: all build compress clean
rm -rf build/wings_*

View File

@@ -4,9 +4,9 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/apex/log"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config"
"go.uber.org/zap"
"io/ioutil"
"net/http"
"strings"
@@ -58,11 +58,13 @@ func (r *PanelRequest) logDebug(req *http.Request) {
headers[k] = []string{v[0][0:15] + "(redacted)"}
}
log.WithFields(log.Fields{
"method": req.Method,
"endpoint": req.URL.String(),
"headers": headers,
}).Debug("making request to external HTTP endpoint")
zap.S().Debugw(
"making request to external HTTP endpoint",
zap.String("method", req.Method),
zap.String("endpoint", req.URL.String()),
zap.Any("headers", headers),
)
}
func (r *PanelRequest) Get(url string) (*http.Response, error) {

View File

@@ -3,9 +3,7 @@ package cmd
import (
"crypto/tls"
"fmt"
"github.com/apex/log"
"github.com/mitchellh/colorstring"
"github.com/pterodactyl/wings/loggers/cli"
"net/http"
"os"
"path"
@@ -95,10 +93,10 @@ func rootCmdRun(*cobra.Command, []string) {
panic(err)
}
log.WithField("path", c.GetPath()).Info("loading configuration from path")
zap.S().Infof("using configuration from path: %s", c.GetPath())
if c.Debug {
log.Debug("running in debug mode")
log.Info("certificate checking is disabled")
zap.S().Debugw("running in debug mode")
zap.S().Infow("certificate checking is disabled")
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{
InsecureSkipVerify: true,
@@ -109,47 +107,42 @@ func rootCmdRun(*cobra.Command, []string) {
config.SetDebugViaFlag(debug)
if err := c.System.ConfigureDirectories(); err != nil {
log.Fatal("failed to configure system directories for pterodactyl")
panic(err)
zap.S().Panicw("failed to configure system directories for pterodactyl", zap.Error(err))
return
}
log.WithField("username", c.System.Username).Info("checking for pterodactyl system user")
zap.S().Infof("checking for pterodactyl system user \"%s\"", c.System.Username)
if su, err := c.EnsurePterodactylUser(); err != nil {
log.Error("failed to create pterodactyl system user")
panic(err)
zap.S().Panicw("failed to create pterodactyl system user", zap.Error(err))
return
} else {
log.WithFields(log.Fields{
"username": su.Username,
"uid": su.Uid,
"gid": su.Gid,
}).Info("configured system user successfully")
zap.S().Infow("configured system user", zap.String("username", su.Username), zap.String("uid", su.Uid), zap.String("gid", su.Gid))
}
log.Info("beginning file permission setting on server data directories")
zap.S().Infow("beginning file permission setting on server data directories")
if err := c.EnsureFilePermissions(); err != nil {
log.WithField("error", err).Error("failed to properly chown data directories")
zap.S().Errorw("failed to properly chown data directories", zap.Error(err))
} else {
log.Info("finished ensuring file permissions")
zap.S().Infow("finished ensuring file permissions")
}
if err := server.LoadDirectory(); err != nil {
log.WithField("error", err).Fatal("failed to load server configurations")
zap.S().Fatalw("failed to load server configurations", zap.Error(errors.WithStack(err)))
return
}
if err := environment.ConfigureDocker(&c.Docker); err != nil {
log.WithField("error", err).Fatal("failed to configure docker environment")
zap.S().Fatalw("failed to configure docker environment", zap.Error(errors.WithStack(err)))
os.Exit(1)
}
if err := c.WriteToDisk(); err != nil {
log.WithField("error", err).Error("failed to save configuration to disk")
zap.S().Errorw("failed to save configuration to disk", zap.Error(errors.WithStack(err)))
}
// Just for some nice log output.
for _, s := range server.GetServers().All() {
log.WithField("server", s.Uuid).Info("loaded configuration for server")
zap.S().Infow("loaded configuration for server", zap.String("server", s.Uuid))
}
// Create a new WaitGroup that limits us to 4 servers being bootstrapped at a time
@@ -161,23 +154,18 @@ func rootCmdRun(*cobra.Command, []string) {
wg.Add()
go func(s *server.Server) {
// Required for tracing purposes.
var err error
defer func() {
s.Log().Trace("ensuring server environment exists").Stop(&err)
wg.Done()
}()
defer wg.Done()
// Create a server environment if none exists currently. This allows us to recover from Docker
// being reinstalled on the host system for example.
if err = s.Environment.Create(); err != nil {
s.Log().WithField("error", err).Error("failed to process environment")
zap.S().Infow("ensuring environment exists", zap.String("server", s.Uuid))
if err := s.Environment.Create(); err != nil {
zap.S().Errorw("failed to create an environment for server", zap.String("server", s.Uuid), zap.Error(err))
}
r, err := s.Environment.IsRunning()
if err != nil {
s.Log().WithField("error", err).Error("error checking server environment status")
zap.S().Errorw("error checking server environment status", zap.String("server", s.Uuid), zap.Error(err))
}
// If the server is currently running on Docker, mark the process as being in that state.
@@ -187,9 +175,13 @@ func rootCmdRun(*cobra.Command, []string) {
// This will also validate that a server process is running if the last tracked state we have
// is that it was running, but we see that the container process is not currently running.
if r || (!r && s.IsRunning()) {
s.Log().Info("detected server is running, re-attaching to process...")
zap.S().Infow("detected server is running, re-attaching to process", zap.String("server", s.Uuid))
if err := s.Environment.Start(); err != nil {
s.Log().WithField("error", errors.WithStack(err)).Warn("failed to properly start server detected as already running")
zap.S().Warnw(
"failed to properly start server detected as already running",
zap.String("server", s.Uuid),
zap.Error(errors.WithStack(err)),
)
}
return
@@ -204,37 +196,33 @@ func rootCmdRun(*cobra.Command, []string) {
// Wait until all of the servers are ready to go before we fire up the HTTP server.
wg.Wait()
// Initalize SFTP.
sftp.Initialize(c)
// If the SFTP subsystem should be started, do so now.
if c.System.Sftp.UseInternalSystem {
sftp.Initialize(c)
}
// Ensure the archive directory exists.
if err := os.MkdirAll(c.System.ArchiveDirectory, 0755); err != nil {
log.WithField("error", err).Error("failed to create archive directory")
zap.S().Errorw("failed to create archive directory", zap.Error(err))
}
// Ensure the backup directory exists.
if err := os.MkdirAll(c.System.BackupDirectory, 0755); err != nil {
log.WithField("error", err).Error("failed to create backup directory")
zap.S().Errorw("failed to create backup directory", zap.Error(err))
}
log.WithFields(log.Fields{
"ssl": c.Api.Ssl.Enabled,
"host": c.Api.Host,
"port": c.Api.Port,
}).Info("configuring webserver...")
zap.S().Infow("configuring webserver", zap.Bool("ssl", c.Api.Ssl.Enabled), zap.String("host", c.Api.Host), zap.Int("port", c.Api.Port))
r := router.Configure()
addr := fmt.Sprintf("%s:%d", c.Api.Host, c.Api.Port)
if c.Api.Ssl.Enabled {
if err := r.RunTLS(addr, c.Api.Ssl.CertificateFile, c.Api.Ssl.KeyFile); err != nil {
log.WithField("error", err).Fatal("failed to configure HTTPS server")
os.Exit(1)
zap.S().Fatalw("failed to configure HTTPS server", zap.Error(err))
}
} else {
if err := r.Run(addr); err != nil {
log.WithField("error", err).Fatal("failed to configure HTTP server")
os.Exit(1)
zap.S().Fatalw("failed to configure HTTP server", zap.Error(err))
}
}
}
@@ -264,9 +252,6 @@ func configureLogging(debug bool) error {
zap.ReplaceGlobals(logger)
log.SetHandler(cli.Default)
log.SetLevel(log.DebugLevel)
return nil
}

View File

@@ -3,10 +3,10 @@ package config
import (
"errors"
"fmt"
"github.com/apex/log"
"github.com/cobaugh/osrelease"
"github.com/creasty/defaults"
"github.com/gbrlsnchs/jwt/v3"
"go.uber.org/zap"
"gopkg.in/yaml.v2"
"io/ioutil"
"os"
@@ -84,6 +84,9 @@ type Configuration struct {
// Defines the configuration of the internal SFTP server.
type SftpConfiguration struct {
// If set to false, the internal SFTP server will not be booted and you will need
// to run the SFTP server independent of this program.
UseInternalSystem bool `default:"true" json:"use_internal" yaml:"use_internal"`
// If set to true disk checking will not be performed. This will prevent the SFTP
// server from checking the total size of a directory when uploading files.
DisableDiskChecking bool `default:"false" yaml:"disable_disk_checking"`
@@ -296,7 +299,7 @@ func (c *Configuration) EnsureFilePermissions() error {
gid, _ := strconv.Atoi(su.Gid)
if err := os.Chown(path.Join(c.System.Data, f.Name()), uid, gid); err != nil {
log.WithField("error", err).WithField("directory", f.Name()).Warn("failed to chown server directory")
zap.S().Warnw("failed to chown server directory", zap.String("directory", f.Name()), zap.Error(err))
}
}(file)
}

View File

@@ -1,7 +1,7 @@
package config
import (
"github.com/apex/log"
"go.uber.org/zap"
"os"
"path"
)
@@ -51,33 +51,33 @@ type SystemConfiguration struct {
// the user did not press the stop button, but the process stopped cleanly.
DetectCleanExitAsCrash bool `default:"true" yaml:"detect_clean_exit_as_crash"`
Sftp SftpConfiguration `yaml:"sftp"`
Sftp *SftpConfiguration `yaml:"sftp"`
}
// Ensures that all of the system directories exist on the system. These directories are
// created so that only the owner can read the data, and no other users.
func (sc *SystemConfiguration) ConfigureDirectories() error {
log.WithField("path", sc.RootDirectory).Debug("ensuring root data directory exists")
zap.S().Debugw("ensuring root data directory exists", zap.String("path", sc.RootDirectory))
if err := os.MkdirAll(sc.RootDirectory, 0700); err != nil {
return err
}
log.WithField("path", sc.LogDirectory).Debug("ensuring log directory exists")
zap.S().Debugw("ensuring log directory exists", zap.String("path", sc.LogDirectory))
if err := os.MkdirAll(path.Join(sc.LogDirectory, "/install"), 0700); err != nil {
return err
}
log.WithField("path", sc.Data).Debug("ensuring server data directory exists")
zap.S().Debugw("ensuring server data directory exists", zap.String("path", sc.Data))
if err := os.MkdirAll(sc.Data, 0700); err != nil {
return err
}
log.WithField("path", sc.ArchiveDirectory).Debug("ensuring archive data directory exists")
zap.S().Debugw("ensuring archive data directory exists", zap.String("path", sc.ArchiveDirectory))
if err := os.MkdirAll(sc.ArchiveDirectory, 0700); err != nil {
return err
}
log.WithField("path", sc.BackupDirectory).Debug("ensuring backup data directory exists")
zap.S().Debugw("ensuring backup data directory exists", zap.String("path", sc.BackupDirectory))
if err := os.MkdirAll(sc.BackupDirectory, 0700); err != nil {
return err
}

View File

@@ -2,12 +2,12 @@ package environment
import (
"context"
"github.com/apex/log"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client"
"github.com/pterodactyl/wings/config"
"go.uber.org/zap"
)
// Configures the required network for the docker environment.
@@ -20,10 +20,10 @@ func ConfigureDocker(c *config.DockerConfiguration) error {
resource, err := cli.NetworkInspect(context.Background(), c.Network.Name, types.NetworkInspectOptions{})
if err != nil && client.IsErrNotFound(err) {
log.Info("creating missing pterodactyl0 interface, this could take a few seconds...")
zap.S().Infow("creating missing pterodactyl0 interface, this could take a few seconds...")
return createDockerNetwork(cli, c)
} else if err != nil {
log.WithField("error", err).Fatal("failed to create required docker network for containers")
zap.S().Fatalw("failed to create required docker network for containers", zap.Error(err))
}
switch resource.Driver {

3
go.mod
View File

@@ -16,7 +16,6 @@ require (
github.com/Jeffail/gabs/v2 v2.2.0
github.com/Microsoft/go-winio v0.4.7 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/apex/log v1.3.0
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
github.com/aws/aws-sdk-go v1.30.14 // indirect
github.com/beevik/etree v1.1.0
@@ -28,7 +27,6 @@ require (
github.com/docker/docker v0.0.0-20180422163414-57142e89befe
github.com/docker/go-connections v0.4.0
github.com/docker/go-units v0.3.3 // indirect
github.com/fatih/color v1.9.0
github.com/gabriel-vasile/mimetype v0.1.4
github.com/gbrlsnchs/jwt/v3 v3.0.0-rc.0
github.com/ghodss/yaml v1.0.0
@@ -42,7 +40,6 @@ require (
github.com/imdario/mergo v0.3.8
github.com/klauspost/pgzip v1.2.3
github.com/magiconair/properties v1.8.1
github.com/mattn/go-colorable v0.1.4
github.com/mattn/go-shellwords v1.0.10 // indirect
github.com/mholt/archiver/v3 v3.3.0
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db

41
go.sum
View File

@@ -18,19 +18,11 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andybalholm/brotli v0.0.0-20190621154722-5f990b63d2d6 h1:bZ28Hqta7TFAK3Q08CMvv8y3/8ATaEqv2nGoc6yff6c=
github.com/andybalholm/brotli v0.0.0-20190621154722-5f990b63d2d6/go.mod h1:+lx6/Aqd1kLJ1GQfkvOnaZ1WGmLpMpbprPuIOOZX30U=
github.com/apex/log v1.3.0 h1:1fyfbPvUwD10nMoh3hY6MXzvZShJQn9/ck7ATgAt5pA=
github.com/apex/log v1.3.0/go.mod h1:jd8Vpsr46WAe3EZSQ/IUMs2qQD/GOycT5rPWCO1yGcs=
github.com/apex/logs v0.0.4/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo=
github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE=
github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.30.14 h1:vZfX2b/fknc9wKcytbLWykM7in5k6dbQ8iHTJDUP1Ng=
github.com/aws/aws-sdk-go v1.30.14/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo=
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -67,10 +59,6 @@ github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gabriel-vasile/mimetype v0.1.4 h1:5mcsq3+DXypREUkW+1juhjeKmE/XnWgs+paHMJn7lf8=
@@ -85,7 +73,6 @@ github.com/gin-gonic/gin v1.6.2 h1:88crIK23zO6TqlQBt+f9FrPJNKm9ZEr7qjp9vl/d5TM=
github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
@@ -134,7 +121,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 h1:VHgatEHNcBFEB7inlalqfNqw65aNkM1lGX2yt3NmbS8=
github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE=
github.com/icza/dyno v0.0.0-20200205103839-49cb13720835 h1:f1irK5f03uGGj+FjgQfZ5VhdKNVQVJ4skHsedzVohQ4=
@@ -143,11 +129,9 @@ github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ=
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
@@ -173,7 +157,6 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ=
github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -186,14 +169,9 @@ github.com/magefile/mage v1.9.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQ
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-shellwords v1.0.10 h1:Y7Xqm8piKOO3v10Thp7Z36h4FYFjt5xB//6XvOrs2Gw=
@@ -219,8 +197,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA
github.com/nwaples/rardecode v1.0.0 h1:r7vGuS5akxOnR4JQSkko62RJ1ReCMXxQRPtxsiFMBOs=
github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
@@ -262,22 +238,17 @@ github.com/pterodactyl/sftp-server v1.1.2/go.mod h1:KjSONrenRr1oCh94QIVAU6yEzMe+
github.com/remeh/sizedwaitgroup v0.0.0-20180822144253-5e7302b12cce h1:aP+C+YbHZfOQlutA4p4soHi7rVUqHQdWEVMSkHfDTqY=
github.com/remeh/sizedwaitgroup v0.0.0-20180822144253-5e7302b12cce/go.mod h1:3j2R4OIe/SeS6YDhICBy22RWjJC5eNCJ1V+9+NVNYlo=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94 h1:G04eS0JkAIVZfaJLjla9dNxkJCPiKIGZlw9AfOhzOD0=
github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94/go.mod h1:b18R55ulyQ/h3RaWyloPyER7fWQVZvimKKhnI5OfrJQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
@@ -298,11 +269,6 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0=
github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao=
github.com/tj/go-spin v1.1.0 h1:lhdWZsvImxvZ3q1C5OIB7d72DuOwP4O2NdBg9PyzNds=
github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/uber-go/zap v1.9.1/go.mod h1:GY+83l3yxBcBw2kmHu/sAWwItnTn+ynxHCRo+WiIQOY=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
@@ -346,7 +312,6 @@ go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -371,7 +336,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -396,14 +360,12 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03i
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=
@@ -451,15 +413,12 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=

View File

@@ -2,13 +2,13 @@ package installer
import (
"encoding/json"
"github.com/apex/log"
"github.com/asaskevich/govalidator"
"github.com/buger/jsonparser"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/server"
"go.uber.org/zap"
"os"
"path"
)
@@ -108,27 +108,24 @@ func (i *Installer) Server() *server.Server {
// associated installation process based on the parameters passed through for
// the server instance.
func (i *Installer) Execute() {
p := path.Join(config.Get().System.Data, i.Uuid())
l := log.WithFields(log.Fields{"server": i.Uuid(), "process": "installer"})
l.WithField("path", p).Debug("creating required server data directory")
if err := os.MkdirAll(p, 0755); err != nil {
l.WithFields(log.Fields{"path": p, "error": errors.WithStack(err)}).Error("failed to create server data directory")
zap.S().Debugw("creating required server data directory", zap.String("server", i.Uuid()))
if err := os.MkdirAll(path.Join(config.Get().System.Data, i.Uuid()), 0755); err != nil {
zap.S().Errorw("failed to create server data directory", zap.String("server", i.Uuid()), zap.Error(errors.WithStack(err)))
return
}
if err := os.Chown(p, config.Get().System.User.Uid, config.Get().System.User.Gid); err != nil {
l.WithField("error", errors.WithStack(err)).Error("failed to chown server data directory")
if err := os.Chown(path.Join(config.Get().System.Data, i.Uuid()), config.Get().System.User.Uid, config.Get().System.User.Gid); err != nil {
zap.S().Errorw("failed to chown server data directory", zap.String("server", i.Uuid()), zap.Error(errors.WithStack(err)))
return
}
l.Debug("creating required environment for server instance")
zap.S().Debugw("creating required environment for server instance", zap.String("server", i.Uuid()))
if err := i.server.Environment.Create(); err != nil {
l.WithField("error", err).Error("failed to create environment for server")
zap.S().Errorw("failed to create environment for server", zap.String("server", i.Uuid()), zap.Error(err))
return
}
l.Info("successfully created environment for server during install process")
zap.S().Debugw("created environment for server during install process", zap.String("server", i.Uuid()))
}
// Returns a string value from the JSON data provided.

View File

@@ -1,93 +0,0 @@
package cli
import (
"fmt"
"github.com/apex/log"
"github.com/apex/log/handlers/cli"
color2 "github.com/fatih/color"
"github.com/mattn/go-colorable"
"github.com/pkg/errors"
"io"
"os"
"sync"
"time"
)
var Default = New(os.Stderr)
var bold = color2.New(color2.Bold)
var Strings = [...]string{
log.DebugLevel: "DEBUG",
log.InfoLevel: " INFO",
log.WarnLevel: " WARN",
log.ErrorLevel: "ERROR",
log.FatalLevel: "FATAL",
}
type Handler struct {
mu sync.Mutex
Writer io.Writer
Padding int
}
func New(w io.Writer) *Handler {
if f, ok := w.(*os.File); ok {
return &Handler{Writer: colorable.NewColorable(f), Padding: 2}
}
return &Handler{Writer: w, Padding: 2}
}
type tracer interface {
StackTrace() errors.StackTrace
}
// HandleLog implements log.Handler.
func (h *Handler) HandleLog(e *log.Entry) error {
color := cli.Colors[e.Level]
level := Strings[e.Level]
names := e.Fields.Names()
h.mu.Lock()
defer h.mu.Unlock()
color.Fprintf(h.Writer, "%s: [%s] %-25s", bold.Sprintf("%*s", h.Padding+1, level), time.Now().Format(time.StampMilli), e.Message)
for _, name := range names {
if name == "source" {
continue
}
fmt.Fprintf(h.Writer, " %s=%v", color.Sprint(name), e.Fields.Get(name))
}
fmt.Fprintln(h.Writer)
for _, name := range names {
if name != "error" {
continue
}
if err, ok := e.Fields.Get("error").(error); ok {
if e, ok := errors.Cause(err).(tracer); ok {
st := e.StackTrace()
l := len(st)
if l > 5 {
l = 5
}
br := color2.New(color2.Bold, color2.FgRed)
fmt.Fprintf(h.Writer, "\n%s%+v\n\n", br.Sprintf("Stacktrace:"), st[0:l])
} else {
fmt.Printf("\n\nINVALID TRACER\n\n")
}
} else {
fmt.Printf("\n\nINVALID ERROR\n\n")
}
}
return nil
}

View File

@@ -3,10 +3,10 @@ package parser
import (
"bytes"
"github.com/Jeffail/gabs/v2"
"github.com/apex/log"
"github.com/buger/jsonparser"
"github.com/iancoleman/strcase"
"github.com/pkg/errors"
"go.uber.org/zap"
"io/ioutil"
"os"
"regexp"
@@ -120,9 +120,11 @@ func (cfr *ConfigurationFileReplacement) SetAtPathway(c *gabs.Container, path st
// We're doing some regex here.
r, err := regexp.Compile(strings.TrimPrefix(cfr.IfValue, "regex:"))
if err != nil {
log.WithFields(log.Fields{"if_value": strings.TrimPrefix(cfr.IfValue, "regex:"), "error": err}).
Warn("configuration if_value using invalid regexp, cannot perform replacement")
zap.S().Warnw(
"configuration if_value using invalid regexp, cannot do replacement",
zap.String("if_value", strings.TrimPrefix(cfr.IfValue, "regex:")),
zap.Error(err),
)
return nil
}
@@ -177,7 +179,11 @@ func (f *ConfigurationFile) LookupConfigurationValue(cfr ConfigurationFileReplac
return match, errors.WithStack(err)
}
log.WithFields(log.Fields{"path": path, "filename": f.FileName}).Debug("attempted to load a configuration value that does not exist")
zap.S().Debugw(
"attempted to load a configuration value that does not exist",
zap.Strings("path", path),
zap.String("filename", f.FileName),
)
// If there is no key, keep the original value intact, that way it is obvious there
// is a replace issue at play.

View File

@@ -3,13 +3,13 @@ package parser
import (
"bufio"
"encoding/json"
"github.com/apex/log"
"github.com/beevik/etree"
"github.com/buger/jsonparser"
"github.com/icza/dyno"
"github.com/magiconair/properties"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config"
"go.uber.org/zap"
"gopkg.in/ini.v1"
"gopkg.in/yaml.v2"
"io/ioutil"
@@ -30,10 +30,6 @@ const (
type ConfigurationParser string
func (cp ConfigurationParser) String() string {
return string(cp)
}
// Defines a configuration file for the server startup. These will be looped over
// and modified before the server finishes booting.
type ConfigurationFile struct {
@@ -67,7 +63,11 @@ func (f *ConfigurationFile) UnmarshalJSON(data []byte) error {
}
if err := json.Unmarshal(*m["replace"], &f.Replace); err != nil {
log.WithField("file", f.FileName).WithField("error", err).Warn("failed to unmarshal configuration file replacement")
zap.S().Warnw(
"failed to unmarshal configuration file replacement",
zap.String("file", f.FileName),
zap.Error(err),
)
f.Replace = []ConfigurationFileReplacement{}
}
@@ -131,7 +131,7 @@ func (cfr *ConfigurationFileReplacement) UnmarshalJSON(data []byte) error {
// Parses a given configuration file and updates all of the values within as defined
// in the API response from the Panel.
func (f *ConfigurationFile) Parse(path string, internal bool) error {
log.WithField("path", path).WithField("parser", f.Parser.String()).Debug("parsing server configuration file")
zap.S().Debugw("parsing configuration file", zap.String("path", path), zap.String("parser", string(f.Parser)))
if mb, err := json.Marshal(config.Get()); err != nil {
return err

View File

@@ -2,11 +2,11 @@ package router
import (
"fmt"
"github.com/apex/log"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/server"
"go.uber.org/zap"
"net/http"
"os"
)
@@ -40,14 +40,6 @@ func TrackedServerError(err error, s *server.Server) *RequestError {
}
}
func (e *RequestError) logger() *log.Entry {
if e.server != nil {
return e.server.Log().WithField("error_id", e.Uuid)
}
return log.WithField("error_id", e.Uuid)
}
// Sets the output message to display to the user in the error.
func (e *RequestError) SetMessage(msg string) *RequestError {
e.Message = msg
@@ -69,11 +61,19 @@ func (e *RequestError) AbortWithStatus(status int, c *gin.Context) {
// Otherwise, log the error to zap, and then report the error back to the user.
if status >= 500 {
e.logger().WithField("error", e.Err).Error("encountered HTTP/500 error while handling request")
if e.server != nil {
zap.S().Errorw("encountered error while handling HTTP request", zap.String("server", e.server.Uuid), zap.String("error_id", e.Uuid), zap.Error(e.Err))
} else {
zap.S().Errorw("encountered error while handling HTTP request", zap.String("error_id", e.Uuid), zap.Error(e.Err))
}
c.Error(errors.WithStack(e))
} else {
e.logger().WithField("error", e.Err).Debug("encountered non-HTTP/500 error while handling request")
if e.server != nil {
zap.S().Debugw("encountered error while handling HTTP request", zap.String("server", e.server.Uuid), zap.String("error_id", e.Uuid), zap.Error(e.Err))
} else {
zap.S().Debugw("encountered error while handling HTTP request", zap.String("error_id", e.Uuid), zap.Error(e.Err))
}
}
msg := "An unexpected error was encountered while processing this request."

View File

@@ -1,32 +1,13 @@
package router
import (
"github.com/apex/log"
"github.com/gin-gonic/gin"
)
// Configures the routing infrastructure for this daemon instance.
func Configure() *gin.Engine {
gin.SetMode("release")
router := gin.New()
router.Use(gin.Recovery())
router := gin.Default()
router.Use(SetAccessControlHeaders)
// @todo log this into a different file so you can setup IP blocking for abusive requests and such.
// This should still dump requests in debug mode since it does help with understanding the request
// lifecycle and quickly seeing what was called leading to the logs. However, it isn't feasible to mix
// this output in production and still get meaningful logs from it since they'll likely just be a huge
// spamfest.
router.Use(gin.LoggerWithFormatter(func(params gin.LogFormatterParams) string {
log.WithFields(log.Fields{
"client_ip": params.ClientIP,
"status": params.StatusCode,
"latency": params.Latency,
}).Debugf("%s %s", params.MethodColor()+params.Method+params.ResetColor(), params.Path)
return ""
}))
router.OPTIONS("/api/system", func(c *gin.Context) {
c.Status(200)

View File

@@ -2,10 +2,10 @@ package router
import (
"bytes"
"github.com/apex/log"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/server"
"go.uber.org/zap"
"net/http"
"os"
"strconv"
@@ -46,10 +46,7 @@ func postServerPower(c *gin.Context) {
s := GetServer(c.Param("server"))
var data server.PowerAction
// BindJSON sends 400 if the request fails, all we need to do is return
if err := c.BindJSON(&data); err != nil {
return
}
c.BindJSON(&data)
if !data.IsValid() {
c.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{
@@ -74,12 +71,15 @@ func postServerPower(c *gin.Context) {
// Pass the actual heavy processing off to a seperate thread to handle so that
// we can immediately return a response from the server. Some of these actions
// can take quite some time, especially stopping or restarting.
go func(server *server.Server) {
if err := server.HandlePowerAction(data); err != nil {
server.Log().WithFields(log.Fields{"action": data, "error": err}).
Error("encountered error processing a server power action in the background")
go func() {
if err := s.HandlePowerAction(data); err != nil {
zap.S().Errorw(
"encountered an error processing a server power action",
zap.String("server", s.Uuid),
zap.Error(err),
)
}
}(s)
}()
c.Status(http.StatusAccepted)
}
@@ -98,17 +98,17 @@ func postServerCommands(c *gin.Context) {
return
}
var data struct {
Commands []string `json:"commands"`
}
// BindJSON sends 400 if the request fails, all we need to do is return
if err := c.BindJSON(&data); err != nil {
return
}
var data struct{ Commands []string `json:"commands"` }
c.BindJSON(&data)
for _, command := range data.Commands {
if err := s.Environment.SendCommand(command); err != nil {
s.Log().WithFields(log.Fields{"command": command, "error": err}).Warn("failed to send command to server instance")
zap.S().Warnw(
"failed to send command to server",
zap.String("server", s.Uuid),
zap.String("command", command),
zap.Error(err),
)
}
}
@@ -136,7 +136,11 @@ func postServerInstall(c *gin.Context) {
go func(serv *server.Server) {
if err := serv.Install(); err != nil {
serv.Log().WithField("error", err).Error("failed to execute server installation process")
zap.S().Errorw(
"failed to execute server installation process",
zap.String("server", serv.Uuid),
zap.Error(err),
)
}
}(s)
@@ -149,7 +153,11 @@ func postServerReinstall(c *gin.Context) {
go func(serv *server.Server) {
if err := serv.Reinstall(); err != nil {
serv.Log().WithField("error", err).Error("failed to complete server re-install process")
zap.S().Errorw(
"failed to complete server reinstall process",
zap.String("server", serv.Uuid),
zap.Error(err),
)
}
}(s)
@@ -167,7 +175,7 @@ func deleteServer(c *gin.Context) {
// Delete the server's archive if it exists. We intentionally don't return
// here, if the archive fails to delete, the server can still be removed.
if err := s.Archiver.DeleteIfExists(); err != nil {
s.Log().WithField("error", err).Warn("failed to delete server archive during deletion process")
zap.S().Warnw("failed to delete server archive during deletion process", zap.String("server", s.Uuid), zap.Error(err))
}
// Unsubscribe all of the event listeners.
@@ -188,10 +196,7 @@ func deleteServer(c *gin.Context) {
// so we don't want to block the HTTP call while waiting on this.
go func(p string) {
if err := os.RemoveAll(p); err != nil {
log.WithFields(log.Fields{
"path": p,
"error": errors.WithStack(err),
}).Warn("failed to remove server files during deletion process")
zap.S().Warnw("failed to remove server files during deletion process", zap.String("path", p), zap.Error(errors.WithStack(err)))
}
}(s.Filesystem.Path())

View File

@@ -6,6 +6,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/pterodactyl/wings/server"
"github.com/pterodactyl/wings/server/backup"
"go.uber.org/zap"
"net/http"
)
@@ -14,10 +15,7 @@ func postServerBackup(c *gin.Context) {
s := GetServer(c.Param("server"))
data := &backup.Request{}
// BindJSON sends 400 if the request fails, all we need to do is return
if err := c.BindJSON(&data); err != nil {
return
}
c.BindJSON(&data)
var adapter backup.BackupInterface
var err error
@@ -39,10 +37,11 @@ func postServerBackup(c *gin.Context) {
go func(b backup.BackupInterface, serv *server.Server) {
if err := serv.Backup(b); err != nil {
serv.Log().WithField("error", err).Error("failed to generate backup for server")
zap.S().Errorw("failed to generate backup for server", zap.Error(err))
}
}(adapter, s)
c.Status(http.StatusAccepted)
}

View File

@@ -89,10 +89,7 @@ func putServerRenameFile(c *gin.Context) {
RenameFrom string `json:"rename_from"`
RenameTo string `json:"rename_to"`
}
// BindJSON sends 400 if the request fails, all we need to do is return
if err := c.BindJSON(&data); err != nil {
return
}
c.BindJSON(&data)
if data.RenameFrom == "" || data.RenameTo == "" {
c.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{
@@ -116,10 +113,7 @@ func postServerCopyFile(c *gin.Context) {
var data struct {
Location string `json:"location"`
}
// BindJSON sends 400 if the request fails, all we need to do is return
if err := c.BindJSON(&data); err != nil {
return
}
c.BindJSON(&data)
if err := s.Filesystem.Copy(data.Location); err != nil {
TrackedServerError(err, s).AbortWithServerError(c)
@@ -136,10 +130,7 @@ func postServerDeleteFile(c *gin.Context) {
var data struct {
Location string `json:"location"`
}
// BindJSON sends 400 if the request fails, all we need to do is return
if err := c.BindJSON(&data); err != nil {
return
}
c.BindJSON(&data)
if err := s.Filesystem.Delete(data.Location); err != nil {
TrackedServerError(err, s).AbortWithServerError(c)
@@ -176,10 +167,7 @@ func postServerCreateDirectory(c *gin.Context) {
Name string `json:"name"`
Path string `json:"path"`
}
// BindJSON sends 400 if the request fails, all we need to do is return
if err := c.BindJSON(&data); err != nil {
return
}
c.BindJSON(&data)
if err := s.Filesystem.CreateDirectory(data.Name, data.Path); err != nil {
TrackedServerError(err, s).AbortWithServerError(c)

View File

@@ -6,6 +6,7 @@ import (
"github.com/gin-gonic/gin"
ws "github.com/gorilla/websocket"
"github.com/pterodactyl/wings/router/websocket"
"go.uber.org/zap"
)
// Upgrades a connection to a websocket and passes events along between.
@@ -39,7 +40,7 @@ func getServerWebsocket(c *gin.Context) {
ws.CloseServiceRestart,
ws.CloseAbnormalClosure,
) {
s.Log().WithField("error", err).Warn("error handling websocket message for server")
zap.S().Warnw("error handling websocket message", zap.Error(err))
}
break
}
@@ -52,7 +53,8 @@ func getServerWebsocket(c *gin.Context) {
}
if err := handler.HandleInbound(j); err != nil {
handler.SendErrorJson(j, err)
handler.SendErrorJson(err)
}
}
}

View File

@@ -2,12 +2,12 @@ package router
import (
"bytes"
"github.com/apex/log"
"github.com/gin-gonic/gin"
"github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/installer"
"github.com/pterodactyl/wings/server"
"github.com/pterodactyl/wings/system"
"go.uber.org/zap"
"net/http"
)
@@ -59,7 +59,11 @@ func postCreateServer(c *gin.Context) {
i.Execute()
if err := i.Server().Install(); err != nil {
log.WithFields(log.Fields{"server": i.Uuid(), "error": err}).Error("failed to run install process for server")
zap.S().Errorw(
"failed to run install process for server",
zap.String("server", i.Uuid()),
zap.Error(err),
)
}
}(install)
@@ -73,10 +77,7 @@ func postUpdateConfiguration(c *gin.Context) {
// A copy of the configuration we're using to bind the data recevied into.
cfg := *config.Get()
// BindJSON sends 400 if the request fails, all we need to do is return
if err := c.BindJSON(&cfg); err != nil {
return
}
c.BindJSON(&cfg)
config.Set(&cfg)
if err := config.Get().WriteToDisk(); err != nil {
@@ -89,4 +90,4 @@ func postUpdateConfiguration(c *gin.Context) {
}
c.Status(http.StatusNoContent)
}
}

View File

@@ -1,9 +1,7 @@
package websocket
import (
"encoding/json"
"fmt"
"github.com/apex/log"
"github.com/gbrlsnchs/jwt/v3"
"github.com/google/uuid"
"github.com/gorilla/websocket"
@@ -11,6 +9,7 @@ import (
"github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/router/tokens"
"github.com/pterodactyl/wings/server"
"go.uber.org/zap"
"net/http"
"os"
"strings"
@@ -85,6 +84,7 @@ func (h *Handler) SendJson(v *Message) error {
// If we're sending installation output but the user does not have the required
// permissions to see the output, don't send it down the line.
if v.Event == server.InstallOutputEvent {
zap.S().Debugf("%+v", v.Args)
if !j.HasPermission(PermissionReceiveInstall) {
return nil
}
@@ -137,7 +137,10 @@ func (h *Handler) TokenValid() error {
// Sends an error back to the connected websocket instance by checking the permissions
// of the token. If the user has the "receive-errors" grant we will send back the actual
// error message, otherwise we just send back a standard error message.
func (h *Handler) SendErrorJson(msg Message, err error) error {
func (h *Handler) SendErrorJson(err error) error {
h.Lock()
defer h.Unlock()
j := h.GetJwt()
message := "an unexpected error was encountered while handling this request"
@@ -151,11 +154,15 @@ func (h *Handler) SendErrorJson(msg Message, err error) error {
wsm.Args = []string{m}
if !server.IsSuspendedError(err) {
h.server.Log().WithFields(log.Fields{"event": msg.Event, "error_identifier": u.String(), "error": err}).
Error("failed to handle websocket process; an error was encountered processing an event")
zap.S().Errorw(
"an error was encountered in the websocket process",
zap.String("server", h.server.Uuid),
zap.String("error_identifier", u.String()),
zap.Error(err),
)
}
return h.unsafeSendJson(wsm)
return h.Connection.WriteJSON(wsm)
}
// Converts an error message into a more readable representation and returns a UUID
@@ -186,7 +193,7 @@ func (h *Handler) GetJwt() *tokens.WebsocketPayload {
func (h *Handler) HandleInbound(m Message) error {
if m.Event != AuthenticationEvent {
if err := h.TokenValid(); err != nil {
log.WithField("message", err.Error()).Debug("jwt for server websocket is no longer valid")
zap.S().Debugw("jwt token is no longer valid", zap.String("message", err.Error()))
h.unsafeSendJson(Message{
Event: ErrorEvent,
@@ -212,57 +219,19 @@ func (h *Handler) HandleInbound(m Message) error {
return err
}
// Check if the user has previously authenticated successfully.
newConnection := h.GetJwt() == nil
// Previously there was a HasPermission(PermissionConnect) check around this,
// however NewTokenPayload will return an error if it doesn't have the connect
// permission meaning that it was a redundant function call.
h.setJwt(token)
// Tell the client they authenticated successfully.
h.unsafeSendJson(Message{
Event: AuthenticationSuccessEvent,
Args: []string{},
})
// Check if the client was refreshing their authentication token
// instead of authenticating for the first time.
if !newConnection {
// This prevents duplicate status messages as outlined in
// https://github.com/pterodactyl/panel/issues/2077
return nil
if token.HasPermission(PermissionConnect) {
h.setJwt(token)
}
// On every authentication event, send the current server status back
// to the client. :)
state := h.server.GetState()
h.SendJson(&Message{
Event: server.StatusEvent,
Args: []string{state},
h.server.Events().Publish(server.StatusEvent, h.server.GetState())
h.unsafeSendJson(Message{
Event: AuthenticationSuccessEvent,
Args: []string{},
})
// Only send the current disk usage if the server is offline, if docker container is running,
// Environment#EnableResourcePolling() will send this data to all clients.
if state == server.ProcessOfflineState {
_ = h.server.Filesystem.HasSpaceAvailable()
resources := server.ResourceUsage{
Memory: 0,
MemoryLimit: 0,
CpuAbsolute: 0.0,
Disk: h.server.Resources.Disk,
}
resources.Network.RxBytes = 0
resources.Network.TxBytes = 0
b, _ := json.Marshal(resources)
h.SendJson(&Message{
Event: server.StatsEvent,
Args: []string{string(b)},
})
}
return nil
}
case SetStateEvent:

View File

@@ -2,10 +2,10 @@ package server
import (
"bufio"
"github.com/apex/log"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/server/backup"
"go.uber.org/zap"
"os"
"path"
)
@@ -17,15 +17,16 @@ func (s *Server) notifyPanelOfBackup(uuid string, ad *backup.ArchiveDetails, suc
rerr, err := r.SendBackupStatus(uuid, ad.ToRequest(successful))
if rerr != nil || err != nil {
if err != nil {
s.Log().WithFields(log.Fields{
"backup": uuid,
"error": err,
}).Error("failed to notify panel of backup status due to internal code error")
zap.S().Errorw(
"failed to notify panel of backup status due to internal code error",
zap.String("backup", s.Uuid),
zap.Error(err),
)
return err
}
s.Log().WithField("backup", uuid).Warn(rerr.String())
zap.S().Warnw(rerr.String(), zap.String("backup", uuid))
return errors.New(rerr.String())
}
@@ -65,7 +66,7 @@ func (s *Server) GetIncludedBackupFiles(ignored []string) (*backup.IncludedFiles
// of the server files directory, and use that to generate the backup.
if len(ignored) == 0 {
if i, err := s.getServerwideIgnoredFiles(); err != nil {
s.Log().WithField("error", err).Warn("failed to retrieve ignored files listing for server")
zap.S().Warnw("failed to retrieve server ignored files", zap.String("server", s.Uuid), zap.Error(err))
} else {
ignored = i
}
@@ -88,10 +89,7 @@ func (s *Server) Backup(b backup.BackupInterface) error {
ad, err := b.Generate(inc, s.Filesystem.Path())
if err != nil {
if notifyError := s.notifyPanelOfBackup(b.Identifier(), &backup.ArchiveDetails{}, false); notifyError != nil {
s.Log().WithFields(log.Fields{
"backup": b.Identifier(),
"error": err,
}).Warn("failed to notify panel of failed backup state")
zap.S().Warnw("failed to notify panel of failed backup state", zap.String("backup", b.Identifier()), zap.Error(err))
}
return errors.WithStack(err)
@@ -114,4 +112,4 @@ func (s *Server) Backup(b backup.BackupInterface) error {
})
return nil
}
}

View File

@@ -3,9 +3,9 @@ package backup
import (
"archive/tar"
"context"
"github.com/apex/log"
gzip "github.com/klauspost/pgzip"
"github.com/remeh/sizedwaitgroup"
"go.uber.org/zap"
"golang.org/x/sync/errgroup"
"io"
"os"
@@ -67,7 +67,7 @@ func (a *Archive) Create(dest string, ctx context.Context) error {
// Attempt to remove the archive if there is an error, report that error to
// the logger if it fails.
if rerr := os.Remove(dest); rerr != nil && !os.IsNotExist(rerr) {
log.WithField("location", dest).Warn("failed to delete corrupted backup archive")
zap.S().Warnw("failed to delete corrupted backup archive", zap.String("location", dest))
}
return err

View File

@@ -3,10 +3,10 @@ package backup
import (
"crypto/sha256"
"encoding/hex"
"github.com/apex/log"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/config"
"go.uber.org/zap"
"io"
"os"
"path"
@@ -121,10 +121,7 @@ func (b *Backup) Details() *ArchiveDetails {
resp, err := b.Checksum()
if err != nil {
log.WithFields(log.Fields{
"backup": b.Identifier(),
"error": err,
}).Error("failed to calculate checksum for backup")
zap.S().Errorw("failed to calculate checksum for backup", zap.String("backup", b.Uuid), zap.Error(err))
}
checksum = hex.EncodeToString(resp)

View File

@@ -3,7 +3,7 @@ package backup
import (
"context"
"fmt"
"github.com/apex/log"
"go.uber.org/zap"
"io"
"net/http"
"os"
@@ -76,11 +76,8 @@ func (s *S3Backup) generateRemoteRequest(rc io.ReadCloser) (*http.Response, erro
}
r.Body = rc
log.WithFields(log.Fields{
"endpoint": s.PresignedUrl,
"headers": r.Header,
}).Debug("uploading backup to remote S3 endpoint")
zap.S().Debugw("uploading backup to remote S3 endpoint", zap.String("endpoint", s.PresignedUrl), zap.Any("headers", r.Header))
return http.DefaultClient.Do(r)
}

View File

@@ -2,6 +2,7 @@ package server
import (
"github.com/pterodactyl/wings/parser"
"go.uber.org/zap"
"sync"
)
@@ -16,15 +17,15 @@ func (s *Server) UpdateConfigurationFiles() {
go func(f parser.ConfigurationFile, server *Server) {
defer wg.Done()
p, err := server.Filesystem.SafePath(f.FileName)
p, err := s.Filesystem.SafePath(f.FileName)
if err != nil {
server.Log().WithField("error", err).Error("failed to generate safe path for configuration file")
zap.S().Errorw("failed to generate safe path for configuration file", zap.String("server", server.Uuid), zap.Error(err))
return
}
if err := f.Parse(p, false); err != nil {
server.Log().WithField("error", err).Error("failed to parse and update server configuration file")
zap.S().Errorw("failed to parse and update server configuration file", zap.String("server", server.Uuid), zap.Error(err))
}
}(v, s)
}

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config"
"go.uber.org/zap"
"time"
)
@@ -26,13 +27,15 @@ type CrashDetection struct {
//
// If the server is determined to have crashed, the process will be restarted and the
// counter for the server will be incremented.
//
// @todo output event to server console
func (s *Server) handleServerCrash() error {
// No point in doing anything here if the server isn't currently offline, there
// is no reason to do a crash detection event. If the server crash detection is
// disabled we want to skip anything after this as well.
if s.GetState() != ProcessOfflineState || !s.CrashDetection.Enabled {
if !s.CrashDetection.Enabled {
s.Log().Debug("server triggered crash detection but handler is disabled for server process")
zap.S().Debugw("server triggered crash detection but handler is disabled for server process", zap.String("server", s.Uuid))
s.PublishConsoleOutputFromDaemon("Server detected as crashed; crash detection is disabled for this instance.")
}
@@ -48,7 +51,7 @@ func (s *Server) handleServerCrash() error {
// If the system is not configured to detect a clean exit code as a crash, and the
// crash is not the result of the program running out of memory, do nothing.
if exitCode == 0 && !oomKilled && !config.Get().System.DetectCleanExitAsCrash {
s.Log().Debug("server exited with successful exit code; system is configured to not detect this as a crash")
zap.S().Debugw("server exited with successful code; system configured to not detect as crash", zap.String("server", s.Uuid))
return nil
}

View File

@@ -6,7 +6,6 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/apex/log"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/mount"
@@ -16,6 +15,7 @@ import (
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/config"
"go.uber.org/zap"
"io"
"os"
"strconv"
@@ -122,13 +122,11 @@ func (d *DockerEnvironment) InSituUpdate() error {
return errors.WithStack(err)
}
ctx, _ := context.WithTimeout(context.Background(), time.Second * 10)
u := container.UpdateConfig{
Resources: d.getResourcesForServer(),
}
d.Server.Log().WithField("limits", fmt.Sprintf("%+v", u.Resources)).Debug("updating server container on-the-fly with passed limits")
if _, err := d.Client.ContainerUpdate(ctx, d.Server.Uuid, u); err != nil {
if _, err := d.Client.ContainerUpdate(context.Background(), d.Server.Uuid, u); err != nil {
return errors.WithStack(err)
}
@@ -143,7 +141,7 @@ func (d *DockerEnvironment) InSituUpdate() error {
// state. This ensures that unexpected container deletion while Wings is running does
// not result in the server becoming unbootable.
func (d *DockerEnvironment) OnBeforeStart() error {
d.Server.Log().Info("syncing server configuration with panel")
zap.S().Infow("syncing server configuration with Panel", zap.String("server", d.Server.Uuid))
if err := d.Server.Sync(); err != nil {
return err
}
@@ -184,10 +182,6 @@ func (d *DockerEnvironment) Start() error {
// that point.
defer func() {
if sawError {
// If we don't set it to stopping first, you'll trigger crash detection which
// we don't want to do at this point since it'll just immediately try to do the
// exact same action that lead to it crashing in the first place...
d.Server.SetState(ProcessStoppingState)
d.Server.SetState(ProcessOfflineState)
}
}()
@@ -254,8 +248,8 @@ func (d *DockerEnvironment) Start() error {
return errors.WithStack(err)
}
ctx, _ := context.WithTimeout(context.Background(), time.Second * 10)
if err := d.Client.ContainerStart(ctx, d.Server.Uuid, types.ContainerStartOptions{}); err != nil {
opts := types.ContainerStartOptions{}
if err := d.Client.ContainerStart(context.Background(), d.Server.Uuid, opts); err != nil {
return errors.WithStack(err)
}
@@ -424,7 +418,7 @@ func (d *DockerEnvironment) Attach() error {
d.attached = true
go func() {
if err := d.EnableResourcePolling(); err != nil {
d.Server.Log().WithField("error", errors.WithStack(err)).Warn("failed to enable resource polling on server")
zap.S().Warnw("failed to enabled resource polling on server", zap.String("server", d.Server.Uuid), zap.Error(errors.WithStack(err)))
}
}()
@@ -472,7 +466,7 @@ func (d *DockerEnvironment) FollowConsoleOutput() error {
}
if err := s.Err(); err != nil {
d.Server.Log().WithField("error", err).Warn("error processing scanner line in console output")
zap.S().Warnw("error processing scanner line in console output", zap.String("server", d.Server.Uuid), zap.Error(err))
}
}(reader)
@@ -502,7 +496,7 @@ func (d *DockerEnvironment) EnableResourcePolling() error {
if err := dec.Decode(&v); err != nil {
if err != io.EOF {
d.Server.Log().WithField("error", err).Warn("encountered error processing server stats, stopping collection")
zap.S().Warnw("encountered error processing server stats; stopping collection", zap.Error(err))
}
d.DisableResourcePolling()
@@ -553,48 +547,17 @@ func (d *DockerEnvironment) DisableResourcePolling() error {
return errors.WithStack(err)
}
// Pulls the image from Docker. If there is an error while pulling the image from the source
// but the image already exists locally, we will report that error to the logger but continue
// with the process.
//
// The reasoning behind this is that Quay has had some serious outages as of late, and we don't
// need to block all of the servers from booting just because of that. I'd imagine in a lot of
// cases an outage shouldn't affect users too badly. It'll at least keep existing servers working
// correctly if anything.
// Pulls the image from Docker.
//
// @todo handle authorization & local images
func (d *DockerEnvironment) ensureImageExists(c *client.Client) error {
ctx, _ := context.WithTimeout(context.Background(), time.Second*10)
out, err := c.ImagePull(ctx, d.Server.Container.Image, types.ImagePullOptions{All: false})
out, err := c.ImagePull(context.Background(), d.Server.Container.Image, types.ImagePullOptions{All: false})
if err != nil {
images, ierr := c.ImageList(ctx, types.ImageListOptions{})
if ierr != nil {
// Well damn, something has gone really wrong here, just go ahead and abort there
// isn't much anything we can do to try and self-recover from this.
return ierr
}
for _, img := range images {
for _, t := range img.RepoTags {
if t == d.Server.Container.Image {
d.Server.Log().WithFields(log.Fields{
"image": d.Server.Container.Image,
"error": errors.New(err.Error()),
}).Warn("unable to pull requested image from remote source, however the image exists locally")
// Okay, we found a matching container image, in that case just go ahead and return
// from this function, since there is nothing else we need to do here.
return nil
}
}
}
return err
}
defer out.Close()
log.WithField("image", d.Server.Container.Image).Debug("pulling docker image... this could take a bit of time")
zap.S().Debugw("pulling docker image... this could take a bit of time", zap.String("image", d.Server.Container.Image))
// I'm not sure what the best approach here is, but this will block execution until the image
// is done being pulled, which is what we need.

View File

@@ -11,6 +11,7 @@ import (
"github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/server/backup"
ignore "github.com/sabhiram/go-gitignore"
"go.uber.org/zap"
"io"
"io/ioutil"
"os"
@@ -133,7 +134,7 @@ func (fs *Filesystem) HasSpaceAvailable() bool {
// the cache once we've gotten it.
size, err := fs.DirectorySize("/")
if err != nil {
fs.Server.Log().WithField("error", err).Warn("failed to determine root server directory size")
zap.S().Warnw("failed to determine directory size", zap.String("server", fs.Server.Uuid), zap.Error(err))
}
// Always cache the size, even if there is an error. We want to always return that value

View File

@@ -4,7 +4,6 @@ import (
"bufio"
"bytes"
"context"
"github.com/apex/log"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/mount"
@@ -12,6 +11,7 @@ import (
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/config"
"go.uber.org/zap"
"io"
"io/ioutil"
"os"
@@ -25,12 +25,14 @@ import (
func (s *Server) Install() error {
err := s.internalInstall()
s.Log().Debug("notifying panel of server install state")
zap.S().Debugw("notifying panel of server install state", zap.String("server", s.Uuid))
if serr := s.SyncInstallState(err == nil); serr != nil {
s.Log().WithFields(log.Fields{
"was_successful": err == nil,
"error": serr,
}).Warn("failed to notify panel of server install state")
zap.S().Warnw(
"failed to notify panel of server install state",
zap.String("server", s.Uuid),
zap.Bool("was_successful", err == nil),
zap.Error(serr),
)
}
return err
@@ -40,7 +42,7 @@ func (s *Server) Install() error {
// does not touch any existing files for the server, other than what the script modifies.
func (s *Server) Reinstall() error {
if s.GetState() != ProcessOfflineState {
s.Log().Debug("waiting for server instance to enter a stopped state")
zap.S().Debugw("waiting for server instance to enter a stopped state", zap.String("server", s.Uuid))
if err := s.Environment.WaitForStop(10, true); err != nil {
return err
}
@@ -65,12 +67,14 @@ func (s *Server) internalInstall() error {
return errors.WithStack(err)
}
s.Log().Info("beginning installation process for server")
zap.S().Infow("beginning installation process for server", zap.String("server", s.Uuid))
if err := p.Run(); err != nil {
return err
}
s.Log().Info("completed installation process for server")
zap.S().Infow("completed installation process for server", zap.String("server", s.Uuid))
return nil
}
@@ -102,13 +106,13 @@ func NewInstallationProcess(s *Server, script *api.InstallationScript) (*Install
// Removes the installer container for the server.
func (ip *InstallationProcess) RemoveContainer() {
err := ip.client.ContainerRemove(context.Background(), ip.Server.Uuid+"_installer", types.ContainerRemoveOptions{
err := ip.client.ContainerRemove(context.Background(), ip.Server.Uuid + "_installer", types.ContainerRemoveOptions{
RemoveVolumes: true,
Force: true,
})
if err != nil && !client.IsErrNotFound(err) {
ip.Server.Log().WithField("error", errors.WithStack(err)).Warn("failed to delete server install container")
zap.S().Warnw("failed to delete server installer container", zap.String("server", ip.Server.Uuid), zap.Error(errors.WithStack(err)))
}
}
@@ -133,7 +137,7 @@ func (ip *InstallationProcess) Run() error {
// If this step fails, log a warning but don't exit out of the process. This is completely
// internal to the daemon's functionality, and does not affect the status of the server itself.
if err := ip.AfterExecute(cid); err != nil {
ip.Server.Log().WithField("error", err).Warn("failed to complete after-execute step of installation process")
zap.S().Warnw("failed to complete after-execute step of installation process", zap.String("server", ip.Server.Uuid), zap.Error(err))
}
return nil
@@ -185,7 +189,7 @@ func (ip *InstallationProcess) pullInstallationImage() error {
// Block continuation until the image has been pulled successfully.
scanner := bufio.NewScanner(r)
for scanner.Scan() {
log.Debug(scanner.Text())
zap.S().Debugw(scanner.Text())
}
if err := scanner.Err(); err != nil {
@@ -261,7 +265,7 @@ func (ip *InstallationProcess) AfterExecute(containerId string) error {
ctx := context.Background()
defer ip.RemoveContainer()
ip.Server.Log().WithField("container_id", containerId).Debug("pulling installation logs for server")
zap.S().Debugw("pulling installation logs for server", zap.String("server", ip.Server.Uuid), zap.String("container_id", containerId))
reader, err := ip.client.ContainerLogs(ctx, containerId, types.ContainerLogsOptions{
ShowStdout: true,
ShowStderr: true,
@@ -291,6 +295,12 @@ func (ip *InstallationProcess) AfterExecute(containerId string) error {
func (ip *InstallationProcess) Execute(installPath string) (string, error) {
ctx := context.Background()
zap.S().Debugw(
"creating server installer container",
zap.String("server", ip.Server.Uuid),
zap.String("script_path", installPath+"/install.sh"),
)
conf := &container.Config{
Hostname: "installer",
AttachStdout: true,
@@ -338,13 +348,17 @@ func (ip *InstallationProcess) Execute(installPath string) (string, error) {
NetworkMode: container.NetworkMode(config.Get().Docker.Network.Mode),
}
ip.Server.Log().WithField("install_script", installPath+"/install.sh").Info("creating install container for server process")
zap.S().Infow("creating installer container for server process", zap.String("server", ip.Server.Uuid))
r, err := ip.client.ContainerCreate(ctx, conf, hostConf, nil, ip.Server.Uuid+"_installer")
if err != nil {
return "", errors.WithStack(err)
}
ip.Server.Log().WithField("container_id", r.ID).Info("running installation script for server in container")
zap.S().Infow(
"running installation script for server in container",
zap.String("server", ip.Server.Uuid),
zap.String("container_id", r.ID),
)
if err := ip.client.ContainerStart(ctx, r.ID, types.ContainerStartOptions{}); err != nil {
return "", err
}
@@ -352,7 +366,11 @@ func (ip *InstallationProcess) Execute(installPath string) (string, error) {
go func(id string) {
ip.Server.Events().Publish(DaemonMessageEvent, "Starting installation process, this could take a few minutes...")
if err := ip.StreamOutput(id); err != nil {
ip.Server.Log().WithField("error", err).Error("error while handling output stream for server install process")
zap.S().Errorw(
"error handling streaming output for server install process",
zap.String("container_id", id),
zap.Error(err),
)
}
ip.Server.Events().Publish(DaemonMessageEvent, "Installation process completed.")
}(r.ID)
@@ -391,10 +409,12 @@ func (ip *InstallationProcess) StreamOutput(id string) error {
}
if err := s.Err(); err != nil {
ip.Server.Log().WithFields(log.Fields{
"container_id": id,
"error": errors.WithStack(err),
}).Warn("error processing scanner line in installation output for server")
zap.S().Warnw(
"error processing scanner line in installation output for server",
zap.String("server", ip.Server.Uuid),
zap.String("container_id", id),
zap.Error(errors.WithStack(err)),
)
}
return nil

View File

@@ -1,8 +1,8 @@
package server
import (
"github.com/apex/log"
"github.com/pterodactyl/wings/api"
"go.uber.org/zap"
"strings"
)
@@ -28,10 +28,9 @@ func (s *Server) onConsoleOutput(data string) {
// set the server to that state. Only do this if the server is not currently stopped
// or stopping.
if s.GetState() == ProcessStartingState && strings.Contains(data, s.processConfiguration.Startup.Done) {
s.Log().WithFields(log.Fields{
"match": s.processConfiguration.Startup.Done,
"against": data,
}).Debug("detected server in running state based on console line output")
zap.S().Debugw(
"detected server in running state based on line output", zap.String("match", s.processConfiguration.Startup.Done), zap.String("against", data),
)
s.SetState(ProcessRunningState)
}

View File

@@ -2,13 +2,13 @@ package server
import (
"fmt"
"github.com/apex/log"
"github.com/creasty/defaults"
"github.com/patrickmn/go-cache"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/config"
"github.com/remeh/sizedwaitgroup"
"go.uber.org/zap"
"math"
"os"
"strings"
@@ -194,13 +194,13 @@ func LoadDirectory() error {
s, err := FromConfiguration(data)
if err != nil {
log.WithField("server", uuid).WithField("error", err).Error("failed to load server, skipping...")
zap.S().Errorw("failed to load server, skipping...", zap.String("server", uuid), zap.Error(err))
return
}
if state, exists := states[s.Uuid]; exists {
s.SetState(state)
s.Log().WithField("state", s.GetState()).Debug("loaded server state from cache file")
zap.S().Debugw("loaded server state from cache", zap.String("server", s.Uuid), zap.String("state", s.GetState()))
}
servers.Add(s)
@@ -247,10 +247,6 @@ func FromConfiguration(data *api.ServerConfigurationResponse) (*Server, error) {
}
s.Resources = ResourceUsage{}
// Force the disk usage to become cached to return in a resources response
// or when connecting to the websocket of an offline server.
go s.Filesystem.HasSpaceAvailable()
// Forces the configuration to be synced with the panel.
if err := s.SyncWithConfiguration(data); err != nil {
return nil, err
@@ -286,10 +282,6 @@ eloop:
return out
}
func (s *Server) Log() *log.Entry {
return log.WithField("server", s.Uuid)
}
// Syncs the state of the server on the Panel with Wings. This ensures that we're always
// using the state of the server from the Panel and allows us to not require successful
// API calls to Wings to do things.

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config"
"go.uber.org/zap"
"io"
"io/ioutil"
"os"
@@ -81,7 +82,7 @@ func (s *Server) SetState(state string) error {
s.State = state
// Emit the event to any listeners that are currently registered.
s.Log().WithField("status", s.State).Debug("saw server status change event")
zap.S().Debugw("saw server status change event", zap.String("server", s.Uuid), zap.String("status", s.State))
s.Events().Publish(StatusEvent, s.State)
// Release the lock as it is no longer needed for the following actions.
@@ -97,7 +98,7 @@ func (s *Server) SetState(state string) error {
// to the disk should we forget to do it elsewhere.
go func() {
if err := saveServerStates(); err != nil {
s.Log().WithField("error", err).Warn("failed to write server states to disk")
zap.S().Warnw("failed to write server states to disk", zap.Error(err))
}
}()
@@ -110,14 +111,14 @@ func (s *Server) SetState(state string) error {
// separate thread as to not block any actions currently taking place in the flow
// that called this function.
if (prevState == ProcessStartingState || prevState == ProcessRunningState) && s.GetState() == ProcessOfflineState {
s.Log().Info("detected server as entering a crashed state; running crash handler")
zap.S().Infow("detected server as entering a potentially crashed state; running handler", zap.String("server", s.Uuid))
go func(server *Server) {
if err := server.handleServerCrash(); err != nil {
if IsTooFrequentCrashError(err) {
server.Log().Info("did not restart server after crash; occurred too soon after the last")
zap.S().Infow("did not restart server after crash; occurred too soon after last", zap.String("server", server.Uuid))
} else {
server.Log().WithField("error", err).Error("failed to handle server crash")
zap.S().Errorw("failed to handle server crash state", zap.String("server", server.Uuid), zap.Error(err))
}
}
}(s)

View File

@@ -5,6 +5,7 @@ import (
"github.com/buger/jsonparser"
"github.com/imdario/mergo"
"github.com/pkg/errors"
"go.uber.org/zap"
)
// Merges data passed through in JSON form into the existing server object.
@@ -33,16 +34,6 @@ func (s *Server) UpdateDataStructure(data []byte, background bool) error {
return errors.WithStack(err)
}
// Don't explode if we're setting CPU limits to 0. Mergo sees that as an empty value
// so it won't override the value we've passed through in the API call. However, we can
// safely assume that we're passing through valid data structures here. I foresee this
// backfiring at some point, but until then...
//
// We'll go ahead and do this with swap as well.
s.Build.CpuLimit = src.Build.CpuLimit
s.Build.Swap = src.Build.Swap
s.Build.DiskSpace = src.Build.DiskSpace
// Mergo can't quite handle this boolean value correctly, so for now we'll just
// handle this edge case manually since none of the other data passed through in this
// request is going to be boolean. Allegedly.
@@ -90,9 +81,12 @@ func (s *Server) runBackgroundActions() {
// Update the environment in place, allowing memory and CPU usage to be adjusted
// on the fly without the user needing to reboot (theoretically).
go func(server *Server) {
server.Log().Info("performing server limit modification on-the-fly")
if err := server.Environment.InSituUpdate(); err != nil {
server.Log().WithField("error", err).Warn("failed to perform on-the-fly update of the server environment")
zap.S().Warnw(
"failed to perform in-situ update of server environment",
zap.String("server", server.Uuid),
zap.Error(err),
)
}
}(s)
@@ -100,10 +94,14 @@ func (s *Server) runBackgroundActions() {
// yet, do it immediately.
go func(server *Server) {
if server.Suspended && server.GetState() != ProcessOfflineState {
server.Log().Info("server suspended with running process state, terminating now")
zap.S().Infow("server suspended with running process state, terminating now", zap.String("server", server.Uuid))
if err := server.Environment.WaitForStop(10, true); err != nil {
server.Log().WithField("error", err).Warn("failed to terminate server environment after suspension")
zap.S().Warnw(
"failed to stop server environment after seeing suspension",
zap.String("server", server.Uuid),
zap.Error(err),
)
}
}
}(s)

View File

@@ -1,7 +1,6 @@
package sftp
import (
"github.com/apex/log"
"github.com/pkg/errors"
"github.com/pterodactyl/sftp-server"
"github.com/pterodactyl/wings/api"
@@ -39,7 +38,7 @@ func Initialize(config *config.Configuration) error {
// a long running operation.
go func(instance *sftp_server.Server) {
if err := c.Initalize(); err != nil {
log.WithField("subsystem", "sftp").WithField("error", errors.WithStack(err)).Error("failed to initialize SFTP subsystem")
zap.S().Named("sftp").Errorw("failed to initialize SFTP subsystem", zap.Error(errors.WithStack(err)))
}
}(c)
@@ -74,8 +73,7 @@ func validateDiskSpace(fs sftp_server.FileSystem) bool {
// the server's UUID if the credentials were valid.
func validateCredentials(c sftp_server.AuthenticationRequest) (*sftp_server.AuthenticationResponse, error) {
resp, err := api.NewRequester().ValidateSftpCredentials(c)
log.WithFields(log.Fields{"subsystem": "sftp", "username": c.User}).Debug("validating credentials for SFTP connection")
zap.S().Named("sftp").Debugw("validating credentials for SFTP connection", zap.String("username", c.User))
if err != nil {
return resp, err
}
@@ -88,7 +86,6 @@ func validateCredentials(c sftp_server.AuthenticationRequest) (*sftp_server.Auth
return resp, errors.New("no matching server with UUID found")
}
s.Log().WithFields(log.Fields{"subsystem": "sftp", "username": c.User}).Debug("matched user to server instance, credentials successfully validated")
zap.S().Named("sftp").Debugw("matched user to server instance, credentials successfully validated", zap.String("username", c.User), zap.String("server", s.Uuid))
return resp, err
}

View File

@@ -2,5 +2,5 @@ package system
const (
// The current version of this software.
Version = "1.0.0-beta.6"
Version = "1.0.0-beta.5"
)