some reorganisation etc. in control package
some minor stuff just pushing so I can try to replace fsouza/go-dockerclient with moby/moby/client
This commit is contained in:
parent
184d7e0afe
commit
501409827e
|
@ -6,7 +6,7 @@ const (
|
||||||
|
|
||||||
// DataPath is a string containing the path where data should
|
// DataPath is a string containing the path where data should
|
||||||
// be stored on the system
|
// be stored on the system
|
||||||
DataPath = "datapath"
|
DataPath = "data"
|
||||||
|
|
||||||
// APIHost is a string containing the interface ip address
|
// APIHost is a string containing the interface ip address
|
||||||
// on what the api should listen on
|
// on what the api should listen on
|
||||||
|
|
|
@ -26,3 +26,7 @@ const ServerDataPath = "data"
|
||||||
|
|
||||||
// JSONIndent is the indent to use with the json.MarshalIndent() function.
|
// JSONIndent is the indent to use with the json.MarshalIndent() function.
|
||||||
const JSONIndent = " "
|
const JSONIndent = " "
|
||||||
|
|
||||||
|
// DockerContainerPrefix is the prefix used for naming Docker containers.
|
||||||
|
// It's also used to prefix the hostnames of the docker containers.
|
||||||
|
const DockerContainerPrefix = "ptdl-"
|
||||||
|
|
|
@ -20,6 +20,7 @@ type dockerEnvironment struct {
|
||||||
container *docker.Container
|
container *docker.Container
|
||||||
context context.Context
|
context context.Context
|
||||||
|
|
||||||
|
attached bool
|
||||||
containerInput io.Writer
|
containerInput io.Writer
|
||||||
containerOutput io.Writer
|
containerOutput io.Writer
|
||||||
closeWaiter docker.CloseWaiter
|
closeWaiter docker.CloseWaiter
|
||||||
|
@ -67,23 +68,33 @@ func (env *dockerEnvironment) checkContainerExists() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (env *dockerEnvironment) attach() error {
|
func (env *dockerEnvironment) attach() error {
|
||||||
|
if env.attached {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
pr, pw := io.Pipe()
|
pr, pw := io.Pipe()
|
||||||
|
env.containerInput = pw
|
||||||
|
|
||||||
|
cw := websockets.ConsoleWriter{
|
||||||
|
Hub: env.server.websockets,
|
||||||
|
}
|
||||||
|
|
||||||
success := make(chan struct{})
|
success := make(chan struct{})
|
||||||
w, err := env.client.AttachToContainerNonBlocking(docker.AttachToContainerOptions{
|
w, err := env.client.AttachToContainerNonBlocking(docker.AttachToContainerOptions{
|
||||||
Container: env.server.DockerContainer.ID,
|
Container: env.server.DockerContainer.ID,
|
||||||
InputStream: pr,
|
InputStream: pr,
|
||||||
OutputStream: os.Stdout,
|
OutputStream: cw,
|
||||||
|
ErrorStream: cw,
|
||||||
Stdin: true,
|
Stdin: true,
|
||||||
Stdout: true,
|
Stdout: true,
|
||||||
|
Stderr: true,
|
||||||
Stream: true,
|
Stream: true,
|
||||||
Success: success,
|
Success: success,
|
||||||
})
|
})
|
||||||
env.closeWaiter = w
|
env.closeWaiter = w
|
||||||
env.containerInput = pw
|
|
||||||
|
|
||||||
<-success
|
<-success
|
||||||
close(success)
|
close(success)
|
||||||
|
env.attached = true
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,11 +102,11 @@ func (env *dockerEnvironment) attach() error {
|
||||||
// settings to it
|
// settings to it
|
||||||
func (env *dockerEnvironment) Create() error {
|
func (env *dockerEnvironment) Create() error {
|
||||||
log.WithField("server", env.server.ID).Debug("Creating docker environment")
|
log.WithField("server", env.server.ID).Debug("Creating docker environment")
|
||||||
// Split image repository and tag to feed it to the library
|
// Split image repository and tag
|
||||||
imageParts := strings.Split(env.server.Service().DockerImage, ":")
|
imageParts := strings.Split(env.server.GetService().DockerImage, ":")
|
||||||
imageRepoParts := strings.Split(imageParts[0], "/")
|
imageRepoParts := strings.Split(imageParts[0], "/")
|
||||||
if len(imageRepoParts) >= 3 {
|
if len(imageRepoParts) >= 3 {
|
||||||
// Handle possibly required authentication
|
// TODO: Handle possibly required authentication
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pull docker image
|
// Pull docker image
|
||||||
|
@ -105,7 +116,7 @@ func (env *dockerEnvironment) Create() error {
|
||||||
if len(imageParts) >= 2 {
|
if len(imageParts) >= 2 {
|
||||||
pullImageOpts.Tag = imageParts[1]
|
pullImageOpts.Tag = imageParts[1]
|
||||||
}
|
}
|
||||||
log.WithField("image", env.server.service.DockerImage).Debug("Pulling docker image")
|
log.WithField("image", env.server.GetService().DockerImage).Debug("Pulling docker image")
|
||||||
err := env.client.PullImage(pullImageOpts, docker.AuthConfiguration{})
|
err := env.client.PullImage(pullImageOpts, docker.AuthConfiguration{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).WithField("server", env.server.ID).Error("Failed to create docker environment")
|
log.WithError(err).WithField("server", env.server.ID).Error("Failed to create docker environment")
|
||||||
|
@ -119,17 +130,21 @@ func (env *dockerEnvironment) Create() error {
|
||||||
// Create docker container
|
// Create docker container
|
||||||
// TODO: apply cpu, io, disk limits.
|
// TODO: apply cpu, io, disk limits.
|
||||||
containerConfig := &docker.Config{
|
containerConfig := &docker.Config{
|
||||||
Image: env.server.Service().DockerImage,
|
Image: env.server.GetService().DockerImage,
|
||||||
Cmd: strings.Split(env.server.StartupCommand, " "),
|
Cmd: strings.Split(env.server.StartupCommand, " "),
|
||||||
OpenStdin: true,
|
OpenStdin: true,
|
||||||
|
ArgsEscaped: false,
|
||||||
|
Hostname: constants.DockerContainerPrefix + env.server.UUIDShort(),
|
||||||
}
|
}
|
||||||
containerHostConfig := &docker.HostConfig{
|
containerHostConfig := &docker.HostConfig{
|
||||||
Memory: env.server.Settings.Memory,
|
Memory: env.server.Settings.Memory,
|
||||||
MemorySwap: env.server.Settings.Swap,
|
MemorySwap: env.server.Settings.Swap,
|
||||||
Binds: []string{env.server.dataPath() + ":/home/container"},
|
// TODO: Allow custom binds via some kind of settings in the service
|
||||||
|
Binds: []string{env.server.dataPath() + ":/home/container"},
|
||||||
|
// TODO: Add port bindings
|
||||||
}
|
}
|
||||||
createContainerOpts := docker.CreateContainerOptions{
|
createContainerOpts := docker.CreateContainerOptions{
|
||||||
Name: "ptdl-" + env.server.UUIDShort(),
|
Name: constants.DockerContainerPrefix + env.server.UUIDShort(),
|
||||||
Config: containerConfig,
|
Config: containerConfig,
|
||||||
HostConfig: containerHostConfig,
|
HostConfig: containerHostConfig,
|
||||||
Context: env.context,
|
Context: env.context,
|
||||||
|
@ -139,12 +154,16 @@ func (env *dockerEnvironment) Create() error {
|
||||||
log.WithError(err).WithField("server", env.server.ID).Error("Failed to create docker container")
|
log.WithError(err).WithField("server", env.server.ID).Error("Failed to create docker container")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
env.server.DockerContainer.ID = container.ID
|
env.server.DockerContainer.ID = container.ID
|
||||||
env.server.Save()
|
env.server.Save()
|
||||||
env.container = container
|
env.container = container
|
||||||
|
if env.closeWaiter != nil {
|
||||||
|
env.closeWaiter.Close()
|
||||||
|
}
|
||||||
|
env.attached = false
|
||||||
|
|
||||||
log.WithField("server", env.server.ID).Debug("Docker environment created")
|
log.WithField("server", env.server.ID).Debug("Docker environment created")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,6 +186,10 @@ func (env *dockerEnvironment) Destroy() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if env.closeWaiter != nil {
|
||||||
|
env.closeWaiter.Close()
|
||||||
|
}
|
||||||
|
env.attached = false
|
||||||
log.WithField("server", env.server.ID).Debug("Docker environment destroyed")
|
log.WithField("server", env.server.ID).Debug("Docker environment destroyed")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
package control
|
package control
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/pterodactyl/wings/api/websockets"
|
"github.com/pterodactyl/wings/api/websockets"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/viper"
|
)
|
||||||
|
|
||||||
|
type Status string
|
||||||
|
|
||||||
|
const (
|
||||||
|
StatusStopped Status = "stopped"
|
||||||
|
StatusStarting Status = "starting"
|
||||||
|
StatusRunning Status = "running"
|
||||||
|
StatusStopping Status = "stopping"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrServerExists is returned when a server already exists on creation.
|
// ErrServerExists is returned when a server already exists on creation.
|
||||||
|
@ -34,6 +37,7 @@ type Server interface {
|
||||||
Save() error
|
Save() error
|
||||||
|
|
||||||
Environment() (Environment, error)
|
Environment() (Environment, error)
|
||||||
|
Websockets() *websockets.Hub
|
||||||
|
|
||||||
HasPermission(string, string) bool
|
HasPermission(string, string) bool
|
||||||
}
|
}
|
||||||
|
@ -41,32 +45,36 @@ type Server interface {
|
||||||
// ServerStruct is a single instance of a Service managed by the panel
|
// ServerStruct is a single instance of a Service managed by the panel
|
||||||
type ServerStruct struct {
|
type ServerStruct struct {
|
||||||
// ID is the unique identifier of the server
|
// ID is the unique identifier of the server
|
||||||
ID string `json:"uuid"`
|
ID string `json:"uuid" jsonapi:"primary,server"`
|
||||||
|
|
||||||
// ServiceName is the name of the service. It is mainly used to allow storing the service
|
// ServiceName is the name of the service. It is mainly used to allow storing the service
|
||||||
// in the config
|
// in the config
|
||||||
ServiceName string `json:"serviceName"`
|
ServiceName string `json:"serviceName"`
|
||||||
service *Service
|
Service *Service `json:"-" jsonapi:"relation,service"`
|
||||||
environment Environment
|
environment Environment
|
||||||
|
|
||||||
// StartupCommand is the command executed in the environment to start the server
|
// StartupCommand is the command executed in the environment to start the server
|
||||||
StartupCommand string `json:"startupCommand"`
|
StartupCommand string `json:"startupCommand" jsonapi:"attr,startup_command"`
|
||||||
|
|
||||||
// DockerContainer holds information regarding the docker container when the server
|
// DockerContainer holds information regarding the docker container when the server
|
||||||
// is running in a docker environment
|
// is running in a docker environment
|
||||||
DockerContainer dockerContainer `json:"dockerContainer"`
|
DockerContainer dockerContainer `json:"dockerContainer" jsonapi:"attr,docker_container"`
|
||||||
|
|
||||||
// EnvironmentVariables are set in the Environment the server is running in
|
// EnvironmentVariables are set in the Environment the server is running in
|
||||||
EnvironmentVariables map[string]string `json:"env"`
|
EnvironmentVariables map[string]string `json:"environmentVariables" jsonapi:"attr,environment_variables"`
|
||||||
|
|
||||||
// Allocations contains the ports and ip addresses assigned to the server
|
// Allocations contains the ports and ip addresses assigned to the server
|
||||||
Allocations allocations `json:"allocation"`
|
Allocations allocations `json:"allocation" jsonapi:"attr,allocations"`
|
||||||
|
|
||||||
// Settings are the environment settings and limitations for the server
|
// Settings are the environment settings and limitations for the server
|
||||||
Settings settings `json:"settings"`
|
Settings settings `json:"settings" jsonapi:"attr,settings"`
|
||||||
|
|
||||||
// Keys are some auth keys we will hopefully replace by something better.
|
// Keys are some auth keys we will hopefully replace by something better.
|
||||||
|
// TODO remove
|
||||||
Keys map[string][]string `json:"keys"`
|
Keys map[string][]string `json:"keys"`
|
||||||
|
|
||||||
|
websockets *websockets.Hub
|
||||||
|
status Status
|
||||||
}
|
}
|
||||||
|
|
||||||
type allocations struct {
|
type allocations struct {
|
||||||
|
@ -98,73 +106,6 @@ type serversMap map[string]*ServerStruct
|
||||||
|
|
||||||
var servers = make(serversMap)
|
var servers = make(serversMap)
|
||||||
|
|
||||||
// LoadServerConfigurations loads the configured servers from a specified path
|
|
||||||
func LoadServerConfigurations(path string) error {
|
|
||||||
serverFiles, err := ioutil.ReadDir(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
servers = make(serversMap)
|
|
||||||
|
|
||||||
for _, file := range serverFiles {
|
|
||||||
if file.IsDir() {
|
|
||||||
server, err := loadServerConfiguration(filepath.Join(path, file.Name(), constants.ServerConfigFile))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
servers[server.ID] = server
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadServerConfiguration(path string) (*ServerStruct, error) {
|
|
||||||
file, err := ioutil.ReadFile(path)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
server := &ServerStruct{}
|
|
||||||
if err := json.Unmarshal(file, server); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return server, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func storeServerConfiguration(server *ServerStruct) error {
|
|
||||||
serverJSON, err := json.MarshalIndent(server, "", constants.JSONIndent)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := os.MkdirAll(server.path(), constants.DefaultFolderPerms); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := ioutil.WriteFile(server.configFilePath(), serverJSON, constants.DefaultFilePerms); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func storeServerConfigurations() error {
|
|
||||||
for _, s := range servers {
|
|
||||||
if err := storeServerConfiguration(s); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteServerFolder(id string) error {
|
|
||||||
path := filepath.Join(viper.GetString(config.DataPath), constants.ServersPath, id)
|
|
||||||
folder, err := os.Stat(path)
|
|
||||||
if os.IsNotExist(err) || !folder.IsDir() {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return os.RemoveAll(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetServers returns an array of all servers the daemon manages
|
// GetServers returns an array of all servers the daemon manages
|
||||||
func GetServers() []Server {
|
func GetServers() []Server {
|
||||||
serverArray := make([]Server, len(servers))
|
serverArray := make([]Server, len(servers))
|
||||||
|
@ -192,6 +133,11 @@ func CreateServer(server *ServerStruct) (Server, error) {
|
||||||
}
|
}
|
||||||
servers[server.ID] = server
|
servers[server.ID] = server
|
||||||
if err := server.Save(); err != nil {
|
if err := server.Save(); err != nil {
|
||||||
|
delete(servers, server.ID)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := server.init(); err != nil {
|
||||||
|
DeleteServer(server.ID)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return server, nil
|
return server, nil
|
||||||
|
@ -207,13 +153,40 @@ func DeleteServer(id string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ServerStruct) init() error {
|
||||||
|
// TODO: Properly use the correct service, mock for now.
|
||||||
|
s.Service = &Service{
|
||||||
|
DockerImage: "quay.io/pterodactyl/core:java",
|
||||||
|
EnvironmentName: "docker",
|
||||||
|
}
|
||||||
|
s.status = StatusStopped
|
||||||
|
|
||||||
|
s.websockets = websockets.NewHub()
|
||||||
|
go s.websockets.Run()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
if s.environment == nil {
|
||||||
|
switch s.GetService().EnvironmentName {
|
||||||
|
case "docker":
|
||||||
|
s.environment, err = NewDockerEnvironment(s)
|
||||||
|
default:
|
||||||
|
log.WithField("service", s.ServiceName).Error("Invalid environment name")
|
||||||
|
return errors.New("Invalid environment name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ServerStruct) Start() error {
|
func (s *ServerStruct) Start() error {
|
||||||
|
s.SetStatus(StatusStarting)
|
||||||
env, err := s.Environment()
|
env, err := s.Environment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
s.SetStatus(StatusStopped)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !env.Exists() {
|
if !env.Exists() {
|
||||||
if err := env.Create(); err != nil {
|
if err := env.Create(); err != nil {
|
||||||
|
s.SetStatus(StatusStopped)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,8 +194,10 @@ func (s *ServerStruct) Start() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerStruct) Stop() error {
|
func (s *ServerStruct) Stop() error {
|
||||||
|
s.SetStatus(StatusStopping)
|
||||||
env, err := s.Environment()
|
env, err := s.Environment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
s.SetStatus(StatusRunning)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return env.Stop()
|
return env.Stop()
|
||||||
|
@ -258,70 +233,3 @@ func (s *ServerStruct) Rebuild() error {
|
||||||
}
|
}
|
||||||
return env.ReCreate()
|
return env.ReCreate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Service returns the server's service configuration
|
|
||||||
func (s *ServerStruct) Service() *Service {
|
|
||||||
if s.service == nil {
|
|
||||||
// TODO: Properly use the correct service, mock for now.
|
|
||||||
s.service = &Service{
|
|
||||||
DockerImage: "quay.io/pterodactyl/core:java",
|
|
||||||
EnvironmentName: "docker",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s.service
|
|
||||||
}
|
|
||||||
|
|
||||||
// UUIDShort returns the first block of the UUID
|
|
||||||
func (s *ServerStruct) UUIDShort() string {
|
|
||||||
return s.ID[0:strings.Index(s.ID, "-")]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Environment returns the servers environment
|
|
||||||
func (s *ServerStruct) Environment() (Environment, error) {
|
|
||||||
var err error
|
|
||||||
if s.environment == nil {
|
|
||||||
switch s.Service().EnvironmentName {
|
|
||||||
case "docker":
|
|
||||||
s.environment, err = NewDockerEnvironment(s)
|
|
||||||
default:
|
|
||||||
log.WithField("service", s.ServiceName).Error("Invalid environment name")
|
|
||||||
return nil, errors.New("Invalid environment name")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s.environment, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasPermission checks wether a provided token has a specific permission
|
|
||||||
func (s *ServerStruct) HasPermission(token string, permission string) bool {
|
|
||||||
for key, perms := range s.Keys {
|
|
||||||
if key == token {
|
|
||||||
for _, perm := range perms {
|
|
||||||
if perm == permission || perm == "s:*" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerStruct) Save() error {
|
|
||||||
if err := storeServerConfiguration(s); err != nil {
|
|
||||||
log.WithField("server", s.ID).WithError(err).Error("Failed to store server configuration.")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerStruct) path() string {
|
|
||||||
return filepath.Join(viper.GetString(config.DataPath), constants.ServersPath, s.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerStruct) dataPath() string {
|
|
||||||
return filepath.Join(s.path(), constants.ServerDataPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerStruct) configFilePath() string {
|
|
||||||
return filepath.Join(s.path(), constants.ServerConfigFile)
|
|
||||||
}
|
|
||||||
|
|
103
control/server_persistance.go
Normal file
103
control/server_persistance.go
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
package control
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/pterodactyl/wings/config"
|
||||||
|
"github.com/pterodactyl/wings/constants"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LoadServerConfigurations loads the configured servers from a specified path
|
||||||
|
func LoadServerConfigurations(path string) error {
|
||||||
|
serverFiles, err := ioutil.ReadDir(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
servers = make(serversMap)
|
||||||
|
|
||||||
|
for _, file := range serverFiles {
|
||||||
|
if file.IsDir() {
|
||||||
|
server, err := loadServerConfiguration(filepath.Join(path, file.Name(), constants.ServerConfigFile))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
servers[server.ID] = server
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadServerConfiguration(path string) (*ServerStruct, error) {
|
||||||
|
file, err := ioutil.ReadFile(path)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &ServerStruct{}
|
||||||
|
if err := json.Unmarshal(file, server); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := server.init(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return server, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func storeServerConfiguration(server *ServerStruct) error {
|
||||||
|
serverJSON, err := json.MarshalIndent(server, "", constants.JSONIndent)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(server.path(), constants.DefaultFolderPerms); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := ioutil.WriteFile(server.configFilePath(), serverJSON, constants.DefaultFilePerms); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func storeServerConfigurations() error {
|
||||||
|
for _, s := range servers {
|
||||||
|
if err := storeServerConfiguration(s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteServerFolder(id string) error {
|
||||||
|
path := filepath.Join(viper.GetString(config.DataPath), constants.ServersPath, id)
|
||||||
|
folder, err := os.Stat(path)
|
||||||
|
if os.IsNotExist(err) || !folder.IsDir() {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.RemoveAll(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerStruct) Save() error {
|
||||||
|
if err := storeServerConfiguration(s); err != nil {
|
||||||
|
log.WithField("server", s.ID).WithError(err).Error("Failed to store server configuration.")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerStruct) path() string {
|
||||||
|
return filepath.Join(viper.GetString(config.DataPath), constants.ServersPath, s.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerStruct) dataPath() string {
|
||||||
|
return filepath.Join(s.path(), constants.ServerDataPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerStruct) configFilePath() string {
|
||||||
|
return filepath.Join(s.path(), constants.ServerConfigFile)
|
||||||
|
}
|
49
control/server_util.go
Normal file
49
control/server_util.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package control
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pterodactyl/wings/api/websockets"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *ServerStruct) SetStatus(st Status) {
|
||||||
|
s.status = st
|
||||||
|
s.websockets.Broadcast <- websockets.Message{
|
||||||
|
Type: websockets.MessageTypeStatus,
|
||||||
|
Payload: s.status,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Service returns the server's service configuration
|
||||||
|
func (s *ServerStruct) GetService() *Service {
|
||||||
|
return s.Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// UUIDShort returns the first block of the UUID
|
||||||
|
func (s *ServerStruct) UUIDShort() string {
|
||||||
|
return s.ID[0:strings.Index(s.ID, "-")]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Environment returns the servers environment
|
||||||
|
func (s *ServerStruct) Environment() (Environment, error) {
|
||||||
|
return s.environment, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerStruct) Websockets() *websockets.Hub {
|
||||||
|
return s.websockets
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasPermission checks wether a provided token has a specific permission
|
||||||
|
func (s *ServerStruct) HasPermission(token string, permission string) bool {
|
||||||
|
for key, perms := range s.Keys {
|
||||||
|
if key == token {
|
||||||
|
for _, perm := range perms {
|
||||||
|
if perm == permission || perm == "s:*" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ type Service struct {
|
||||||
server *Server
|
server *Server
|
||||||
|
|
||||||
// EnvironmentName is the name of the environment used by the service
|
// EnvironmentName is the name of the environment used by the service
|
||||||
EnvironmentName string `json:"environmentName"`
|
EnvironmentName string `json:"environmentName" jsonapi:"primary,service"`
|
||||||
|
|
||||||
DockerImage string `json:"dockerImage"`
|
DockerImage string `json:"dockerImage" jsonapi:"attr,docker_image"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/pterodactyl/wings/constants"
|
"github.com/pterodactyl/wings/constants"
|
||||||
|
|
||||||
rotatelogs "github.com/lestrrat/go-file-rotatelogs"
|
"github.com/lestrrat/go-file-rotatelogs"
|
||||||
"github.com/rifflock/lfshook"
|
"github.com/rifflock/lfshook"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user