Added more data to message info

This commit is contained in:
ACoolName 2024-05-15 21:54:30 +03:00
parent 4bffae63b7
commit 3c08208a60
2 changed files with 100 additions and 56 deletions

View File

@ -14,6 +14,7 @@ type ImageInfo struct {
type ServerInfo struct { type ServerInfo struct {
Id string Id string
OwnerId string OwnerId string
DefaultCommand string
Image ImageInfo Image ImageInfo
On bool On bool
Nickname string Nickname string
@ -33,4 +34,6 @@ type ServerData struct {
VolumeId string VolumeId string
Nickname string Nickname string
UserPermissions map[string]Permission UserPermissions map[string]Permission
DefaultCommand string
DefaultPorts []Port
} }

View File

@ -61,33 +61,51 @@ var upgrader = websocket.Upgrader{
func (con Connection) getServerInfo(volume volume.Volume) (*models.ServerInfo, error) { func (con Connection) getServerInfo(volume volume.Volume) (*models.ServerInfo, error) {
var volumeLabels VolumeLabels var volumeLabels VolumeLabels
var serverData models.ServerData
con.connection.Database("Backend").Collection("Servers").FindOne(context.TODO(), bson.D{{Key: "id", Value: volume.Name}}).Decode(&serverData)
jsonData, err := json.Marshal(volume.Labels) jsonData, err := json.Marshal(volume.Labels)
if err != nil {
return nil, err
}
err = json.Unmarshal(jsonData, &volumeLabels)
if err != nil {
return nil, err
}
var imagePorts []models.Port
if len(serverData.DefaultPorts) == 0 {
imageList, err := con.apiClient.ImageList(context.TODO(), image.ListOptions{Filters: filters.NewArgs(filters.Arg("reference", volumeLabels.ImageId))})
if err != nil { if err != nil {
return nil, err return nil, err
} }
json.Unmarshal(jsonData, &volumeLabels)
imageList, err := con.apiClient.ImageList(context.Background(), image.ListOptions{Filters: filters.NewArgs(filters.Arg("reference", volumeLabels.ImageId))})
if len(imageList) == 0 { if len(imageList) == 0 {
return nil, fmt.Errorf("ImageId %s does not exist", volumeLabels.ImageId) return nil, fmt.Errorf("ImageId %s does not exist", volumeLabels.ImageId)
} }
imageSummery := imageList[0] imageSummery := imageList[0]
imageInspect, _, err := con.apiClient.ImageInspectWithRaw(context.Background(), imageSummery.ID) imageInspect, _, err := con.apiClient.ImageInspectWithRaw(context.TODO(), imageSummery.ID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var imagePorts []models.Port = make([]models.Port, len(imageInspect.Config.ExposedPorts)) imagePorts = make([]models.Port, len(imageInspect.Config.ExposedPorts))
i := 0 i := 0
for imagePort := range imageInspect.Config.ExposedPorts { for imagePort := range imageInspect.Config.ExposedPorts {
imagePorts[i] = models.Port{Protocol: imagePort.Proto(), Number: imagePort.Int()} imagePorts[i] = models.Port{Protocol: imagePort.Proto(), Number: imagePort.Int()}
i += 1 i += 1
} }
} else {
imagePorts = serverData.DefaultPorts
}
imageNameAndVersion := strings.Split(volumeLabels.ImageId, ":") imageNameAndVersion := strings.Split(volumeLabels.ImageId, ":")
imageName := imageNameAndVersion[0] imageName := imageNameAndVersion[0]
imageVersion := imageNameAndVersion[1] imageVersion := imageNameAndVersion[1]
containers, err := con.apiClient.ContainerList(context.Background(), container.ListOptions{ containers, err := con.apiClient.ContainerList(context.TODO(), container.ListOptions{
All: true, All: true,
Filters: filters.NewArgs(filters.Arg("label", "type=GAME"), filters.Arg("label", fmt.Sprintf("volume_id=%s", volume.Name))), Filters: filters.NewArgs(filters.Arg("label", "type=GAME"), filters.Arg("label", fmt.Sprintf("volume_id=%s", volume.Name))),
}) })
@ -101,8 +119,6 @@ func (con Connection) getServerInfo(volume volume.Volume) (*models.ServerInfo, e
state = container.State == "running" state = container.State == "running"
ports = transformContainerPortsToModel(container.Ports) ports = transformContainerPortsToModel(container.Ports)
} }
var serverData models.ServerData
con.connection.Database("backend").Collection("servers").FindOne(context.TODO(), bson.D{{Key: "volume_id", Value: volume.Name}}).Decode(&serverData)
serverInfo := models.ServerInfo{ serverInfo := models.ServerInfo{
Id: volume.Name, Id: volume.Name,
@ -115,13 +131,14 @@ func (con Connection) getServerInfo(volume volume.Volume) (*models.ServerInfo, e
On: state, On: state,
Ports: ports, Ports: ports,
Nickname: serverData.Nickname, Nickname: serverData.Nickname,
DefaultCommand: serverData.DefaultCommand,
} }
return &serverInfo, nil return &serverInfo, nil
} }
func (con Connection) getServerInfoFromId(ServerId string) (*models.ServerInfo, error) { func (con Connection) getServerInfoFromId(ServerId string) (*models.ServerInfo, error) {
volume, err := con.apiClient.VolumeInspect(context.Background(), ServerId) volume, err := con.apiClient.VolumeInspect(context.TODO(), ServerId)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -152,6 +169,8 @@ func convertLabelsToMap(v any) (map[string]string, error) {
type CreateServerRequest struct { type CreateServerRequest struct {
ImageId string `json:"image_id"` ImageId string `json:"image_id"`
DefaultPorts []models.Port `json:"default_ports"`
DefaultCommand string `json:"default_command"`
} }
func (con Connection) CreateServer(ctx *gin.Context) { func (con Connection) CreateServer(ctx *gin.Context) {
@ -167,7 +186,7 @@ func (con Connection) CreateServer(ctx *gin.Context) {
return return
} }
imageList, err := con.apiClient.ImageList(context.Background(), image.ListOptions{All: true, Filters: filters.NewArgs(filters.Arg("reference", request.ImageId))}) imageList, err := con.apiClient.ImageList(context.TODO(), image.ListOptions{All: true, Filters: filters.NewArgs(filters.Arg("reference", request.ImageId))})
if err != nil { if err != nil {
ctx.AbortWithError(400, err) ctx.AbortWithError(400, err)
return return
@ -182,13 +201,21 @@ func (con Connection) CreateServer(ctx *gin.Context) {
ctx.AbortWithError(400, err) ctx.AbortWithError(400, err)
return return
} }
volumeResponse, err := con.apiClient.VolumeCreate(context.Background(), volume.CreateOptions{ volumeResponse, err := con.apiClient.VolumeCreate(context.TODO(), volume.CreateOptions{
Labels: labels, Labels: labels,
}) })
if err != nil { if err != nil {
ctx.AbortWithError(500, err) ctx.AbortWithError(500, err)
return return
} }
con.connection.Database("Backend").Collection("Servers").InsertOne(context.TODO(), models.ServerData{
Id: volumeResponse.Name,
OwnerId: claims.(*auth.AuthClaims).Username,
Image: imageSummary.RepoTags[0],
VolumeId: volumeResponse.Name,
DefaultPorts: request.DefaultPorts,
DefaultCommand: request.DefaultCommand,
})
ctx.JSON(200, volumeResponse.Name) ctx.JSON(200, volumeResponse.Name)
} }
@ -225,6 +252,7 @@ func (con Connection) StartServer(ctx *gin.Context) {
ctx.Status(200) ctx.Status(200)
return return
} }
imageId := serverInfo.Image.Name + ":" + serverInfo.Image.Version imageId := serverInfo.Image.Name + ":" + serverInfo.Image.Version
labels := ContainerLabels{ labels := ContainerLabels{
OwnerId: claims.(*auth.AuthClaims).Username, OwnerId: claims.(*auth.AuthClaims).Username,
@ -243,7 +271,7 @@ func (con Connection) StartServer(ctx *gin.Context) {
volumes := make(map[string]struct{}) volumes := make(map[string]struct{})
image, _, err := con.apiClient.ImageInspectWithRaw(context.Background(), imageId) image, _, err := con.apiClient.ImageInspectWithRaw(context.TODO(), imageId)
if err != nil { if err != nil {
ctx.AbortWithError(500, err) ctx.AbortWithError(500, err)
return return
@ -261,7 +289,7 @@ func (con Connection) StartServer(ctx *gin.Context) {
} }
} else { } else {
for _, portCouple := range request.Ports { for _, portCouple := range request.Ports {
portMapping[nat.Port(fmt.Sprintf("%d/%s", portCouple.Source.Number, portCouple.Source.Protocol))] = []nat.PortBinding{{HostPort: fmt.Sprint(portCouple.Destination.Number)}} portMapping[nat.Port(fmt.Sprintf("%d/%s", portCouple.Source.Number, portCouple.Source.Protocol))] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: fmt.Sprint(portCouple.Destination.Number)}}
} }
} }
@ -274,9 +302,12 @@ func (con Connection) StartServer(ctx *gin.Context) {
if len(words) == 0 { if len(words) == 0 {
words = nil words = nil
} }
portSet := make(nat.PortSet)
for port, _ := range portMapping {
portSet[port] = struct{}{}
}
response, err := con.apiClient.ContainerCreate( response, err := con.apiClient.ContainerCreate(
context.Background(), context.TODO(),
&container.Config{ &container.Config{
AttachStdin: true, AttachStdin: true,
AttachStdout: true, AttachStdout: true,
@ -288,6 +319,7 @@ func (con Connection) StartServer(ctx *gin.Context) {
Volumes: volumes, Volumes: volumes,
Labels: jsonLabels, Labels: jsonLabels,
Cmd: words, Cmd: words,
ExposedPorts: portSet,
}, },
&container.HostConfig{ &container.HostConfig{
AutoRemove: true, AutoRemove: true,
@ -310,7 +342,7 @@ func (con Connection) StartServer(ctx *gin.Context) {
HostIP, hostIPexists := os.LookupEnv("HOST_IP") HostIP, hostIPexists := os.LookupEnv("HOST_IP")
if exists && hostIPexists { if exists && hostIPexists {
time.Sleep(time.Millisecond * 100) time.Sleep(time.Millisecond * 100)
containerData, err := con.apiClient.ContainerInspect(context.Background(), response.ID) containerData, err := con.apiClient.ContainerInspect(context.TODO(), response.ID)
if err != nil { if err != nil {
ctx.AbortWithError(500, err) ctx.AbortWithError(500, err)
return return
@ -366,7 +398,7 @@ func (con Connection) GetServers(ctx *gin.Context) {
func (con Connection) StopServer(ctx *gin.Context) { func (con Connection) StopServer(ctx *gin.Context) {
serverId := ctx.Param("server_id") serverId := ctx.Param("server_id")
containersList, err := con.apiClient.ContainerList(context.Background(), container.ListOptions{ containersList, err := con.apiClient.ContainerList(context.TODO(), container.ListOptions{
Filters: filters.NewArgs(filters.Arg("label", "volume_id="+serverId), filters.Arg("label", "type=GAME")), Filters: filters.NewArgs(filters.Arg("label", "volume_id="+serverId), filters.Arg("label", "type=GAME")),
}) })
if err != nil { if err != nil {
@ -379,29 +411,31 @@ func (con Connection) StopServer(ctx *gin.Context) {
} }
for _, containerData := range containersList { for _, containerData := range containersList {
con.apiClient.ContainerStop(context.Background(), containerData.ID, container.StopOptions{}) con.apiClient.ContainerStop(context.TODO(), containerData.ID, container.StopOptions{})
} }
ctx.Status(200) ctx.Status(200)
} }
func (con Connection) DeleteServer(ctx *gin.Context) { func (con Connection) DeleteServer(ctx *gin.Context) {
serverId := ctx.Param("server_id") serverId := ctx.Param("server_id")
containers, err := con.apiClient.ContainerList(context.Background(), container.ListOptions{All: true, Filters: filters.NewArgs(filters.Arg("label", "volume_id="+serverId))}) containers, err := con.apiClient.ContainerList(context.TODO(), container.ListOptions{All: true, Filters: filters.NewArgs(filters.Arg("label", "volume_id="+serverId))})
if err != nil { if err != nil {
ctx.AbortWithError(500, err) ctx.AbortWithError(500, err)
return return
} }
for _, containerInstance := range containers { for _, containerInstance := range containers {
con.apiClient.ContainerStop(context.Background(), containerInstance.ID, container.StopOptions{}) con.apiClient.ContainerStop(context.TODO(), containerInstance.ID, container.StopOptions{})
err := con.apiClient.ContainerRemove(context.Background(), containerInstance.ID, container.RemoveOptions{Force: true, RemoveLinks: true}) err := con.apiClient.ContainerRemove(context.TODO(), containerInstance.ID, container.RemoveOptions{Force: true, RemoveLinks: true})
if err != nil { if err != nil {
ctx.AbortWithError(500, err) ctx.AbortWithError(500, err)
return return
} }
} }
con.apiClient.VolumeRemove(context.Background(), serverId, false) con.apiClient.VolumeRemove(context.TODO(), serverId, false)
con.connection.Database("Backend").Collection("Servers").FindOneAndDelete(context.TODO(), bson.D{{Key: "id", Value: serverId}})
ctx.JSON(200, "ok") ctx.JSON(200, "ok")
} }
@ -412,16 +446,20 @@ type RunCommandRequest struct {
func (con Connection) RunCommand(ctx *gin.Context) { func (con Connection) RunCommand(ctx *gin.Context) {
var request RunCommandRequest var request RunCommandRequest
err := json.NewDecoder(ctx.Request.Body).Decode(&request) err := json.NewDecoder(ctx.Request.Body).Decode(&request)
if err != nil {
ctx.AbortWithError(500, err)
}
serverId := ctx.Param("server_id") serverId := ctx.Param("server_id")
log.Print("Writing command \"", request.Command, "\"") log.Print("Writing command \"", request.Command, "\"")
containers, err := con.apiClient.ContainerList(context.Background(), container.ListOptions{Filters: filters.NewArgs(filters.Arg("label", "volume_id="+serverId))}) containers, err := con.apiClient.ContainerList(context.TODO(), container.ListOptions{Filters: filters.NewArgs(filters.Arg("label", "volume_id="+serverId))})
if err != nil { if err != nil {
ctx.AbortWithError(500, err) ctx.AbortWithError(500, err)
return return
} }
for _, containerData := range containers { for _, containerData := range containers {
hijacked, err := con.apiClient.ContainerAttach(context.Background(), containerData.ID, container.AttachOptions{Stream: true, Stdin: true}) hijacked, err := con.apiClient.ContainerAttach(context.TODO(), containerData.ID, container.AttachOptions{Stream: true, Stdin: true})
defer func() { hijacked.Close(); hijacked.CloseWrite() }() defer func() { hijacked.Close(); hijacked.CloseWrite() }()
if err != nil { if err != nil {
ctx.AbortWithError(500, err) ctx.AbortWithError(500, err)
@ -464,7 +502,7 @@ func (con Connection) AttachServer(ctx *gin.Context) {
ctx.AbortWithStatus(404) ctx.AbortWithStatus(404)
return return
} }
hijacked, err := con.apiClient.ContainerAttach(context.Background(), containers[0].ID, container.AttachOptions{Stream: true, Stdin: true, Stdout: true, Stderr: true, Logs: true}) hijacked, err := con.apiClient.ContainerAttach(context.TODO(), containers[0].ID, container.AttachOptions{Stream: true, Stdin: true, Stdout: true, Stderr: true, Logs: true})
if err != nil { if err != nil {
ctx.AbortWithError(500, err) ctx.AbortWithError(500, err)
return return
@ -478,7 +516,7 @@ func (con Connection) AttachServer(ctx *gin.Context) {
defer ws.Close() defer ws.Close()
go func() { go func() {
data := make([]byte, 0, 1024) data := make([]byte, 1024)
for { for {
if stop { if stop {
break break
@ -490,10 +528,10 @@ func (con Connection) AttachServer(ctx *gin.Context) {
} }
if count > 0 { if count > 0 {
log.Println("Got ", count, " bytes: ", data) log.Println("Got ", count, " bytes: ", string(data[:count]))
containerRead <- string(data[:count])
} }
containerRead <- string(data)
} }
}() }()
@ -520,6 +558,10 @@ func (con Connection) AttachServer(ctx *gin.Context) {
} }
for { for {
if stop {
break
}
select { select {
case Command := <-websocketRead: case Command := <-websocketRead:
switch Command.CommandType { switch Command.CommandType {
@ -532,13 +574,12 @@ func (con Connection) AttachServer(ctx *gin.Context) {
case "close": case "close":
stop = true stop = true
break
} }
case data := <-containerRead: case data := <-containerRead:
err := ws.WriteJSON(data) err := ws.WriteJSON(data)
if err != nil { if err != nil {
stop = true stop = true
break
} }
} }
} }
@ -559,7 +600,7 @@ func (con Connection) serverAuthorized(permissions models.Permission) func(*gin.
var serverData models.ServerData var serverData models.ServerData
con.connection.Database("Backend").Collection("Servers").FindOne(context.Background(), bson.D{{Key: "ServerId", Value: server_id}}).Decode(&serverData) con.connection.Database("Backend").Collection("Servers").FindOne(context.TODO(), bson.D{{Key: "id", Value: server_id}}).Decode(&serverData)
if serverData.OwnerId == claims.(*auth.AuthClaims).Username { if serverData.OwnerId == claims.(*auth.AuthClaims).Username {
return true return true