attach
This commit is contained in:
parent
343e16a4db
commit
4bffae63b7
1
go.mod
1
go.mod
@ -17,6 +17,7 @@ require (
|
|||||||
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||||
|
github.com/gorilla/websocket v1.5.1 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||||
github.com/leodido/go-urn v1.2.4 // indirect
|
github.com/leodido/go-urn v1.2.4 // indirect
|
||||||
|
2
go.sum
2
go.sum
@ -31,6 +31,8 @@ github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzq
|
|||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||||
|
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -22,6 +23,7 @@ import (
|
|||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
@ -49,6 +51,14 @@ type ImageLabels struct {
|
|||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var upgrader = websocket.Upgrader{
|
||||||
|
ReadBufferSize: 1024,
|
||||||
|
WriteBufferSize: 1024,
|
||||||
|
CheckOrigin: func(r *http.Request) bool {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
jsonData, err := json.Marshal(volume.Labels)
|
jsonData, err := json.Marshal(volume.Labels)
|
||||||
@ -428,6 +438,113 @@ func (con Connection) RunCommand(ctx *gin.Context) {
|
|||||||
ctx.JSON(200, "OK")
|
ctx.JSON(200, "OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Commands struct {
|
||||||
|
CommandType string `json:"command_type"`
|
||||||
|
Arguments []string `json:"arguments"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (con Connection) AttachServer(ctx *gin.Context) {
|
||||||
|
serverId := ctx.Param("server_id")
|
||||||
|
stop := false
|
||||||
|
|
||||||
|
websocketRead := make(chan Commands)
|
||||||
|
containerRead := make(chan string)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
close(websocketRead)
|
||||||
|
close(containerRead)
|
||||||
|
}()
|
||||||
|
|
||||||
|
containers, err := con.apiClient.ContainerList(context.TODO(), container.ListOptions{Filters: filters.NewArgs(filters.Arg("label", "volume_id="+serverId))})
|
||||||
|
if err != nil {
|
||||||
|
ctx.AbortWithError(500, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(containers) == 0 {
|
||||||
|
ctx.AbortWithStatus(404)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hijacked, err := con.apiClient.ContainerAttach(context.Background(), containers[0].ID, container.AttachOptions{Stream: true, Stdin: true, Stdout: true, Stderr: true, Logs: true})
|
||||||
|
if err != nil {
|
||||||
|
ctx.AbortWithError(500, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer hijacked.Close()
|
||||||
|
|
||||||
|
ws, err := upgrader.Upgrade(ctx.Writer, ctx.Request, nil)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer ws.Close()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
data := make([]byte, 0, 1024)
|
||||||
|
for {
|
||||||
|
if stop {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
count, err := hijacked.Reader.Read(data)
|
||||||
|
if err != nil {
|
||||||
|
stop = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if count > 0 {
|
||||||
|
|
||||||
|
log.Println("Got ", count, " bytes: ", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
containerRead <- string(data)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
var command Commands
|
||||||
|
for {
|
||||||
|
if stop {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
err := ws.ReadJSON(&command)
|
||||||
|
if err != nil {
|
||||||
|
command.CommandType = "close"
|
||||||
|
websocketRead <- command
|
||||||
|
break
|
||||||
|
}
|
||||||
|
websocketRead <- command
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
ctx.AbortWithError(500, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case Command := <-websocketRead:
|
||||||
|
switch Command.CommandType {
|
||||||
|
case "insert":
|
||||||
|
_, err = hijacked.Conn.Write([]byte(Command.Arguments[0]))
|
||||||
|
if err != nil {
|
||||||
|
stop = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
case "close":
|
||||||
|
stop = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case data := <-containerRead:
|
||||||
|
err := ws.WriteJSON(data)
|
||||||
|
if err != nil {
|
||||||
|
stop = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
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")
|
||||||
@ -472,4 +589,5 @@ func LoadGroup(group *gin.RouterGroup, mongo_client *mongo.Client) {
|
|||||||
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/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)
|
group.POST("/:server_id/run_command", auth.AuthorizedTo(models.RunCommand, connection.serverAuthorized(models.RunCommand)), connection.RunCommand)
|
||||||
|
group.GET("/:server_id/attach", auth.AuthorizedTo(models.RunCommand, connection.serverAuthorized(models.RunCommand)), connection.AttachServer)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user