2019-11-16 23:10:53 +00:00
|
|
|
package installer
|
|
|
|
|
|
|
|
import (
|
2021-02-02 05:28:46 +00:00
|
|
|
"context"
|
2019-11-16 23:10:53 +00:00
|
|
|
"encoding/json"
|
2021-01-10 01:22:39 +00:00
|
|
|
|
|
|
|
"emperror.dev/errors"
|
2019-11-16 23:10:53 +00:00
|
|
|
"github.com/asaskevich/govalidator"
|
|
|
|
"github.com/buger/jsonparser"
|
2020-08-11 04:38:42 +00:00
|
|
|
"github.com/pterodactyl/wings/environment"
|
2021-02-02 05:28:46 +00:00
|
|
|
"github.com/pterodactyl/wings/remote"
|
2019-11-16 23:10:53 +00:00
|
|
|
"github.com/pterodactyl/wings/server"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Installer struct {
|
|
|
|
server *server.Server
|
|
|
|
}
|
|
|
|
|
2021-02-02 05:28:46 +00:00
|
|
|
// New validates the received data to ensure that all of the required fields
|
2019-11-16 23:10:53 +00:00
|
|
|
// have been passed along in the request. This should be manually run before
|
|
|
|
// calling Execute().
|
2021-02-02 05:28:46 +00:00
|
|
|
func New(ctx context.Context, manager *server.Manager, data []byte) (*Installer, error) {
|
2019-11-16 23:10:53 +00:00
|
|
|
if !govalidator.IsUUIDv4(getString(data, "uuid")) {
|
2020-04-12 00:55:00 +00:00
|
|
|
return nil, NewValidationError("uuid provided was not in a valid format")
|
2019-11-16 23:10:53 +00:00
|
|
|
}
|
|
|
|
|
2020-07-19 23:27:55 +00:00
|
|
|
cfg := &server.Configuration{
|
2020-08-30 16:54:33 +00:00
|
|
|
Uuid: getString(data, "uuid"),
|
|
|
|
Suspended: false,
|
|
|
|
Invocation: getString(data, "invocation"),
|
2020-08-30 16:41:14 +00:00
|
|
|
SkipEggScripts: getBoolean(data, "skip_egg_scripts"),
|
2020-08-11 04:38:42 +00:00
|
|
|
Build: environment.Limits{
|
2019-11-16 23:10:53 +00:00
|
|
|
MemoryLimit: getInt(data, "build", "memory"),
|
2019-11-16 23:48:50 +00:00
|
|
|
Swap: getInt(data, "build", "swap"),
|
|
|
|
IoWeight: uint16(getInt(data, "build", "io")),
|
|
|
|
CpuLimit: getInt(data, "build", "cpu"),
|
|
|
|
DiskSpace: getInt(data, "build", "disk"),
|
2020-03-29 19:31:17 +00:00
|
|
|
Threads: getString(data, "build", "threads"),
|
2019-11-16 23:10:53 +00:00
|
|
|
},
|
2020-07-19 23:27:55 +00:00
|
|
|
CrashDetectionEnabled: true,
|
2019-11-16 23:10:53 +00:00
|
|
|
}
|
|
|
|
|
2020-07-19 23:27:55 +00:00
|
|
|
cfg.Allocations.DefaultMapping.Ip = getString(data, "allocations", "default", "ip")
|
|
|
|
cfg.Allocations.DefaultMapping.Port = int(getInt(data, "allocations", "default", "port"))
|
2019-11-16 23:10:53 +00:00
|
|
|
|
2019-11-25 04:40:13 +00:00
|
|
|
// Unmarshal the environment variables from the request into the server struct.
|
|
|
|
if b, _, _, err := jsonparser.Get(data, "environment"); err != nil {
|
2021-03-04 04:56:18 +00:00
|
|
|
return nil, errors.WithStackIf(err)
|
2019-11-25 04:40:13 +00:00
|
|
|
} else {
|
2020-08-11 04:38:42 +00:00
|
|
|
cfg.EnvVars = make(environment.Variables)
|
2020-07-19 23:27:55 +00:00
|
|
|
if err := json.Unmarshal(b, &cfg.EnvVars); err != nil {
|
2021-03-04 04:56:18 +00:00
|
|
|
return nil, errors.WrapIf(err, "installer: could not unmarshal environment variables for server")
|
2019-11-16 23:10:53 +00:00
|
|
|
}
|
2019-11-25 04:40:13 +00:00
|
|
|
}
|
2019-11-16 23:10:53 +00:00
|
|
|
|
2019-11-25 04:40:13 +00:00
|
|
|
// Unmarshal the allocation mappings from the request into the server struct.
|
|
|
|
if b, _, _, err := jsonparser.Get(data, "allocations", "mappings"); err != nil {
|
2021-03-04 04:56:18 +00:00
|
|
|
return nil, errors.WithStackIf(err)
|
2019-11-25 04:40:13 +00:00
|
|
|
} else {
|
2020-07-19 23:27:55 +00:00
|
|
|
cfg.Allocations.Mappings = make(map[string][]int)
|
|
|
|
if err := json.Unmarshal(b, &cfg.Allocations.Mappings); err != nil {
|
2021-03-04 04:56:18 +00:00
|
|
|
return nil, errors.Wrap(err, "installer: could not unmarshal allocation mappings")
|
2019-11-16 23:10:53 +00:00
|
|
|
}
|
2019-11-25 04:40:13 +00:00
|
|
|
}
|
2019-11-16 23:10:53 +00:00
|
|
|
|
2020-07-19 23:27:55 +00:00
|
|
|
cfg.Container.Image = getString(data, "container", "image")
|
2019-11-16 23:10:53 +00:00
|
|
|
|
2021-02-02 05:28:46 +00:00
|
|
|
c, err := manager.Client().GetServerConfiguration(ctx, cfg.Uuid)
|
2020-10-31 17:04:20 +00:00
|
|
|
if err != nil {
|
2021-02-02 05:28:46 +00:00
|
|
|
if !remote.IsRequestError(err) {
|
2021-03-04 04:56:18 +00:00
|
|
|
return nil, errors.WithStackIf(err)
|
2020-04-10 22:33:30 +00:00
|
|
|
}
|
2021-03-04 04:56:18 +00:00
|
|
|
return nil, errors.WrapIf(err, "installer: could not get server configuration from remote API")
|
2020-04-10 22:33:30 +00:00
|
|
|
}
|
|
|
|
|
2019-11-16 23:48:50 +00:00
|
|
|
// Create a new server instance using the configuration we wrote to the disk
|
|
|
|
// so that everything gets instantiated correctly on the struct.
|
2021-02-02 05:28:46 +00:00
|
|
|
s, err := manager.InitServer(c)
|
2021-03-04 04:56:18 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, errors.WrapIf(err, "installer: could not init server instance")
|
|
|
|
}
|
|
|
|
return &Installer{server: s}, nil
|
2019-11-16 23:10:53 +00:00
|
|
|
}
|
|
|
|
|
2021-02-02 05:28:46 +00:00
|
|
|
// Uuid returns the UUID associated with this installer instance.
|
2019-11-16 23:10:53 +00:00
|
|
|
func (i *Installer) Uuid() string {
|
2020-07-20 00:53:41 +00:00
|
|
|
return i.server.Id()
|
2019-11-16 23:10:53 +00:00
|
|
|
}
|
|
|
|
|
2021-02-02 05:28:46 +00:00
|
|
|
// Server returns the server instance.
|
2019-11-16 23:48:50 +00:00
|
|
|
func (i *Installer) Server() *server.Server {
|
|
|
|
return i.server
|
|
|
|
}
|
|
|
|
|
2019-11-16 23:10:53 +00:00
|
|
|
// Returns a string value from the JSON data provided.
|
|
|
|
func getString(data []byte, key ...string) string {
|
|
|
|
value, _ := jsonparser.GetString(data, key...)
|
|
|
|
|
|
|
|
return value
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns an int value from the JSON data provided.
|
|
|
|
func getInt(data []byte, key ...string) int64 {
|
|
|
|
value, _ := jsonparser.GetInt(data, key...)
|
|
|
|
|
|
|
|
return value
|
|
|
|
}
|
2020-08-30 16:41:14 +00:00
|
|
|
|
|
|
|
func getBoolean(data []byte, key ...string) bool {
|
|
|
|
value, _ := jsonparser.GetBoolean(data, key...)
|
|
|
|
|
|
|
|
return value
|
|
|
|
}
|