Add base code to convert json data into a server object

This is not great code, but wow dealing with JSON is a nightmare in go.
This commit is contained in:
Dane Everitt 2019-11-16 15:10:53 -08:00
parent c9bfb18b1c
commit 22e6ce2f7e
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53
4 changed files with 118 additions and 0 deletions

1
go.mod
View File

@ -6,6 +6,7 @@ require (
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
github.com/Microsoft/go-winio v0.4.7 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 // indirect
github.com/docker/distribution v2.7.1+incompatible // indirect

2
go.sum
View File

@ -4,6 +4,8 @@ github.com/Microsoft/go-winio v0.4.7 h1:vOvDiY/F1avSWlCWiKJjdYKz2jVjTK3pWPHndeG4
github.com/Microsoft/go-winio v0.4.7/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 h1:D21IyuvjDCshj1/qq+pCNd3VZOAEI9jy6Bi131YlXgI=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 h1:PUD50EuOMkXVcpBIA/R95d56duJR9VxhwncsFbNnxW4=

16
http.go
View File

@ -8,6 +8,7 @@ import (
"github.com/buger/jsonparser"
"github.com/gorilla/websocket"
"github.com/julienschmidt/httprouter"
"github.com/pterodactyl/wings/installer"
"github.com/pterodactyl/wings/server"
"go.uber.org/zap"
"io"
@ -391,6 +392,20 @@ func (rt *Router) routeServerSendCommand(w http.ResponseWriter, r *http.Request,
w.WriteHeader(http.StatusNoContent)
}
func (rt *Router) routeCreateServer(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
defer r.Body.Close()
err, inst := installer.New(rt.ReaderToBytes(r.Body))
if err != nil {
zap.S().Warnw("failed to validate the received data", zap.Error(err))
}
inst.Execute()
w.WriteHeader(http.StatusAccepted)
}
func (rt *Router) ReaderToBytes(r io.Reader) []byte {
buf := bytes.Buffer{}
buf.ReadFrom(r)
@ -410,6 +425,7 @@ func (rt *Router) ConfigureRouter() *httprouter.Router {
router.GET("/api/servers/:server/files/contents", rt.AuthenticateRequest(rt.routeServerFileRead))
router.GET("/api/servers/:server/files/list-directory", rt.AuthenticateRequest(rt.routeServerListDirectory))
router.PUT("/api/servers/:server/files/rename", rt.AuthenticateRequest(rt.routeServerRenameFile))
router.POST("/api/servers", rt.AuthenticateToken(rt.routeCreateServer));
router.POST("/api/servers/:server/files/copy", rt.AuthenticateRequest(rt.routeServerCopyFile))
router.POST("/api/servers/:server/files/write", rt.AuthenticateRequest(rt.routeServerWriteFile))
router.POST("/api/servers/:server/files/create-directory", rt.AuthenticateRequest(rt.routeServerCreateDirectory))

99
installer/installer.go Normal file
View File

@ -0,0 +1,99 @@
package installer
import (
"encoding/json"
"errors"
"github.com/asaskevich/govalidator"
"github.com/buger/jsonparser"
"github.com/pterodactyl/wings/server"
"go.uber.org/zap"
)
type Installer struct {
server *server.Server
}
// Validates the received data to ensure that all of the required fields
// have been passed along in the request. This should be manually run before
// calling Execute().
func New(data []byte) (error, *Installer) {
if !govalidator.IsUUIDv4(getString(data, "uuid")) {
return errors.New("uuid provided was not in a valid format"), nil
}
if !govalidator.IsUUIDv4(getString(data, "service", "egg")) {
return errors.New("service egg provided was not in a valid format"), nil
}
s := &server.Server{
Uuid: getString(data, "uuid"),
Suspended: false,
State: server.ProcessOfflineState,
Invocation: "",
EnvVars: make(map[string]string),
Build: &server.BuildSettings{
MemoryLimit: getInt(data, "build", "memory"),
Swap: getInt(data, "build", "swap"),
IoWeight: uint16(getInt(data, "build", "io")),
CpuLimit: getInt(data, "build", "cpu"),
DiskSpace: getInt(data, "build", "disk"),
},
Allocations: &server.Allocations{
Mappings: make(map[string][]int),
},
}
s.Allocations.DefaultMapping.Ip = getString(data, "allocations", "default", "ip")
s.Allocations.DefaultMapping.Port = int(getInt(data, "allocations", "default", "port"))
jsonparser.ObjectEach(data, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error {
s.EnvVars[string(key)] = string(value)
return nil
}, "environment")
jsonparser.ArrayEach(data, func(value []byte, dataType jsonparser.ValueType, offset int, err error) {
var dat map[string][]int
if err := json.Unmarshal(value, &dat); err != nil {
return
}
for i, k := range dat {
s.Allocations.Mappings[i] = k
}
}, "allocations", "mappings")
s.Container.Image = getString(data, "container", "image")
return nil, &Installer{
server: s,
}
}
// Returns the UUID associated with this installer instance.
func (i *Installer) Uuid() string {
return i.server.Uuid
}
// Executes the installer process, creating the server and running through the
// associated installation process based on the parameters passed through for
// the server instance.
func (i *Installer) Execute() error {
zap.S().Debugw("beginning installation process for server", zap.String("server", i.server.Uuid))
return nil
}
// 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
}