added commands
This commit is contained in:
parent
16b6850635
commit
343e16a4db
1
go.mod
1
go.mod
@ -5,6 +5,7 @@ go 1.22.0
|
||||
require github.com/gin-gonic/gin v1.9.1
|
||||
|
||||
require (
|
||||
github.com/buildkite/shellwords v0.0.0-20180315110454-59467a9b8e10 // indirect
|
||||
github.com/bytedance/sonic v1.9.1 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/docker/docker v26.1.2+incompatible // indirect
|
||||
|
2
go.sum
2
go.sum
@ -1,3 +1,5 @@
|
||||
github.com/buildkite/shellwords v0.0.0-20180315110454-59467a9b8e10 h1:XwHQ5xDtYPdtBbVPyRO6UZoWZe8/mbKUb076f8x7RvI=
|
||||
github.com/buildkite/shellwords v0.0.0-20180315110454-59467a9b8e10/go.mod h1:gv0DYOzHEsKgo31lTCDGauIg4DTTGn41Bzp+t3wSOlk=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
|
@ -4,12 +4,14 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"acooldomain.co/backend/auth"
|
||||
"acooldomain.co/backend/models"
|
||||
"github.com/buildkite/shellwords"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
@ -181,16 +183,27 @@ func (con Connection) CreateServer(ctx *gin.Context) {
|
||||
ctx.JSON(200, volumeResponse.Name)
|
||||
}
|
||||
|
||||
type PortMappingRequest struct {
|
||||
Source models.Port
|
||||
Destination models.Port
|
||||
}
|
||||
|
||||
type StartServerRequest struct {
|
||||
Command string `json:"command"`
|
||||
Ports []PortMappingRequest `json:"ports"`
|
||||
}
|
||||
|
||||
func (con Connection) StartServer(ctx *gin.Context) {
|
||||
serverId := ctx.Param("server_id")
|
||||
claims, exists := ctx.Get("claims")
|
||||
var request StartServerRequest
|
||||
json.NewDecoder(ctx.Request.Body).Decode(&request)
|
||||
|
||||
if !exists {
|
||||
ctx.AbortWithStatus(403)
|
||||
return
|
||||
}
|
||||
|
||||
// command := ctx.Param("command")
|
||||
|
||||
serverInfo, err := con.getServerInfoFromId(serverId)
|
||||
|
||||
if err != nil {
|
||||
@ -227,14 +240,29 @@ func (con Connection) StartServer(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
var portMapping nat.PortMap = make(nat.PortMap)
|
||||
|
||||
for _, port := range serverInfo.Image.Ports {
|
||||
dockerPort, err := nat.NewPort(port.Protocol, fmt.Sprint(port.Number))
|
||||
if err != nil {
|
||||
ctx.AbortWithError(500, err)
|
||||
return
|
||||
if len(request.Ports) == 0 {
|
||||
for _, port := range serverInfo.Image.Ports {
|
||||
dockerPort, err := nat.NewPort(port.Protocol, fmt.Sprint(port.Number))
|
||||
if err != nil {
|
||||
ctx.AbortWithError(500, err)
|
||||
return
|
||||
}
|
||||
portMapping[dockerPort] = []nat.PortBinding{{HostIP: "0.0.0.0"}}
|
||||
}
|
||||
portMapping[dockerPort] = []nat.PortBinding{{HostIP: "0.0.0.0"}}
|
||||
} else {
|
||||
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)}}
|
||||
}
|
||||
}
|
||||
|
||||
words, err := shellwords.Split(request.Command)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(500, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(words) == 0 {
|
||||
words = nil
|
||||
}
|
||||
|
||||
response, err := con.apiClient.ContainerCreate(
|
||||
@ -244,11 +272,12 @@ func (con Connection) StartServer(ctx *gin.Context) {
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
Tty: true,
|
||||
OpenStdin: false,
|
||||
OpenStdin: true,
|
||||
StdinOnce: false,
|
||||
Image: imageId,
|
||||
Volumes: volumes,
|
||||
Labels: jsonLabels,
|
||||
Cmd: words,
|
||||
},
|
||||
&container.HostConfig{
|
||||
AutoRemove: true,
|
||||
@ -345,6 +374,60 @@ func (con Connection) StopServer(ctx *gin.Context) {
|
||||
ctx.Status(200)
|
||||
}
|
||||
|
||||
func (con Connection) DeleteServer(ctx *gin.Context) {
|
||||
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))})
|
||||
if err != nil {
|
||||
ctx.AbortWithError(500, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, containerInstance := range containers {
|
||||
con.apiClient.ContainerStop(context.Background(), containerInstance.ID, container.StopOptions{})
|
||||
err := con.apiClient.ContainerRemove(context.Background(), containerInstance.ID, container.RemoveOptions{Force: true, RemoveLinks: true})
|
||||
if err != nil {
|
||||
ctx.AbortWithError(500, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
con.apiClient.VolumeRemove(context.Background(), serverId, false)
|
||||
ctx.JSON(200, "ok")
|
||||
}
|
||||
|
||||
type RunCommandRequest struct {
|
||||
Command string `json:"command"`
|
||||
}
|
||||
|
||||
func (con Connection) RunCommand(ctx *gin.Context) {
|
||||
var request RunCommandRequest
|
||||
err := json.NewDecoder(ctx.Request.Body).Decode(&request)
|
||||
serverId := ctx.Param("server_id")
|
||||
log.Print("Writing command \"", request.Command, "\"")
|
||||
containers, err := con.apiClient.ContainerList(context.Background(), container.ListOptions{Filters: filters.NewArgs(filters.Arg("label", "volume_id="+serverId))})
|
||||
if err != nil {
|
||||
ctx.AbortWithError(500, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, containerData := range containers {
|
||||
hijacked, err := con.apiClient.ContainerAttach(context.Background(), containerData.ID, container.AttachOptions{Stream: true, Stdin: true})
|
||||
defer func() { hijacked.Close(); hijacked.CloseWrite() }()
|
||||
if err != nil {
|
||||
ctx.AbortWithError(500, err)
|
||||
return
|
||||
}
|
||||
number, err := hijacked.Conn.Write([]byte(request.Command + "\n"))
|
||||
log.Print("Wrote ", number, " bytes")
|
||||
if err != nil {
|
||||
ctx.AbortWithError(500, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ctx.JSON(200, "OK")
|
||||
}
|
||||
|
||||
func (con Connection) serverAuthorized(permissions models.Permission) func(*gin.Context) bool {
|
||||
return func(ctx *gin.Context) bool {
|
||||
claims, exists := ctx.Get("claims")
|
||||
@ -387,4 +470,6 @@ func LoadGroup(group *gin.RouterGroup, mongo_client *mongo.Client) {
|
||||
group.POST("/", auth.AuthorizedTo(models.Create), connection.CreateServer)
|
||||
group.GET("/", auth.AuthorizedTo(0), connection.GetServers)
|
||||
group.POST("/:server_id/stop", auth.AuthorizedTo(models.Stop, connection.serverAuthorized(models.Stop)), connection.StopServer)
|
||||
group.POST("/:server_id/delete", auth.AuthorizedTo(models.Delete, connection.serverAuthorized(models.Delete)), connection.DeleteServer)
|
||||
group.POST("/:server_id/run_command", auth.AuthorizedTo(models.RunCommand, connection.serverAuthorized(models.RunCommand)), connection.RunCommand)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user