From 9e30d638180a017fc2640fb2c467d7bc12d4cef9 Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Fri, 10 Apr 2020 12:00:04 -0600 Subject: [PATCH 1/9] Add debug logs when a non-500 error occurs, force sync the configuration during installation of a new server --- config/config.go | 2 +- installer/installer.go | 2 +- router/error.go | 7 +++++++ server/server.go | 8 ++++---- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/config/config.go b/config/config.go index 0326f8e..508261c 100644 --- a/config/config.go +++ b/config/config.go @@ -82,7 +82,7 @@ type SystemConfiguration struct { Gid int } - // Determines wether or not server data should be synced when the Daemon is started. + // Determines whether or not server data should be synced when the Daemon is started. // If set to false, data will only be synced when a server process is started, or // detected as started when booting. SyncServersOnBoot bool `default:"true" yaml:"sync_servers_on_boot"` diff --git a/installer/installer.go b/installer/installer.go index 4ee7f32..d450baf 100644 --- a/installer/installer.go +++ b/installer/installer.go @@ -84,7 +84,7 @@ func New(data []byte) (*Installer, error) { // Create a new server instance using the configuration we wrote to the disk // so that everything gets instantiated correctly on the struct. - s2, err := server.FromConfiguration(b, &config.Get().System) + s2, err := server.FromConfiguration(b, &config.Get().System, true) return &Installer{ server: s2, diff --git a/router/error.go b/router/error.go index ed84fe5..aa985d2 100644 --- a/router/error.go +++ b/router/error.go @@ -5,6 +5,7 @@ import ( "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/pkg/errors" + "github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/server" "go.uber.org/zap" "net/http" @@ -68,6 +69,12 @@ func (e *RequestError) AbortWithStatus(status int, c *gin.Context) { } c.Error(errors.WithStack(e)) + } else if config.Get().Debug { + if e.server != nil { + zap.S().Debugw("encountered error while handling HTTP request", zap.String("server", e.server.Uuid), zap.String("error_id", e.Uuid), zap.Error(e.Err)) + } else { + zap.S().Debugw("encountered error while handling HTTP request", zap.String("error_id", e.Uuid), zap.Error(e.Err)) + } } msg := "An unexpected error was encountered while processing this request." diff --git a/server/server.go b/server/server.go index 05eb264..b095b84 100644 --- a/server/server.go +++ b/server/server.go @@ -179,7 +179,7 @@ func LoadDirectory(dir string, cfg *config.SystemConfiguration) error { return } - s, err := FromConfiguration(b, cfg) + s, err := FromConfiguration(b, cfg, false) if err != nil { if IsServerDoesNotExistError(err) { zap.S().Infow("server does not exist on remote system", zap.String("server", file.Name())) @@ -209,7 +209,7 @@ func (s *Server) Init() { // Initializes a server using a data byte array. This will be marshaled into the // given struct using a YAML marshaler. This will also configure the given environment // for a server. -func FromConfiguration(data []byte, cfg *config.SystemConfiguration) (*Server, error) { +func FromConfiguration(data []byte, cfg *config.SystemConfiguration, forceSync bool) (*Server, error) { s := new(Server) if err := defaults.Set(s); err != nil { @@ -244,7 +244,7 @@ func FromConfiguration(data []byte, cfg *config.SystemConfiguration) (*Server, e // This is also done when the server is booted, however we need to account for instances // where the server is already running and the Daemon reboots. In those cases this will // allow us to you know, stop servers. - if cfg.SyncServersOnBoot { + if forceSync || cfg.SyncServersOnBoot { if err := s.Sync(); err != nil { return nil, err } @@ -414,4 +414,4 @@ func (s *Server) HandlePowerAction(action PowerAction) error { default: return errors.New("an invalid power action was provided") } -} \ No newline at end of file +} From 2278347b4c43158e15aaad918b701bfd25eee488 Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Fri, 10 Apr 2020 12:11:37 -0600 Subject: [PATCH 2/9] Fix typo --- cmd/root.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 7a92700..b859b45 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -23,7 +23,7 @@ var debug = false var root = &cobra.Command{ Use: "wings", - Short: "The wings of the pterodactly game management panel", + Short: "The wings of the pterodactyl game management panel", Long: ``, Run: rootCmdRun, } @@ -71,7 +71,7 @@ func rootCmdRun(cmd *cobra.Command, args []string) { zap.S().Infow("configured system user", zap.String("username", su.Username), zap.String("uid", su.Uid), zap.String("gid", su.Gid)) } - zap.S().Infow("beginnning file permission setting on server data directories") + zap.S().Infow("beginning file permission setting on server data directories") if err := c.EnsureFilePermissions(); err != nil { zap.S().Errorw("failed to properly chown data directories", zap.Error(err)) } else { From e719c67e0b82ece53e81894a86d96143c7966fa3 Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Fri, 10 Apr 2020 12:15:46 -0600 Subject: [PATCH 3/9] Removes SyncServersOnBoot configuration option and requires that servers are synced when the daemon boots --- config/config.go | 5 ----- installer/installer.go | 2 +- server/server.go | 14 +++++--------- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/config/config.go b/config/config.go index 508261c..3b5f47c 100644 --- a/config/config.go +++ b/config/config.go @@ -82,11 +82,6 @@ type SystemConfiguration struct { Gid int } - // Determines whether or not server data should be synced when the Daemon is started. - // If set to false, data will only be synced when a server process is started, or - // detected as started when booting. - SyncServersOnBoot bool `default:"true" yaml:"sync_servers_on_boot"` - // The path to the system's timezone file that will be mounted into running Docker containers. TimezonePath string `yaml:"timezone_path"` diff --git a/installer/installer.go b/installer/installer.go index d450baf..4ee7f32 100644 --- a/installer/installer.go +++ b/installer/installer.go @@ -84,7 +84,7 @@ func New(data []byte) (*Installer, error) { // Create a new server instance using the configuration we wrote to the disk // so that everything gets instantiated correctly on the struct. - s2, err := server.FromConfiguration(b, &config.Get().System, true) + s2, err := server.FromConfiguration(b, &config.Get().System) return &Installer{ server: s2, diff --git a/server/server.go b/server/server.go index b095b84..9b66559 100644 --- a/server/server.go +++ b/server/server.go @@ -179,7 +179,7 @@ func LoadDirectory(dir string, cfg *config.SystemConfiguration) error { return } - s, err := FromConfiguration(b, cfg, false) + s, err := FromConfiguration(b, cfg) if err != nil { if IsServerDoesNotExistError(err) { zap.S().Infow("server does not exist on remote system", zap.String("server", file.Name())) @@ -209,7 +209,7 @@ func (s *Server) Init() { // Initializes a server using a data byte array. This will be marshaled into the // given struct using a YAML marshaler. This will also configure the given environment // for a server. -func FromConfiguration(data []byte, cfg *config.SystemConfiguration, forceSync bool) (*Server, error) { +func FromConfiguration(data []byte, cfg *config.SystemConfiguration) (*Server, error) { s := new(Server) if err := defaults.Set(s); err != nil { @@ -241,13 +241,9 @@ func FromConfiguration(data []byte, cfg *config.SystemConfiguration, forceSync b } s.Resources = ResourceUsage{} - // This is also done when the server is booted, however we need to account for instances - // where the server is already running and the Daemon reboots. In those cases this will - // allow us to you know, stop servers. - if forceSync || cfg.SyncServersOnBoot { - if err := s.Sync(); err != nil { - return nil, err - } + // Forces the configuration to be synced with the panel. + if err := s.Sync(); err != nil { + return nil, err } return s, nil From 28c8f3f40092134cd2a3f667c04ec2c795b68d1d Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Fri, 10 Apr 2020 15:39:07 -0600 Subject: [PATCH 4/9] Add the ability to fetch all servers, fix cpu usage leak again.. --- api/api.go | 2 +- api/server_endpoints.go | 24 +++++++++++++ cmd/root.go | 3 ++ data/servers/.gitkeep | 0 go.mod | 12 ++----- go.sum | 63 +++++++++-------------------------- installer/installer.go | 2 +- router/router_server_ws.go | 2 +- router/websocket/listeners.go | 7 +--- router/websocket/websocket.go | 7 ++++ server/server.go | 41 +++++++++++++++++------ 11 files changed, 87 insertions(+), 76 deletions(-) delete mode 100644 data/servers/.gitkeep diff --git a/api/api.go b/api/api.go index fefedda..161a7d2 100644 --- a/api/api.go +++ b/api/api.go @@ -13,7 +13,7 @@ import ( "time" ) -// Initalizes the requester instance. +// Initializes the requester instance. func NewRequester() *PanelRequest { return &PanelRequest{ Response: nil, diff --git a/api/server_endpoints.go b/api/server_endpoints.go index f7f2d16..828f12f 100644 --- a/api/server_endpoints.go +++ b/api/server_endpoints.go @@ -49,6 +49,30 @@ type InstallationScript struct { Script string `json:"script"` } +// GetAllServerConfigurations fetches configurations for all servers assigned to this node. +func (r *PanelRequest) GetAllServerConfigurations() (map[string]*ServerConfigurationResponse, *RequestError, error) { + resp, err := r.Get("/servers") + if err != nil { + return nil, nil, errors.WithStack(err) + } + defer resp.Body.Close() + + r.Response = resp + + if r.HasError() { + return nil, r.Error(), nil + } + + res := map[string]*ServerConfigurationResponse{} + b, _ := r.ReadBody() + + if err := json.Unmarshal(b, &res); err != nil { + return nil, nil, errors.WithStack(err) + } + + return res, nil, nil +} + // Fetches the server configuration and returns the struct for it. func (r *PanelRequest) GetServerConfiguration(uuid string) (*ServerConfigurationResponse, *RequestError, error) { resp, err := r.Get(fmt.Sprintf("/servers/%s", uuid)) diff --git a/cmd/root.go b/cmd/root.go index b859b45..6ce53c7 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -7,6 +7,7 @@ import ( "os" "github.com/pkg/errors" + "github.com/pkg/profile" "github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/router" @@ -36,6 +37,8 @@ func init() { } func rootCmdRun(cmd *cobra.Command, args []string) { + defer profile.Start().Stop() + c, err := config.ReadConfiguration(configPath) if err != nil { panic(err) diff --git a/data/servers/.gitkeep b/data/servers/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/go.mod b/go.mod index 38097cf..a717a0a 100644 --- a/go.mod +++ b/go.mod @@ -29,33 +29,29 @@ require ( github.com/gbrlsnchs/jwt/v3 v3.0.0-rc.0 github.com/ghodss/yaml v1.0.0 github.com/gin-gonic/gin v1.6.2 - github.com/gogo/protobuf v1.2.1 // indirect github.com/golang/protobuf v1.3.5 // indirect - github.com/google/gofuzz v1.1.0 // indirect github.com/google/uuid v1.1.1 github.com/gorilla/websocket v1.4.0 github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 github.com/imdario/mergo v0.3.8 - github.com/julienschmidt/httprouter v1.2.0 github.com/magiconair/properties v1.8.1 github.com/mattn/go-shellwords v1.0.10 // indirect github.com/mholt/archiver/v3 v3.3.0 github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect - github.com/onsi/ginkgo v1.8.0 // indirect - github.com/onsi/gomega v1.5.0 // indirect + github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/opencontainers/go-digest v1.0.0-rc1 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.8.1 + github.com/pkg/profile v1.4.0 github.com/pkg/sftp v1.10.1 // indirect github.com/pterodactyl/sftp-server v1.1.1 github.com/remeh/sizedwaitgroup v0.0.0-20180822144253-5e7302b12cce github.com/smartystreets/goconvey v1.6.4 // indirect github.com/spf13/cobra v0.0.7 - github.com/stretchr/objx v0.2.0 // indirect github.com/stretchr/testify v1.5.1 // indirect go.uber.org/atomic v1.5.1 // indirect go.uber.org/multierr v1.4.0 // indirect @@ -63,13 +59,9 @@ require ( golang.org/x/crypto v0.0.0-20200403201458-baeed622b8d8 // indirect golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f // indirect golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect - golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a // indirect golang.org/x/sys v0.0.0-20200331124033-c3d80250170d // indirect - golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b // indirect - gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect - gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect gopkg.in/ini.v1 v1.51.0 gopkg.in/yaml.v2 v2.2.8 gotest.tools v2.2.0+incompatible // indirect diff --git a/go.sum b/go.sum index 8929c51..3aa5e0e 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,4 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/AlecAivazis/survey v1.8.8 h1:Y4yypp763E8cbqb5RBqZhGgkCFLRFnbRBHrxnpMMsgQ= github.com/AlecAivazis/survey/v2 v2.0.7 h1:+f825XHLse/hWd2tE/V5df04WFGimk34Eyg/z35w/rc= github.com/AlecAivazis/survey/v2 v2.0.7/go.mod h1:mlizQTaPjnR4jcpwRSaSlkbsRfYFEyKgLQvYTzxxiHA= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= @@ -10,6 +9,7 @@ github.com/Jeffail/gabs/v2 v2.2.0 h1:7touC+WzbQ7LO5+mwgxT44miyTqAVCOlIWLA6PiIB5w github.com/Jeffail/gabs/v2 v2.2.0/go.mod h1:xCn81vdHKxFUuWWAaD5jCTQDNPBMh5pPs9IJ+NcziBI= github.com/Microsoft/go-winio v0.4.7 h1:vOvDiY/F1avSWlCWiKJjdYKz2jVjTK3pWPHndeG4OAY= github.com/Microsoft/go-winio v0.4.7/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= @@ -28,10 +28,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/buger/jsonparser v0.0.0-20191204142016-1a29609e0929 h1:MW/JDk68Rny52yI0M0N+P8lySNgB+NhpI/uAmhgOhUM= github.com/buger/jsonparser v0.0.0-20191204142016-1a29609e0929/go.mod h1:tgcrVJ81GPSF0mz+0nu1Xaz0fazGPrmmJfJtxjbHhUQ= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 h1:PUD50EuOMkXVcpBIA/R95d56duJR9VxhwncsFbNnxW4= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= @@ -74,6 +70,7 @@ github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwv github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= @@ -104,7 +101,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -118,9 +114,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmg github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 h1:VHgatEHNcBFEB7inlalqfNqw65aNkM1lGX2yt3NmbS8= github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= @@ -128,11 +123,10 @@ github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= @@ -145,6 +139,7 @@ github.com/klauspost/compress v1.9.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/pgzip v1.2.1 h1:oIPZROsWuPHpOdMVWLuJZXwgjhrW8r1yEX8UqMyeNHM= github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -152,25 +147,19 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ= github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw= -github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/magefile/mage v1.9.0 h1:t3AU2wNwehMCW97vuqQLtw6puppWXHO+O2MHo5a50XE= github.com/magefile/mage v1.9.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/manifoldco/promptui v0.7.0 h1:3l11YT8tm9MnwGFQ4kETwkzpAwY2Jt9lCrumCUW4+z4= -github.com/manifoldco/promptui v0.7.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= -github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= @@ -186,18 +175,17 @@ github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nwaples/rardecode v1.0.0 h1:r7vGuS5akxOnR4JQSkko62RJ1ReCMXxQRPtxsiFMBOs= github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= @@ -211,6 +199,8 @@ github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.4.0 h1:uCmaf4vVbWAOZz36k1hrQD7ijGRzLwaME8Am/7a4jZI= +github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE= github.com/pkg/sftp v1.8.3 h1:9jSe2SxTM8/3bXZjtqnkgTBW+lA8db0knZJyns7gpBA= github.com/pkg/sftp v1.8.3/go.mod h1:NxmoDg/QLVWluQDUYG7XBZTLUpKeFa8e3aMf1BfjyHk= github.com/pkg/sftp v1.10.1 h1:VasscCm72135zRysgrJDKsntdmPN+OuU3+nnHYA9wyc= @@ -234,8 +224,6 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.0.5 h1:8c8b5uO0zS4X6RPl/sd1ENwSkIc0/H2PaHxE3udaE8I= -github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= @@ -254,12 +242,12 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/uber-go/zap v1.9.1/go.mod h1:GY+83l3yxBcBw2kmHu/sAWwItnTn+ynxHCRo+WiIQOY= @@ -302,8 +290,6 @@ golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g= -golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200403201458-baeed622b8d8 h1:fpnn/HnJONpIu6hkXi1u/7rR0NzilgWr4T0JmWkEitk= golang.org/x/crypto v0.0.0-20200403201458-baeed622b8d8/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -314,18 +300,15 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -337,20 +320,14 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab h1:FvshnhkKW+LO3HWHodML8kuVX8rnJTxKm9dFPuI68UM= -golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA= @@ -373,8 +350,7 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64 golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191206204035-259af5ff87bd h1:Zc7EU2PqpsNeIfOoVA7hvQX4cS3YDJEs5KlfatT3hLo= -golang.org/x/tools v0.0.0-20191206204035-259af5ff87bd/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b h1:AFZdJUT7jJYXQEC29hYH/WZkoV7+KhwxQGmdZ19yYoY= golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools/gopls v0.1.3/go.mod h1:vrCQzOKxvuiZLjCKSmbbov04oeBQQOb4VQqwYK2PWIY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= @@ -386,23 +362,16 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= diff --git a/installer/installer.go b/installer/installer.go index 4ee7f32..bfd5f9b 100644 --- a/installer/installer.go +++ b/installer/installer.go @@ -84,7 +84,7 @@ func New(data []byte) (*Installer, error) { // Create a new server instance using the configuration we wrote to the disk // so that everything gets instantiated correctly on the struct. - s2, err := server.FromConfiguration(b, &config.Get().System) + s2, err := server.FromConfiguration(b, &config.Get().System, nil) return &Installer{ server: s2, diff --git a/router/router_server_ws.go b/router/router_server_ws.go index 665617d..2917749 100644 --- a/router/router_server_ws.go +++ b/router/router_server_ws.go @@ -20,7 +20,7 @@ func getServerWebsocket(c *gin.Context) { defer handler.Connection.Close() // Create a context that can be canceled when the user disconnects from this - // socket that will also cancel listeners running in seperate threads. + // socket that will also cancel listeners running in separate threads. ctx, cancel := context.WithCancel(context.Background()) defer cancel() diff --git a/router/websocket/listeners.go b/router/websocket/listeners.go index 6d99b51..36d6b07 100644 --- a/router/websocket/listeners.go +++ b/router/websocket/listeners.go @@ -13,19 +13,14 @@ func (h *Handler) ListenForExpiration(ctx context.Context) { // Make a ticker and completion channel that is used to continuously poll the // JWT stored in the session to send events to the socket when it is expiring. ticker := time.NewTicker(time.Second * 30) - done := make(chan bool) // Whenever this function is complete, end the ticker, close out the channel, // and then close the websocket connection. - defer func() { - ticker.Stop() - done <- true - }() + defer ticker.Stop() for { select { case <-ctx.Done(): - case <-done: return case <-ticker.C: { diff --git a/router/websocket/websocket.go b/router/websocket/websocket.go index 403ab43..27f7cb2 100644 --- a/router/websocket/websocket.go +++ b/router/websocket/websocket.go @@ -194,6 +194,13 @@ func (h *Handler) HandleInbound(m Message) error { { token, err := NewTokenPayload([]byte(strings.Join(m.Args, ""))) if err != nil { + // If the error says the JWT expired, send a token expired + // event and hopefully the client renews the token. + if err == jwt.ErrExpValidation { + h.SendJson(&Message{Event: TokenExpiredEvent}) + return nil + } + return err } diff --git a/server/server.go b/server/server.go index 9b66559..aa71faa 100644 --- a/server/server.go +++ b/server/server.go @@ -142,6 +142,11 @@ type Allocations struct { Mappings map[string][]int `json:"mappings"` } +// Initializes the default required internal struct components for a Server. +func (s *Server) Init() { + s.mutex = &sync.Mutex{} +} + // Iterates over a given directory and loads all of the servers listed before returning // them to the calling function. func LoadDirectory(dir string, cfg *config.SystemConfiguration) error { @@ -160,6 +165,15 @@ func LoadDirectory(dir string, cfg *config.SystemConfiguration) error { return err } + configs, rerr, err := api.NewRequester().GetAllServerConfigurations() + if err != nil || rerr != nil { + if err != nil { + return errors.WithStack(err) + } + + return errors.New(rerr.String()) + } + servers = NewCollection(nil) for _, file := range f { @@ -168,6 +182,7 @@ func LoadDirectory(dir string, cfg *config.SystemConfiguration) error { } wg.Add() + // For each of the YAML files we find, parse it and create a new server // configuration object that can then be returned to the caller. go func(file os.FileInfo) { @@ -179,7 +194,7 @@ func LoadDirectory(dir string, cfg *config.SystemConfiguration) error { return } - s, err := FromConfiguration(b, cfg) + s, err := FromConfiguration(b, cfg, configs[file.Name()[:len(file.Name())-4]]) if err != nil { if IsServerDoesNotExistError(err) { zap.S().Infow("server does not exist on remote system", zap.String("server", file.Name())) @@ -201,15 +216,10 @@ func LoadDirectory(dir string, cfg *config.SystemConfiguration) error { return nil } -// Initializes the default required internal struct components for a Server. -func (s *Server) Init() { - s.mutex = &sync.Mutex{} -} - // Initializes a server using a data byte array. This will be marshaled into the // given struct using a YAML marshaler. This will also configure the given environment // for a server. -func FromConfiguration(data []byte, cfg *config.SystemConfiguration) (*Server, error) { +func FromConfiguration(data []byte, cfg *config.SystemConfiguration, apiCfg *api.ServerConfigurationResponse) (*Server, error) { s := new(Server) if err := defaults.Set(s); err != nil { @@ -242,8 +252,16 @@ func FromConfiguration(data []byte, cfg *config.SystemConfiguration) (*Server, e s.Resources = ResourceUsage{} // Forces the configuration to be synced with the panel. - if err := s.Sync(); err != nil { - return nil, err + if apiCfg == nil { + zap.S().Debug("syncing config with panel", zap.String("server", s.Uuid)) + if err := s.Sync(); err != nil { + return nil, err + } + } else { + zap.S().Debug("syncing with local config", zap.String("server", s.Uuid)) + if err := s.SyncWithConfiguration(apiCfg); err != nil { + return nil, err + } } return s, nil @@ -296,13 +314,16 @@ func (s *Server) Sync() error { return errors.New(rerr.String()) } + return s.SyncWithConfiguration(cfg) +} + +func (s *Server) SyncWithConfiguration(cfg *api.ServerConfigurationResponse) error { // Update the data structure and persist it to the disk. if err := s.UpdateDataStructure(cfg.Settings, false); err != nil { return errors.WithStack(err) } s.processConfiguration = cfg.ProcessConfiguration - return nil } From 1e12b7b37cbcd8569412f0b2fd5ec0a2d640daae Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Fri, 10 Apr 2020 16:33:30 -0600 Subject: [PATCH 5/9] Remove server configurations files and add shared state file --- cmd/root.go | 16 +++++-- data/.gitignore | 3 +- installer/installer.go | 16 +++++-- server/server.go | 74 ++++++++++++++------------------ server/state.go | 95 ++++++++++++++++++++++++++++++++++++++++++ server/update.go | 4 +- 6 files changed, 156 insertions(+), 52 deletions(-) create mode 100644 server/state.go diff --git a/cmd/root.go b/cmd/root.go index 6ce53c7..14afe6a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -21,6 +21,7 @@ import ( var configPath = "config.yml" var debug = false +var shouldRunProfiler = false var root = &cobra.Command{ Use: "wings", @@ -32,12 +33,16 @@ var root = &cobra.Command{ func init() { root.PersistentFlags().StringVar(&configPath, "config", "config.yml", "set the location for the configuration file") root.PersistentFlags().BoolVar(&debug, "debug", false, "pass in order to run wings in debug mode") + root.PersistentFlags().BoolVar(&shouldRunProfiler, "profile", false, "pass in order to profile wings") root.AddCommand(configureCmd) } -func rootCmdRun(cmd *cobra.Command, args []string) { - defer profile.Start().Stop() +func rootCmdRun(*cobra.Command, []string) { + // Profile wings in production!!!! + if shouldRunProfiler { + defer profile.Start().Stop() + } c, err := config.ReadConfiguration(configPath) if err != nil { @@ -113,7 +118,7 @@ func rootCmdRun(cmd *cobra.Command, args []string) { // Create a server environment if none exists currently. This allows us to recover from Docker // being reinstalled on the host system for example. - zap.S().Infow("ensuring envrionment exists", zap.String("server", s.Uuid)) + zap.S().Infow("ensuring environment exists", zap.String("server", s.Uuid)) if err := s.Environment.Create(); err != nil { zap.S().Errorw("failed to create an environment for server", zap.String("server", s.Uuid), zap.Error(err)) } @@ -161,6 +166,11 @@ func rootCmdRun(cmd *cobra.Command, args []string) { zap.S().Errorw("failed to create archive directory", zap.Error(err)) } + // Ensure the backup directory exists. + if err := os.MkdirAll(c.System.BackupDirectory, 0755); err != nil { + zap.S().Errorw("failed to create backup directory", zap.Error(err)) + } + zap.S().Infow("configuring webserver", zap.Bool("ssl", c.Api.Ssl.Enabled), zap.String("host", c.Api.Host), zap.Int("port", c.Api.Port)) r := router.Configure() diff --git a/data/.gitignore b/data/.gitignore index 9c677ba..3da70bf 100644 --- a/data/.gitignore +++ b/data/.gitignore @@ -1,3 +1,4 @@ servers/*.yml !install_logs/.gitkeep -install_logs/* \ No newline at end of file +install_logs/* +states.json diff --git a/installer/installer.go b/installer/installer.go index bfd5f9b..2f8ef55 100644 --- a/installer/installer.go +++ b/installer/installer.go @@ -5,6 +5,7 @@ import ( "github.com/asaskevich/govalidator" "github.com/buger/jsonparser" "github.com/pkg/errors" + "github.com/pterodactyl/wings/api" "github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/server" "go.uber.org/zap" @@ -74,17 +75,26 @@ func New(data []byte) (*Installer, error) { s.Container.Image = getString(data, "container", "image") - b, err := s.WriteConfigurationToDisk() + c, rerr, err := api.NewRequester().GetServerConfiguration(s.Uuid) + if err != nil || rerr != nil { + if err != nil { + return nil, errors.WithStack(err) + } + + return nil, errors.New(rerr.String()) + } + + /*b, err := s.WriteConfigurationToDisk() if err != nil { return nil, err - } + }*/ // Destroy the temporary server instance. s = nil // Create a new server instance using the configuration we wrote to the disk // so that everything gets instantiated correctly on the struct. - s2, err := server.FromConfiguration(b, &config.Get().System, nil) + s2, err := server.FromConfiguration(c, &config.Get().System) return &Installer{ server: s2, diff --git a/server/server.go b/server/server.go index aa71faa..bf9508d 100644 --- a/server/server.go +++ b/server/server.go @@ -1,6 +1,7 @@ package server import ( + "encoding/json" "fmt" "github.com/creasty/defaults" "github.com/patrickmn/go-cache" @@ -9,10 +10,7 @@ import ( "github.com/pterodactyl/wings/config" "github.com/remeh/sizedwaitgroup" "go.uber.org/zap" - "gopkg.in/yaml.v2" - "io/ioutil" "os" - "path" "strings" "sync" "time" @@ -160,11 +158,6 @@ func LoadDirectory(dir string, cfg *config.SystemConfiguration) error { // the road to help big instances scale better. wg := sizedwaitgroup.New(10) - f, err := ioutil.ReadDir(dir) - if err != nil { - return err - } - configs, rerr, err := api.NewRequester().GetAllServerConfigurations() if err != nil || rerr != nil { if err != nil { @@ -174,39 +167,32 @@ func LoadDirectory(dir string, cfg *config.SystemConfiguration) error { return errors.New(rerr.String()) } + states, err := FetchServerStates() + if err != nil { + return errors.WithStack(err) + } + servers = NewCollection(nil) - for _, file := range f { - if !strings.HasSuffix(file.Name(), ".yml") || file.IsDir() { - continue - } - + for uuid, data := range configs { wg.Add() - // For each of the YAML files we find, parse it and create a new server - // configuration object that can then be returned to the caller. - go func(file os.FileInfo) { + go func(uuid string, data *api.ServerConfigurationResponse) { defer wg.Done() - b, err := ioutil.ReadFile(path.Join(dir, file.Name())) + s, err := FromConfiguration(data, cfg) if err != nil { - zap.S().Errorw("failed to read server configuration file, skipping...", zap.String("server", file.Name()), zap.Error(err)) + zap.S().Errorw("failed to load server, skipping...", zap.String("server", uuid), zap.Error(err)) return } - s, err := FromConfiguration(b, cfg, configs[file.Name()[:len(file.Name())-4]]) - if err != nil { - if IsServerDoesNotExistError(err) { - zap.S().Infow("server does not exist on remote system", zap.String("server", file.Name())) - } else { - zap.S().Errorw("failed to parse server configuration, skipping...", zap.String("server", file.Name()), zap.Error(err)) - } - - return + if state, exists := states[s.Uuid]; exists { + s.State = state + zap.S().Debug("loaded server state from cache", zap.String("server", s.Uuid), zap.String("state", s.State)) } servers.Add(s) - }(file) + }(uuid, data) } // Wait until we've processed all of the configuration files in the directory @@ -219,7 +205,7 @@ func LoadDirectory(dir string, cfg *config.SystemConfiguration) error { // Initializes a server using a data byte array. This will be marshaled into the // given struct using a YAML marshaler. This will also configure the given environment // for a server. -func FromConfiguration(data []byte, cfg *config.SystemConfiguration, apiCfg *api.ServerConfigurationResponse) (*Server, error) { +func FromConfiguration(data *api.ServerConfigurationResponse, cfg *config.SystemConfiguration) (*Server, error) { s := new(Server) if err := defaults.Set(s); err != nil { @@ -228,7 +214,12 @@ func FromConfiguration(data []byte, cfg *config.SystemConfiguration, apiCfg *api s.Init() - if err := yaml.Unmarshal(data, s); err != nil { + j, err := json.Marshal(data) + if err != nil { + return nil, err + } + + if err := s.UpdateDataStructure(j, false); err != nil { return nil, err } @@ -252,16 +243,9 @@ func FromConfiguration(data []byte, cfg *config.SystemConfiguration, apiCfg *api s.Resources = ResourceUsage{} // Forces the configuration to be synced with the panel. - if apiCfg == nil { - zap.S().Debug("syncing config with panel", zap.String("server", s.Uuid)) - if err := s.Sync(); err != nil { - return nil, err - } - } else { - zap.S().Debug("syncing with local config", zap.String("server", s.Uuid)) - if err := s.SyncWithConfiguration(apiCfg); err != nil { - return nil, err - } + zap.S().Debug("syncing config with panel", zap.String("server", s.Uuid)) + if err := s.SyncWithConfiguration(data); err != nil { + return nil, err } return s, nil @@ -371,11 +355,15 @@ func (s *Server) SetState(state string) error { // // We also get the benefit of server status changes always propagating corrected configurations // to the disk should we forget to do it elsewhere. - go func(server *Server) { - if _, err := server.WriteConfigurationToDisk(); err != nil { + go func() { + /*if _, err := server.WriteConfigurationToDisk(); err != nil { zap.S().Warnw("failed to write server state change to disk", zap.String("server", server.Uuid), zap.Error(err)) + }*/ + + if err := SaveServerStates(); err != nil { + zap.S().Warnw("failed to write server states to disk", zap.Error(err)) } - }(s) + }() zap.S().Debugw("saw server status change event", zap.String("server", s.Uuid), zap.String("status", s.State)) diff --git a/server/state.go b/server/state.go new file mode 100644 index 0000000..0528449 --- /dev/null +++ b/server/state.go @@ -0,0 +1,95 @@ +package server + +import ( + "encoding/json" + "github.com/pkg/errors" + "os" +) + +var statesFile = "data/states.json" + +// DoesStatesFileExist . +func DoesStatesFileExist() (bool, error) { + if _, err := os.Stat(statesFile); err != nil { + if !os.IsNotExist(err) { + return false, errors.WithStack(err) + } + + return false, nil + } + + return true, nil +} + +// FetchServerStates . +func FetchServerStates() (map[string]string, error) { + // Check if the states file exists. + exists, err := DoesStatesFileExist() + if err != nil { + return nil, errors.WithStack(err) + } + + // Return an empty map if the file does not exist. + if !exists { + return map[string]string{}, nil + } + + // Open the states file. + f, err := os.Open(statesFile) + if err != nil { + return nil, errors.WithStack(err) + } + defer f.Close() + + // Convert the json object to a map. + states := map[string]string{} + if err := json.NewDecoder(f).Decode(states); err != nil { + return nil, errors.WithStack(err) + } + + return states, nil +} + +// SaveServerStates . +func SaveServerStates() error { + // Get the states of all servers on the daemon. + states := map[string]string{} + for _, s := range GetServers().All() { + states[s.Uuid] = s.State + } + + // Convert the map to a json object. + data, err := json.Marshal(states) + if err != nil { + return errors.WithStack(err) + } + + // Check if the states file exists. + exists, err := DoesStatesFileExist() + if err != nil { + return errors.WithStack(err) + } + + // Create the file if it doesn't exist or open it if it already does. + var f *os.File + if !exists { + f, err = os.Create(statesFile) + if err != nil { + return errors.WithStack(err) + } + } else { + f, err = os.Open(statesFile) + if err != nil { + return errors.WithStack(err) + } + } + defer f.Close() + + // Write the data to the file + if _, err := f.Write(data); err != nil { + return errors.WithStack(err) + } + + // Save the file basically. + return f.Sync() +} diff --git a/server/update.go b/server/update.go index 9e74676..d2b36ae 100644 --- a/server/update.go +++ b/server/update.go @@ -69,9 +69,9 @@ func (s *Server) UpdateDataStructure(data []byte, background bool) error { s.Allocations.Mappings = src.Allocations.Mappings } - if _, err := s.WriteConfigurationToDisk(); err != nil { + /*if _, err := s.WriteConfigurationToDisk(); err != nil { return errors.WithStack(err) - } + }*/ if background { s.runBackgroundActions() From acf425b705e1d7eadfcbffd8a2dc9c506f28a316 Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Fri, 10 Apr 2020 16:37:10 -0600 Subject: [PATCH 6/9] Add a lock to the states file --- server/state.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/server/state.go b/server/state.go index 0528449..f1c569b 100644 --- a/server/state.go +++ b/server/state.go @@ -4,12 +4,19 @@ import ( "encoding/json" "github.com/pkg/errors" "os" + "sync" ) -var statesFile = "data/states.json" +var ( + statesLock sync.Mutex + statesFile = "data/states.json" +) // DoesStatesFileExist . func DoesStatesFileExist() (bool, error) { + statesLock.Lock() + defer statesLock.Unlock() + if _, err := os.Stat(statesFile); err != nil { if !os.IsNotExist(err) { return false, errors.WithStack(err) @@ -29,6 +36,10 @@ func FetchServerStates() (map[string]string, error) { return nil, errors.WithStack(err) } + // Request a lock after we check if the file exists. + statesLock.Lock() + defer statesLock.Unlock() + // Return an empty map if the file does not exist. if !exists { return map[string]string{}, nil @@ -70,6 +81,10 @@ func SaveServerStates() error { return errors.WithStack(err) } + // Request a lock after we check if the file exists. + statesLock.Lock() + defer statesLock.Unlock() + // Create the file if it doesn't exist or open it if it already does. var f *os.File if !exists { From 12648b43faaed9fe6c087ca2bab3223013c11805 Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Fri, 10 Apr 2020 17:19:35 -0600 Subject: [PATCH 7/9] Disable config saving temporarily --- cmd/root.go | 4 ++-- config/config.go | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 14afe6a..81f0adc 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -96,9 +96,9 @@ func rootCmdRun(*cobra.Command, []string) { os.Exit(1) } - if err := c.WriteToDisk(); err != nil { + /*if err := c.WriteToDisk(); err != nil { zap.S().Errorw("failed to save configuration to disk", zap.Error(errors.WithStack(err))) - } + }*/ // Just for some nice log output. for _, s := range server.GetServers().All() { diff --git a/config/config.go b/config/config.go index 3b5f47c..910f06a 100644 --- a/config/config.go +++ b/config/config.go @@ -291,7 +291,8 @@ func (c *Configuration) setSystemUser(u *user.User) error { c.System.User.Uid = uid c.System.User.Gid = gid - return c.WriteToDisk() + // return c.WriteToDisk() + return nil } // Ensures that the configured data directory has the correct permissions assigned to From 1f4aca8210b3b9797a29e6f6cd20625538e875d6 Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Fri, 10 Apr 2020 17:55:36 -0600 Subject: [PATCH 8/9] Fix issue with config file saving, fix issue with state file saving, fix issue when merging a uuid into a server without one --- cmd/root.go | 4 ++-- config/config.go | 11 ++--------- server/server.go | 12 +++--------- server/state.go | 30 ++++-------------------------- server/update.go | 2 +- 5 files changed, 12 insertions(+), 47 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 81f0adc..14afe6a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -96,9 +96,9 @@ func rootCmdRun(*cobra.Command, []string) { os.Exit(1) } - /*if err := c.WriteToDisk(); err != nil { + if err := c.WriteToDisk(); err != nil { zap.S().Errorw("failed to save configuration to disk", zap.Error(errors.WithStack(err))) - }*/ + } // Just for some nice log output. for _, s := range server.GetServers().All() { diff --git a/config/config.go b/config/config.go index 0177672..c0c613e 100644 --- a/config/config.go +++ b/config/config.go @@ -298,8 +298,7 @@ func (c *Configuration) setSystemUser(u *user.User) error { c.System.User.Uid = uid c.System.User.Gid = gid - // return c.WriteToDisk() - return nil + return c.WriteToDisk() } // Ensures that the configured data directory has the correct permissions assigned to @@ -358,12 +357,6 @@ func (c *Configuration) EnsureFilePermissions() error { // lock on the file. This prevents something else from writing at the exact same time and // leading to bad data conditions. func (c *Configuration) WriteToDisk() error { - f, err := os.OpenFile("config.yml", os.O_WRONLY, os.ModeExclusive) - if err != nil { - return err - } - defer f.Close() - ccopy := *c // If debugging is set with the flag, don't save that to the configuration file, otherwise // you'll always end up in debug mode. @@ -376,7 +369,7 @@ func (c *Configuration) WriteToDisk() error { return err } - if _, err := f.Write(b); err != nil { + if err := ioutil.WriteFile("config.yml", b, 0644); err != nil { return err } diff --git a/server/server.go b/server/server.go index bf9508d..567fd11 100644 --- a/server/server.go +++ b/server/server.go @@ -1,7 +1,6 @@ package server import ( - "encoding/json" "fmt" "github.com/creasty/defaults" "github.com/patrickmn/go-cache" @@ -188,7 +187,7 @@ func LoadDirectory(dir string, cfg *config.SystemConfiguration) error { if state, exists := states[s.Uuid]; exists { s.State = state - zap.S().Debug("loaded server state from cache", zap.String("server", s.Uuid), zap.String("state", s.State)) + zap.S().Debugw("loaded server state from cache", zap.String("server", s.Uuid), zap.String("state", s.State)) } servers.Add(s) @@ -214,12 +213,7 @@ func FromConfiguration(data *api.ServerConfigurationResponse, cfg *config.System s.Init() - j, err := json.Marshal(data) - if err != nil { - return nil, err - } - - if err := s.UpdateDataStructure(j, false); err != nil { + if err := s.UpdateDataStructure(data.Settings, false); err != nil { return nil, err } @@ -243,7 +237,7 @@ func FromConfiguration(data *api.ServerConfigurationResponse, cfg *config.System s.Resources = ResourceUsage{} // Forces the configuration to be synced with the panel. - zap.S().Debug("syncing config with panel", zap.String("server", s.Uuid)) + zap.S().Debugw("syncing config with panel", zap.String("server", s.Uuid)) if err := s.SyncWithConfiguration(data); err != nil { return nil, err } diff --git a/server/state.go b/server/state.go index f1c569b..6369827 100644 --- a/server/state.go +++ b/server/state.go @@ -3,6 +3,7 @@ package server import ( "encoding/json" "github.com/pkg/errors" + "io/ioutil" "os" "sync" ) @@ -54,7 +55,7 @@ func FetchServerStates() (map[string]string, error) { // Convert the json object to a map. states := map[string]string{} - if err := json.NewDecoder(f).Decode(states); err != nil { + if err := json.NewDecoder(f).Decode(&states); err != nil { return nil, errors.WithStack(err) } @@ -75,36 +76,13 @@ func SaveServerStates() error { return errors.WithStack(err) } - // Check if the states file exists. - exists, err := DoesStatesFileExist() - if err != nil { - return errors.WithStack(err) - } - - // Request a lock after we check if the file exists. statesLock.Lock() defer statesLock.Unlock() - // Create the file if it doesn't exist or open it if it already does. - var f *os.File - if !exists { - f, err = os.Create(statesFile) - if err != nil { - return errors.WithStack(err) - } - } else { - f, err = os.Open(statesFile) - if err != nil { - return errors.WithStack(err) - } - } - defer f.Close() - // Write the data to the file - if _, err := f.Write(data); err != nil { + if err := ioutil.WriteFile(statesFile, data, 0644); err != nil { return errors.WithStack(err) } - // Save the file basically. - return f.Sync() + return nil } diff --git a/server/update.go b/server/update.go index d2b36ae..f852d64 100644 --- a/server/update.go +++ b/server/update.go @@ -24,7 +24,7 @@ func (s *Server) UpdateDataStructure(data []byte, background bool) error { // Don't allow obviously corrupted data to pass through into this function. If the UUID // doesn't match something has gone wrong and the API is attempting to meld this server // instance into a totally different one, which would be bad. - if src.Uuid != "" && src.Uuid != s.Uuid { + if src.Uuid != "" && s.Uuid != "" && src.Uuid != s.Uuid { return errors.New("attempting to merge a data stack with an invalid UUID") } From 814914ca19fd166c10df3fdfb8c1ea4438750068 Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Fri, 10 Apr 2020 18:23:45 -0600 Subject: [PATCH 9/9] Fix json#Unmarshal when there are no servers --- api/server_endpoints.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/api/server_endpoints.go b/api/server_endpoints.go index 828f12f..d76bbd2 100644 --- a/api/server_endpoints.go +++ b/api/server_endpoints.go @@ -63,8 +63,11 @@ func (r *PanelRequest) GetAllServerConfigurations() (map[string]*ServerConfigura return nil, r.Error(), nil } - res := map[string]*ServerConfigurationResponse{} b, _ := r.ReadBody() + res := map[string]*ServerConfigurationResponse{} + if len(b) == 2 { + return res, nil, nil + } if err := json.Unmarshal(b, &res); err != nil { return nil, nil, errors.WithStack(err)