Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96256ac63e | ||
|
|
6701aa6dc1 | ||
|
|
ff8926bba8 | ||
|
|
217ca72eb3 | ||
|
|
648072436f | ||
|
|
6fe2468a5a | ||
|
|
948d927eb9 | ||
|
|
b2eaa3f7f8 | ||
|
|
93417dddb1 | ||
|
|
044c46fc9a | ||
|
|
c9d972d544 | ||
|
|
0aab4b1ac2 | ||
|
|
4f4b4fd2e6 | ||
|
|
66c9be357c | ||
|
|
1d36811dfe |
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,5 +1,19 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v1.2.3
|
||||||
|
### Fixed
|
||||||
|
* **[Security]** Fixes a remaining security vulnerability in the code handling remote file downloads for servers relating to redirect validation.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* Adds a configuration key at `api.disable_remote_download` that can be set to `true` to completely download the remote download system.
|
||||||
|
|
||||||
|
## v1.2.2
|
||||||
|
### Fixed
|
||||||
|
* Reverts changes to logic handling blocking until a server process is done running when polling stats. This change exposed a bug in the underlying Docker system causing servers to enter a state in which Wings was unable to terminate the process and Docker commands would hang if executed against the container.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* Adds logic to handle a console stream unexpectedly returning an EOF when reading console logs. New code should automatically re-attach the stream avoiding issues where the console would stop live updating for servers.
|
||||||
|
|
||||||
## v1.2.1
|
## v1.2.1
|
||||||
### Fixed
|
### Fixed
|
||||||
* Fixes servers not be properly marked as no longer transfering if an error occurs during the archive process.
|
* Fixes servers not be properly marked as no longer transfering if an error occurs during the archive process.
|
||||||
|
|||||||
@@ -2,17 +2,18 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"emperror.dev/errors"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/apex/log"
|
|
||||||
"github.com/pterodactyl/wings/config"
|
|
||||||
"github.com/pterodactyl/wings/system"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
|
"github.com/apex/log"
|
||||||
|
"github.com/pterodactyl/wings/config"
|
||||||
|
"github.com/pterodactyl/wings/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Initializes the requester instance.
|
// Initializes the requester instance.
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/apex/log"
|
|
||||||
"github.com/pterodactyl/wings/parser"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/apex/log"
|
||||||
|
"github.com/pterodactyl/wings/parser"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OutputLineMatcher struct {
|
type OutputLineMatcher struct {
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"regexp"
|
||||||
|
|
||||||
"emperror.dev/errors"
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"regexp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SftpAuthRequest struct {
|
type SftpAuthRequest struct {
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pterodactyl/wings/config"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/pterodactyl/wings/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// We've gone through a couple of iterations of where the configuration is stored. This
|
// We've gone through a couple of iterations of where the configuration is stored. This
|
||||||
|
|||||||
@@ -4,10 +4,6 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/AlecAivazis/survey/v2"
|
|
||||||
"github.com/AlecAivazis/survey/v2/terminal"
|
|
||||||
"github.com/pterodactyl/wings/config"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -15,6 +11,11 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"regexp"
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/AlecAivazis/survey/v2"
|
||||||
|
"github.com/AlecAivazis/survey/v2/terminal"
|
||||||
|
"github.com/pterodactyl/wings/config"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pterodactyl/wings/environment"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -16,6 +15,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/pterodactyl/wings/environment"
|
||||||
|
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/AlecAivazis/survey/v2/terminal"
|
"github.com/AlecAivazis/survey/v2/terminal"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
|||||||
119
cmd/root.go
119
cmd/root.go
@@ -2,8 +2,15 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"emperror.dev/errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
log2 "log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/NYTimes/logrotate"
|
"github.com/NYTimes/logrotate"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/apex/log/handlers/multi"
|
"github.com/apex/log/handlers/multi"
|
||||||
@@ -21,47 +28,54 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"golang.org/x/crypto/acme"
|
"golang.org/x/crypto/acme"
|
||||||
"golang.org/x/crypto/acme/autocert"
|
"golang.org/x/crypto/acme/autocert"
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
profiler = ""
|
configPath = config.DefaultLocation
|
||||||
configPath = config.DefaultLocation
|
debug = false
|
||||||
debug = false
|
|
||||||
useAutomaticTls = false
|
|
||||||
tlsHostname = ""
|
|
||||||
showVersion = false
|
|
||||||
ignoreCertificateErrors = false
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var root = &cobra.Command{
|
var rootCommand = &cobra.Command{
|
||||||
Use: "wings",
|
Use: "wings",
|
||||||
Short: "The wings of the pterodactyl game management panel",
|
Short: "Runs the API server allowing programatic control of game servers for Pterodactyl Panel.",
|
||||||
Long: ``,
|
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
if useAutomaticTls && len(tlsHostname) == 0 {
|
if tls, _ := cmd.Flags().GetBool("auto-tls"); tls {
|
||||||
fmt.Println("A TLS hostname must be provided when running wings with automatic TLS, e.g.:\n\n ./wings --auto-tls --tls-hostname my.example.com")
|
if host, _ := cmd.Flags().GetString("tls-hostname"); host == "" {
|
||||||
os.Exit(1)
|
fmt.Println("A TLS hostname must be provided when running wings with automatic TLS, e.g.:\n\n ./wings --auto-tls --tls-hostname my.example.com")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Run: rootCmdRun,
|
Run: rootCmdRun,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
var versionCommand = &cobra.Command{
|
||||||
root.PersistentFlags().BoolVar(&showVersion, "version", false, "show the version and exit")
|
Use: "version",
|
||||||
root.PersistentFlags().StringVar(&configPath, "config", config.DefaultLocation, "set the location for the configuration file")
|
Short: "Prints the current executable version and exits.",
|
||||||
root.PersistentFlags().BoolVar(&debug, "debug", false, "pass in order to run wings in debug mode")
|
Run: func(cmd *cobra.Command, _ []string) {
|
||||||
root.PersistentFlags().StringVar(&profiler, "profiler", "", "the profiler to run for this instance")
|
fmt.Printf("wings v%s\nCopyright © 2018 - 2021 Dane Everitt & Contributors\n", system.Version)
|
||||||
root.PersistentFlags().BoolVar(&useAutomaticTls, "auto-tls", false, "pass in order to have wings generate and manage it's own SSL certificates using Let's Encrypt")
|
},
|
||||||
root.PersistentFlags().StringVar(&tlsHostname, "tls-hostname", "", "required with --auto-tls, the FQDN for the generated SSL certificate")
|
}
|
||||||
root.PersistentFlags().BoolVar(&ignoreCertificateErrors, "ignore-certificate-errors", false, "if passed any SSL certificate errors will be ignored by wings")
|
|
||||||
|
|
||||||
root.AddCommand(configureCmd)
|
func Execute() {
|
||||||
root.AddCommand(diagnosticsCmd)
|
if err := rootCommand.Execute(); err != nil {
|
||||||
|
log2.Fatalf("failed to execute command: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCommand.PersistentFlags().StringVar(&configPath, "config", config.DefaultLocation, "set the location for the configuration file")
|
||||||
|
rootCommand.PersistentFlags().BoolVar(&debug, "debug", false, "pass in order to run wings in debug mode")
|
||||||
|
|
||||||
|
// Flags specifically used when running the API.
|
||||||
|
rootCommand.Flags().String("profiler", "", "the profiler to run for this instance")
|
||||||
|
rootCommand.Flags().Bool("auto-tls", false, "pass in order to have wings generate and manage it's own SSL certificates using Let's Encrypt")
|
||||||
|
rootCommand.Flags().String("tls-hostname", "", "required with --auto-tls, the FQDN for the generated SSL certificate")
|
||||||
|
rootCommand.Flags().Bool("ignore-certificate-errors", false, "ignore certificate verification errors when executing API calls")
|
||||||
|
|
||||||
|
rootCommand.AddCommand(versionCommand)
|
||||||
|
rootCommand.AddCommand(configureCmd)
|
||||||
|
rootCommand.AddCommand(diagnosticsCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the configuration path based on the arguments provided.
|
// Get the configuration path based on the arguments provided.
|
||||||
@@ -85,13 +99,8 @@ func readConfiguration() (*config.Configuration, error) {
|
|||||||
return config.ReadConfiguration(p)
|
return config.ReadConfiguration(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func rootCmdRun(*cobra.Command, []string) {
|
func rootCmdRun(cmd *cobra.Command, _ []string) {
|
||||||
if showVersion {
|
switch cmd.Flag("profiler").Value.String() {
|
||||||
fmt.Println(system.Version)
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch profiler {
|
|
||||||
case "cpu":
|
case "cpu":
|
||||||
defer profile.Start(profile.CPUProfile).Stop()
|
defer profile.Start(profile.CPUProfile).Stop()
|
||||||
case "mem":
|
case "mem":
|
||||||
@@ -117,7 +126,6 @@ func rootCmdRun(*cobra.Command, []string) {
|
|||||||
if errors.Is(err, os.ErrNotExist) {
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
exitWithConfigurationNotice()
|
exitWithConfigurationNotice()
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,7 +149,7 @@ func rootCmdRun(*cobra.Command, []string) {
|
|||||||
log.Debug("running in debug mode")
|
log.Debug("running in debug mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
if ignoreCertificateErrors {
|
if ok, _ := cmd.Flags().GetBool("ignore-certificate-errors"); ok {
|
||||||
log.Warn("running with --ignore-certificate-errors: TLS certificate host chains and name will not be verified")
|
log.Warn("running with --ignore-certificate-errors: TLS certificate host chains and name will not be verified")
|
||||||
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{
|
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
@@ -280,9 +288,15 @@ func rootCmdRun(*cobra.Command, []string) {
|
|||||||
log.WithField("error", err).Error("failed to create backup directory")
|
log.WithField("error", err).Error("failed to create backup directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
autotls, _ := cmd.Flags().GetBool("auto-tls")
|
||||||
|
tlshostname, _ := cmd.Flags().GetString("tls-hostname")
|
||||||
|
if autotls && tlshostname == "" {
|
||||||
|
autotls = false
|
||||||
|
}
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"use_ssl": c.Api.Ssl.Enabled,
|
"use_ssl": c.Api.Ssl.Enabled,
|
||||||
"use_auto_tls": useAutomaticTls && len(tlsHostname) > 0,
|
"use_auto_tls": autotls,
|
||||||
"host_address": c.Api.Host,
|
"host_address": c.Api.Host,
|
||||||
"host_port": c.Api.Port,
|
"host_port": c.Api.Port,
|
||||||
}).Info("configuring internal webserver")
|
}).Info("configuring internal webserver")
|
||||||
@@ -293,7 +307,6 @@ func rootCmdRun(*cobra.Command, []string) {
|
|||||||
s := &http.Server{
|
s := &http.Server{
|
||||||
Addr: fmt.Sprintf("%s:%d", c.Api.Host, c.Api.Port),
|
Addr: fmt.Sprintf("%s:%d", c.Api.Host, c.Api.Port),
|
||||||
Handler: r,
|
Handler: r,
|
||||||
|
|
||||||
TLSConfig: &tls.Config{
|
TLSConfig: &tls.Config{
|
||||||
NextProtos: []string{"h2", "http/1.1"},
|
NextProtos: []string{"h2", "http/1.1"},
|
||||||
// @see https://blog.cloudflare.com/exposing-go-on-the-internet
|
// @see https://blog.cloudflare.com/exposing-go-on-the-internet
|
||||||
@@ -313,14 +326,14 @@ func rootCmdRun(*cobra.Command, []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the server should run with TLS but using autocert.
|
// Check if the server should run with TLS but using autocert.
|
||||||
if useAutomaticTls && len(tlsHostname) > 0 {
|
if autotls {
|
||||||
m := autocert.Manager{
|
m := autocert.Manager{
|
||||||
Prompt: autocert.AcceptTOS,
|
Prompt: autocert.AcceptTOS,
|
||||||
Cache: autocert.DirCache(path.Join(c.System.RootDirectory, "/.tls-cache")),
|
Cache: autocert.DirCache(path.Join(c.System.RootDirectory, "/.tls-cache")),
|
||||||
HostPolicy: autocert.HostWhitelist(tlsHostname),
|
HostPolicy: autocert.HostWhitelist(tlshostname),
|
||||||
}
|
}
|
||||||
|
|
||||||
log.WithField("hostname", tlsHostname).
|
log.WithField("hostname", tlshostname).
|
||||||
Info("webserver is now listening with auto-TLS enabled; certificates will be automatically generated by Let's Encrypt")
|
Info("webserver is now listening with auto-TLS enabled; certificates will be automatically generated by Let's Encrypt")
|
||||||
|
|
||||||
// Hook autocert into the main http server.
|
// Hook autocert into the main http server.
|
||||||
@@ -336,7 +349,7 @@ func rootCmdRun(*cobra.Command, []string) {
|
|||||||
|
|
||||||
// Start the main http server with TLS using autocert.
|
// Start the main http server with TLS using autocert.
|
||||||
if err := s.ListenAndServeTLS("", ""); err != nil {
|
if err := s.ListenAndServeTLS("", ""); err != nil {
|
||||||
log.WithFields(log.Fields{"auto_tls": true, "tls_hostname": tlsHostname, "error": err}).
|
log.WithFields(log.Fields{"auto_tls": true, "tls_hostname": tlshostname, "error": err}).
|
||||||
Fatal("failed to configure HTTP server using auto-tls")
|
Fatal("failed to configure HTTP server using auto-tls")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,11 +377,6 @@ func rootCmdRun(*cobra.Command, []string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute calls cobra to handle cli commands
|
|
||||||
func Execute() error {
|
|
||||||
return root.Execute()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configures the global logger for Zap so that we can call it from any location
|
// Configures the global logger for Zap so that we can call it from any location
|
||||||
// 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 {
|
||||||
@@ -379,20 +387,15 @@ func configureLogging(logDir string, debug bool) error {
|
|||||||
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.WithMessage(err, "failed to open process log file"))
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.SetLevel(log.InfoLevel)
|
||||||
if debug {
|
if debug {
|
||||||
log.SetLevel(log.DebugLevel)
|
log.SetLevel(log.DebugLevel)
|
||||||
} else {
|
|
||||||
log.SetLevel(log.InfoLevel)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SetHandler(multi.New(
|
log.SetHandler(multi.New(cli.Default, cli.New(w.File, false)))
|
||||||
cli.Default,
|
|
||||||
cli.New(w.File, false),
|
|
||||||
))
|
|
||||||
|
|
||||||
log.WithField("path", p).Info("writing log files to disk")
|
log.WithField("path", p).Info("writing log files to disk")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -406,7 +409,7 @@ __ [blue][bold]Pterodactyl[reset] _____/___/_______ _______ ______
|
|||||||
\_____\ \/\/ / / / __ / ___/
|
\_____\ \/\/ / / / __ / ___/
|
||||||
\___\ / / / / /_/ /___ /
|
\___\ / / / / /_/ /___ /
|
||||||
\___/\___/___/___/___/___ /______/
|
\___/\___/___/___/___/___ /______/
|
||||||
/_______/ [bold]v%s[reset]
|
/_______/ [bold]%s[reset]
|
||||||
|
|
||||||
Copyright © 2018 - 2021 Dane Everitt & Contributors
|
Copyright © 2018 - 2021 Dane Everitt & Contributors
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"emperror.dev/errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/cobaugh/osrelease"
|
|
||||||
"github.com/creasty/defaults"
|
|
||||||
"github.com/gbrlsnchs/jwt/v3"
|
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -14,6 +9,12 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
|
"github.com/cobaugh/osrelease"
|
||||||
|
"github.com/creasty/defaults"
|
||||||
|
"github.com/gbrlsnchs/jwt/v3"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const DefaultLocation = "/etc/pterodactyl/config.yml"
|
const DefaultLocation = "/etc/pterodactyl/config.yml"
|
||||||
@@ -87,11 +88,16 @@ type ApiConfiguration struct {
|
|||||||
|
|
||||||
// SSL configuration for the daemon.
|
// SSL configuration for the daemon.
|
||||||
Ssl struct {
|
Ssl struct {
|
||||||
Enabled bool `default:"false"`
|
Enabled bool `json:"enabled" yaml:"enabled"`
|
||||||
CertificateFile string `json:"cert" yaml:"cert"`
|
CertificateFile string `json:"cert" yaml:"cert"`
|
||||||
KeyFile string `json:"key" yaml:"key"`
|
KeyFile string `json:"key" yaml:"key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determines if functionality for allowing remote download of files into server directories
|
||||||
|
// is enabled on this instance. If set to "true" remote downloads will not be possible for
|
||||||
|
// servers.
|
||||||
|
DisableRemoteDownload bool `json:"disable_remote_download" yaml:"disable_remote_download"`
|
||||||
|
|
||||||
// The maximum size for files uploaded through the Panel in bytes.
|
// The maximum size for files uploaded through the Panel in bytes.
|
||||||
UploadLimit int `default:"100" json:"upload_limit" yaml:"upload_limit"`
|
UploadLimit int `default:"100" json:"upload_limit" yaml:"upload_limit"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package config
|
|||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"emperror.dev/errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/apex/log"
|
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@@ -13,6 +11,9 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
|
"github.com/apex/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Defines basic system configuration settings.
|
// Defines basic system configuration settings.
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ package environment
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Defines the allocations available for a given server. When using the Docker environment
|
// Defines the allocations available for a given server. When using the Docker environment
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ package environment
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/apex/log"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/apex/log"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
|||||||
@@ -26,6 +26,18 @@ type imagePullStatus struct {
|
|||||||
Progress string `json:"progress"`
|
Progress string `json:"progress"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A custom console writer that allows us to keep a function blocked until the
|
||||||
|
// given stream is properly closed. This does nothing special, only exists to
|
||||||
|
// make a noop io.Writer.
|
||||||
|
type noopWriter struct{}
|
||||||
|
|
||||||
|
var _ io.Writer = noopWriter{}
|
||||||
|
|
||||||
|
// Implement the required Write function to satisfy the io.Writer interface.
|
||||||
|
func (nw noopWriter) Write(b []byte) (int, error) {
|
||||||
|
return len(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Attaches to the docker container itself and ensures that we can pipe data in and out
|
// Attaches to the docker container itself and ensures that we can pipe data in and out
|
||||||
// of the process stream. This should not be used for reading console data as you *will*
|
// of the process stream. This should not be used for reading console data as you *will*
|
||||||
// miss important output at the beginning because of the time delay with attaching to the
|
// miss important output at the beginning because of the time delay with attaching to the
|
||||||
@@ -60,8 +72,8 @@ func (e *Environment) Attach() error {
|
|||||||
go func() {
|
go func() {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
defer e.stream.Close()
|
||||||
defer func() {
|
defer func() {
|
||||||
e.stream.Close()
|
|
||||||
e.SetState(environment.ProcessOfflineState)
|
e.SetState(environment.ProcessOfflineState)
|
||||||
e.SetStream(nil)
|
e.SetStream(nil)
|
||||||
}()
|
}()
|
||||||
@@ -78,24 +90,18 @@ func (e *Environment) Attach() error {
|
|||||||
|
|
||||||
// Block the completion of this routine until the container is no longer running. This allows
|
// Block the completion of this routine until the container is no longer running. This allows
|
||||||
// the pollResources function to run until it needs to be stopped. Because the container
|
// the pollResources function to run until it needs to be stopped. Because the container
|
||||||
// can be polled for resource usage, even when sropped, we need to have this logic present
|
// can be polled for resource usage, even when stopped, we need to have this logic present
|
||||||
// in order to cancel the context and therefore stop the routine that is spawned.
|
// in order to cancel the context and therefore stop the routine that is spawned.
|
||||||
ok, err := e.client.ContainerWait(ctx, e.Id, container.WaitConditionNotRunning)
|
//
|
||||||
select {
|
// For now, DO NOT use client#ContainerWait from the Docker package. There is a nasty
|
||||||
case <-ctx.Done():
|
// bug causing containers to hang on deletion and cause servers to lock up on the system.
|
||||||
// Do nothing, the context was canceled by a different process, there is no error
|
//
|
||||||
// to report at this point.
|
// This weird code isn't intuitive, but it keeps the function from ending until the container
|
||||||
e.log().Debug("terminating ContainerWait blocking process, context canceled")
|
// is stopped and therefore the stream reader ends up closed.
|
||||||
return
|
// @see https://github.com/moby/moby/issues/41827
|
||||||
case _ = <-err:
|
c := new(noopWriter)
|
||||||
// An error occurred with the ContainerWait call, report it here and then hope
|
if _, err := io.Copy(c, e.stream.Reader); err != nil {
|
||||||
// for the fucking best I guess?
|
e.log().WithField("error", err).Error("could not copy from environment stream to noop writer")
|
||||||
e.log().WithField("error", err).Error("error while blocking using ContainerWait")
|
|
||||||
return
|
|
||||||
case <-ok:
|
|
||||||
// Do nothing, everything is running as expected. This will allow us to keep
|
|
||||||
// blocking the termination of this function until the container stops at which
|
|
||||||
// point all of our deferred functions can run.
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -272,6 +278,8 @@ func (e *Environment) Destroy() error {
|
|||||||
Force: true,
|
Force: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
e.SetState(environment.ProcessOfflineState)
|
||||||
|
|
||||||
// Don't trigger a destroy failure if we try to delete a container that does not
|
// Don't trigger a destroy failure if we try to delete a container that does not
|
||||||
// exist on the system. We're just a step ahead of ourselves in that case.
|
// exist on the system. We're just a step ahead of ourselves in that case.
|
||||||
//
|
//
|
||||||
@@ -280,8 +288,6 @@ func (e *Environment) Destroy() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
e.SetState(environment.ProcessOfflineState)
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,19 +313,39 @@ func (e *Environment) followOutput() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go func(reader io.ReadCloser) {
|
|
||||||
defer reader.Close()
|
go e.scanOutput(reader)
|
||||||
evts := e.Events()
|
|
||||||
err := system.ScanReader(reader, func(line string) {
|
|
||||||
evts.Publish(environment.ConsoleOutputEvent, line)
|
|
||||||
})
|
|
||||||
if err != nil && err != io.EOF {
|
|
||||||
log.WithField("error", err).WithField("container_id", e.Id).Warn("error processing scanner line in console output")
|
|
||||||
}
|
|
||||||
}(reader)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Environment) scanOutput(reader io.ReadCloser) {
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
|
events := e.Events()
|
||||||
|
|
||||||
|
err := system.ScanReader(reader, func(line string) {
|
||||||
|
events.Publish(environment.ConsoleOutputEvent, line)
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
log.WithField("error", err).WithField("container_id", e.Id).Warn("error processing scanner line in console output")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return here if the server is offline or currently stopping.
|
||||||
|
if e.State() == environment.ProcessStoppingState || e.State() == environment.ProcessOfflineState {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the current reader before starting a new one, the defer will still run
|
||||||
|
// but it will do nothing if we already closed the stream.
|
||||||
|
_ = reader.Close()
|
||||||
|
|
||||||
|
// Start following the output of the server again.
|
||||||
|
go e.followOutput()
|
||||||
|
}
|
||||||
|
|
||||||
// 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
|
||||||
// but the image already exists locally, we will report that error to the logger but continue
|
// but the image already exists locally, we will report that error to the logger but continue
|
||||||
// with the process.
|
// with the process.
|
||||||
@@ -403,9 +429,11 @@ func (e *Environment) ensureImageExists(image string) error {
|
|||||||
// I'm not sure what the best approach here is, but this will block execution until the image
|
// I'm not sure what the best approach here is, but this will block execution until the image
|
||||||
// is done being pulled, which is what we need.
|
// is done being pulled, which is what we need.
|
||||||
scanner := bufio.NewScanner(out)
|
scanner := bufio.NewScanner(out)
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
s := imagePullStatus{}
|
s := imagePullStatus{}
|
||||||
fmt.Println(scanner.Text())
|
fmt.Println(scanner.Text())
|
||||||
|
|
||||||
if err := json.Unmarshal(scanner.Bytes(), &s); err == nil {
|
if err := json.Unmarshal(scanner.Bytes(), &s); err == nil {
|
||||||
e.Events().Publish(environment.DockerImagePullStatus, s.Status+" "+s.Progress)
|
e.Events().Publish(environment.DockerImagePullStatus, s.Status+" "+s.Progress)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,8 +82,9 @@ func (e *Environment) Type() string {
|
|||||||
// Set if this process is currently attached to the process.
|
// Set if this process is currently attached to the process.
|
||||||
func (e *Environment) SetStream(s *types.HijackedResponse) {
|
func (e *Environment) SetStream(s *types.HijackedResponse) {
|
||||||
e.mu.Lock()
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
|
||||||
e.stream = s
|
e.stream = s
|
||||||
e.mu.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine if the this process is currently attached to the container.
|
// Determine if the this process is currently attached to the container.
|
||||||
@@ -98,6 +99,7 @@ func (e *Environment) Events() *events.EventBus {
|
|||||||
e.eventMu.Do(func() {
|
e.eventMu.Do(func() {
|
||||||
e.emitter = events.New()
|
e.emitter = events.New()
|
||||||
})
|
})
|
||||||
|
|
||||||
return e.emitter
|
return e.emitter
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,12 +176,14 @@ func (e *Environment) Config() *environment.Configuration {
|
|||||||
// Sets the stop configuration for the environment.
|
// Sets the stop configuration for the environment.
|
||||||
func (e *Environment) SetStopConfiguration(c api.ProcessStopConfiguration) {
|
func (e *Environment) SetStopConfiguration(c api.ProcessStopConfiguration) {
|
||||||
e.mu.Lock()
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
|
||||||
e.meta.Stop = c
|
e.meta.Stop = c
|
||||||
e.mu.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Environment) SetImage(i string) {
|
func (e *Environment) SetImage(i string) {
|
||||||
e.mu.Lock()
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
|
||||||
e.meta.Image = i
|
e.meta.Image = i
|
||||||
e.mu.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,9 @@ import (
|
|||||||
//
|
//
|
||||||
// This process will also confirm that the server environment exists and is in a bootable
|
// This process will also confirm that the server environment exists and is in a bootable
|
||||||
// state. This ensures that unexpected container deletion while Wings is running does
|
// state. This ensures that unexpected container deletion while Wings is running does
|
||||||
// not result in the server becoming unbootable.
|
// not result in the server becoming un-bootable.
|
||||||
func (e *Environment) OnBeforeStart() error {
|
func (e *Environment) OnBeforeStart() error {
|
||||||
// Always destroy and re-create the server container to ensure that synced data from
|
// Always destroy and re-create the server container to ensure that synced data from the Panel is used.
|
||||||
// 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.WithMessage(err, "failed to remove server docker container during pre-boot")
|
return errors.WithMessage(err, "failed to remove server docker container during pre-boot")
|
||||||
@@ -49,6 +48,7 @@ func (e *Environment) OnBeforeStart() error {
|
|||||||
// call to OnBeforeStart().
|
// call to OnBeforeStart().
|
||||||
func (e *Environment) Start() error {
|
func (e *Environment) Start() error {
|
||||||
sawError := false
|
sawError := false
|
||||||
|
|
||||||
// If sawError is set to true there was an error somewhere in the pipeline that
|
// If sawError is set to true there was an error somewhere in the pipeline that
|
||||||
// got passed up, but we also want to ensure we set the server to be offline at
|
// got passed up, but we also want to ensure we set the server to be offline at
|
||||||
// that point.
|
// that point.
|
||||||
@@ -235,7 +235,7 @@ func (e *Environment) Terminate(signal os.Signal) error {
|
|||||||
|
|
||||||
sig := strings.TrimSuffix(strings.TrimPrefix(signal.String(), "signal "), "ed")
|
sig := strings.TrimSuffix(strings.TrimPrefix(signal.String(), "signal "), "ed")
|
||||||
|
|
||||||
if err := e.client.ContainerKill(context.Background(), e.Id, sig); err != nil {
|
if err := e.client.ContainerKill(context.Background(), e.Id, sig); err != nil && !client.IsErrNotFound(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ var ErrNotAttached = errors.New("not attached to instance")
|
|||||||
|
|
||||||
func (e *Environment) setStream(s *types.HijackedResponse) {
|
func (e *Environment) setStream(s *types.HijackedResponse) {
|
||||||
e.mu.Lock()
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
|
||||||
e.stream = s
|
e.stream = s
|
||||||
e.mu.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends the specified command to the stdin of the running container instance. There is no
|
// Sends the specified command to the stdin of the running container instance. There is no
|
||||||
@@ -71,7 +72,7 @@ func (e *Environment) Readlog(lines int) ([]string, error) {
|
|||||||
// Docker stores the logs for server output in a JSON format. This function will iterate over the JSON
|
// Docker stores the logs for server output in a JSON format. This function will iterate over the JSON
|
||||||
// that was read from the log file and parse it into a more human readable format.
|
// that was read from the log file and parse it into a more human readable format.
|
||||||
func (e *Environment) parseLogToStrings(b []byte) ([]string, error) {
|
func (e *Environment) parseLogToStrings(b []byte) ([]string, error) {
|
||||||
var hasError = false
|
hasError := false
|
||||||
var out []string
|
var out []string
|
||||||
|
|
||||||
scanner := bufio.NewScanner(bytes.NewReader(b))
|
scanner := bufio.NewScanner(bytes.NewReader(b))
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package environment
|
package environment
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pterodactyl/wings/events"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/pterodactyl/wings/events"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ package environment
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/apex/log"
|
|
||||||
"math"
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/apex/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Mount struct {
|
type Mount struct {
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ package events
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/gammazero/workerpool"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/gammazero/workerpool"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Event struct {
|
type Event struct {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package events
|
package events
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gammazero/workerpool"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/gammazero/workerpool"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CallbackPool struct {
|
type CallbackPool struct {
|
||||||
|
|||||||
1
go.mod
1
go.mod
@@ -63,6 +63,7 @@ require (
|
|||||||
github.com/sabhiram/go-gitignore v0.0.0-20201211210132-54b8a0bf510f
|
github.com/sabhiram/go-gitignore v0.0.0-20201211210132-54b8a0bf510f
|
||||||
github.com/sirupsen/logrus v1.7.0 // indirect
|
github.com/sirupsen/logrus v1.7.0 // indirect
|
||||||
github.com/spf13/cobra v1.1.1
|
github.com/spf13/cobra v1.1.1
|
||||||
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/ugorji/go v1.2.2 // indirect
|
github.com/ugorji/go v1.2.2 // indirect
|
||||||
github.com/ulikunitz/xz v0.5.9 // indirect
|
github.com/ulikunitz/xz v0.5.9 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package installer
|
package installer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"emperror.dev/errors"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/asaskevich/govalidator"
|
"github.com/asaskevich/govalidator"
|
||||||
"github.com/buger/jsonparser"
|
"github.com/buger/jsonparser"
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
|
|||||||
@@ -2,16 +2,17 @@ package parser
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"emperror.dev/errors"
|
|
||||||
"github.com/Jeffail/gabs/v2"
|
|
||||||
"github.com/apex/log"
|
|
||||||
"github.com/buger/jsonparser"
|
|
||||||
"github.com/iancoleman/strcase"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
|
"github.com/Jeffail/gabs/v2"
|
||||||
|
"github.com/apex/log"
|
||||||
|
"github.com/buger/jsonparser"
|
||||||
|
"github.com/iancoleman/strcase"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Regex to match anything that has a value matching the format of {{ config.$1 }} which
|
// Regex to match anything that has a value matching the format of {{ config.$1 }} which
|
||||||
|
|||||||
@@ -2,8 +2,14 @@ package parser
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"emperror.dev/errors"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/beevik/etree"
|
"github.com/beevik/etree"
|
||||||
"github.com/buger/jsonparser"
|
"github.com/buger/jsonparser"
|
||||||
@@ -12,11 +18,6 @@ import (
|
|||||||
"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"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// The file parsing options that are available for a server configuration file.
|
// The file parsing options that are available for a server configuration file.
|
||||||
|
|||||||
@@ -18,7 +18,22 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var client = &http.Client{Timeout: time.Hour * 12}
|
var client = &http.Client{
|
||||||
|
Timeout: time.Hour * 12,
|
||||||
|
// Disallow any redirect on a HTTP call. This is a security requirement: do not modify
|
||||||
|
// this logic without first ensuring that the new target location IS NOT within the current
|
||||||
|
// instance's local network.
|
||||||
|
//
|
||||||
|
// This specific error response just causes the client to not follow the redirect and
|
||||||
|
// returns the actual redirect response to the caller. Not perfect, but simple and most
|
||||||
|
// people won't be using URLs that redirect anyways hopefully?
|
||||||
|
//
|
||||||
|
// We'll re-evaluate this down the road if needed.
|
||||||
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||||
|
return http.ErrUseLastResponse
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
var instance = &Downloader{
|
var instance = &Downloader{
|
||||||
// Tracks all of the active downloads.
|
// Tracks all of the active downloads.
|
||||||
downloadCache: make(map[string]*Download),
|
downloadCache: make(map[string]*Download),
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"emperror.dev/errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
"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/pterodactyl/wings/server"
|
"github.com/pterodactyl/wings/server"
|
||||||
"github.com/pterodactyl/wings/server/filesystem"
|
"github.com/pterodactyl/wings/server/filesystem"
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type RequestError struct {
|
type RequestError struct {
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"emperror.dev/errors"
|
"emperror.dev/errors"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/server"
|
"github.com/pterodactyl/wings/server"
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Middleware struct{}
|
type Middleware struct{}
|
||||||
@@ -119,6 +120,21 @@ func (m *Middleware) ServerExists() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks if remote file downloading is enabled on this instance before allowing access
|
||||||
|
// to the given endpoint.
|
||||||
|
func (m *Middleware) CheckRemoteDownloadEnabled() gin.HandlerFunc {
|
||||||
|
disabled := config.Get().Api.DisableRemoteDownload
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
if disabled {
|
||||||
|
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": "This functionality is not currently enabled on this instance.",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the server instance from the gin context. If there is no server set in the
|
// Returns the server instance from the gin context. If there is no server set in the
|
||||||
// context (e.g. calling from a controller not protected by ServerExists) this function
|
// context (e.g. calling from a controller not protected by ServerExists) this function
|
||||||
// will panic.
|
// will panic.
|
||||||
|
|||||||
@@ -88,9 +88,9 @@ func Configure() *gin.Engine {
|
|||||||
files.POST("/decompress", postServerDecompressFiles)
|
files.POST("/decompress", postServerDecompressFiles)
|
||||||
files.POST("/chmod", postServerChmodFile)
|
files.POST("/chmod", postServerChmodFile)
|
||||||
|
|
||||||
files.GET("/pull", getServerPullingFiles)
|
files.GET("/pull", m.CheckRemoteDownloadEnabled(), getServerPullingFiles)
|
||||||
files.POST("/pull", postServerPullRemoteFile)
|
files.POST("/pull", m.CheckRemoteDownloadEnabled(), postServerPullRemoteFile)
|
||||||
files.DELETE("/pull/:download", deleteServerPullRemoteFile)
|
files.DELETE("/pull/:download", m.CheckRemoteDownloadEnabled(), deleteServerPullRemoteFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
backup := server.Group("/backup")
|
backup := server.Group("/backup")
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ package router
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/pterodactyl/wings/router/tokens"
|
|
||||||
"github.com/pterodactyl/wings/server/backup"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/pterodactyl/wings/router/tokens"
|
||||||
|
"github.com/pterodactyl/wings/server/backup"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handle a download request for a server backup.
|
// Handle a download request for a server backup.
|
||||||
|
|||||||
@@ -3,15 +3,16 @@ package router
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"emperror.dev/errors"
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/pterodactyl/wings/router/downloader"
|
"github.com/pterodactyl/wings/router/downloader"
|
||||||
"github.com/pterodactyl/wings/router/tokens"
|
"github.com/pterodactyl/wings/router/tokens"
|
||||||
"github.com/pterodactyl/wings/server"
|
"github.com/pterodactyl/wings/server"
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type serverProcData struct {
|
type serverProcData struct {
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"emperror.dev/errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/pterodactyl/wings/server"
|
"github.com/pterodactyl/wings/server"
|
||||||
"github.com/pterodactyl/wings/server/backup"
|
"github.com/pterodactyl/wings/server/backup"
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Backs up a server.
|
// Backs up a server.
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ package router
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
ws "github.com/gorilla/websocket"
|
ws "github.com/gorilla/websocket"
|
||||||
"github.com/pterodactyl/wings/router/websocket"
|
"github.com/pterodactyl/wings/router/websocket"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Upgrades a connection to a websocket and passes events along between.
|
// Upgrades a connection to a websocket and passes events along between.
|
||||||
|
|||||||
@@ -2,14 +2,15 @@ package router
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/installer"
|
"github.com/pterodactyl/wings/installer"
|
||||||
"github.com/pterodactyl/wings/server"
|
"github.com/pterodactyl/wings/server"
|
||||||
"github.com/pterodactyl/wings/system"
|
"github.com/pterodactyl/wings/system"
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Returns information about the system that wings is running on.
|
// Returns information about the system that wings is running on.
|
||||||
|
|||||||
@@ -3,10 +3,19 @@ package router
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"emperror.dev/errors"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
"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"
|
||||||
@@ -19,14 +28,6 @@ import (
|
|||||||
"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/system"
|
"github.com/pterodactyl/wings/system"
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Number of ticks in the progress bar
|
// Number of ticks in the progress bar
|
||||||
|
|||||||
@@ -2,15 +2,16 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"emperror.dev/errors"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"github.com/mholt/archiver/v3"
|
|
||||||
"github.com/pterodactyl/wings/config"
|
|
||||||
"github.com/pterodactyl/wings/server/filesystem"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
|
"github.com/mholt/archiver/v3"
|
||||||
|
"github.com/pterodactyl/wings/config"
|
||||||
|
"github.com/pterodactyl/wings/server/filesystem"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Archiver represents a Server Archiver.
|
// Archiver represents a Server Archiver.
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
|
||||||
"emperror.dev/errors"
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"github.com/pterodactyl/wings/server/backup"
|
"github.com/pterodactyl/wings/server/backup"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Notifies the panel of a backup's state and returns an error if one is encountered
|
// Notifies the panel of a backup's state and returns an error if one is encountered
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gammazero/workerpool"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/gammazero/workerpool"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parent function that will update all of the defined configuration files for a server
|
// Parent function that will update all of the defined configuration files for a server
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pterodactyl/wings/environment"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/pterodactyl/wings/environment"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Configuration struct {
|
type Configuration struct {
|
||||||
|
|||||||
@@ -2,14 +2,15 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"emperror.dev/errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/colorstring"
|
|
||||||
"github.com/pterodactyl/wings/config"
|
|
||||||
"github.com/pterodactyl/wings/system"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
|
"github.com/mitchellh/colorstring"
|
||||||
|
"github.com/pterodactyl/wings/config"
|
||||||
|
"github.com/pterodactyl/wings/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrTooMuchConsoleData = errors.New("console is outputting too much data")
|
var ErrTooMuchConsoleData = errors.New("console is outputting too much data")
|
||||||
@@ -114,7 +115,7 @@ func (ct *ConsoleThrottler) Increment(onTrigger func()) error {
|
|||||||
func (s *Server) Throttler() *ConsoleThrottler {
|
func (s *Server) Throttler() *ConsoleThrottler {
|
||||||
s.throttleOnce.Do(func() {
|
s.throttleOnce.Do(func() {
|
||||||
s.throttler = &ConsoleThrottler{
|
s.throttler = &ConsoleThrottler{
|
||||||
isThrottled: system.NewAtomicBool(false),
|
isThrottled: system.NewAtomicBool(false),
|
||||||
ConsoleThrottles: config.Get().Throttles,
|
ConsoleThrottles: config.Get().Throttles,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pterodactyl/wings/config"
|
|
||||||
"github.com/pterodactyl/wings/environment"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/pterodactyl/wings/config"
|
||||||
|
"github.com/pterodactyl/wings/environment"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CrashHandler struct {
|
type CrashHandler struct {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pterodactyl/wings/server/filesystem"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/pterodactyl/wings/server/filesystem"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) Filesystem() *filesystem.Filesystem {
|
func (s *Server) Filesystem() *filesystem.Filesystem {
|
||||||
|
|||||||
@@ -4,6 +4,13 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"html/template"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"emperror.dev/errors"
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
@@ -14,12 +21,6 @@ import (
|
|||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
"github.com/pterodactyl/wings/system"
|
"github.com/pterodactyl/wings/system"
|
||||||
"html/template"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Executes the installation stack for a server process. Bubbles any errors up to the calling
|
// Executes the installation stack for a server process. Bubbles any errors up to the calling
|
||||||
|
|||||||
@@ -2,14 +2,15 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"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"
|
||||||
"github.com/pterodactyl/wings/events"
|
"github.com/pterodactyl/wings/events"
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var dockerEvents = []string{
|
var dockerEvents = []string{
|
||||||
@@ -64,9 +65,11 @@ func (s *Server) StartEventListeners() {
|
|||||||
// to terminate again.
|
// to terminate again.
|
||||||
if s.Environment.State() != environment.ProcessStoppingState {
|
if s.Environment.State() != environment.ProcessStoppingState {
|
||||||
s.Environment.SetState(environment.ProcessStoppingState)
|
s.Environment.SetState(environment.ProcessStoppingState)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
s.Log().Warn("stopping server instance, violating throttle limits")
|
s.Log().Warn("stopping server instance, violating throttle limits")
|
||||||
s.PublishConsoleOutputFromDaemon("Your server is being stopped for outputting too much data in a short period of time.")
|
s.PublishConsoleOutputFromDaemon("Your server is being stopped for outputting too much data in a short period of time.")
|
||||||
|
|
||||||
// Completely skip over server power actions and terminate the running instance. This gives the
|
// Completely skip over server power actions and terminate the running instance. This gives the
|
||||||
// server 15 seconds to finish stopping gracefully before it is forcefully terminated.
|
// server 15 seconds to finish stopping gracefully before it is forcefully terminated.
|
||||||
if err := s.Environment.WaitForStop(config.Get().Throttles.StopGracePeriod, true); err != nil {
|
if err := s.Environment.WaitForStop(config.Get().Throttles.StopGracePeriod, true); err != nil {
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"emperror.dev/errors"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/gammazero/workerpool"
|
"github.com/gammazero/workerpool"
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
@@ -11,10 +16,6 @@ import (
|
|||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
"github.com/pterodactyl/wings/environment/docker"
|
"github.com/pterodactyl/wings/environment/docker"
|
||||||
"github.com/pterodactyl/wings/server/filesystem"
|
"github.com/pterodactyl/wings/server/filesystem"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var servers = NewCollection(nil)
|
var servers = NewCollection(nil)
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// To avoid confusion when working with mounts, assume that a server.Mount has not been properly
|
// To avoid confusion when working with mounts, assume that a server.Mount has not been properly
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
"emperror.dev/errors"
|
"emperror.dev/errors"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
"golang.org/x/sync/semaphore"
|
"golang.org/x/sync/semaphore"
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type PowerAction string
|
type PowerAction string
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pterodactyl/wings/environment"
|
|
||||||
"github.com/pterodactyl/wings/system"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/pterodactyl/wings/environment"
|
||||||
|
"github.com/pterodactyl/wings/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Defines the current resource usage for a given server instance. If a server is offline you
|
// Defines the current resource usage for a given server instance. If a server is offline you
|
||||||
|
|||||||
@@ -2,8 +2,11 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"emperror.dev/errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/creasty/defaults"
|
"github.com/creasty/defaults"
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
@@ -14,8 +17,6 @@ import (
|
|||||||
"github.com/pterodactyl/wings/server/filesystem"
|
"github.com/pterodactyl/wings/server/filesystem"
|
||||||
"github.com/pterodactyl/wings/system"
|
"github.com/pterodactyl/wings/system"
|
||||||
"golang.org/x/sync/semaphore"
|
"golang.org/x/sync/semaphore"
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// High level definition for a server instance being controlled by Wings.
|
// High level definition for a server instance being controlled by Wings.
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/pterodactyl/wings/config"
|
|
||||||
"github.com/pterodactyl/wings/environment"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/pterodactyl/wings/config"
|
||||||
|
"github.com/pterodactyl/wings/environment"
|
||||||
)
|
)
|
||||||
|
|
||||||
var stateMutex sync.Mutex
|
var stateMutex sync.Mutex
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"emperror.dev/errors"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
"github.com/buger/jsonparser"
|
"github.com/buger/jsonparser"
|
||||||
"github.com/imdario/mergo"
|
"github.com/imdario/mergo"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/google/uuid"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WebsocketBag struct {
|
type WebsocketBag struct {
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
package sftp
|
package sftp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/apex/log"
|
|
||||||
"github.com/patrickmn/go-cache"
|
|
||||||
"github.com/pkg/sftp"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/apex/log"
|
||||||
|
"github.com/patrickmn/go-cache"
|
||||||
|
"github.com/pkg/sftp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FileSystem struct {
|
type FileSystem struct {
|
||||||
|
|||||||
@@ -6,11 +6,6 @@ import (
|
|||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/apex/log"
|
|
||||||
"github.com/patrickmn/go-cache"
|
|
||||||
"github.com/pkg/sftp"
|
|
||||||
"github.com/pterodactyl/wings/api"
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
@@ -18,6 +13,12 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/apex/log"
|
||||||
|
"github.com/patrickmn/go-cache"
|
||||||
|
"github.com/pkg/sftp"
|
||||||
|
"github.com/pterodactyl/wings/api"
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Settings struct {
|
type Settings struct {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package system
|
package system
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/docker/docker/pkg/parsers/kernel"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/docker/docker/pkg/parsers/kernel"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Information struct {
|
type Information struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user