Remove server configurations files and add shared state file
This commit is contained in:
parent
28c8f3f400
commit
1e12b7b37c
14
cmd/root.go
14
cmd/root.go
|
@ -21,6 +21,7 @@ import (
|
||||||
|
|
||||||
var configPath = "config.yml"
|
var configPath = "config.yml"
|
||||||
var debug = false
|
var debug = false
|
||||||
|
var shouldRunProfiler = false
|
||||||
|
|
||||||
var root = &cobra.Command{
|
var root = &cobra.Command{
|
||||||
Use: "wings",
|
Use: "wings",
|
||||||
|
@ -32,12 +33,16 @@ var root = &cobra.Command{
|
||||||
func init() {
|
func init() {
|
||||||
root.PersistentFlags().StringVar(&configPath, "config", "config.yml", "set the location for the configuration file")
|
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(&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)
|
root.AddCommand(configureCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func rootCmdRun(cmd *cobra.Command, args []string) {
|
func rootCmdRun(*cobra.Command, []string) {
|
||||||
|
// Profile wings in production!!!!
|
||||||
|
if shouldRunProfiler {
|
||||||
defer profile.Start().Stop()
|
defer profile.Start().Stop()
|
||||||
|
}
|
||||||
|
|
||||||
c, err := config.ReadConfiguration(configPath)
|
c, err := config.ReadConfiguration(configPath)
|
||||||
if err != nil {
|
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
|
// Create a server environment if none exists currently. This allows us to recover from Docker
|
||||||
// being reinstalled on the host system for example.
|
// 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 {
|
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))
|
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))
|
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))
|
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()
|
r := router.Configure()
|
||||||
|
|
1
data/.gitignore
vendored
1
data/.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
servers/*.yml
|
servers/*.yml
|
||||||
!install_logs/.gitkeep
|
!install_logs/.gitkeep
|
||||||
install_logs/*
|
install_logs/*
|
||||||
|
states.json
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"github.com/asaskevich/govalidator"
|
"github.com/asaskevich/govalidator"
|
||||||
"github.com/buger/jsonparser"
|
"github.com/buger/jsonparser"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/pterodactyl/wings/api"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/server"
|
"github.com/pterodactyl/wings/server"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
@ -74,17 +75,26 @@ func New(data []byte) (*Installer, error) {
|
||||||
|
|
||||||
s.Container.Image = getString(data, "container", "image")
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Destroy the temporary server instance.
|
// Destroy the temporary server instance.
|
||||||
s = nil
|
s = nil
|
||||||
|
|
||||||
// Create a new server instance using the configuration we wrote to the disk
|
// Create a new server instance using the configuration we wrote to the disk
|
||||||
// so that everything gets instantiated correctly on the struct.
|
// 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{
|
return &Installer{
|
||||||
server: s2,
|
server: s2,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/creasty/defaults"
|
"github.com/creasty/defaults"
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
|
@ -9,10 +10,7 @@ import (
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/remeh/sizedwaitgroup"
|
"github.com/remeh/sizedwaitgroup"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -160,11 +158,6 @@ func LoadDirectory(dir string, cfg *config.SystemConfiguration) error {
|
||||||
// the road to help big instances scale better.
|
// the road to help big instances scale better.
|
||||||
wg := sizedwaitgroup.New(10)
|
wg := sizedwaitgroup.New(10)
|
||||||
|
|
||||||
f, err := ioutil.ReadDir(dir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
configs, rerr, err := api.NewRequester().GetAllServerConfigurations()
|
configs, rerr, err := api.NewRequester().GetAllServerConfigurations()
|
||||||
if err != nil || rerr != nil {
|
if err != nil || rerr != nil {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -174,39 +167,32 @@ func LoadDirectory(dir string, cfg *config.SystemConfiguration) error {
|
||||||
return errors.New(rerr.String())
|
return errors.New(rerr.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
states, err := FetchServerStates()
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
servers = NewCollection(nil)
|
servers = NewCollection(nil)
|
||||||
|
|
||||||
for _, file := range f {
|
for uuid, data := range configs {
|
||||||
if !strings.HasSuffix(file.Name(), ".yml") || file.IsDir() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Add()
|
wg.Add()
|
||||||
|
|
||||||
// For each of the YAML files we find, parse it and create a new server
|
go func(uuid string, data *api.ServerConfigurationResponse) {
|
||||||
// configuration object that can then be returned to the caller.
|
|
||||||
go func(file os.FileInfo) {
|
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
b, err := ioutil.ReadFile(path.Join(dir, file.Name()))
|
s, err := FromConfiguration(data, cfg)
|
||||||
if err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := FromConfiguration(b, cfg, configs[file.Name()[:len(file.Name())-4]])
|
if state, exists := states[s.Uuid]; exists {
|
||||||
if err != nil {
|
s.State = state
|
||||||
if IsServerDoesNotExistError(err) {
|
zap.S().Debug("loaded server state from cache", zap.String("server", s.Uuid), zap.String("state", s.State))
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
servers.Add(s)
|
servers.Add(s)
|
||||||
}(file)
|
}(uuid, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait until we've processed all of the configuration files in the directory
|
// 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
|
// 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
|
// given struct using a YAML marshaler. This will also configure the given environment
|
||||||
// for a server.
|
// 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)
|
s := new(Server)
|
||||||
|
|
||||||
if err := defaults.Set(s); err != nil {
|
if err := defaults.Set(s); err != nil {
|
||||||
|
@ -228,7 +214,12 @@ func FromConfiguration(data []byte, cfg *config.SystemConfiguration, apiCfg *api
|
||||||
|
|
||||||
s.Init()
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,17 +243,10 @@ func FromConfiguration(data []byte, cfg *config.SystemConfiguration, apiCfg *api
|
||||||
s.Resources = ResourceUsage{}
|
s.Resources = ResourceUsage{}
|
||||||
|
|
||||||
// Forces the configuration to be synced with the panel.
|
// Forces the configuration to be synced with the panel.
|
||||||
if apiCfg == nil {
|
|
||||||
zap.S().Debug("syncing config with panel", zap.String("server", s.Uuid))
|
zap.S().Debug("syncing config with panel", zap.String("server", s.Uuid))
|
||||||
if err := s.Sync(); err != nil {
|
if err := s.SyncWithConfiguration(data); err != nil {
|
||||||
return nil, err
|
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
|
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
|
// We also get the benefit of server status changes always propagating corrected configurations
|
||||||
// to the disk should we forget to do it elsewhere.
|
// to the disk should we forget to do it elsewhere.
|
||||||
go func(server *Server) {
|
go func() {
|
||||||
if _, err := server.WriteConfigurationToDisk(); err != nil {
|
/*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))
|
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))
|
zap.S().Debugw("saw server status change event", zap.String("server", s.Uuid), zap.String("status", s.State))
|
||||||
|
|
||||||
|
|
95
server/state.go
Normal file
95
server/state.go
Normal file
|
@ -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()
|
||||||
|
}
|
|
@ -69,9 +69,9 @@ func (s *Server) UpdateDataStructure(data []byte, background bool) error {
|
||||||
s.Allocations.Mappings = src.Allocations.Mappings
|
s.Allocations.Mappings = src.Allocations.Mappings
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := s.WriteConfigurationToDisk(); err != nil {
|
/*if _, err := s.WriteConfigurationToDisk(); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if background {
|
if background {
|
||||||
s.runBackgroundActions()
|
s.runBackgroundActions()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user