Don't abort entire boot process due to one bad server egg; closes pterodactyl/panel#2448
This commit is contained in:
		
							parent
							
								
									ad1ed0f24a
								
							
						
					
					
						commit
						947279a07c
					
				| 
						 | 
				
			
			@ -34,7 +34,7 @@ type InstallationScript struct {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// GetAllServerConfigurations fetches configurations for all servers assigned to this node.
 | 
			
		||||
func (r *PanelRequest) GetAllServerConfigurations() (map[string]*ServerConfigurationResponse, *RequestError, error) {
 | 
			
		||||
func (r *PanelRequest) GetAllServerConfigurations() (map[string]json.RawMessage, *RequestError, error) {
 | 
			
		||||
	resp, err := r.Get("/servers")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, errors.WithStack(err)
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ func (r *PanelRequest) GetAllServerConfigurations() (map[string]*ServerConfigura
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	b, _ := r.ReadBody()
 | 
			
		||||
	res := map[string]*ServerConfigurationResponse{}
 | 
			
		||||
	res := map[string]json.RawMessage{}
 | 
			
		||||
	if len(b) == 2 {
 | 
			
		||||
		return res, nil, nil
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -61,24 +61,23 @@ func (r *PanelRequest) GetAllServerConfigurations() (map[string]*ServerConfigura
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// Fetches the server configuration and returns the struct for it.
 | 
			
		||||
func (r *PanelRequest) GetServerConfiguration(uuid string) (*ServerConfigurationResponse, *RequestError, error) {
 | 
			
		||||
func (r *PanelRequest) GetServerConfiguration(uuid string) (ServerConfigurationResponse, *RequestError, error) {
 | 
			
		||||
	res := ServerConfigurationResponse{}
 | 
			
		||||
 | 
			
		||||
	resp, err := r.Get(fmt.Sprintf("/servers/%s", uuid))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, errors.WithStack(err)
 | 
			
		||||
		return res, nil, errors.WithStack(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
 | 
			
		||||
	r.Response = resp
 | 
			
		||||
 | 
			
		||||
	if r.HasError() {
 | 
			
		||||
		return nil, r.Error(), nil
 | 
			
		||||
		return res, r.Error(), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res := &ServerConfigurationResponse{}
 | 
			
		||||
	b, _ := r.ReadBody()
 | 
			
		||||
 | 
			
		||||
	if err := json.Unmarshal(b, res); err != nil {
 | 
			
		||||
		return nil, nil, errors.WithStack(err)
 | 
			
		||||
	if err := json.Unmarshal(b, &res); err != nil {
 | 
			
		||||
		return res, nil, errors.WithStack(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return res, nil, nil
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ import (
 | 
			
		|||
 | 
			
		||||
type Metadata struct {
 | 
			
		||||
	Image string
 | 
			
		||||
	Stop  *api.ProcessStopConfiguration
 | 
			
		||||
	Stop  api.ProcessStopConfiguration
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Ensure that the Docker environment is always implementing all of the methods
 | 
			
		||||
| 
						 | 
				
			
			@ -171,7 +171,7 @@ func (e *Environment) Config() *environment.Configuration {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// 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.meta.Stop = c
 | 
			
		||||
	e.mu.Unlock()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -126,8 +126,8 @@ func (e *Environment) Stop() error {
 | 
			
		|||
	s := e.meta.Stop
 | 
			
		||||
	e.mu.RUnlock()
 | 
			
		||||
 | 
			
		||||
	if s == nil || s.Type == api.ProcessStopSignal {
 | 
			
		||||
		if s == nil {
 | 
			
		||||
	if s.Type == "" || s.Type == api.ProcessStopSignal {
 | 
			
		||||
		if s.Type == "" {
 | 
			
		||||
			log.WithField("container_id", e.Id).Warn("no stop configuration detected for environment, using termination procedure")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,13 +33,11 @@ func (e *Environment) SendCommand(c string) error {
 | 
			
		|||
	e.mu.RLock()
 | 
			
		||||
	defer e.mu.RUnlock()
 | 
			
		||||
 | 
			
		||||
	if e.meta.Stop != nil {
 | 
			
		||||
		// If the command being processed is the same as the process stop command then we want to mark
 | 
			
		||||
		// the server as entering the stopping state otherwise the process will stop and Wings will think
 | 
			
		||||
		// it has crashed and attempt to restart it.
 | 
			
		||||
		if e.meta.Stop.Type == "command" && c == e.meta.Stop.Value {
 | 
			
		||||
			e.Events().Publish(environment.StateChangeEvent, environment.ProcessStoppingState)
 | 
			
		||||
		}
 | 
			
		||||
	// If the command being processed is the same as the process stop command then we want to mark
 | 
			
		||||
	// the server as entering the stopping state otherwise the process will stop and Wings will think
 | 
			
		||||
	// it has crashed and attempt to restart it.
 | 
			
		||||
	if e.meta.Stop.Type == "command" && c == e.meta.Stop.Value {
 | 
			
		||||
		e.Events().Publish(environment.StateChangeEvent, environment.ProcessStoppingState)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err := e.stream.Conn.Write([]byte(c + "\n"))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
package server
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/apex/log"
 | 
			
		||||
	"github.com/creasty/defaults"
 | 
			
		||||
| 
						 | 
				
			
			@ -49,8 +50,18 @@ func LoadDirectory() error {
 | 
			
		|||
		data := data
 | 
			
		||||
 | 
			
		||||
		pool.Submit(func() {
 | 
			
		||||
			// Parse the json.RawMessage into an expected struct value. We do this here so that a single broken
 | 
			
		||||
			// server does not cause the entire boot process to hang, and allows us to show more useful error
 | 
			
		||||
			// messaging in the output.
 | 
			
		||||
			d := api.ServerConfigurationResponse{}
 | 
			
		||||
 | 
			
		||||
			log.WithField("server", uuid).Info("creating new server object from API response")
 | 
			
		||||
			s, err := FromConfiguration(data)
 | 
			
		||||
			if err := json.Unmarshal(data, &d); err != nil {
 | 
			
		||||
				log.WithField("server", uuid).WithField("error", err).Error("failed to parse server configuration from API response, skipping...")
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			s, err := FromConfiguration(d)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.WithField("server", uuid).WithField("error", err).Error("failed to load server, skipping...")
 | 
			
		||||
				return
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +84,7 @@ func LoadDirectory() 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 *api.ServerConfigurationResponse) (*Server, error) {
 | 
			
		||||
func FromConfiguration(data api.ServerConfigurationResponse) (*Server, error) {
 | 
			
		||||
	cfg := Configuration{}
 | 
			
		||||
	if err := defaults.Set(&cfg); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "failed to set struct defaults for server configuration")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -128,7 +128,7 @@ func (s *Server) Sync() error {
 | 
			
		|||
	return s.SyncWithConfiguration(cfg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Server) SyncWithConfiguration(cfg *api.ServerConfigurationResponse) error {
 | 
			
		||||
func (s *Server) SyncWithConfiguration(cfg api.ServerConfigurationResponse) error {
 | 
			
		||||
	// Update the data structure and persist it to the disk.
 | 
			
		||||
	if err := s.UpdateDataStructure(cfg.Settings); err != nil {
 | 
			
		||||
		return errors.WithStack(err)
 | 
			
		||||
| 
						 | 
				
			
			@ -147,7 +147,7 @@ func (s *Server) SyncWithConfiguration(cfg *api.ServerConfigurationResponse) err
 | 
			
		|||
	if e, ok := s.Environment.(*docker.Environment); ok {
 | 
			
		||||
		s.Log().Debug("syncing stop configuration with configured docker environment")
 | 
			
		||||
		e.SetImage(s.Config().Container.Image)
 | 
			
		||||
		e.SetStopConfiguration(&cfg.ProcessConfiguration.Stop)
 | 
			
		||||
		e.SetStopConfiguration(cfg.ProcessConfiguration.Stop)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
| 
						 | 
				
			
			@ -178,7 +178,7 @@ func (s *Server) CreateEnvironment() error {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// Gets the process configuration data for the server.
 | 
			
		||||
func (s *Server) GetProcessConfiguration() (*api.ServerConfigurationResponse, *api.RequestError, error) {
 | 
			
		||||
func (s *Server) GetProcessConfiguration() (api.ServerConfigurationResponse, *api.RequestError, error) {
 | 
			
		||||
	return api.NewRequester().GetServerConfiguration(s.Id())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user