Replace error handling package with emperror; add better reporting for errors escaping server root
This commit is contained in:
parent
0989c78d4b
commit
be9d1a3986
10
api/api.go
10
api/api.go
|
@ -2,10 +2,10 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/system"
|
"github.com/pterodactyl/wings/system"
|
||||||
"io"
|
"io"
|
||||||
|
@ -69,7 +69,7 @@ func (r *Request) Endpoint(endpoint string) string {
|
||||||
func (r *Request) Make(method, url string, body io.Reader, opts ...func(r *http.Request)) (*Response, error) {
|
func (r *Request) Make(method, url string, body io.Reader, opts ...func(r *http.Request)) (*Response, error) {
|
||||||
req, err := http.NewRequest(method, url, body)
|
req, err := http.NewRequest(method, url, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Set("User-Agent", fmt.Sprintf("Pterodactyl Wings/v%s (id:%s)", system.Version, config.Get().AuthenticationTokenId))
|
req.Header.Set("User-Agent", fmt.Sprintf("Pterodactyl Wings/v%s (id:%s)", system.Version, config.Get().AuthenticationTokenId))
|
||||||
|
@ -127,7 +127,7 @@ func (r *Request) Get(url string, data Q) (*Response, error) {
|
||||||
func (r *Request) Post(url string, data interface{}) (*Response, error) {
|
func (r *Request) Post(url string, data interface{}) (*Response, error) {
|
||||||
b, err := json.Marshal(data)
|
b, err := json.Marshal(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return r.Make(http.MethodPost, r.Endpoint(url), bytes.NewBuffer(b))
|
return r.Make(http.MethodPost, r.Endpoint(url), bytes.NewBuffer(b))
|
||||||
|
@ -167,10 +167,10 @@ func (r *Response) Read() ([]byte, error) {
|
||||||
func (r *Response) Bind(v interface{}) error {
|
func (r *Response) Bind(v interface{}) error {
|
||||||
b, err := r.Read()
|
b, err := r.Read()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.WithStack(json.Unmarshal(b, &v))
|
return errors.WithStackIf(json.Unmarshal(b, &v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the error message from the API call as a string. The error message will be formatted
|
// Returns the error message from the API call as a string. The error message will be formatted
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ type BackupRemoteUploadResponse struct {
|
||||||
func (r *Request) GetBackupRemoteUploadURLs(backup string, size int64) (*BackupRemoteUploadResponse, error) {
|
func (r *Request) GetBackupRemoteUploadURLs(backup string, size int64) (*BackupRemoteUploadResponse, error) {
|
||||||
resp, err := r.Get(fmt.Sprintf("/backups/%s", backup), Q{"size": strconv.FormatInt(size, 10)})
|
resp, err := r.Get(fmt.Sprintf("/backups/%s", backup), Q{"size": strconv.FormatInt(size, 10)})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ func (r *Request) GetBackupRemoteUploadURLs(backup string, size int64) (*BackupR
|
||||||
|
|
||||||
var res BackupRemoteUploadResponse
|
var res BackupRemoteUploadResponse
|
||||||
if err := resp.Bind(&res); err != nil {
|
if err := resp.Bind(&res); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &res, nil
|
return &res, nil
|
||||||
|
@ -44,7 +44,7 @@ type BackupRequest struct {
|
||||||
func (r *Request) SendBackupStatus(backup string, data BackupRequest) error {
|
func (r *Request) SendBackupStatus(backup string, data BackupRequest) error {
|
||||||
resp, err := r.Post(fmt.Sprintf("/backups/%s", backup), data)
|
resp, err := r.Post(fmt.Sprintf("/backups/%s", backup), data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -57,7 +57,7 @@ type RawServerData struct {
|
||||||
func (r *Request) GetServers() ([]RawServerData, error) {
|
func (r *Request) GetServers() ([]RawServerData, error) {
|
||||||
resp, err := r.Get("/servers", Q{"per_page": strconv.Itoa(int(config.Get().RemoteQuery.BootServersPerPage))})
|
resp, err := r.Get("/servers", Q{"per_page": strconv.Itoa(int(config.Get().RemoteQuery.BootServersPerPage))})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ func (r *Request) GetServers() ([]RawServerData, error) {
|
||||||
|
|
||||||
var res allServerResponse
|
var res allServerResponse
|
||||||
if err := resp.Bind(&res); err != nil {
|
if err := resp.Bind(&res); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
|
@ -117,7 +117,7 @@ func (r *Request) GetServers() ([]RawServerData, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := g.Wait(); err != nil {
|
if err := g.Wait(); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ func (r *Request) GetServerConfiguration(uuid string) (ServerConfigurationRespon
|
||||||
|
|
||||||
resp, err := r.Get(fmt.Sprintf("/servers/%s", uuid), nil)
|
resp, err := r.Get(fmt.Sprintf("/servers/%s", uuid), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cfg, errors.WithStack(err)
|
return cfg, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ func (r *Request) GetServerConfiguration(uuid string) (ServerConfigurationRespon
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := resp.Bind(&cfg); err != nil {
|
if err := resp.Bind(&cfg); err != nil {
|
||||||
return cfg, errors.WithStack(err)
|
return cfg, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
|
@ -150,7 +150,7 @@ func (r *Request) GetInstallationScript(uuid string) (InstallationScript, error)
|
||||||
var is InstallationScript
|
var is InstallationScript
|
||||||
resp, err := r.Get(fmt.Sprintf("/servers/%s/install", uuid), nil)
|
resp, err := r.Get(fmt.Sprintf("/servers/%s/install", uuid), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return is, errors.WithStack(err)
|
return is, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ func (r *Request) GetInstallationScript(uuid string) (InstallationScript, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := resp.Bind(&is); err != nil {
|
if err := resp.Bind(&is); err != nil {
|
||||||
return is, errors.WithStack(err)
|
return is, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return is, nil
|
return is, nil
|
||||||
|
@ -169,7 +169,7 @@ func (r *Request) GetInstallationScript(uuid string) (InstallationScript, error)
|
||||||
func (r *Request) SendInstallationStatus(uuid string, successful bool) error {
|
func (r *Request) SendInstallationStatus(uuid string, successful bool) error {
|
||||||
resp, err := r.Post(fmt.Sprintf("/servers/%s/install", uuid), D{"successful": successful})
|
resp, err := r.Post(fmt.Sprintf("/servers/%s/install", uuid), D{"successful": successful})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ func (r *Request) SendInstallationStatus(uuid string, successful bool) error {
|
||||||
func (r *Request) SendArchiveStatus(uuid string, successful bool) error {
|
func (r *Request) SendArchiveStatus(uuid string, successful bool) error {
|
||||||
resp, err := r.Post(fmt.Sprintf("/servers/%s/archive", uuid), D{"successful": successful})
|
resp, err := r.Post(fmt.Sprintf("/servers/%s/archive", uuid), D{"successful": successful})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ func (r *Request) SendArchiveStatus(uuid string, successful bool) error {
|
||||||
func (r *Request) SendTransferFailure(uuid string) error {
|
func (r *Request) SendTransferFailure(uuid string) error {
|
||||||
resp, err := r.Get(fmt.Sprintf("/servers/%s/transfer/failure", uuid), nil)
|
resp, err := r.Get(fmt.Sprintf("/servers/%s/transfer/failure", uuid), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ func (r *Request) SendTransferFailure(uuid string) error {
|
||||||
func (r *Request) SendTransferSuccess(uuid string) error {
|
func (r *Request) SendTransferSuccess(uuid string) error {
|
||||||
resp, err := r.Get(fmt.Sprintf("/servers/%s/transfer/success", uuid), nil)
|
resp, err := r.Get(fmt.Sprintf("/servers/%s/transfer/success", uuid), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
14
cmd/root.go
14
cmd/root.go
|
@ -19,7 +19,7 @@ import (
|
||||||
"github.com/pterodactyl/wings/loggers/cli"
|
"github.com/pterodactyl/wings/loggers/cli"
|
||||||
"golang.org/x/crypto/acme/autocert"
|
"golang.org/x/crypto/acme/autocert"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"emperror.dev/errors"
|
||||||
"github.com/pkg/profile"
|
"github.com/pkg/profile"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
|
@ -77,7 +77,7 @@ func readConfiguration() (*config.Configuration, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if s, err := os.Stat(p); err != nil {
|
if s, err := os.Stat(p); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
} else if s.IsDir() {
|
} else if s.IsDir() {
|
||||||
return nil, errors.New("cannot use directory as configuration file path")
|
return nil, errors.New("cannot use directory as configuration file path")
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,7 @@ func rootCmdRun(*cobra.Command, []string) {
|
||||||
|
|
||||||
states, err := server.CachedServerStates()
|
states, err := server.CachedServerStates()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithField("error", errors.WithStack(err)).Error("failed to retrieve locally cached server states from disk, assuming all servers in offline state")
|
log.WithField("error", errors.WithStackIf(err)).Error("failed to retrieve locally cached server states from disk, assuming all servers in offline state")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new workerpool that limits us to 4 servers being bootstrapped at a time
|
// Create a new workerpool that limits us to 4 servers being bootstrapped at a time
|
||||||
|
@ -235,7 +235,7 @@ func rootCmdRun(*cobra.Command, []string) {
|
||||||
// as a result will result in a slow boot.
|
// as a result will result in a slow boot.
|
||||||
if !r && (st == environment.ProcessRunningState || st == environment.ProcessStartingState) {
|
if !r && (st == environment.ProcessRunningState || st == environment.ProcessStartingState) {
|
||||||
if err := s.HandlePowerAction(server.PowerActionStart); err != nil {
|
if err := s.HandlePowerAction(server.PowerActionStart); err != nil {
|
||||||
s.Log().WithField("error", errors.WithStack(err)).Warn("failed to return server to running state")
|
s.Log().WithField("error", errors.WithStackIf(err)).Warn("failed to return server to running state")
|
||||||
}
|
}
|
||||||
} else if r || (!r && s.IsRunning()) {
|
} else if r || (!r && s.IsRunning()) {
|
||||||
// If the server is currently running on Docker, mark the process as being in that state.
|
// If the server is currently running on Docker, mark the process as being in that state.
|
||||||
|
@ -248,7 +248,7 @@ func rootCmdRun(*cobra.Command, []string) {
|
||||||
|
|
||||||
s.Environment.SetState(environment.ProcessRunningState)
|
s.Environment.SetState(environment.ProcessRunningState)
|
||||||
if err := s.Environment.Attach(); err != nil {
|
if err := s.Environment.Attach(); err != nil {
|
||||||
s.Log().WithField("error", errors.WithStack(err)).Warn("failed to attach to running server environment")
|
s.Log().WithField("error", errors.WithStackIf(err)).Warn("failed to attach to running server environment")
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -369,13 +369,13 @@ func Execute() error {
|
||||||
// in the code without having to pass around a logger instance.
|
// in the code without having to pass around a logger instance.
|
||||||
func configureLogging(logDir string, debug bool) error {
|
func configureLogging(logDir string, debug bool) error {
|
||||||
if err := os.MkdirAll(path.Join(logDir, "/install"), 0700); err != nil {
|
if err := os.MkdirAll(path.Join(logDir, "/install"), 0700); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
p := filepath.Join(logDir, "/wings.log")
|
p := filepath.Join(logDir, "/wings.log")
|
||||||
w, err := logrotate.NewFile(p)
|
w, err := logrotate.NewFile(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(errors.Wrap(err, "failed to open process log file"))
|
panic(errors.WrapIf(err, "failed to open process log file"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
if debug {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/cobaugh/osrelease"
|
"github.com/cobaugh/osrelease"
|
||||||
"github.com/creasty/defaults"
|
"github.com/creasty/defaults"
|
||||||
"github.com/gbrlsnchs/jwt/v3"
|
"github.com/gbrlsnchs/jwt/v3"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
@ -198,7 +198,7 @@ func GetJwtAlgorithm() *jwt.HMACSHA {
|
||||||
func NewFromPath(path string) (*Configuration, error) {
|
func NewFromPath(path string) (*Configuration, error) {
|
||||||
c := new(Configuration)
|
c := new(Configuration)
|
||||||
if err := defaults.Set(c); err != nil {
|
if err := defaults.Set(c); err != nil {
|
||||||
return c, errors.WithStack(err)
|
return c, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.unsafeSetPath(path)
|
c.unsafeSetPath(path)
|
||||||
|
@ -236,12 +236,12 @@ func (c *Configuration) EnsurePterodactylUser() (*user.User, error) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return u, c.setSystemUser(u)
|
return u, c.setSystemUser(u)
|
||||||
} else if _, ok := err.(user.UnknownUserError); !ok {
|
} else if _, ok := err.(user.UnknownUserError); !ok {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sysName, err := getSystemName()
|
sysName, err := getSystemName()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var command = fmt.Sprintf("useradd --system --no-create-home --shell /bin/false %s", c.System.Username)
|
var command = fmt.Sprintf("useradd --system --no-create-home --shell /bin/false %s", c.System.Username)
|
||||||
|
@ -254,17 +254,17 @@ func (c *Configuration) EnsurePterodactylUser() (*user.User, error) {
|
||||||
// We have to create the group first on Alpine, so do that here before continuing on
|
// We have to create the group first on Alpine, so do that here before continuing on
|
||||||
// to the user creation process.
|
// to the user creation process.
|
||||||
if _, err := exec.Command("addgroup", "-S", c.System.Username).Output(); err != nil {
|
if _, err := exec.Command("addgroup", "-S", c.System.Username).Output(); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
split := strings.Split(command, " ")
|
split := strings.Split(command, " ")
|
||||||
if _, err := exec.Command(split[0], split[1:]...).Output(); err != nil {
|
if _, err := exec.Command(split[0], split[1:]...).Output(); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if u, err := user.Lookup(c.System.Username); err != nil {
|
if u, err := user.Lookup(c.System.Username); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
} else {
|
} else {
|
||||||
return u, c.setSystemUser(u)
|
return u, c.setSystemUser(u)
|
||||||
}
|
}
|
||||||
|
@ -306,11 +306,11 @@ func (c *Configuration) WriteToDisk() error {
|
||||||
|
|
||||||
b, err := yaml.Marshal(&ccopy)
|
b, err := yaml.Marshal(&ccopy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ioutil.WriteFile(c.GetPath(), b, 0644); err != nil {
|
if err := ioutil.WriteFile(c.GetPath(), b, 0644); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -320,7 +320,7 @@ func (c *Configuration) WriteToDisk() error {
|
||||||
func getSystemName() (string, error) {
|
func getSystemName() (string, error) {
|
||||||
// use osrelease to get release version and ID
|
// use osrelease to get release version and ID
|
||||||
if release, err := osrelease.Read(); err != nil {
|
if release, err := osrelease.Read(); err != nil {
|
||||||
return "", errors.WithStack(err)
|
return "", errors.WithStackIf(err)
|
||||||
} else {
|
} else {
|
||||||
return release["ID"], nil
|
return release["ID"], nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type dockerNetworkInterfaces struct {
|
type dockerNetworkInterfaces struct {
|
||||||
|
@ -73,7 +73,7 @@ func (c RegistryConfiguration) Base64() (string, error) {
|
||||||
|
|
||||||
b, err := json.Marshal(authConfig)
|
b, err := json.Marshal(authConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.WithStack(err)
|
return "", errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return base64.URLEncoding.EncodeToString(b), nil
|
return base64.URLEncoding.EncodeToString(b), nil
|
||||||
|
|
|
@ -2,9 +2,9 @@ package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
@ -94,7 +94,7 @@ func (sc *SystemConfiguration) ConfigureDirectories() error {
|
||||||
// that.
|
// that.
|
||||||
if d, err := filepath.EvalSymlinks(sc.Data); err != nil {
|
if d, err := filepath.EvalSymlinks(sc.Data); err != nil {
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
} else if d != sc.Data {
|
} else if d != sc.Data {
|
||||||
sc.Data = d
|
sc.Data = d
|
||||||
|
@ -130,13 +130,13 @@ func (sc *SystemConfiguration) EnableLogRotation() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if st, err := os.Stat("/etc/logrotate.d"); err != nil && !os.IsNotExist(err) {
|
if st, err := os.Stat("/etc/logrotate.d"); err != nil && !os.IsNotExist(err) {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
} else if (err != nil && os.IsNotExist(err)) || !st.IsDir() {
|
} else if (err != nil && os.IsNotExist(err)) || !st.IsDir() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := os.Stat("/etc/logrotate.d/wings"); err != nil && !os.IsNotExist(err) {
|
if _, err := os.Stat("/etc/logrotate.d/wings"); err != nil && !os.IsNotExist(err) {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
} else if err == nil {
|
} else if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ func (sc *SystemConfiguration) EnableLogRotation() error {
|
||||||
// it so files can be rotated easily.
|
// it so files can be rotated easily.
|
||||||
f, err := os.Create("/etc/logrotate.d/wings")
|
f, err := os.Create("/etc/logrotate.d/wings")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
|
@ -167,10 +167,10 @@ func (sc *SystemConfiguration) EnableLogRotation() error {
|
||||||
}`)
|
}`)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.Wrap(t.Execute(f, sc), "failed to write logrotate file to disk")
|
return errors.WrapIf(t.Execute(f, sc), "failed to write logrotate file to disk")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the location of the JSON file that tracks server states.
|
// Returns the location of the JSON file that tracks server states.
|
||||||
|
@ -190,7 +190,7 @@ func (sc *SystemConfiguration) ConfigureTimezone() error {
|
||||||
if sc.Timezone == "" {
|
if sc.Timezone == "" {
|
||||||
if b, err := ioutil.ReadFile("/etc/timezone"); err != nil {
|
if b, err := ioutil.ReadFile("/etc/timezone"); err != nil {
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
return errors.Wrap(err, "failed to open /etc/timezone for automatic server timezone calibration")
|
return errors.WrapIf(err, "failed to open /etc/timezone for automatic server timezone calibration")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
|
@ -224,5 +224,5 @@ func (sc *SystemConfiguration) ConfigureTimezone() error {
|
||||||
|
|
||||||
_, err := time.LoadLocation(sc.Timezone)
|
_, err := time.LoadLocation(sc.Timezone)
|
||||||
|
|
||||||
return errors.Wrap(err, fmt.Sprintf("the supplied timezone %s is invalid", sc.Timezone))
|
return errors.WrapIf(err, fmt.Sprintf("the supplied timezone %s is invalid", sc.Timezone))
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
|
@ -12,7 +13,6 @@ import (
|
||||||
"github.com/docker/docker/api/types/mount"
|
"github.com/docker/docker/api/types/mount"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/docker/docker/daemon/logger/jsonfilelog"
|
"github.com/docker/docker/daemon/logger/jsonfilelog"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
"io"
|
"io"
|
||||||
|
@ -36,7 +36,7 @@ func (e *Environment) Attach() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := e.followOutput(); err != nil {
|
if err := e.followOutput(); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := types.ContainerAttachOptions{
|
opts := types.ContainerAttachOptions{
|
||||||
|
@ -48,7 +48,7 @@ func (e *Environment) Attach() error {
|
||||||
|
|
||||||
// Set the stream again with the container.
|
// Set the stream again with the container.
|
||||||
if st, err := e.client.ContainerAttach(context.Background(), e.Id, opts); err != nil {
|
if st, err := e.client.ContainerAttach(context.Background(), e.Id, opts); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
} else {
|
} else {
|
||||||
e.SetStream(&st)
|
e.SetStream(&st)
|
||||||
}
|
}
|
||||||
|
@ -70,14 +70,14 @@ func (e *Environment) Attach() error {
|
||||||
// indicates that the container is no longer running.
|
// indicates that the container is no longer running.
|
||||||
go func(ctx context.Context) {
|
go func(ctx context.Context) {
|
||||||
if err := e.pollResources(ctx); err != nil {
|
if err := e.pollResources(ctx); err != nil {
|
||||||
log.WithField("environment_id", e.Id).WithField("error", errors.WithStack(err)).Error("error during environment resource polling")
|
log.WithField("environment_id", e.Id).WithField("error", errors.WithStackIf(err)).Error("error during environment resource polling")
|
||||||
}
|
}
|
||||||
}(ctx)
|
}(ctx)
|
||||||
|
|
||||||
// Stream the reader output to the console which will then fire off events and handle console
|
// Stream the reader output to the console which will then fire off events and handle console
|
||||||
// throttling and sending the output to the user.
|
// throttling and sending the output to the user.
|
||||||
if _, err := io.Copy(console, e.stream.Reader); err != nil {
|
if _, err := io.Copy(console, e.stream.Reader); err != nil {
|
||||||
log.WithField("environment_id", e.Id).WithField("error", errors.WithStack(err)).Error("error while copying environment output to console")
|
log.WithField("environment_id", e.Id).WithField("error", errors.WithStackIf(err)).Error("error while copying environment output to console")
|
||||||
}
|
}
|
||||||
}(c)
|
}(c)
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ func (e *Environment) InSituUpdate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
u := container.UpdateConfig{
|
u := container.UpdateConfig{
|
||||||
|
@ -125,7 +125,7 @@ func (e *Environment) InSituUpdate() error {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
if _, err := e.client.ContainerUpdate(ctx, e.Id, u); err != nil {
|
if _, err := e.client.ContainerUpdate(ctx, e.Id, u); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -140,12 +140,12 @@ func (e *Environment) Create() error {
|
||||||
if _, err := e.client.ContainerInspect(context.Background(), e.Id); err == nil {
|
if _, err := e.client.ContainerInspect(context.Background(), e.Id); err == nil {
|
||||||
return nil
|
return nil
|
||||||
} else if !client.IsErrNotFound(err) {
|
} else if !client.IsErrNotFound(err) {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to pull the requested image before creating the container.
|
// Try to pull the requested image before creating the container.
|
||||||
if err := e.ensureImageExists(e.meta.Image); err != nil {
|
if err := e.ensureImageExists(e.meta.Image); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a := e.Configuration.Allocations()
|
a := e.Configuration.Allocations()
|
||||||
|
@ -220,7 +220,7 @@ func (e *Environment) Create() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := e.client.ContainerCreate(context.Background(), conf, hostConf, nil, e.Id); err != nil {
|
if _, err := e.client.ContainerCreate(context.Background(), conf, hostConf, nil, e.Id); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -272,7 +272,7 @@ func (e *Environment) Destroy() error {
|
||||||
func (e *Environment) followOutput() error {
|
func (e *Environment) followOutput() error {
|
||||||
if exists, err := e.Exists(); !exists {
|
if exists, err := e.Exists(); !exists {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.New(fmt.Sprintf("no such container: %s", e.Id))
|
return errors.New(fmt.Sprintf("no such container: %s", e.Id))
|
||||||
|
@ -338,7 +338,7 @@ func (e *Environment) followOutput() error {
|
||||||
}
|
}
|
||||||
}(reader)
|
}(reader)
|
||||||
|
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pulls the image from Docker. If there is an error while pulling the image from the source
|
// Pulls the image from Docker. If there is an error while pulling the image from the source
|
||||||
|
|
|
@ -2,9 +2,9 @@ package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
"github.com/pterodactyl/wings/events"
|
"github.com/pterodactyl/wings/events"
|
||||||
|
@ -156,7 +156,7 @@ func (e *Environment) ExitState() (uint32, bool, error) {
|
||||||
return 1, false, nil
|
return 1, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, false, errors.WithStack(err)
|
return 0, false, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return uint32(c.State.ExitCode), c.State.OOMKilled, nil
|
return uint32(c.State.ExitCode), c.State.OOMKilled, nil
|
||||||
|
|
|
@ -2,11 +2,11 @@ package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
"os"
|
"os"
|
||||||
|
@ -26,7 +26,7 @@ func (e *Environment) OnBeforeStart() error {
|
||||||
// the Panel is usee.
|
// the Panel is usee.
|
||||||
if err := e.client.ContainerRemove(context.Background(), e.Id, types.ContainerRemoveOptions{RemoveVolumes: true}); err != nil {
|
if err := e.client.ContainerRemove(context.Background(), e.Id, types.ContainerRemoveOptions{RemoveVolumes: true}); err != nil {
|
||||||
if !client.IsErrNotFound(err) {
|
if !client.IsErrNotFound(err) {
|
||||||
return errors.Wrap(err, "failed to remove server docker container during pre-boot")
|
return errors.WrapIf(err, "failed to remove server docker container during pre-boot")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ func (e *Environment) Start() error {
|
||||||
//
|
//
|
||||||
// @see https://github.com/pterodactyl/panel/issues/2000
|
// @see https://github.com/pterodactyl/panel/issues/2000
|
||||||
if !client.IsErrNotFound(err) {
|
if !client.IsErrNotFound(err) {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If the server is running update our internal state and continue on with the attach.
|
// If the server is running update our internal state and continue on with the attach.
|
||||||
|
@ -84,7 +84,7 @@ func (e *Environment) Start() error {
|
||||||
// to truncate them.
|
// to truncate them.
|
||||||
if _, err := os.Stat(c.LogPath); err == nil {
|
if _, err := os.Stat(c.LogPath); err == nil {
|
||||||
if err := os.Truncate(c.LogPath, 0); err != nil {
|
if err := os.Truncate(c.LogPath, 0); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,14 +99,14 @@ func (e *Environment) Start() error {
|
||||||
// exists on the system, and rebuild the container if that is required for server booting to
|
// exists on the system, and rebuild the container if that is required for server booting to
|
||||||
// occur.
|
// occur.
|
||||||
if err := e.OnBeforeStart(); err != nil {
|
if err := e.OnBeforeStart(); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if err := e.client.ContainerStart(ctx, e.Id, types.ContainerStartOptions{}); err != nil {
|
if err := e.client.ContainerStart(ctx, e.Id, types.ContainerStartOptions{}); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// No errors, good to continue through.
|
// No errors, good to continue through.
|
||||||
|
@ -169,7 +169,7 @@ func (e *Environment) Stop() error {
|
||||||
// will be terminated forcefully depending on the value of the second argument.
|
// will be terminated forcefully depending on the value of the second argument.
|
||||||
func (e *Environment) WaitForStop(seconds uint, terminate bool) error {
|
func (e *Environment) WaitForStop(seconds uint, terminate bool) error {
|
||||||
if err := e.Stop(); err != nil {
|
if err := e.Stop(); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(seconds)*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(seconds)*time.Second)
|
||||||
|
@ -185,20 +185,20 @@ func (e *Environment) WaitForStop(seconds uint, terminate bool) error {
|
||||||
if terminate {
|
if terminate {
|
||||||
log.WithField("container_id", e.Id).Debug("server did not stop in time, executing process termination")
|
log.WithField("container_id", e.Id).Debug("server did not stop in time, executing process termination")
|
||||||
|
|
||||||
return errors.WithStack(e.Terminate(os.Kill))
|
return errors.WithStackIf(e.Terminate(os.Kill))
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.WithStack(ctxErr)
|
return errors.WithStackIf(ctxErr)
|
||||||
}
|
}
|
||||||
case err := <-errChan:
|
case err := <-errChan:
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if terminate {
|
if terminate {
|
||||||
log.WithField("container_id", e.Id).WithField("error", errors.WithStack(err)).Warn("error while waiting for container stop, attempting process termination")
|
log.WithField("container_id", e.Id).WithField("error", errors.WithStackIf(err)).Warn("error while waiting for container stop, attempting process termination")
|
||||||
|
|
||||||
return errors.WithStack(e.Terminate(os.Kill))
|
return errors.WithStackIf(e.Terminate(os.Kill))
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
case <-ok:
|
case <-ok:
|
||||||
}
|
}
|
||||||
|
@ -210,7 +210,7 @@ func (e *Environment) WaitForStop(seconds uint, terminate bool) error {
|
||||||
func (e *Environment) Terminate(signal os.Signal) error {
|
func (e *Environment) Terminate(signal os.Signal) error {
|
||||||
c, err := e.client.ContainerInspect(context.Background(), e.Id)
|
c, err := e.client.ContainerInspect(context.Background(), e.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.State.Running {
|
if !c.State.Running {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@ package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
@ -26,7 +26,7 @@ func (e *Environment) pollResources(ctx context.Context) error {
|
||||||
|
|
||||||
stats, err := e.client.ContainerStats(context.Background(), e.Id, true)
|
stats, err := e.client.ContainerStats(context.Background(), e.Id, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer stats.Body.Close()
|
defer stats.Body.Close()
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ func (e *Environment) pollResources(ctx context.Context) error {
|
||||||
|
|
||||||
if err := dec.Decode(&v); err != nil {
|
if err := dec.Decode(&v); err != nil {
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
l.WithField("error", errors.WithStack(err)).Warn("error while processing Docker stats output for container")
|
l.WithField("error", errors.WithStackIf(err)).Warn("error while processing Docker stats output for container")
|
||||||
} else {
|
} else {
|
||||||
l.Debug("io.EOF encountered during stats decode, stopping polling...")
|
l.Debug("io.EOF encountered during stats decode, stopping polling...")
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ func (e *Environment) pollResources(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if b, err := json.Marshal(st); err != nil {
|
if b, err := json.Marshal(st); err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Warn("error while marshaling stats object for environment")
|
l.WithField("error", errors.WithStackIf(err)).Warn("error while marshaling stats object for environment")
|
||||||
} else {
|
} else {
|
||||||
e.Events().Publish(environment.ResourceEvent, string(b))
|
e.Events().Publish(environment.ResourceEvent, string(b))
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
@ -15,7 +15,7 @@ type dockerLogLine struct {
|
||||||
Log string `json:"log"`
|
Log string `json:"log"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrNotAttached = errors.New("not attached to instance")
|
var ErrNotAttached = errors.Sentinel("not attached to instance")
|
||||||
|
|
||||||
func (e *Environment) setStream(s *types.HijackedResponse) {
|
func (e *Environment) setStream(s *types.HijackedResponse) {
|
||||||
e.mu.Lock()
|
e.mu.Lock()
|
||||||
|
@ -42,7 +42,7 @@ func (e *Environment) SendCommand(c string) error {
|
||||||
|
|
||||||
_, err := e.stream.Conn.Write([]byte(c + "\n"))
|
_, err := e.stream.Conn.Write([]byte(c + "\n"))
|
||||||
|
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reads the log file for the server. This does not care if the server is running or not, it will
|
// Reads the log file for the server. This does not care if the server is running or not, it will
|
||||||
|
@ -54,7 +54,7 @@ func (e *Environment) Readlog(lines int) ([]string, error) {
|
||||||
Tail: strconv.Itoa(lines),
|
Tail: strconv.Itoa(lines),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package events
|
package events
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/gammazero/workerpool"
|
"github.com/gammazero/workerpool"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
@ -69,7 +69,7 @@ func (e *EventBus) Publish(topic string, data string) {
|
||||||
func (e *EventBus) PublishJson(topic string, data interface{}) error {
|
func (e *EventBus) PublishJson(topic string, data interface{}) error {
|
||||||
b, err := json.Marshal(data)
|
b, err := json.Marshal(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Publish(topic, string(b))
|
e.Publish(topic, string(b))
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -3,6 +3,7 @@ module github.com/pterodactyl/wings
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
emperror.dev/errors v0.8.0
|
||||||
github.com/AlecAivazis/survey/v2 v2.1.0
|
github.com/AlecAivazis/survey/v2 v2.1.0
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
|
||||||
github.com/Jeffail/gabs/v2 v2.5.1
|
github.com/Jeffail/gabs/v2 v2.5.1
|
||||||
|
@ -57,7 +58,6 @@ require (
|
||||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
|
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
|
||||||
github.com/pkg/errors v0.9.1
|
|
||||||
github.com/pkg/profile v1.5.0
|
github.com/pkg/profile v1.5.0
|
||||||
github.com/pkg/sftp v1.11.0
|
github.com/pkg/sftp v1.11.0
|
||||||
github.com/prometheus/common v0.11.1 // indirect
|
github.com/prometheus/common v0.11.1 // indirect
|
||||||
|
|
6
go.sum
6
go.sum
|
@ -1,5 +1,7 @@
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
emperror.dev/errors v0.8.0 h1:4lycVEx0sdJkwDUfQ9pdu6SR0x7rgympt5f4+ok8jDk=
|
||||||
|
emperror.dev/errors v0.8.0/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE=
|
||||||
github.com/AlecAivazis/survey/v2 v2.1.0 h1:AT4+23hOFopXYZaNGugbk7MWItkz0SfTmH/Hk92KeeE=
|
github.com/AlecAivazis/survey/v2 v2.1.0 h1:AT4+23hOFopXYZaNGugbk7MWItkz0SfTmH/Hk92KeeE=
|
||||||
github.com/AlecAivazis/survey/v2 v2.1.0/go.mod h1:9FJRdMdDm8rnT+zHVbvQT2RTSTLq0Ttd6q3Vl2fahjk=
|
github.com/AlecAivazis/survey/v2 v2.1.0/go.mod h1:9FJRdMdDm8rnT+zHVbvQT2RTSTLq0Ttd6q3Vl2fahjk=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||||
|
@ -561,9 +563,13 @@ go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
|
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||||
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||||
|
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||||
|
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
|
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
|
||||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package installer
|
package installer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/asaskevich/govalidator"
|
"github.com/asaskevich/govalidator"
|
||||||
"github.com/buger/jsonparser"
|
"github.com/buger/jsonparser"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
"github.com/pterodactyl/wings/server"
|
"github.com/pterodactyl/wings/server"
|
||||||
|
@ -43,21 +43,21 @@ func New(data []byte) (*Installer, error) {
|
||||||
|
|
||||||
// Unmarshal the environment variables from the request into the server struct.
|
// Unmarshal the environment variables from the request into the server struct.
|
||||||
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.WithStackIf(err)
|
||||||
} else {
|
} else {
|
||||||
cfg.EnvVars = make(environment.Variables)
|
cfg.EnvVars = make(environment.Variables)
|
||||||
if err := json.Unmarshal(b, &cfg.EnvVars); err != nil {
|
if err := json.Unmarshal(b, &cfg.EnvVars); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal the allocation mappings from the request into the server struct.
|
// Unmarshal the allocation mappings from the request into the server struct.
|
||||||
if b, _, _, err := jsonparser.Get(data, "allocations", "mappings"); err != nil {
|
if b, _, _, err := jsonparser.Get(data, "allocations", "mappings"); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
} else {
|
} else {
|
||||||
cfg.Allocations.Mappings = make(map[string][]int)
|
cfg.Allocations.Mappings = make(map[string][]int)
|
||||||
if err := json.Unmarshal(b, &cfg.Allocations.Mappings); err != nil {
|
if err := json.Unmarshal(b, &cfg.Allocations.Mappings); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ func New(data []byte) (*Installer, error) {
|
||||||
c, err := api.New().GetServerConfiguration(cfg.Uuid)
|
c, err := api.New().GetServerConfiguration(cfg.Uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !api.IsRequestError(err) {
|
if !api.IsRequestError(err) {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New(err.Error())
|
return nil, errors.New(err.Error())
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"github.com/apex/log/handlers/cli"
|
"github.com/apex/log/handlers/cli"
|
||||||
color2 "github.com/fatih/color"
|
color2 "github.com/fatih/color"
|
||||||
"github.com/mattn/go-colorable"
|
"github.com/mattn/go-colorable"
|
||||||
"github.com/pkg/errors"
|
"emperror.dev/errors"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -88,10 +88,10 @@ func getErrorStack(err error, i bool) errors.StackTrace {
|
||||||
if i {
|
if i {
|
||||||
// Just abort out of this and return a stacktrace leading up to this point. It isn't perfect
|
// Just abort out of this and return a stacktrace leading up to this point. It isn't perfect
|
||||||
// but it'll at least include what function lead to this being called which we can then handle.
|
// but it'll at least include what function lead to this being called which we can then handle.
|
||||||
return errors.Wrap(err, "failed to generate stacktrace for caught error").(tracer).StackTrace()
|
return errors.WrapIf(err, "failed to generate stacktrace for caught error").(tracer).StackTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
return getErrorStack(errors.Wrap(err, err.Error()), true)
|
return getErrorStack(errors.WrapIf(err, err.Error()), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
st := e.StackTrace()
|
st := e.StackTrace()
|
||||||
|
@ -101,7 +101,7 @@ func getErrorStack(err error, i bool) errors.StackTrace {
|
||||||
// trace since they'll point to the error that was generated by this function.
|
// trace since they'll point to the error that was generated by this function.
|
||||||
f := 0
|
f := 0
|
||||||
if i {
|
if i {
|
||||||
f = 4
|
f = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
if i && l > 9 {
|
if i && l > 9 {
|
||||||
|
|
|
@ -2,11 +2,11 @@ package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/Jeffail/gabs/v2"
|
"github.com/Jeffail/gabs/v2"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/buger/jsonparser"
|
"github.com/buger/jsonparser"
|
||||||
"github.com/iancoleman/strcase"
|
"github.com/iancoleman/strcase"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -76,13 +76,13 @@ func (cfr *ConfigurationFileReplacement) getKeyValue(value []byte) interface{} {
|
||||||
func (f *ConfigurationFile) IterateOverJson(data []byte) (*gabs.Container, error) {
|
func (f *ConfigurationFile) IterateOverJson(data []byte) (*gabs.Container, error) {
|
||||||
parsed, err := gabs.ParseJSON(data)
|
parsed, err := gabs.ParseJSON(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range f.Replace {
|
for _, v := range f.Replace {
|
||||||
value, err := f.LookupConfigurationValue(v)
|
value, err := f.LookupConfigurationValue(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for a wildcard character, and if found split the key on that value to
|
// Check for a wildcard character, and if found split the key on that value to
|
||||||
|
@ -101,7 +101,7 @@ func (f *ConfigurationFile) IterateOverJson(data []byte) (*gabs.Container, error
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.Wrap(err, "failed to set config value of array child")
|
return nil, errors.WrapIf(err, "failed to set config value of array child")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -110,7 +110,7 @@ func (f *ConfigurationFile) IterateOverJson(data []byte) (*gabs.Container, error
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.Wrap(err, "unable to set config value at pathway: "+v.Match)
|
return nil, errors.WrapIf(err, "unable to set config value at pathway: "+v.Match)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ func setValueAtPath(c *gabs.Container, path string, value interface{}) error {
|
||||||
_, err = c.SetP(value, path)
|
_, err = c.SetP(value, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
i, _ := strconv.Atoi(matches[2])
|
i, _ := strconv.Atoi(matches[2])
|
||||||
|
@ -147,7 +147,7 @@ func setValueAtPath(c *gabs.Container, path string, value interface{}) error {
|
||||||
ct, err := c.ArrayElementP(i, matches[1])
|
ct, err := c.ArrayElementP(i, matches[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if i != 0 || (!errors.Is(err, gabs.ErrNotArray) && !errors.Is(err, gabs.ErrNotFound)) {
|
if i != 0 || (!errors.Is(err, gabs.ErrNotArray) && !errors.Is(err, gabs.ErrNotFound)) {
|
||||||
return errors.Wrap(err, "error while parsing array element at path")
|
return errors.WrapIf(err, "error while parsing array element at path")
|
||||||
}
|
}
|
||||||
|
|
||||||
var t = make([]interface{}, 1)
|
var t = make([]interface{}, 1)
|
||||||
|
@ -162,7 +162,7 @@ func setValueAtPath(c *gabs.Container, path string, value interface{}) error {
|
||||||
// an empty object if we have additional things to set on the array, or just an empty array type
|
// an empty object if we have additional things to set on the array, or just an empty array type
|
||||||
// if there is not an object structure detected (no matches[3] available).
|
// if there is not an object structure detected (no matches[3] available).
|
||||||
if _, err = c.SetP(t, matches[1]); err != nil {
|
if _, err = c.SetP(t, matches[1]); err != nil {
|
||||||
return errors.Wrap(err, "failed to create empty array for missing element")
|
return errors.WrapIf(err, "failed to create empty array for missing element")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set our cursor to be the array element we expect, which in this case is just the first element
|
// Set our cursor to be the array element we expect, which in this case is just the first element
|
||||||
|
@ -170,7 +170,7 @@ func setValueAtPath(c *gabs.Container, path string, value interface{}) error {
|
||||||
// to match additional elements. In those cases the server will just have to be rebooted or something.
|
// to match additional elements. In those cases the server will just have to be rebooted or something.
|
||||||
ct, err = c.ArrayElementP(0, matches[1])
|
ct, err = c.ArrayElementP(0, matches[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to find array element at path")
|
return errors.WrapIf(err, "failed to find array element at path")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ func setValueAtPath(c *gabs.Container, path string, value interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to set value at config path: "+path)
|
return errors.WrapIf(err, "failed to set value at config path: "+path)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -253,7 +253,7 @@ func (f *ConfigurationFile) LookupConfigurationValue(cfr ConfigurationFileReplac
|
||||||
match, _, _, err := jsonparser.Get(f.configuration, path...)
|
match, _, _, err := jsonparser.Get(f.configuration, path...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != jsonparser.KeyPathNotFoundError {
|
if err != jsonparser.KeyPathNotFoundError {
|
||||||
return string(match), errors.WithStack(err)
|
return string(match), errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.WithFields(log.Fields{"path": path, "filename": f.FileName}).Debug("attempted to load a configuration value that does not exist")
|
log.WithFields(log.Fields{"path": path, "filename": f.FileName}).Debug("attempted to load a configuration value that does not exist")
|
||||||
|
|
|
@ -2,13 +2,13 @@ package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/beevik/etree"
|
"github.com/beevik/etree"
|
||||||
"github.com/buger/jsonparser"
|
"github.com/buger/jsonparser"
|
||||||
"github.com/icza/dyno"
|
"github.com/icza/dyno"
|
||||||
"github.com/magiconair/properties"
|
"github.com/magiconair/properties"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
|
@ -166,17 +166,17 @@ func (f *ConfigurationFile) Parse(path string, internal bool) error {
|
||||||
|
|
||||||
b := strings.TrimSuffix(path, filepath.Base(path))
|
b := strings.TrimSuffix(path, filepath.Base(path))
|
||||||
if err := os.MkdirAll(b, 0755); err != nil {
|
if err := os.MkdirAll(b, 0755); err != nil {
|
||||||
return errors.Wrap(err, "failed to create base directory for missing configuration file")
|
return errors.WrapIf(err, "failed to create base directory for missing configuration file")
|
||||||
} else {
|
} else {
|
||||||
if _, err := os.Create(path); err != nil {
|
if _, err := os.Create(path); err != nil {
|
||||||
return errors.Wrap(err, "failed to create missing configuration file")
|
return errors.WrapIf(err, "failed to create missing configuration file")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return f.Parse(path, true)
|
return f.Parse(path, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses an xml file.
|
// Parses an xml file.
|
||||||
|
@ -348,12 +348,12 @@ func (f *ConfigurationFile) parseJsonFile(path string) error {
|
||||||
func (f *ConfigurationFile) parseYamlFile(path string) error {
|
func (f *ConfigurationFile) parseYamlFile(path string) error {
|
||||||
b, err := readFileBytes(path)
|
b, err := readFileBytes(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
i := make(map[string]interface{})
|
i := make(map[string]interface{})
|
||||||
if err := yaml.Unmarshal(b, &i); err != nil {
|
if err := yaml.Unmarshal(b, &i); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal the yaml data into a JSON interface such that we can work with
|
// Unmarshal the yaml data into a JSON interface such that we can work with
|
||||||
|
@ -361,20 +361,20 @@ func (f *ConfigurationFile) parseYamlFile(path string) error {
|
||||||
// makes working with unknown JSON significantly easier.
|
// makes working with unknown JSON significantly easier.
|
||||||
jsonBytes, err := json.Marshal(dyno.ConvertMapI2MapS(i))
|
jsonBytes, err := json.Marshal(dyno.ConvertMapI2MapS(i))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that the data is converted, treat it just like JSON and pass it to the
|
// Now that the data is converted, treat it just like JSON and pass it to the
|
||||||
// iterator function to update values as necessary.
|
// iterator function to update values as necessary.
|
||||||
data, err := f.IterateOverJson(jsonBytes)
|
data, err := f.IterateOverJson(jsonBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remarshal the JSON into YAML format before saving it back to the disk.
|
// Remarshal the JSON into YAML format before saving it back to the disk.
|
||||||
marshaled, err := yaml.Marshal(data.Data())
|
marshaled, err := yaml.Marshal(data.Data())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ioutil.WriteFile(path, marshaled, 0644)
|
return ioutil.WriteFile(path, marshaled, 0644)
|
||||||
|
@ -386,7 +386,7 @@ func (f *ConfigurationFile) parseYamlFile(path string) error {
|
||||||
func (f *ConfigurationFile) parseTextFile(path string) error {
|
func (f *ConfigurationFile) parseTextFile(path string) error {
|
||||||
input, err := ioutil.ReadFile(path)
|
input, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lines := strings.Split(string(input), "\n")
|
lines := strings.Split(string(input), "\n")
|
||||||
|
@ -403,7 +403,7 @@ func (f *ConfigurationFile) parseTextFile(path string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ioutil.WriteFile(path, []byte(strings.Join(lines, "\n")), 0644); err != nil {
|
if err := ioutil.WriteFile(path, []byte(strings.Join(lines, "\n")), 0644); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -415,7 +415,7 @@ func (f *ConfigurationFile) parsePropertiesFile(path string) error {
|
||||||
// Open the file.
|
// Open the file.
|
||||||
f2, err := os.Open(path)
|
f2, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var s strings.Builder
|
var s strings.Builder
|
||||||
|
@ -437,20 +437,20 @@ func (f *ConfigurationFile) parsePropertiesFile(path string) error {
|
||||||
|
|
||||||
// Handle any scanner errors.
|
// Handle any scanner errors.
|
||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode the properties file.
|
// Decode the properties file.
|
||||||
p, err := properties.LoadFile(path, properties.UTF8)
|
p, err := properties.LoadFile(path, properties.UTF8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace any values that need to be replaced.
|
// Replace any values that need to be replaced.
|
||||||
for _, replace := range f.Replace {
|
for _, replace := range f.Replace {
|
||||||
data, err := f.LookupConfigurationValue(replace)
|
data, err := f.LookupConfigurationValue(replace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
v, ok := p.Get(replace.Match)
|
v, ok := p.Get(replace.Match)
|
||||||
|
@ -462,7 +462,7 @@ func (f *ConfigurationFile) parsePropertiesFile(path string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, _, err := p.Set(replace.Match, data); err != nil {
|
if _, _, err := p.Set(replace.Match, data); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,7 +482,7 @@ func (f *ConfigurationFile) parsePropertiesFile(path string) error {
|
||||||
// Open the file for writing.
|
// Open the file for writing.
|
||||||
w, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
w, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer w.Close()
|
defer w.Close()
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/server"
|
"github.com/pterodactyl/wings/server"
|
||||||
"github.com/pterodactyl/wings/server/filesystem"
|
"github.com/pterodactyl/wings/server/filesystem"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -75,7 +75,7 @@ func (e *RequestError) AbortWithStatus(status int, c *gin.Context) {
|
||||||
if status >= 500 {
|
if status >= 500 {
|
||||||
e.logger().WithField("error", e.Err).Error("encountered HTTP/500 error while handling request")
|
e.logger().WithField("error", e.Err).Error("encountered HTTP/500 error while handling request")
|
||||||
|
|
||||||
c.Error(errors.WithStack(e))
|
c.Error(errors.WithStackIf(e))
|
||||||
} else {
|
} else {
|
||||||
e.logger().WithField("error", e.Err).Debug("encountered non-HTTP/500 error while handling request")
|
e.logger().WithField("error", e.Err).Debug("encountered non-HTTP/500 error while handling request")
|
||||||
}
|
}
|
||||||
|
@ -99,38 +99,32 @@ func (e *RequestError) AbortWithServerError(c *gin.Context) {
|
||||||
|
|
||||||
// Handle specific filesystem errors for a server.
|
// Handle specific filesystem errors for a server.
|
||||||
func (e *RequestError) AbortFilesystemError(c *gin.Context) {
|
func (e *RequestError) AbortFilesystemError(c *gin.Context) {
|
||||||
if errors.Is(e.Err, os.ErrNotExist) {
|
if errors.Is(e.Err, os.ErrNotExist) || filesystem.IsBadPathResolutionError(e.Err) {
|
||||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{
|
if filesystem.IsBadPathResolutionError(e.Err) {
|
||||||
"error": "The requested resource was not found.",
|
e.logger().Warn(e.Err.Error())
|
||||||
})
|
}
|
||||||
|
|
||||||
|
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "The requested resource was not found."})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(e.Err, filesystem.ErrNotEnoughDiskSpace) {
|
if errors.Is(e.Err, filesystem.ErrNotEnoughDiskSpace) {
|
||||||
c.AbortWithStatusJSON(http.StatusConflict, gin.H{
|
c.AbortWithStatusJSON(http.StatusConflict, gin.H{"error": "There is not enough disk space available to perform that action."})
|
||||||
"error": "There is not enough disk space available to perform that action.",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasSuffix(e.Err.Error(), "file name too long") {
|
if strings.HasSuffix(e.Err.Error(), "file name too long") {
|
||||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
|
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "File name is too long."})
|
||||||
"error": "File name is too long.",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if e, ok := e.Err.(*os.SyscallError); ok && e.Syscall == "readdirent" {
|
if e, ok := e.Err.(*os.SyscallError); ok && e.Syscall == "readdirent" {
|
||||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{
|
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "The requested directory does not exist."})
|
||||||
"error": "The requested directory does not exist.",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasSuffix(e.Err.Error(), "file name too long") {
|
if strings.HasSuffix(e.Err.Error(), "file name too long") {
|
||||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
|
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Cannot perform that action: file name is too long."})
|
||||||
"error": "Cannot perform that action: file name is too long.",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@ package router
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/router/tokens"
|
"github.com/pterodactyl/wings/router/tokens"
|
||||||
"github.com/pterodactyl/wings/server"
|
"github.com/pterodactyl/wings/server"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -227,7 +227,7 @@ func deleteServer(c *gin.Context) {
|
||||||
if err := os.RemoveAll(p); err != nil {
|
if err := os.RemoveAll(p); err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"path": p,
|
"path": p,
|
||||||
"error": errors.WithStack(err),
|
"error": errors.WithStackIf(err),
|
||||||
}).Warn("failed to remove server files during deletion process")
|
}).Warn("failed to remove server files during deletion process")
|
||||||
}
|
}
|
||||||
}(s.Filesystem().Path())
|
}(s.Filesystem().Path())
|
||||||
|
|
|
@ -2,8 +2,8 @@ package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/router/tokens"
|
"github.com/pterodactyl/wings/router/tokens"
|
||||||
"github.com/pterodactyl/wings/server"
|
"github.com/pterodactyl/wings/server"
|
||||||
"github.com/pterodactyl/wings/server/filesystem"
|
"github.com/pterodactyl/wings/server/filesystem"
|
||||||
|
@ -35,19 +35,19 @@ func getServerFileContents(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Header("X-Mime-Type", st.Mimetype)
|
|
||||||
c.Header("Content-Length", strconv.Itoa(int(st.Info.Size())))
|
|
||||||
|
|
||||||
// If a download parameter is included in the URL go ahead and attach the necessary headers
|
|
||||||
// so that the file can be downloaded.
|
|
||||||
if c.Query("download") != "" {
|
|
||||||
c.Header("Content-Disposition", "attachment; filename="+st.Info.Name())
|
|
||||||
c.Header("Content-Type", "application/octet-stream")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := s.Filesystem().Readfile(p, c.Writer); err != nil {
|
if err := s.Filesystem().Readfile(p, c.Writer); err != nil {
|
||||||
TrackedServerError(err, s).AbortFilesystemError(c)
|
TrackedServerError(err, s).AbortFilesystemError(c)
|
||||||
return
|
return
|
||||||
|
} else {
|
||||||
|
c.Header("X-Mime-Type", st.Mimetype)
|
||||||
|
c.Header("Content-Length", strconv.Itoa(int(st.Info.Size())))
|
||||||
|
|
||||||
|
// If a download parameter is included in the URL go ahead and attach the necessary headers
|
||||||
|
// so that the file can be downloaded.
|
||||||
|
if c.Query("download") != "" {
|
||||||
|
c.Header("Content-Disposition", "attachment; filename="+st.Info.Name())
|
||||||
|
c.Header("Content-Type", "application/octet-stream")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,12 +413,12 @@ func postServerUploadFiles(c *gin.Context) {
|
||||||
func handleFileUpload(p string, s *server.Server, header *multipart.FileHeader) error {
|
func handleFileUpload(p string, s *server.Server, header *multipart.FileHeader) error {
|
||||||
file, err := header.Open()
|
file, err := header.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
if err := s.Filesystem().Writefile(p, file); err != nil {
|
if err := s.Filesystem().Writefile(p, file); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -4,12 +4,12 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/buger/jsonparser"
|
"github.com/buger/jsonparser"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/mholt/archiver/v3"
|
"github.com/mholt/archiver/v3"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/installer"
|
"github.com/pterodactyl/wings/installer"
|
||||||
|
@ -157,7 +157,7 @@ func postTransfer(c *gin.Context) {
|
||||||
// Make a new GET request to the URL the panel gave us.
|
// Make a new GET request to the URL the panel gave us.
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithField("error", errors.WithStack(err)).Error("failed to create http request for archive transfer")
|
log.WithField("error", errors.WithStackIf(err)).Error("failed to create http request for archive transfer")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ func postTransfer(c *gin.Context) {
|
||||||
// Execute the http request.
|
// Execute the http request.
|
||||||
res, err := client.Do(req)
|
res, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to send archive http request")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to send archive http request")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
@ -176,12 +176,12 @@ func postTransfer(c *gin.Context) {
|
||||||
if res.StatusCode != 200 {
|
if res.StatusCode != 200 {
|
||||||
_, err := ioutil.ReadAll(res.Body)
|
_, err := ioutil.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).WithField("status", res.StatusCode).Error("failed read transfer response body")
|
l.WithField("error", errors.WithStackIf(err)).WithField("status", res.StatusCode).Error("failed read transfer response body")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
l.WithField("error", errors.WithStack(err)).WithField("status", res.StatusCode).Error("failed to request server archive")
|
l.WithField("error", errors.WithStackIf(err)).WithField("status", res.StatusCode).Error("failed to request server archive")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -193,12 +193,12 @@ func postTransfer(c *gin.Context) {
|
||||||
_, err = os.Stat(archivePath)
|
_, err = os.Stat(archivePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to stat archive file")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to stat archive file")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := os.Remove(archivePath); err != nil {
|
if err := os.Remove(archivePath); err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Warn("failed to remove old archive file")
|
l.WithField("error", errors.WithStackIf(err)).Warn("failed to remove old archive file")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ func postTransfer(c *gin.Context) {
|
||||||
// Create the file.
|
// Create the file.
|
||||||
file, err := os.Create(archivePath)
|
file, err := os.Create(archivePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to open archive on disk")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to open archive on disk")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -216,14 +216,14 @@ func postTransfer(c *gin.Context) {
|
||||||
buf := make([]byte, 1024*4)
|
buf := make([]byte, 1024*4)
|
||||||
_, err = io.CopyBuffer(file, res.Body, buf)
|
_, err = io.CopyBuffer(file, res.Body, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to copy archive file to disk")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to copy archive file to disk")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the file so it can be opened to verify the checksum.
|
// Close the file so it can be opened to verify the checksum.
|
||||||
if err := file.Close(); err != nil {
|
if err := file.Close(); err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to close archive file")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to close archive file")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,7 @@ func postTransfer(c *gin.Context) {
|
||||||
// Open the archive file for computing a checksum.
|
// Open the archive file for computing a checksum.
|
||||||
file, err = os.Open(archivePath)
|
file, err = os.Open(archivePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to open archive on disk")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to open archive on disk")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ func postTransfer(c *gin.Context) {
|
||||||
hash := sha256.New()
|
hash := sha256.New()
|
||||||
buf = make([]byte, 1024*4)
|
buf = make([]byte, 1024*4)
|
||||||
if _, err := io.CopyBuffer(hash, file, buf); err != nil {
|
if _, err := io.CopyBuffer(hash, file, buf); err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to copy archive file for checksum verification")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to copy archive file for checksum verification")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@ func postTransfer(c *gin.Context) {
|
||||||
|
|
||||||
// Close the file.
|
// Close the file.
|
||||||
if err := file.Close(); err != nil {
|
if err := file.Close(); err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to close archive file after calculating checksum")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to close archive file after calculating checksum")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ func postTransfer(c *gin.Context) {
|
||||||
// Create a new server installer (note this does not execute the install script)
|
// Create a new server installer (note this does not execute the install script)
|
||||||
i, err := installer.New(serverData)
|
i, err := installer.New(serverData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to validate received server data")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to validate received server data")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ func postTransfer(c *gin.Context) {
|
||||||
|
|
||||||
// Un-archive the archive. That sounds weird..
|
// Un-archive the archive. That sounds weird..
|
||||||
if err := archiver.NewTarGz().Unarchive(archivePath, i.Server().Filesystem().Path()); err != nil {
|
if err := archiver.NewTarGz().Unarchive(archivePath, i.Server().Filesystem().Path()); err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to extract server archive")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to extract server archive")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ func postTransfer(c *gin.Context) {
|
||||||
err = api.New().SendTransferSuccess(serverID)
|
err = api.New().SendTransferSuccess(serverID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !api.IsRequestError(err) {
|
if !api.IsRequestError(err) {
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to notify panel of transfer success")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to notify panel of transfer success")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,13 @@ package websocket
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/gbrlsnchs/jwt/v3"
|
"github.com/gbrlsnchs/jwt/v3"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
"github.com/pterodactyl/wings/environment/docker"
|
"github.com/pterodactyl/wings/environment/docker"
|
||||||
|
@ -41,10 +41,10 @@ type Handler struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrJwtNotPresent = errors.New("jwt: no jwt present")
|
ErrJwtNotPresent = errors.Sentinel("jwt: no jwt present")
|
||||||
ErrJwtNoConnectPerm = errors.New("jwt: missing connect permission")
|
ErrJwtNoConnectPerm = errors.Sentinel("jwt: missing connect permission")
|
||||||
ErrJwtUuidMismatch = errors.New("jwt: server uuid mismatch")
|
ErrJwtUuidMismatch = errors.Sentinel("jwt: server uuid mismatch")
|
||||||
ErrJwtOnDenylist = errors.New("jwt: created too far in past (denylist)")
|
ErrJwtOnDenylist = errors.Sentinel("jwt: created too far in past (denylist)")
|
||||||
)
|
)
|
||||||
|
|
||||||
func IsJwtError(err error) bool {
|
func IsJwtError(err error) bool {
|
||||||
|
@ -108,7 +108,7 @@ func GetHandler(s *server.Server, w http.ResponseWriter, r *http.Request) (*Hand
|
||||||
|
|
||||||
u, err := uuid.NewRandom()
|
u, err := uuid.NewRandom()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Handler{
|
return &Handler{
|
||||||
|
|
|
@ -2,9 +2,9 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"github.com/mholt/archiver/v3"
|
"github.com/mholt/archiver/v3"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/server/filesystem"
|
"github.com/pterodactyl/wings/server/filesystem"
|
||||||
"io"
|
"io"
|
||||||
|
@ -41,7 +41,7 @@ func (a *Archiver) Exists() bool {
|
||||||
func (a *Archiver) Stat() (*filesystem.Stat, error) {
|
func (a *Archiver) Stat() (*filesystem.Stat, error) {
|
||||||
s, err := os.Stat(a.Path())
|
s, err := os.Stat(a.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &filesystem.Stat{
|
return &filesystem.Stat{
|
||||||
|
@ -99,7 +99,7 @@ func (a *Archiver) DeleteIfExists() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.Remove(a.Path()); err != nil {
|
if err := os.Remove(a.Path()); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -2,8 +2,8 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"github.com/pterodactyl/wings/server/backup"
|
"github.com/pterodactyl/wings/server/backup"
|
||||||
"os"
|
"os"
|
||||||
|
@ -80,7 +80,7 @@ func (s *Server) Backup(b backup.BackupInterface) error {
|
||||||
// Get the included files based on the root path and the ignored files provided.
|
// Get the included files based on the root path and the ignored files provided.
|
||||||
inc, err := s.GetIncludedBackupFiles(b.Ignored())
|
inc, err := s.GetIncludedBackupFiles(b.Ignored())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ad, err := b.Generate(inc, s.Filesystem().Path())
|
ad, err := b.Generate(inc, s.Filesystem().Path())
|
||||||
|
@ -100,7 +100,7 @@ func (s *Server) Backup(b backup.BackupInterface) error {
|
||||||
"file_size": 0,
|
"file_size": 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
return errors.Wrap(err, "error while generating server backup")
|
return errors.WrapIf(err, "error while generating server backup")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to notify the panel about the status of this backup. If for some reason this request
|
// Try to notify the panel about the status of this backup. If for some reason this request
|
||||||
|
|
|
@ -3,9 +3,9 @@ package backup
|
||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
gzip "github.com/klauspost/pgzip"
|
gzip "github.com/klauspost/pgzip"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/remeh/sizedwaitgroup"
|
"github.com/remeh/sizedwaitgroup"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
"io"
|
"io"
|
||||||
|
@ -26,7 +26,7 @@ type Archive struct {
|
||||||
func (a *Archive) Create(dst string, ctx context.Context) error {
|
func (a *Archive) Create(dst string, ctx context.Context) error {
|
||||||
f, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
f, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ func (a *Archive) Create(dst string, ctx context.Context) error {
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return errors.WithStack(ctx.Err())
|
return errors.WithStackIf(ctx.Err())
|
||||||
default:
|
default:
|
||||||
return a.addToArchive(p, tw)
|
return a.addToArchive(p, tw)
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ func (a *Archive) Create(dst string, ctx context.Context) error {
|
||||||
log.WithField("location", dst).Warn("failed to delete corrupted backup archive")
|
log.WithField("location", dst).Warn("failed to delete corrupted backup archive")
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -91,7 +91,7 @@ func (a *Archive) addToArchive(p string, w *tar.Writer) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ func (a *Archive) addToArchive(p string, w *tar.Writer) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
header := &tar.Header{
|
header := &tar.Header{
|
||||||
|
@ -120,12 +120,12 @@ func (a *Archive) addToArchive(p string, w *tar.Writer) error {
|
||||||
defer a.Unlock()
|
defer a.Unlock()
|
||||||
|
|
||||||
if err := w.WriteHeader(header); err != nil {
|
if err := w.WriteHeader(header); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, 4*1024)
|
buf := make([]byte, 4*1024)
|
||||||
if _, err := io.CopyBuffer(w, f, buf); err != nil {
|
if _, err := io.CopyBuffer(w, f, buf); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -2,9 +2,9 @@ package backup
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"io"
|
"io"
|
||||||
|
@ -87,7 +87,7 @@ func (b *Backup) Path() string {
|
||||||
func (b *Backup) Size() (int64, error) {
|
func (b *Backup) Size() (int64, error) {
|
||||||
st, err := os.Stat(b.Path())
|
st, err := os.Stat(b.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.WithStack(err)
|
return 0, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return st.Size(), nil
|
return st.Size(), nil
|
||||||
|
@ -99,7 +99,7 @@ func (b *Backup) Checksum() ([]byte, error) {
|
||||||
|
|
||||||
f, err := os.Open(b.Path())
|
f, err := os.Open(b.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ package backup
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/pkg/errors"
|
"emperror.dev/errors"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ func LocateLocal(uuid string) (*LocalBackup, os.FileInfo, error) {
|
||||||
|
|
||||||
st, err := os.Stat(b.Path())
|
st, err := os.Stat(b.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.WithStack(err)
|
return nil, nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if st.IsDir() {
|
if st.IsDir() {
|
||||||
|
@ -48,7 +48,7 @@ func (b *LocalBackup) Generate(included *IncludedFiles, prefix string) (*Archive
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.Create(b.Path(), context.Background()); err != nil {
|
if err := a.Create(b.Path(), context.Background()); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.Details(), nil
|
return b.Details(), nil
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package backup
|
package backup
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
|
|
|
@ -3,9 +3,9 @@ package backup
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -31,17 +31,17 @@ func (s *S3Backup) Generate(included *IncludedFiles, prefix string) (*ArchiveDet
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.Create(s.Path(), context.Background()); err != nil {
|
if err := a.Create(s.Path(), context.Background()); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, err := os.Open(s.Path())
|
rc, err := os.Open(s.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer rc.Close()
|
defer rc.Close()
|
||||||
|
|
||||||
if err := s.generateRemoteRequest(rc); err != nil {
|
if err := s.generateRemoteRequest(rc); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.Details(), err
|
return s.Details(), err
|
||||||
|
|
|
@ -2,9 +2,9 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/colorstring"
|
"github.com/mitchellh/colorstring"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/system"
|
"github.com/pterodactyl/wings/system"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -12,7 +12,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrTooMuchConsoleData = errors.New("console is outputting too much data")
|
var ErrTooMuchConsoleData = errors.Sentinel("console is outputting too much data")
|
||||||
|
|
||||||
type ConsoleThrottler struct {
|
type ConsoleThrottler struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -57,7 +57,7 @@ func (s *Server) handleServerCrash() error {
|
||||||
|
|
||||||
exitCode, oomKilled, err := s.Environment.ExitState()
|
exitCode, oomKilled, err := s.Environment.ExitState()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the system is not configured to detect a clean exit code as a crash, and the
|
// If the system is not configured to detect a clean exit code as a crash, and the
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import "github.com/pkg/errors"
|
import "emperror.dev/errors"
|
||||||
|
|
||||||
var ErrIsRunning = errors.New("server is running")
|
var ErrIsRunning = errors.Sentinel("server is running")
|
||||||
var ErrSuspended = errors.New("server is currently in a suspended state")
|
var ErrSuspended = errors.Sentinel("server is currently in a suspended state")
|
||||||
|
|
||||||
type crashTooFrequent struct {
|
type crashTooFrequent struct {
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pkg/errors"
|
"emperror.dev/errors"
|
||||||
"github.com/pterodactyl/wings/server/filesystem"
|
"github.com/pterodactyl/wings/server/filesystem"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
@ -13,12 +13,12 @@ func (s *Server) Filesystem() *filesystem.Filesystem {
|
||||||
// Ensures that the data directory for the server instance exists.
|
// Ensures that the data directory for the server instance exists.
|
||||||
func (s *Server) EnsureDataDirectoryExists() error {
|
func (s *Server) EnsureDataDirectoryExists() error {
|
||||||
if _, err := os.Stat(s.fs.Path()); err != nil && !os.IsNotExist(err) {
|
if _, err := os.Stat(s.fs.Path()); err != nil && !os.IsNotExist(err) {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
// Create the server data directory because it does not currently exist
|
// Create the server data directory because it does not currently exist
|
||||||
// on the system.
|
// on the system.
|
||||||
if err := os.MkdirAll(s.fs.Path(), 0700); err != nil {
|
if err := os.MkdirAll(s.fs.Path(), 0700); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.fs.Chown("/"); err != nil {
|
if err := s.fs.Chown("/"); err != nil {
|
||||||
|
|
|
@ -2,9 +2,9 @@ package filesystem
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/karrick/godirwalk"
|
"github.com/karrick/godirwalk"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/server/backup"
|
"github.com/pterodactyl/wings/server/backup"
|
||||||
ignore "github.com/sabhiram/go-gitignore"
|
ignore "github.com/sabhiram/go-gitignore"
|
||||||
"os"
|
"os"
|
||||||
|
@ -41,7 +41,7 @@ func (fs *Filesystem) GetIncludedFiles(dir string, ignored []string) (*backup.In
|
||||||
if e.IsSymlink() {
|
if e.IsSymlink() {
|
||||||
sp, err = fs.SafePath(p)
|
sp, err = fs.SafePath(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, ErrBadPathResolution) {
|
if IsBadPathResolutionError(err) {
|
||||||
return godirwalk.SkipThis
|
return godirwalk.SkipThis
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ func (fs *Filesystem) GetIncludedFiles(dir string, ignored []string) (*backup.In
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
return inc, errors.WithStack(err)
|
return inc, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compresses all of the files matching the given paths in the specified directory. This function
|
// Compresses all of the files matching the given paths in the specified directory. This function
|
||||||
|
@ -115,7 +115,7 @@ func (fs *Filesystem) CompressFiles(dir string, paths []string) (os.FileInfo, er
|
||||||
// use the resolved location for the rest of this function.
|
// use the resolved location for the rest of this function.
|
||||||
sp, err = fs.SafePath(p)
|
sp, err = fs.SafePath(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, ErrBadPathResolution) {
|
if IsBadPathResolutionError(err) {
|
||||||
return godirwalk.SkipThis
|
return godirwalk.SkipThis
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ func (fs *Filesystem) CompressFiles(dir string, paths []string) (os.FileInfo, er
|
||||||
d := path.Join(cleanedRootDir, fmt.Sprintf("archive-%s.tar.gz", strings.ReplaceAll(time.Now().Format(time.RFC3339), ":", "")))
|
d := path.Join(cleanedRootDir, fmt.Sprintf("archive-%s.tar.gz", strings.ReplaceAll(time.Now().Format(time.RFC3339), ":", "")))
|
||||||
|
|
||||||
if err := a.Create(d, context.Background()); err != nil {
|
if err := a.Create(d, context.Background()); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.Stat(d)
|
f, err := os.Stat(d)
|
||||||
|
|
|
@ -4,9 +4,9 @@ import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
|
"emperror.dev/errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mholt/archiver/v3"
|
"github.com/mholt/archiver/v3"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -47,10 +47,10 @@ func (fs *Filesystem) SpaceAvailableForDecompression(dir string, file string) (b
|
||||||
return false, ErrUnknownArchiveFormat
|
return false, ErrUnknownArchiveFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
return false, errors.WithStack(err)
|
return false, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, errors.WithStack(err)
|
return true, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decompress a file in a given directory by using the archiver tool to infer the file
|
// Decompress a file in a given directory by using the archiver tool to infer the file
|
||||||
|
@ -60,12 +60,12 @@ func (fs *Filesystem) SpaceAvailableForDecompression(dir string, file string) (b
|
||||||
func (fs *Filesystem) DecompressFile(dir string, file string) error {
|
func (fs *Filesystem) DecompressFile(dir string, file string) error {
|
||||||
source, err := fs.SafePath(filepath.Join(dir, file))
|
source, err := fs.SafePath(filepath.Join(dir, file))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the file exists basically.
|
// Make sure the file exists basically.
|
||||||
if _, err := os.Stat(source); err != nil {
|
if _, err := os.Stat(source); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk over all of the files spinning up an additional go-routine for each file we've encountered
|
// Walk over all of the files spinning up an additional go-routine for each file we've encountered
|
||||||
|
@ -93,17 +93,17 @@ func (fs *Filesystem) DecompressFile(dir string, file string) error {
|
||||||
|
|
||||||
p, err := fs.SafePath(filepath.Join(dir, name))
|
p, err := fs.SafePath(filepath.Join(dir, name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to generate a safe path to server file")
|
return errors.WrapIf(err, "failed to generate a safe path to server file")
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.Wrap(fs.Writefile(p, f), "could not extract file from archive")
|
return errors.WrapIf(fs.Writefile(p, f), "could not extract file from archive")
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.HasPrefix(err.Error(), "format ") {
|
if strings.HasPrefix(err.Error(), "format ") {
|
||||||
return errors.WithStack(ErrUnknownArchiveFormat)
|
return errors.WithStackIf(ErrUnknownArchiveFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package filesystem
|
package filesystem
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/karrick/godirwalk"
|
"github.com/karrick/godirwalk"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -153,7 +153,7 @@ func (fs *Filesystem) updateCachedDiskUsage() (int64, error) {
|
||||||
func (fs *Filesystem) DirectorySize(dir string) (int64, error) {
|
func (fs *Filesystem) DirectorySize(dir string) (int64, error) {
|
||||||
d, err := fs.SafePath(dir)
|
d, err := fs.SafePath(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.WithStack(err)
|
return 0, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var size int64
|
var size int64
|
||||||
|
@ -167,7 +167,7 @@ func (fs *Filesystem) DirectorySize(dir string) (int64, error) {
|
||||||
// it. Otherwise, allow it to continue.
|
// it. Otherwise, allow it to continue.
|
||||||
if e.IsSymlink() {
|
if e.IsSymlink() {
|
||||||
if _, err := fs.SafePath(p); err != nil {
|
if _, err := fs.SafePath(p); err != nil {
|
||||||
if errors.Is(err, ErrBadPathResolution) {
|
if IsBadPathResolutionError(err) {
|
||||||
return godirwalk.SkipThis
|
return godirwalk.SkipThis
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ func (fs *Filesystem) DirectorySize(dir string) (int64, error) {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
return size, errors.WithStack(err)
|
return size, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to determine if a server has space available for a file of a given size.
|
// Helper function to determine if a server has space available for a file of a given size.
|
||||||
|
|
|
@ -1,16 +1,43 @@
|
||||||
package filesystem
|
package filesystem
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
|
"fmt"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrIsDirectory = errors.New("filesystem: is a directory")
|
var ErrIsDirectory = errors.Sentinel("filesystem: is a directory")
|
||||||
var ErrNotEnoughDiskSpace = errors.New("filesystem: not enough disk space")
|
var ErrNotEnoughDiskSpace = errors.Sentinel("filesystem: not enough disk space")
|
||||||
var ErrBadPathResolution = errors.New("filesystem: invalid path resolution")
|
var ErrUnknownArchiveFormat = errors.Sentinel("filesystem: unknown archive format")
|
||||||
var ErrUnknownArchiveFormat = errors.New("filesystem: unknown archive format")
|
|
||||||
|
type BadPathResolutionError struct {
|
||||||
|
path string
|
||||||
|
resolved string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the specific error for a bad path resolution.
|
||||||
|
func (b *BadPathResolutionError) Error() string {
|
||||||
|
r := b.resolved
|
||||||
|
if r == "" {
|
||||||
|
r = "<empty>"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("filesystem: server path [%s] resolves to a location outside the server root: %s", b.path, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a new BadPathResolution error.
|
||||||
|
func NewBadPathResolution(path string, resolved string) *BadPathResolutionError {
|
||||||
|
return &BadPathResolutionError{path, resolved}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determines if the given error is a bad path resolution error.
|
||||||
|
func IsBadPathResolutionError(err error) bool {
|
||||||
|
if _, ok := err.(*BadPathResolutionError); ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Generates an error logger instance with some basic information.
|
// Generates an error logger instance with some basic information.
|
||||||
func (fs *Filesystem) error(err error) *log.Entry {
|
func (fs *Filesystem) error(err error) *log.Entry {
|
||||||
|
@ -23,8 +50,8 @@ func (fs *Filesystem) error(err error) *log.Entry {
|
||||||
// directory, otherwise return nil. Returning this error for a file will stop the walking
|
// directory, otherwise return nil. Returning this error for a file will stop the walking
|
||||||
// for the remainder of the directory. This is assuming an os.FileInfo struct was even returned.
|
// for the remainder of the directory. This is assuming an os.FileInfo struct was even returned.
|
||||||
func (fs *Filesystem) handleWalkerError(err error, f os.FileInfo) error {
|
func (fs *Filesystem) handleWalkerError(err error, f os.FileInfo) error {
|
||||||
if !errors.Is(err, ErrBadPathResolution) {
|
if !IsBadPathResolutionError(err) {
|
||||||
return err
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if f != nil && f.IsDir() {
|
if f != nil && f.IsDir() {
|
||||||
|
@ -32,4 +59,4 @@ func (fs *Filesystem) handleWalkerError(err error, f os.FileInfo) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@ package filesystem
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/gabriel-vasile/mimetype"
|
"github.com/gabriel-vasile/mimetype"
|
||||||
"github.com/karrick/godirwalk"
|
"github.com/karrick/godirwalk"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/system"
|
"github.com/pterodactyl/wings/system"
|
||||||
"io"
|
"io"
|
||||||
|
@ -80,7 +80,7 @@ func (fs *Filesystem) Readfile(p string, w io.Writer) error {
|
||||||
func (fs *Filesystem) Writefile(p string, r io.Reader) error {
|
func (fs *Filesystem) Writefile(p string, r io.Reader) error {
|
||||||
cleaned, err := fs.SafePath(p)
|
cleaned, err := fs.SafePath(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentSize int64
|
var currentSize int64
|
||||||
|
@ -88,15 +88,15 @@ func (fs *Filesystem) Writefile(p string, r io.Reader) error {
|
||||||
// to it and an empty file. We'll then write to it later on after this completes.
|
// to it and an empty file. We'll then write to it later on after this completes.
|
||||||
if stat, err := os.Stat(cleaned); err != nil {
|
if stat, err := os.Stat(cleaned); err != nil {
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(filepath.Dir(cleaned), 0755); err != nil {
|
if err := os.MkdirAll(filepath.Dir(cleaned), 0755); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := fs.Chown(filepath.Dir(cleaned)); err != nil {
|
if err := fs.Chown(filepath.Dir(cleaned)); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if stat.IsDir() {
|
if stat.IsDir() {
|
||||||
|
@ -119,7 +119,7 @@ func (fs *Filesystem) Writefile(p string, r io.Reader) error {
|
||||||
// truncate the existing file.
|
// truncate the existing file.
|
||||||
file, err := o.open(cleaned, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
|
file, err := o.open(cleaned, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ func (fs *Filesystem) Writefile(p string, r io.Reader) error {
|
||||||
func (fs *Filesystem) CreateDirectory(name string, p string) error {
|
func (fs *Filesystem) CreateDirectory(name string, p string) error {
|
||||||
cleaned, err := fs.SafePath(path.Join(p, name))
|
cleaned, err := fs.SafePath(path.Join(p, name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return os.MkdirAll(cleaned, 0755)
|
return os.MkdirAll(cleaned, 0755)
|
||||||
|
@ -148,12 +148,12 @@ func (fs *Filesystem) CreateDirectory(name string, p string) error {
|
||||||
func (fs *Filesystem) Rename(from string, to string) error {
|
func (fs *Filesystem) Rename(from string, to string) error {
|
||||||
cleanedFrom, err := fs.SafePath(from)
|
cleanedFrom, err := fs.SafePath(from)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanedTo, err := fs.SafePath(to)
|
cleanedTo, err := fs.SafePath(to)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the target file or directory already exists the rename function will fail, so just
|
// If the target file or directory already exists the rename function will fail, so just
|
||||||
|
@ -171,7 +171,7 @@ func (fs *Filesystem) Rename(from string, to string) error {
|
||||||
// we're not at the root directory level.
|
// we're not at the root directory level.
|
||||||
if d != fs.Path() {
|
if d != fs.Path() {
|
||||||
if mkerr := os.MkdirAll(d, 0755); mkerr != nil {
|
if mkerr := os.MkdirAll(d, 0755); mkerr != nil {
|
||||||
return errors.Wrap(mkerr, "failed to create directory structure for file rename")
|
return errors.WrapIf(mkerr, "failed to create directory structure for file rename")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ func (fs *Filesystem) Rename(from string, to string) error {
|
||||||
func (fs *Filesystem) Chown(path string) error {
|
func (fs *Filesystem) Chown(path string) error {
|
||||||
cleaned, err := fs.SafePath(path)
|
cleaned, err := fs.SafePath(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if fs.isTest {
|
if fs.isTest {
|
||||||
|
@ -197,7 +197,7 @@ func (fs *Filesystem) Chown(path string) error {
|
||||||
|
|
||||||
// Start by just chowning the initial path that we received.
|
// Start by just chowning the initial path that we received.
|
||||||
if err := os.Chown(cleaned, uid, gid); err != nil {
|
if err := os.Chown(cleaned, uid, gid); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is not a directory we can now return from the function, there is nothing
|
// If this is not a directory we can now return from the function, there is nothing
|
||||||
|
@ -268,12 +268,12 @@ func (fs *Filesystem) findCopySuffix(dir string, name string, extension string)
|
||||||
func (fs *Filesystem) Copy(p string) error {
|
func (fs *Filesystem) Copy(p string) error {
|
||||||
cleaned, err := fs.SafePath(p)
|
cleaned, err := fs.SafePath(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := os.Stat(cleaned)
|
s, err := os.Stat(cleaned)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
} else if s.IsDir() || !s.Mode().IsRegular() {
|
} else if s.IsDir() || !s.Mode().IsRegular() {
|
||||||
// If this is a directory or not a regular file, just throw a not-exist error
|
// If this is a directory or not a regular file, just throw a not-exist error
|
||||||
// since anything calling this function should understand what that means.
|
// since anything calling this function should understand what that means.
|
||||||
|
@ -300,7 +300,7 @@ func (fs *Filesystem) Copy(p string) error {
|
||||||
|
|
||||||
source, err := os.Open(cleaned)
|
source, err := os.Open(cleaned)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer source.Close()
|
defer source.Close()
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ func (fs *Filesystem) Delete(p string) error {
|
||||||
// exists within the data directory.
|
// exists within the data directory.
|
||||||
resolved := fs.unsafeFilePath(p)
|
resolved := fs.unsafeFilePath(p)
|
||||||
if !fs.unsafeIsInDataDirectory(resolved) {
|
if !fs.unsafeIsInDataDirectory(resolved) {
|
||||||
return ErrBadPathResolution
|
return NewBadPathResolution(p, resolved)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block any whoopsies.
|
// Block any whoopsies.
|
||||||
|
|
|
@ -134,22 +134,22 @@ func TestFilesystem_SafePath(t *testing.T) {
|
||||||
g.It("blocks access to files outside the root directory", func() {
|
g.It("blocks access to files outside the root directory", func() {
|
||||||
p, err := fs.SafePath("../test.txt")
|
p, err := fs.SafePath("../test.txt")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
g.Assert(p).Equal("")
|
g.Assert(p).Equal("")
|
||||||
|
|
||||||
p, err = fs.SafePath("/../test.txt")
|
p, err = fs.SafePath("/../test.txt")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
g.Assert(p).Equal("")
|
g.Assert(p).Equal("")
|
||||||
|
|
||||||
p, err = fs.SafePath("./foo/../../test.txt")
|
p, err = fs.SafePath("./foo/../../test.txt")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
g.Assert(p).Equal("")
|
g.Assert(p).Equal("")
|
||||||
|
|
||||||
p, err = fs.SafePath("..")
|
p, err = fs.SafePath("..")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
g.Assert(p).Equal("")
|
g.Assert(p).Equal("")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -185,7 +185,7 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
|
||||||
|
|
||||||
err := fs.Readfile("symlinked.txt", &b)
|
err := fs.Readfile("symlinked.txt", &b)
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
|
||||||
|
|
||||||
err := fs.Writefile("symlinked.txt", r)
|
err := fs.Writefile("symlinked.txt", r)
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("cannot write a file to a directory symlinked outside the root", func() {
|
g.It("cannot write a file to a directory symlinked outside the root", func() {
|
||||||
|
@ -203,7 +203,7 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
|
||||||
|
|
||||||
err := fs.Writefile("external_dir/foo.txt", r)
|
err := fs.Writefile("external_dir/foo.txt", r)
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -211,19 +211,19 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
|
||||||
g.It("cannot create a directory outside the root", func() {
|
g.It("cannot create a directory outside the root", func() {
|
||||||
err := fs.CreateDirectory("my_dir", "external_dir")
|
err := fs.CreateDirectory("my_dir", "external_dir")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("cannot create a nested directory outside the root", func() {
|
g.It("cannot create a nested directory outside the root", func() {
|
||||||
err := fs.CreateDirectory("my/nested/dir", "external_dir/foo/bar")
|
err := fs.CreateDirectory("my/nested/dir", "external_dir/foo/bar")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("cannot create a nested directory outside the root", func() {
|
g.It("cannot create a nested directory outside the root", func() {
|
||||||
err := fs.CreateDirectory("my/nested/dir", "external_dir/server")
|
err := fs.CreateDirectory("my/nested/dir", "external_dir/server")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -231,13 +231,13 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
|
||||||
g.It("cannot rename a file symlinked outside the directory root", func() {
|
g.It("cannot rename a file symlinked outside the directory root", func() {
|
||||||
err := fs.Rename("symlinked.txt", "foo.txt")
|
err := fs.Rename("symlinked.txt", "foo.txt")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("cannot rename a symlinked directory outside the root", func() {
|
g.It("cannot rename a symlinked directory outside the root", func() {
|
||||||
err := fs.Rename("external_dir", "foo")
|
err := fs.Rename("external_dir", "foo")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("cannot rename a file to a location outside the directory root", func() {
|
g.It("cannot rename a file to a location outside the directory root", func() {
|
||||||
|
@ -245,7 +245,7 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
|
||||||
|
|
||||||
err := fs.Rename("my_file.txt", "external_dir/my_file.txt")
|
err := fs.Rename("my_file.txt", "external_dir/my_file.txt")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -253,13 +253,13 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
|
||||||
g.It("cannot chown a file symlinked outside the directory root", func() {
|
g.It("cannot chown a file symlinked outside the directory root", func() {
|
||||||
err := fs.Chown("symlinked.txt")
|
err := fs.Chown("symlinked.txt")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("cannot chown a directory symlinked outside the directory root", func() {
|
g.It("cannot chown a directory symlinked outside the directory root", func() {
|
||||||
err := fs.Chown("external_dir")
|
err := fs.Chown("external_dir")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
|
||||||
g.It("cannot copy a file symlinked outside the directory root", func() {
|
g.It("cannot copy a file symlinked outside the directory root", func() {
|
||||||
err := fs.Copy("symlinked.txt")
|
err := fs.Copy("symlinked.txt")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ func TestFilesystem_Readfile(t *testing.T) {
|
||||||
|
|
||||||
err = fs.Readfile("/../test.txt", buf)
|
err = fs.Readfile("/../test.txt", buf)
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.AfterEach(func() {
|
g.AfterEach(func() {
|
||||||
|
@ -386,7 +386,7 @@ func TestFilesystem_Writefile(t *testing.T) {
|
||||||
|
|
||||||
err := fs.Writefile("/some/../foo/../../test.txt", r)
|
err := fs.Writefile("/some/../foo/../../test.txt", r)
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("cannot write a file that exceeds the disk limits", func() {
|
g.It("cannot write a file that exceeds the disk limits", func() {
|
||||||
|
@ -477,7 +477,7 @@ func TestFilesystem_CreateDirectory(t *testing.T) {
|
||||||
g.It("should not allow the creation of directories outside the root", func() {
|
g.It("should not allow the creation of directories outside the root", func() {
|
||||||
err := fs.CreateDirectory("test", "e/../../something")
|
err := fs.CreateDirectory("test", "e/../../something")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("should not increment the disk usage", func() {
|
g.It("should not increment the disk usage", func() {
|
||||||
|
@ -527,7 +527,7 @@ func TestFilesystem_Rename(t *testing.T) {
|
||||||
g.It("does not allow renaming to a location outside the root", func() {
|
g.It("does not allow renaming to a location outside the root", func() {
|
||||||
err := fs.Rename("source.txt", "../target.txt")
|
err := fs.Rename("source.txt", "../target.txt")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("does not allow renaming from a location outside the root", func() {
|
g.It("does not allow renaming from a location outside the root", func() {
|
||||||
|
@ -535,7 +535,7 @@ func TestFilesystem_Rename(t *testing.T) {
|
||||||
|
|
||||||
err = fs.Rename("/../ext-source.txt", "target.txt")
|
err = fs.Rename("/../ext-source.txt", "target.txt")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("allows a file to be renamed", func() {
|
g.It("allows a file to be renamed", func() {
|
||||||
|
@ -613,7 +613,7 @@ func TestFilesystem_Copy(t *testing.T) {
|
||||||
|
|
||||||
err = fs.Copy("../ext-source.txt")
|
err = fs.Copy("../ext-source.txt")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("should return an error if the source directory is outside the root", func() {
|
g.It("should return an error if the source directory is outside the root", func() {
|
||||||
|
@ -625,11 +625,11 @@ func TestFilesystem_Copy(t *testing.T) {
|
||||||
|
|
||||||
err = fs.Copy("../nested/in/dir/ext-source.txt")
|
err = fs.Copy("../nested/in/dir/ext-source.txt")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
|
|
||||||
err = fs.Copy("nested/in/../../../nested/in/dir/ext-source.txt")
|
err = fs.Copy("nested/in/../../../nested/in/dir/ext-source.txt")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("should return an error if the source is a directory", func() {
|
g.It("should return an error if the source is a directory", func() {
|
||||||
|
@ -721,7 +721,7 @@ func TestFilesystem_Delete(t *testing.T) {
|
||||||
|
|
||||||
err = fs.Delete("../ext-source.txt")
|
err = fs.Delete("../ext-source.txt")
|
||||||
g.Assert(err).IsNotNil()
|
g.Assert(err).IsNotNil()
|
||||||
g.Assert(errors.Is(err, ErrBadPathResolution)).IsTrue()
|
g.Assert(IsBadPathResolutionError(err)).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("does not allow the deletion of the root directory", func() {
|
g.It("does not allow the deletion of the root directory", func() {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package filesystem
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -23,9 +24,9 @@ func (fs *Filesystem) SafePath(p string) (string, error) {
|
||||||
|
|
||||||
// At the same time, evaluate the symlink status and determine where this file or folder
|
// At the same time, evaluate the symlink status and determine where this file or folder
|
||||||
// is truly pointing to.
|
// is truly pointing to.
|
||||||
p, err := filepath.EvalSymlinks(r)
|
ep, err := filepath.EvalSymlinks(r)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return "", err
|
return "", errors.WithStackIf(err)
|
||||||
} else if os.IsNotExist(err) {
|
} else if os.IsNotExist(err) {
|
||||||
// The requested directory doesn't exist, so at this point we need to iterate up the
|
// The requested directory doesn't exist, so at this point we need to iterate up the
|
||||||
// path chain until we hit a directory that _does_ exist and can be validated.
|
// path chain until we hit a directory that _does_ exist and can be validated.
|
||||||
|
@ -53,7 +54,7 @@ func (fs *Filesystem) SafePath(p string) (string, error) {
|
||||||
// attempt going on, and we should NOT resolve this path for them.
|
// attempt going on, and we should NOT resolve this path for them.
|
||||||
if nonExistentPathResolution != "" {
|
if nonExistentPathResolution != "" {
|
||||||
if !fs.unsafeIsInDataDirectory(nonExistentPathResolution) {
|
if !fs.unsafeIsInDataDirectory(nonExistentPathResolution) {
|
||||||
return "", ErrBadPathResolution
|
return "", NewBadPathResolution(p, nonExistentPathResolution)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the nonExistentPathResolution variable is not empty then the initial path requested
|
// If the nonExistentPathResolution variable is not empty then the initial path requested
|
||||||
|
@ -66,11 +67,11 @@ func (fs *Filesystem) SafePath(p string) (string, error) {
|
||||||
// If the requested directory from EvalSymlinks begins with the server root directory go
|
// If the requested directory from EvalSymlinks begins with the server root directory go
|
||||||
// ahead and return it. If not we'll return an error which will block any further action
|
// ahead and return it. If not we'll return an error which will block any further action
|
||||||
// on the file.
|
// on the file.
|
||||||
if fs.unsafeIsInDataDirectory(p) {
|
if fs.unsafeIsInDataDirectory(ep) {
|
||||||
return p, nil
|
return ep, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", ErrBadPathResolution
|
return "", NewBadPathResolution(p, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a path to the file by cleaning it up and appending the root server path to it. This
|
// Generate a path to the file by cleaning it up and appending the root server path to it. This
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package filesystem
|
package filesystem
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/gabriel-vasile/mimetype"
|
"github.com/gabriel-vasile/mimetype"
|
||||||
"os"
|
"os"
|
||||||
|
@ -50,14 +51,14 @@ func (fs *Filesystem) Stat(p string) (*Stat, error) {
|
||||||
func (fs *Filesystem) unsafeStat(p string) (*Stat, error) {
|
func (fs *Filesystem) unsafeStat(p string) (*Stat, error) {
|
||||||
s, err := os.Stat(p)
|
s, err := os.Stat(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var m *mimetype.MIME
|
var m *mimetype.MIME
|
||||||
if !s.IsDir() {
|
if !s.IsDir() {
|
||||||
m, err = mimetype.DetectFile(p)
|
m, err = mimetype.DetectFile(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,12 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/mount"
|
"github.com/docker/docker/api/types/mount"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
|
@ -90,7 +90,7 @@ func (s *Server) internalInstall() error {
|
||||||
script, err := api.New().GetInstallationScript(s.Id())
|
script, err := api.New().GetInstallationScript(s.Id())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !api.IsRequestError(err) {
|
if !api.IsRequestError(err) {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.New(err.Error())
|
return errors.New(err.Error())
|
||||||
|
@ -98,7 +98,7 @@ func (s *Server) internalInstall() error {
|
||||||
|
|
||||||
p, err := NewInstallationProcess(s, &script)
|
p, err := NewInstallationProcess(s, &script)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Log().Info("beginning installation process for server")
|
s.Log().Info("beginning installation process for server")
|
||||||
|
@ -130,7 +130,7 @@ func NewInstallationProcess(s *Server, script *api.InstallationScript) (*Install
|
||||||
s.installer.cancel = &cancel
|
s.installer.cancel = &cancel
|
||||||
|
|
||||||
if c, err := environment.DockerClient(); err != nil {
|
if c, err := environment.DockerClient(); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
} else {
|
} else {
|
||||||
proc.client = c
|
proc.client = c
|
||||||
proc.context = ctx
|
proc.context = ctx
|
||||||
|
@ -193,7 +193,7 @@ func (ip *InstallationProcess) RemoveContainer() {
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil && !client.IsErrNotFound(err) {
|
if err != nil && !client.IsErrNotFound(err) {
|
||||||
ip.Server.Log().WithField("error", errors.WithStack(err)).Warn("failed to delete server install container")
|
ip.Server.Log().WithField("error", errors.WithStackIf(err)).Warn("failed to delete server install container")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,14 +218,14 @@ func (ip *InstallationProcess) Run() error {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := ip.BeforeExecute(); err != nil {
|
if err := ip.BeforeExecute(); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cid, err := ip.Execute()
|
cid, err := ip.Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ip.RemoveContainer()
|
ip.RemoveContainer()
|
||||||
|
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this step fails, log a warning but don't exit out of the process. This is completely
|
// If this step fails, log a warning but don't exit out of the process. This is completely
|
||||||
|
@ -248,12 +248,12 @@ func (ip *InstallationProcess) writeScriptToDisk() error {
|
||||||
// Make sure the temp directory root exists before trying to make a directory within it. The
|
// Make sure the temp directory root exists before trying to make a directory within it. The
|
||||||
// ioutil.TempDir call expects this base to exist, it won't create it for you.
|
// ioutil.TempDir call expects this base to exist, it won't create it for you.
|
||||||
if err := os.MkdirAll(ip.tempDir(), 0700); err != nil {
|
if err := os.MkdirAll(ip.tempDir(), 0700); err != nil {
|
||||||
return errors.Wrap(err, "could not create temporary directory for install process")
|
return errors.WrapIf(err, "could not create temporary directory for install process")
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.OpenFile(filepath.Join(ip.tempDir(), "install.sh"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
|
f, err := os.OpenFile(filepath.Join(ip.tempDir(), "install.sh"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to write server installation script to disk before mount")
|
return errors.WrapIf(err, "failed to write server installation script to disk before mount")
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ func (ip *InstallationProcess) writeScriptToDisk() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Flush()
|
w.Flush()
|
||||||
|
@ -277,7 +277,7 @@ func (ip *InstallationProcess) writeScriptToDisk() error {
|
||||||
func (ip *InstallationProcess) pullInstallationImage() error {
|
func (ip *InstallationProcess) pullInstallationImage() error {
|
||||||
r, err := ip.client.ImagePull(ip.context, ip.Script.ContainerImage, types.ImagePullOptions{})
|
r, err := ip.client.ImagePull(ip.context, ip.Script.ContainerImage, types.ImagePullOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block continuation until the image has been pulled successfully.
|
// Block continuation until the image has been pulled successfully.
|
||||||
|
@ -287,7 +287,7 @@ func (ip *InstallationProcess) pullInstallationImage() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -298,11 +298,11 @@ func (ip *InstallationProcess) pullInstallationImage() error {
|
||||||
// manner, if either one fails the error is returned.
|
// manner, if either one fails the error is returned.
|
||||||
func (ip *InstallationProcess) BeforeExecute() error {
|
func (ip *InstallationProcess) BeforeExecute() error {
|
||||||
if err := ip.writeScriptToDisk(); err != nil {
|
if err := ip.writeScriptToDisk(); err != nil {
|
||||||
return errors.Wrap(err, "failed to write installation script to disk")
|
return errors.WrapIf(err, "failed to write installation script to disk")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ip.pullInstallationImage(); err != nil {
|
if err := ip.pullInstallationImage(); err != nil {
|
||||||
return errors.Wrap(err, "failed to pull updated installation container image for server")
|
return errors.WrapIf(err, "failed to pull updated installation container image for server")
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := types.ContainerRemoveOptions{
|
opts := types.ContainerRemoveOptions{
|
||||||
|
@ -312,7 +312,7 @@ func (ip *InstallationProcess) BeforeExecute() error {
|
||||||
|
|
||||||
if err := ip.client.ContainerRemove(ip.context, ip.Server.Id()+"_installer", opts); err != nil {
|
if err := ip.client.ContainerRemove(ip.context, ip.Server.Id()+"_installer", opts); err != nil {
|
||||||
if !client.IsErrNotFound(err) {
|
if !client.IsErrNotFound(err) {
|
||||||
return errors.Wrap(err, "failed to remove existing install container for server")
|
return errors.WrapIf(err, "failed to remove existing install container for server")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,12 +338,12 @@ func (ip *InstallationProcess) AfterExecute(containerId string) error {
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil && !client.IsErrNotFound(err) {
|
if err != nil && !client.IsErrNotFound(err) {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.OpenFile(ip.GetLogPath(), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
f, err := os.OpenFile(ip.GetLogPath(), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
|
@ -372,15 +372,15 @@ func (ip *InstallationProcess) AfterExecute(containerId string) error {
|
||||||
| ------------------------------
|
| ------------------------------
|
||||||
`)
|
`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tmpl.Execute(f, ip); err != nil {
|
if err := tmpl.Execute(f, ip); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := io.Copy(f, reader); err != nil {
|
if _, err := io.Copy(f, reader); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -448,7 +448,7 @@ func (ip *InstallationProcess) Execute() (string, error) {
|
||||||
|
|
||||||
r, err := ip.client.ContainerCreate(ip.context, conf, hostConf, nil, ip.Server.Id()+"_installer")
|
r, err := ip.client.ContainerCreate(ip.context, conf, hostConf, nil, ip.Server.Id()+"_installer")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.WithStack(err)
|
return "", errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ip.Server.Log().WithField("container_id", r.ID).Info("running installation script for server in container")
|
ip.Server.Log().WithField("container_id", r.ID).Info("running installation script for server in container")
|
||||||
|
@ -468,7 +468,7 @@ func (ip *InstallationProcess) Execute() (string, error) {
|
||||||
select {
|
select {
|
||||||
case err := <-eChan:
|
case err := <-eChan:
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.WithStack(err)
|
return "", errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
case <-sChan:
|
case <-sChan:
|
||||||
}
|
}
|
||||||
|
@ -487,7 +487,7 @@ func (ip *InstallationProcess) StreamOutput(id string) error {
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
|
@ -500,7 +500,7 @@ func (ip *InstallationProcess) StreamOutput(id string) error {
|
||||||
if err := s.Err(); err != nil {
|
if err := s.Err(); err != nil {
|
||||||
ip.Server.Log().WithFields(log.Fields{
|
ip.Server.Log().WithFields(log.Fields{
|
||||||
"container_id": id,
|
"container_id": id,
|
||||||
"error": errors.WithStack(err),
|
"error": errors.WithStackIf(err),
|
||||||
}).Warn("error processing scanner line in installation output for server")
|
}).Warn("error processing scanner line in installation output for server")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,7 +515,7 @@ func (s *Server) SyncInstallState(successful bool) error {
|
||||||
err := api.New().SendInstallationStatus(s.Id(), successful)
|
err := api.New().SendInstallationStatus(s.Id(), successful)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !api.IsRequestError(err) {
|
if !api.IsRequestError(err) {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.New(err.Error())
|
return errors.New(err.Error())
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
|
@ -77,7 +77,7 @@ func (s *Server) StartEventListeners() {
|
||||||
s.Environment.SetState(environment.ProcessRunningState)
|
s.Environment.SetState(environment.ProcessRunningState)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Log().WithField("error", errors.WithStack(err)).Error("failed to terminate environment after triggering throttle")
|
s.Log().WithField("error", errors.WithStackIf(err)).Error("failed to terminate environment after triggering throttle")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ func (s *Server) StartEventListeners() {
|
||||||
stats := func(e events.Event) {
|
stats := func(e events.Event) {
|
||||||
st := new(environment.Stats)
|
st := new(environment.Stats)
|
||||||
if err := json.Unmarshal([]byte(e.Data), st); err != nil {
|
if err := json.Unmarshal([]byte(e.Data), st); err != nil {
|
||||||
s.Log().WithField("error", errors.WithStack(err)).Warn("failed to unmarshal server environment stats")
|
s.Log().WithField("error", errors.WithStackIf(err)).Warn("failed to unmarshal server environment stats")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/creasty/defaults"
|
"github.com/creasty/defaults"
|
||||||
"github.com/gammazero/workerpool"
|
"github.com/gammazero/workerpool"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
|
@ -35,7 +35,7 @@ func LoadDirectory() error {
|
||||||
configs, err := api.New().GetServers()
|
configs, err := api.New().GetServers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !api.IsRequestError(err) {
|
if !api.IsRequestError(err) {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.New(err.Error())
|
return errors.New(err.Error())
|
||||||
|
@ -89,12 +89,12 @@ func LoadDirectory() error {
|
||||||
func FromConfiguration(data api.ServerConfigurationResponse) (*Server, error) {
|
func FromConfiguration(data api.ServerConfigurationResponse) (*Server, error) {
|
||||||
cfg := Configuration{}
|
cfg := Configuration{}
|
||||||
if err := defaults.Set(&cfg); err != nil {
|
if err := defaults.Set(&cfg); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to set struct defaults for server configuration")
|
return nil, errors.WrapIf(err, "failed to set struct defaults for server configuration")
|
||||||
}
|
}
|
||||||
|
|
||||||
s := new(Server)
|
s := new(Server)
|
||||||
if err := defaults.Set(s); err != nil {
|
if err := defaults.Set(s); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to set struct defaults for server")
|
return nil, errors.WrapIf(err, "failed to set struct defaults for server")
|
||||||
}
|
}
|
||||||
|
|
||||||
s.cfg = cfg
|
s.cfg = cfg
|
||||||
|
|
|
@ -2,7 +2,7 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/pkg/errors"
|
"emperror.dev/errors"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
"github.com/pterodactyl/wings/server/filesystem"
|
"github.com/pterodactyl/wings/server/filesystem"
|
||||||
|
@ -80,13 +80,13 @@ func (s *Server) HandlePowerAction(action PowerAction, waitSeconds ...int) error
|
||||||
// time than that passes an error will be propagated back up the chain and this
|
// time than that passes an error will be propagated back up the chain and this
|
||||||
// request will be aborted.
|
// request will be aborted.
|
||||||
if err := s.powerLock.Acquire(ctx, 1); err != nil {
|
if err := s.powerLock.Acquire(ctx, 1); err != nil {
|
||||||
return errors.Wrap(err, "could not acquire lock on power state")
|
return errors.WrapIf(err, "could not acquire lock on power state")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If no wait duration was provided we will attempt to immediately acquire the lock
|
// If no wait duration was provided we will attempt to immediately acquire the lock
|
||||||
// and bail out with a context deadline error if it is not acquired immediately.
|
// and bail out with a context deadline error if it is not acquired immediately.
|
||||||
if ok := s.powerLock.TryAcquire(1); !ok {
|
if ok := s.powerLock.TryAcquire(1); !ok {
|
||||||
return errors.Wrap(context.DeadlineExceeded, "could not acquire lock on power state")
|
return errors.WrapIf(context.DeadlineExceeded, "could not acquire lock on power state")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ func (s *Server) HandlePowerAction(action PowerAction, waitSeconds ...int) error
|
||||||
func (s *Server) onBeforeStart() error {
|
func (s *Server) onBeforeStart() error {
|
||||||
s.Log().Info("syncing server configuration with panel")
|
s.Log().Info("syncing server configuration with panel")
|
||||||
if err := s.Sync(); err != nil {
|
if err := s.Sync(); err != nil {
|
||||||
return errors.Wrap(err, "unable to sync server data from Panel instance")
|
return errors.WrapIf(err, "unable to sync server data from Panel instance")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disallow start & restart if the server is suspended. Do this check after performing a sync
|
// Disallow start & restart if the server is suspended. Do this check after performing a sync
|
||||||
|
@ -185,7 +185,7 @@ func (s *Server) onBeforeStart() error {
|
||||||
s.PublishConsoleOutputFromDaemon("Ensuring file permissions are set correctly, this could take a few seconds...")
|
s.PublishConsoleOutputFromDaemon("Ensuring file permissions are set correctly, this could take a few seconds...")
|
||||||
// Ensure all of the server file permissions are set correctly before booting the process.
|
// Ensure all of the server file permissions are set correctly before booting the process.
|
||||||
if err := s.Filesystem().Chown("/"); err != nil {
|
if err := s.Filesystem().Chown("/"); err != nil {
|
||||||
return errors.Wrap(err, "failed to chown root server directory during pre-boot process")
|
return errors.WrapIf(err, "failed to chown root server directory during pre-boot process")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"emperror.dev/errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
|
@ -115,7 +115,7 @@ func (s *Server) Sync() error {
|
||||||
cfg, err := api.New().GetServerConfiguration(s.Id())
|
cfg, err := api.New().GetServerConfiguration(s.Id())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !api.IsRequestError(err) {
|
if !api.IsRequestError(err) {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err.(*api.RequestError).Status == "404" {
|
if err.(*api.RequestError).Status == "404" {
|
||||||
|
@ -131,7 +131,7 @@ func (s *Server) Sync() error {
|
||||||
func (s *Server) SyncWithConfiguration(cfg api.ServerConfigurationResponse) error {
|
func (s *Server) SyncWithConfiguration(cfg api.ServerConfigurationResponse) error {
|
||||||
// Update the data structure and persist it to the disk.
|
// Update the data structure and persist it to the disk.
|
||||||
if err := s.UpdateDataStructure(cfg.Settings); err != nil {
|
if err := s.UpdateDataStructure(cfg.Settings); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Lock()
|
s.Lock()
|
||||||
|
@ -171,7 +171,7 @@ func (s *Server) IsBootable() bool {
|
||||||
func (s *Server) CreateEnvironment() error {
|
func (s *Server) CreateEnvironment() error {
|
||||||
// Ensure the data directory exists before getting too far through this process.
|
// Ensure the data directory exists before getting too far through this process.
|
||||||
if err := s.EnsureDataDirectoryExists(); err != nil {
|
if err := s.EnsureDataDirectoryExists(); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.Environment.Create()
|
return s.Environment.Create()
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
"io"
|
"io"
|
||||||
|
@ -22,14 +22,14 @@ func CachedServerStates() (map[string]string, error) {
|
||||||
// Open the states file.
|
// Open the states file.
|
||||||
f, err := os.OpenFile(config.Get().System.GetStatesPath(), os.O_RDONLY|os.O_CREATE, 0644)
|
f, err := os.OpenFile(config.Get().System.GetStatesPath(), os.O_RDONLY|os.O_CREATE, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
// Convert the json object to a map.
|
// Convert the json object to a map.
|
||||||
states := map[string]string{}
|
states := map[string]string{}
|
||||||
if err := json.NewDecoder(f).Decode(&states); err != nil && err != io.EOF {
|
if err := json.NewDecoder(f).Decode(&states); err != nil && err != io.EOF {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return states, nil
|
return states, nil
|
||||||
|
@ -46,7 +46,7 @@ func saveServerStates() error {
|
||||||
// Convert the map to a json object.
|
// Convert the map to a json object.
|
||||||
data, err := json.Marshal(states)
|
data, err := json.Marshal(states)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
stateMutex.Lock()
|
stateMutex.Lock()
|
||||||
|
@ -54,7 +54,7 @@ func saveServerStates() error {
|
||||||
|
|
||||||
// Write the data to the file
|
// Write the data to the file
|
||||||
if err := ioutil.WriteFile(config.Get().System.GetStatesPath(), data, 0644); err != nil {
|
if err := ioutil.WriteFile(config.Get().System.GetStatesPath(), data, 0644); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/buger/jsonparser"
|
"github.com/buger/jsonparser"
|
||||||
"github.com/imdario/mergo"
|
"github.com/imdario/mergo"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ import (
|
||||||
func (s *Server) UpdateDataStructure(data []byte) error {
|
func (s *Server) UpdateDataStructure(data []byte) error {
|
||||||
src := new(Configuration)
|
src := new(Configuration)
|
||||||
if err := json.Unmarshal(data, src); err != nil {
|
if err := json.Unmarshal(data, src); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow obviously corrupted data to pass through into this function. If the UUID
|
// Don't allow obviously corrupted data to pass through into this function. If the UUID
|
||||||
|
@ -47,7 +47,7 @@ func (s *Server) UpdateDataStructure(data []byte) error {
|
||||||
// Merge the new data object that we have received with the existing server data object
|
// Merge the new data object that we have received with the existing server data object
|
||||||
// and then save it to the disk so it is persistent.
|
// and then save it to the disk so it is persistent.
|
||||||
if err := mergo.Merge(&c, src, mergo.WithOverride); err != nil {
|
if err := mergo.Merge(&c, src, mergo.WithOverride); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't explode if we're setting CPU limits to 0. Mergo sees that as an empty value
|
// Don't explode if we're setting CPU limits to 0. Mergo sees that as an empty value
|
||||||
|
@ -65,7 +65,7 @@ func (s *Server) UpdateDataStructure(data []byte) error {
|
||||||
// request is going to be boolean. Allegedly.
|
// request is going to be boolean. Allegedly.
|
||||||
if v, err := jsonparser.GetBoolean(data, "container", "oom_disabled"); err != nil {
|
if v, err := jsonparser.GetBoolean(data, "container", "oom_disabled"); err != nil {
|
||||||
if err != jsonparser.KeyPathNotFoundError {
|
if err != jsonparser.KeyPathNotFoundError {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.Build.OOMDisabled = v
|
c.Build.OOMDisabled = v
|
||||||
|
@ -74,7 +74,7 @@ func (s *Server) UpdateDataStructure(data []byte) error {
|
||||||
// Mergo also cannot handle this boolean value.
|
// Mergo also cannot handle this boolean value.
|
||||||
if v, err := jsonparser.GetBoolean(data, "suspended"); err != nil {
|
if v, err := jsonparser.GetBoolean(data, "suspended"); err != nil {
|
||||||
if err != jsonparser.KeyPathNotFoundError {
|
if err != jsonparser.KeyPathNotFoundError {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.Suspended = v
|
c.Suspended = v
|
||||||
|
@ -82,7 +82,7 @@ func (s *Server) UpdateDataStructure(data []byte) error {
|
||||||
|
|
||||||
if v, err := jsonparser.GetBoolean(data, "skip_egg_scripts"); err != nil {
|
if v, err := jsonparser.GetBoolean(data, "skip_egg_scripts"); err != nil {
|
||||||
if err != jsonparser.KeyPathNotFoundError {
|
if err != jsonparser.KeyPathNotFoundError {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.SkipEggScripts = v
|
c.SkipEggScripts = v
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type WebsocketBag struct {
|
type WebsocketBag struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
conns map[uuid.UUID]*context.CancelFunc
|
conns map[uuid.UUID]*context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,4 +58,4 @@ func (w *WebsocketBag) CancelAll() {
|
||||||
|
|
||||||
// Reset the connections.
|
// Reset the connections.
|
||||||
w.conns = make(map[uuid.UUID]*context.CancelFunc)
|
w.conns = make(map[uuid.UUID]*context.CancelFunc)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package sftp
|
package sftp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pkg/sftp"
|
"github.com/pkg/sftp"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -58,14 +58,14 @@ func (fs FileSystem) Fileread(request *sftp.Request) (io.ReaderAt, error) {
|
||||||
if _, err := os.Stat(p); os.IsNotExist(err) {
|
if _, err := os.Stat(p); os.IsNotExist(err) {
|
||||||
return nil, sftp.ErrSshFxNoSuchFile
|
return nil, sftp.ErrSshFxNoSuchFile
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
fs.logger.WithField("error", errors.WithStack(err)).Error("error while processing file stat")
|
fs.logger.WithField("error", errors.WithStackIf(err)).Error("error while processing file stat")
|
||||||
|
|
||||||
return nil, sftp.ErrSshFxFailure
|
return nil, sftp.ErrSshFxFailure
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := os.Open(p)
|
file, err := os.Open(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fs.logger.WithField("source", p).WithField("error", errors.WithStack(err)).Error("could not open file for reading")
|
fs.logger.WithField("source", p).WithField("error", errors.WithStackIf(err)).Error("could not open file for reading")
|
||||||
return nil, sftp.ErrSshFxFailure
|
return nil, sftp.ErrSshFxFailure
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ func (fs FileSystem) Filewrite(request *sftp.Request) (io.WriterAt, error) {
|
||||||
if err := os.MkdirAll(filepath.Dir(p), 0755); err != nil {
|
if err := os.MkdirAll(filepath.Dir(p), 0755); err != nil {
|
||||||
l.WithFields(log.Fields{
|
l.WithFields(log.Fields{
|
||||||
"path": filepath.Dir(p),
|
"path": filepath.Dir(p),
|
||||||
"error": errors.WithStack(err),
|
"error": errors.WithStackIf(err),
|
||||||
}).Error("error making path for file")
|
}).Error("error making path for file")
|
||||||
|
|
||||||
return nil, sftp.ErrSshFxFailure
|
return nil, sftp.ErrSshFxFailure
|
||||||
|
@ -116,7 +116,7 @@ func (fs FileSystem) Filewrite(request *sftp.Request) (io.WriterAt, error) {
|
||||||
|
|
||||||
file, err := os.Create(p)
|
file, err := os.Create(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to create file")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to create file")
|
||||||
|
|
||||||
return nil, sftp.ErrSshFxFailure
|
return nil, sftp.ErrSshFxFailure
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ func (fs FileSystem) Filewrite(request *sftp.Request) (io.WriterAt, error) {
|
||||||
// Not failing here is intentional. We still made the file, it is just owned incorrectly
|
// Not failing here is intentional. We still made the file, it is just owned incorrectly
|
||||||
// and will likely cause some issues.
|
// and will likely cause some issues.
|
||||||
if err := os.Chown(p, fs.User.Uid, fs.User.Gid); err != nil {
|
if err := os.Chown(p, fs.User.Uid, fs.User.Gid); err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Warn("failed to set permissions on file")
|
l.WithField("error", errors.WithStackIf(err)).Warn("failed to set permissions on file")
|
||||||
}
|
}
|
||||||
|
|
||||||
return file, nil
|
return file, nil
|
||||||
|
@ -133,7 +133,7 @@ func (fs FileSystem) Filewrite(request *sftp.Request) (io.WriterAt, error) {
|
||||||
// If the stat error isn't about the file not existing, there is some other issue
|
// If the stat error isn't about the file not existing, there is some other issue
|
||||||
// at play and we need to go ahead and bail out of the process.
|
// at play and we need to go ahead and bail out of the process.
|
||||||
if statErr != nil {
|
if statErr != nil {
|
||||||
l.WithField("error", errors.WithStack(statErr)).Error("encountered error performing file stat")
|
l.WithField("error", errors.WithStackIf(statErr)).Error("encountered error performing file stat")
|
||||||
|
|
||||||
return nil, sftp.ErrSshFxFailure
|
return nil, sftp.ErrSshFxFailure
|
||||||
}
|
}
|
||||||
|
@ -159,14 +159,14 @@ func (fs FileSystem) Filewrite(request *sftp.Request) (io.WriterAt, error) {
|
||||||
return nil, sftp.ErrSSHFxNoSuchFile
|
return nil, sftp.ErrSSHFxNoSuchFile
|
||||||
}
|
}
|
||||||
|
|
||||||
l.WithField("flags", request.Flags).WithField("error", errors.WithStack(err)).Error("failed to open existing file on system")
|
l.WithField("flags", request.Flags).WithField("error", errors.WithStackIf(err)).Error("failed to open existing file on system")
|
||||||
return nil, sftp.ErrSshFxFailure
|
return nil, sftp.ErrSshFxFailure
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not failing here is intentional. We still made the file, it is just owned incorrectly
|
// Not failing here is intentional. We still made the file, it is just owned incorrectly
|
||||||
// and will likely cause some issues.
|
// and will likely cause some issues.
|
||||||
if err := os.Chown(p, fs.User.Uid, fs.User.Gid); err != nil {
|
if err := os.Chown(p, fs.User.Uid, fs.User.Gid); err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Warn("error chowning file")
|
l.WithField("error", errors.WithStackIf(err)).Warn("error chowning file")
|
||||||
}
|
}
|
||||||
|
|
||||||
return file, nil
|
return file, nil
|
||||||
|
@ -220,7 +220,7 @@ func (fs FileSystem) Filecmd(request *sftp.Request) error {
|
||||||
return sftp.ErrSSHFxNoSuchFile
|
return sftp.ErrSSHFxNoSuchFile
|
||||||
}
|
}
|
||||||
|
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to perform setstat on item")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to perform setstat on item")
|
||||||
return sftp.ErrSSHFxFailure
|
return sftp.ErrSSHFxFailure
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -234,7 +234,7 @@ func (fs FileSystem) Filecmd(request *sftp.Request) error {
|
||||||
return sftp.ErrSSHFxNoSuchFile
|
return sftp.ErrSSHFxNoSuchFile
|
||||||
}
|
}
|
||||||
|
|
||||||
l.WithField("target", target).WithField("error", errors.WithStack(err)).Error("failed to rename file")
|
l.WithField("target", target).WithField("error", errors.WithStackIf(err)).Error("failed to rename file")
|
||||||
|
|
||||||
return sftp.ErrSshFxFailure
|
return sftp.ErrSshFxFailure
|
||||||
}
|
}
|
||||||
|
@ -246,7 +246,7 @@ func (fs FileSystem) Filecmd(request *sftp.Request) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.RemoveAll(p); err != nil {
|
if err := os.RemoveAll(p); err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to remove directory")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to remove directory")
|
||||||
|
|
||||||
return sftp.ErrSshFxFailure
|
return sftp.ErrSshFxFailure
|
||||||
}
|
}
|
||||||
|
@ -258,7 +258,7 @@ func (fs FileSystem) Filecmd(request *sftp.Request) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(p, 0755); err != nil {
|
if err := os.MkdirAll(p, 0755); err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to create directory")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to create directory")
|
||||||
|
|
||||||
return sftp.ErrSshFxFailure
|
return sftp.ErrSshFxFailure
|
||||||
}
|
}
|
||||||
|
@ -270,7 +270,7 @@ func (fs FileSystem) Filecmd(request *sftp.Request) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.Symlink(p, target); err != nil {
|
if err := os.Symlink(p, target); err != nil {
|
||||||
l.WithField("target", target).WithField("error", errors.WithStack(err)).Error("failed to create symlink")
|
l.WithField("target", target).WithField("error", errors.WithStackIf(err)).Error("failed to create symlink")
|
||||||
|
|
||||||
return sftp.ErrSshFxFailure
|
return sftp.ErrSshFxFailure
|
||||||
}
|
}
|
||||||
|
@ -286,7 +286,7 @@ func (fs FileSystem) Filecmd(request *sftp.Request) error {
|
||||||
return sftp.ErrSSHFxNoSuchFile
|
return sftp.ErrSSHFxNoSuchFile
|
||||||
}
|
}
|
||||||
|
|
||||||
l.WithField("error", errors.WithStack(err)).Error("failed to remove a file")
|
l.WithField("error", errors.WithStackIf(err)).Error("failed to remove a file")
|
||||||
|
|
||||||
return sftp.ErrSshFxFailure
|
return sftp.ErrSshFxFailure
|
||||||
}
|
}
|
||||||
|
@ -305,7 +305,7 @@ func (fs FileSystem) Filecmd(request *sftp.Request) error {
|
||||||
// and will likely cause some issues. There is no logical check for if the file was removed
|
// and will likely cause some issues. There is no logical check for if the file was removed
|
||||||
// because both of those cases (Rmdir, Remove) have an explicit return rather than break.
|
// because both of those cases (Rmdir, Remove) have an explicit return rather than break.
|
||||||
if err := os.Chown(fileLocation, fs.User.Uid, fs.User.Gid); err != nil {
|
if err := os.Chown(fileLocation, fs.User.Uid, fs.User.Gid); err != nil {
|
||||||
l.WithField("error", errors.WithStack(err)).Warn("error chowning file")
|
l.WithField("error", errors.WithStackIf(err)).Warn("error chowning file")
|
||||||
}
|
}
|
||||||
|
|
||||||
return sftp.ErrSshFxOk
|
return sftp.ErrSshFxOk
|
||||||
|
@ -327,7 +327,7 @@ func (fs FileSystem) Filelist(request *sftp.Request) (sftp.ListerAt, error) {
|
||||||
|
|
||||||
files, err := ioutil.ReadDir(p)
|
files, err := ioutil.ReadDir(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fs.logger.WithField("error", errors.WithStack(err)).Error("error while listing directory")
|
fs.logger.WithField("error", errors.WithStackIf(err)).Error("error while listing directory")
|
||||||
|
|
||||||
return nil, sftp.ErrSshFxFailure
|
return nil, sftp.ErrSshFxFailure
|
||||||
}
|
}
|
||||||
|
@ -342,7 +342,7 @@ func (fs FileSystem) Filelist(request *sftp.Request) (sftp.ListerAt, error) {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil, sftp.ErrSshFxNoSuchFile
|
return nil, sftp.ErrSshFxNoSuchFile
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
fs.logger.WithField("source", p).WithField("error", errors.WithStack(err)).Error("error performing stat on file")
|
fs.logger.WithField("source", p).WithField("error", errors.WithStackIf(err)).Error("error performing stat on file")
|
||||||
|
|
||||||
return nil, sftp.ErrSshFxFailure
|
return nil, sftp.ErrSshFxFailure
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package sftp
|
package sftp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/server"
|
"github.com/pterodactyl/wings/server"
|
||||||
|
@ -28,14 +28,14 @@ func Initialize(config config.SystemConfiguration) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := New(s); err != nil {
|
if err := New(s); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the SFTP server in a background thread since this is
|
// Initialize the SFTP server in a background thread since this is
|
||||||
// a long running operation.
|
// a long running operation.
|
||||||
go func(s *Server) {
|
go func(s *Server) {
|
||||||
if err := s.Initialize(); err != nil {
|
if err := s.Initialize(); err != nil {
|
||||||
log.WithField("subsystem", "sftp").WithField("error", errors.WithStack(err)).Error("failed to initialize SFTP subsystem")
|
log.WithField("subsystem", "sftp").WithField("error", errors.WithStackIf(err)).Error("failed to initialize SFTP subsystem")
|
||||||
}
|
}
|
||||||
}(s)
|
}(s)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user