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/gin-gonic/gin v1.9.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/buildkite/shellwords v0.0.0-20180315110454-59467a9b8e10 // indirect
|
||||||
github.com/bytedance/sonic v1.9.1 // indirect
|
github.com/bytedance/sonic v1.9.1 // indirect
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||||
github.com/docker/docker v26.1.2+incompatible // 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.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 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||||
|
@ -4,12 +4,14 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"acooldomain.co/backend/auth"
|
"acooldomain.co/backend/auth"
|
||||||
"acooldomain.co/backend/models"
|
"acooldomain.co/backend/models"
|
||||||
|
"github.com/buildkite/shellwords"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
@ -181,16 +183,27 @@ func (con Connection) CreateServer(ctx *gin.Context) {
|
|||||||
ctx.JSON(200, volumeResponse.Name)
|
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) {
|
func (con Connection) StartServer(ctx *gin.Context) {
|
||||||
serverId := ctx.Param("server_id")
|
serverId := ctx.Param("server_id")
|
||||||
claims, exists := ctx.Get("claims")
|
claims, exists := ctx.Get("claims")
|
||||||
|
var request StartServerRequest
|
||||||
|
json.NewDecoder(ctx.Request.Body).Decode(&request)
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
ctx.AbortWithStatus(403)
|
ctx.AbortWithStatus(403)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// command := ctx.Param("command")
|
|
||||||
|
|
||||||
serverInfo, err := con.getServerInfoFromId(serverId)
|
serverInfo, err := con.getServerInfoFromId(serverId)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -227,7 +240,7 @@ func (con Connection) StartServer(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var portMapping nat.PortMap = make(nat.PortMap)
|
var portMapping nat.PortMap = make(nat.PortMap)
|
||||||
|
if len(request.Ports) == 0 {
|
||||||
for _, port := range serverInfo.Image.Ports {
|
for _, port := range serverInfo.Image.Ports {
|
||||||
dockerPort, err := nat.NewPort(port.Protocol, fmt.Sprint(port.Number))
|
dockerPort, err := nat.NewPort(port.Protocol, fmt.Sprint(port.Number))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -236,6 +249,21 @@ func (con Connection) StartServer(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
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(
|
response, err := con.apiClient.ContainerCreate(
|
||||||
context.Background(),
|
context.Background(),
|
||||||
@ -244,11 +272,12 @@ func (con Connection) StartServer(ctx *gin.Context) {
|
|||||||
AttachStdout: true,
|
AttachStdout: true,
|
||||||
AttachStderr: true,
|
AttachStderr: true,
|
||||||
Tty: true,
|
Tty: true,
|
||||||
OpenStdin: false,
|
OpenStdin: true,
|
||||||
StdinOnce: false,
|
StdinOnce: false,
|
||||||
Image: imageId,
|
Image: imageId,
|
||||||
Volumes: volumes,
|
Volumes: volumes,
|
||||||
Labels: jsonLabels,
|
Labels: jsonLabels,
|
||||||
|
Cmd: words,
|
||||||
},
|
},
|
||||||
&container.HostConfig{
|
&container.HostConfig{
|
||||||
AutoRemove: true,
|
AutoRemove: true,
|
||||||
@ -345,6 +374,60 @@ func (con Connection) StopServer(ctx *gin.Context) {
|
|||||||
ctx.Status(200)
|
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 {
|
func (con Connection) serverAuthorized(permissions models.Permission) func(*gin.Context) bool {
|
||||||
return func(ctx *gin.Context) bool {
|
return func(ctx *gin.Context) bool {
|
||||||
claims, exists := ctx.Get("claims")
|
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.POST("/", auth.AuthorizedTo(models.Create), connection.CreateServer)
|
||||||
group.GET("/", auth.AuthorizedTo(0), connection.GetServers)
|
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/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