Different implementation of multi-check for done
Co-Authored-By: Matthew Penner <me@matthewp.io>
This commit is contained in:
parent
1a4c6726c5
commit
642e6e6a96
66
api/process_configuration.go
Normal file
66
api/process_configuration.go
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/apex/log"
|
||||||
|
"github.com/pterodactyl/wings/parser"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OutputLineMatcher struct {
|
||||||
|
// The raw string to match against. This may or may not be prefixed with
|
||||||
|
// regex: which indicates we want to match against the regex expression.
|
||||||
|
raw string
|
||||||
|
reg *regexp.Regexp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine if a given string "s" matches the given line.
|
||||||
|
func (olm *OutputLineMatcher) Matches(s string) bool {
|
||||||
|
if olm.reg == nil {
|
||||||
|
return strings.Contains(s, olm.raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
return olm.reg.MatchString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the matcher's raw comparison string.
|
||||||
|
func (olm *OutputLineMatcher) String() string {
|
||||||
|
return olm.raw
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal the startup lines into individual structs for easier matching abilities.
|
||||||
|
func (olm *OutputLineMatcher) UnmarshalJSON(data []byte) error {
|
||||||
|
if err := json.Unmarshal(data, &olm.raw); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(olm.raw, "regex:") && len(olm.raw) > 6 {
|
||||||
|
r, err := regexp.Compile(strings.TrimPrefix(olm.raw, "regex:"))
|
||||||
|
if err != nil {
|
||||||
|
log.WithField("error", err).WithField("raw", olm.raw).Warn("failed to compile output line marked as being regex")
|
||||||
|
}
|
||||||
|
|
||||||
|
olm.reg = r
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defines the process configuration for a given server instance. This sets what the
|
||||||
|
// daemon is looking for to mark a server as done starting, what to do when stopping,
|
||||||
|
// and what changes to make to the configuration file for a server.
|
||||||
|
type ProcessConfiguration struct {
|
||||||
|
Startup struct {
|
||||||
|
Done []*OutputLineMatcher `json:"done"`
|
||||||
|
UserInteraction []string `json:"user_interaction"`
|
||||||
|
StripAnsi bool `json:"strip_ansi"`
|
||||||
|
} `json:"startup"`
|
||||||
|
|
||||||
|
Stop struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
} `json:"stop"`
|
||||||
|
|
||||||
|
ConfigurationFiles []parser.ConfigurationFile `json:"configs"`
|
||||||
|
}
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/pterodactyl/wings/parser"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -26,24 +25,6 @@ type ServerConfigurationResponse struct {
|
||||||
ProcessConfiguration *ProcessConfiguration `json:"process_configuration"`
|
ProcessConfiguration *ProcessConfiguration `json:"process_configuration"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defines the process configuration for a given server instance. This sets what the
|
|
||||||
// daemon is looking for to mark a server as done starting, what to do when stopping,
|
|
||||||
// and what changes to make to the configuration file for a server.
|
|
||||||
type ProcessConfiguration struct {
|
|
||||||
Startup struct {
|
|
||||||
Done []string `json:"done"`
|
|
||||||
UserInteraction []string `json:"user_interaction"`
|
|
||||||
StripAnsi bool `json:"strip_ansi"`
|
|
||||||
} `json:"startup"`
|
|
||||||
|
|
||||||
Stop struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Value string `json:"value"`
|
|
||||||
} `json:"stop"`
|
|
||||||
|
|
||||||
ConfigurationFiles []parser.ConfigurationFile `json:"configs"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defines installation script information for a server process. This is used when
|
// Defines installation script information for a server process. This is used when
|
||||||
// a server is installed for the first time, and when a server is marked for re-installation.
|
// a server is installed for the first time, and when a server is marked for re-installation.
|
||||||
type InstallationScript struct {
|
type InstallationScript struct {
|
||||||
|
|
|
@ -4,8 +4,6 @@ import (
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Adds all of the internal event listeners we want to use for a server.
|
// Adds all of the internal event listeners we want to use for a server.
|
||||||
|
@ -23,12 +21,7 @@ func (s *Server) AddEventListeners() {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var stripAnsiRegex = regexp.MustCompile("[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))")
|
||||||
stripAnsiRegex = regexp.MustCompile("[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))")
|
|
||||||
|
|
||||||
regexpCacheMx sync.RWMutex
|
|
||||||
regexpCache map[string]*regexp.Regexp
|
|
||||||
)
|
|
||||||
|
|
||||||
// Custom listener for console output events that will check if the given line
|
// Custom listener for console output events that will check if the given line
|
||||||
// of output matches one that should mark the server as started or not.
|
// of output matches one that should mark the server as started or not.
|
||||||
|
@ -38,10 +31,6 @@ func (s *Server) onConsoleOutput(data string) {
|
||||||
|
|
||||||
// Check if the server is currently starting.
|
// Check if the server is currently starting.
|
||||||
if s.GetState() == ProcessStartingState {
|
if s.GetState() == ProcessStartingState {
|
||||||
// If the specific line of output is one that would mark the server as started,
|
|
||||||
// set the server to that state. Only do this if the server is not currently stopped
|
|
||||||
// or stopping.
|
|
||||||
|
|
||||||
// Check if we should strip ansi color codes.
|
// Check if we should strip ansi color codes.
|
||||||
if processConfiguration.Startup.StripAnsi {
|
if processConfiguration.Startup.StripAnsi {
|
||||||
// Strip ansi color codes from the data string.
|
// Strip ansi color codes from the data string.
|
||||||
|
@ -49,40 +38,19 @@ func (s *Server) onConsoleOutput(data string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over all the done lines.
|
// Iterate over all the done lines.
|
||||||
for _, match := range processConfiguration.Startup.Done {
|
for _, l := range processConfiguration.Startup.Done {
|
||||||
if strings.HasPrefix(match, "regex:") && len(match) > 6 {
|
if !l.Matches(data) {
|
||||||
match = match[6:]
|
|
||||||
|
|
||||||
regexpCacheMx.RLock()
|
|
||||||
rxp, ok := regexpCache[match]
|
|
||||||
regexpCacheMx.RUnlock()
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
rxp, err = regexp.Compile(match)
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Warn("failed to compile regexp")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
regexpCacheMx.Lock()
|
|
||||||
regexpCache[match] = rxp
|
|
||||||
regexpCacheMx.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !rxp.MatchString(data) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else if !strings.Contains(data, match) {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Log().WithFields(log.Fields{
|
s.Log().WithFields(log.Fields{
|
||||||
"match": match,
|
"match": l.String(),
|
||||||
"against": data,
|
"against": data,
|
||||||
}).Debug("detected server in running state based on console line output")
|
}).Debug("detected server in running state based on console line output")
|
||||||
|
|
||||||
|
// If the specific line of output is one that would mark the server as started,
|
||||||
|
// set the server to that state. Only do this if the server is not currently stopped
|
||||||
|
// or stopping.
|
||||||
_ = s.SetState(ProcessRunningState)
|
_ = s.SetState(ProcessRunningState)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user