basic docker impl
This commit is contained in:
parent
2212eee35a
commit
9f19744dce
@ -4,22 +4,43 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
instancemanager "git.acooldomain.co/server-manager/backend-kubernetes-go/instance_manager"
|
||||
"git.acooldomain.co/server-manager/backend-kubernetes-go/models"
|
||||
"github.com/buildkite/shellwords"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/go-connections/nat"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type InstanceManager struct {
|
||||
instancemanager.InstanceManager
|
||||
client client.Client
|
||||
config models.DockerInstanceManagerConfig
|
||||
}
|
||||
|
||||
func (self *InstanceManager) containerList(ctx context.Context, labels ContainerLabels, all bool) ([]types.Container, error) {
|
||||
filters, err := convertLabelsToFilter(labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
containers, err := self.client.ContainerList(ctx, container.ListOptions{Filters: *filters, All: all})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return containers, nil
|
||||
}
|
||||
|
||||
func (self *InstanceManager) getVolume(ctx context.Context, serverId string) (*volume.Volume, error) {
|
||||
@ -27,14 +48,8 @@ func (self *InstanceManager) getVolume(ctx context.Context, serverId string) (*v
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var labels VolumeLabels
|
||||
|
||||
rawLabels, err := json.Marshal(volume.Labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(rawLabels, &labels)
|
||||
labels, err := convertVolumeLabelsToStruct(volume.Labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -46,30 +61,6 @@ func (self *InstanceManager) getVolume(ctx context.Context, serverId string) (*v
|
||||
return &volume, err
|
||||
}
|
||||
|
||||
func convertImagePortsToPorts(rawPorts nat.PortSet) []instancemanager.Port {
|
||||
ports := make([]instancemanager.Port, len(rawPorts))
|
||||
i := 0
|
||||
for imagePort := range rawPorts {
|
||||
portNumber := imagePort.Int()
|
||||
var protocol models.PortProtocol
|
||||
switch imagePort.Proto() {
|
||||
case "TCP":
|
||||
protocol = models.TCP
|
||||
case "UDP":
|
||||
protocol = models.UDP
|
||||
default:
|
||||
log.Default().Println(fmt.Sprintf("Unknown port protocol %s using TCP", imagePort.Proto()))
|
||||
protocol = models.TCP
|
||||
}
|
||||
ports[i] = instancemanager.Port{
|
||||
Number: uint16(portNumber),
|
||||
Protocol: protocol,
|
||||
}
|
||||
i++
|
||||
}
|
||||
return ports
|
||||
}
|
||||
|
||||
// General
|
||||
// Read Only
|
||||
func (self *InstanceManager) ListImages(ctx context.Context) ([]instancemanager.Image, error) {
|
||||
@ -108,17 +99,12 @@ func (self *InstanceManager) GetServer(ctx context.Context, serverId string) (*i
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filterArgs, err := convertLabelsToFilter(ContainerLabels{
|
||||
VolumeId: volume.Name,
|
||||
Type: Game,
|
||||
})
|
||||
|
||||
serverContainers, err := self.client.ContainerList(
|
||||
serverContainers, err := self.containerList(
|
||||
ctx,
|
||||
container.ListOptions{
|
||||
Filters: *filterArgs,
|
||||
ContainerLabels{
|
||||
VolumeId: serverId,
|
||||
},
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -136,17 +122,6 @@ func (self *InstanceManager) GetServer(ctx context.Context, serverId string) (*i
|
||||
|
||||
serverContainer := serverContainers[0]
|
||||
|
||||
var containerLabels ContainerLabels
|
||||
|
||||
rawContainerLabels, err := json.Marshal(serverContainer.Labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = json.Unmarshal(rawContainerLabels, &containerLabels); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
running := serverContainer.State == "running"
|
||||
|
||||
runningCommand := serverContainer.Command
|
||||
@ -167,11 +142,6 @@ func (self *InstanceManager) ListServers(ctx context.Context) ([]instancemanager
|
||||
return nil, err
|
||||
}
|
||||
|
||||
containerFilters, err := convertLabelsToFilter(ContainerLabels{Type: Game})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
volumes, err := self.client.VolumeList(ctx, volume.ListOptions{Filters: *volumeFilter})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -189,7 +159,7 @@ func (self *InstanceManager) ListServers(ctx context.Context) ([]instancemanager
|
||||
}
|
||||
}
|
||||
|
||||
containers, err := self.client.ContainerList(ctx, container.ListOptions{Filters: *containerFilters})
|
||||
containers, err := self.containerList(ctx, ContainerLabels{Type: Game}, false)
|
||||
|
||||
for _, container := range containers {
|
||||
rawLabels, err := json.Marshal(container.Labels)
|
||||
@ -227,52 +197,358 @@ func (self *InstanceManager) ListServers(ctx context.Context) ([]instancemanager
|
||||
}
|
||||
|
||||
// State Changing
|
||||
func (self *InstanceManager) StartServer(ctx context.Context, serverId string, command string, ports []models.Port) error {
|
||||
func (self *InstanceManager) StartServer(ctx context.Context, serverId string, image instancemanager.Image, command string, ports []models.Port) error {
|
||||
server, err := self.GetServer(ctx, serverId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if server.Running {
|
||||
return fmt.Errorf("Server %s already running", serverId)
|
||||
}
|
||||
|
||||
imageId := image.Registry + ":" + image.Tag
|
||||
containerLabels := ContainerLabels{
|
||||
VolumeId: server.Id,
|
||||
Type: "GAME",
|
||||
}
|
||||
|
||||
volumes := make(map[string]struct{})
|
||||
|
||||
var portMapping nat.PortMap = make(nat.PortMap)
|
||||
|
||||
if len(ports) == 0 {
|
||||
for _, port := range image.Ports {
|
||||
dockerPort, err := nat.NewPort(string(port.Protocol), fmt.Sprint(port.Number))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
portMapping[dockerPort] = []nat.PortBinding{{HostIP: "0.0.0.0"}}
|
||||
}
|
||||
} else {
|
||||
for _, portCouple := range ports {
|
||||
portMapping[nat.Port(fmt.Sprintf("%d/%s", portCouple.ContainerPort, portCouple.Protocol))] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: fmt.Sprint(portCouple.PublicPort)}}
|
||||
}
|
||||
}
|
||||
|
||||
rawImage, _, err := self.client.ImageInspectWithRaw(ctx, imageId)
|
||||
|
||||
if command == "" {
|
||||
command = image.Command
|
||||
}
|
||||
|
||||
words, err := shellwords.Split(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(words) == 0 {
|
||||
words = nil
|
||||
}
|
||||
|
||||
portSet := make(nat.PortSet)
|
||||
for port := range portMapping {
|
||||
portSet[port] = struct{}{}
|
||||
}
|
||||
|
||||
labels, err := convertLabelsToMap(containerLabels)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
createdContainer, err := self.client.ContainerCreate(
|
||||
context.TODO(),
|
||||
&container.Config{
|
||||
AttachStdin: true,
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
Tty: true,
|
||||
OpenStdin: true,
|
||||
StdinOnce: false,
|
||||
Image: imageId,
|
||||
Volumes: volumes,
|
||||
Labels: *labels,
|
||||
Cmd: words,
|
||||
ExposedPorts: portSet,
|
||||
},
|
||||
&container.HostConfig{
|
||||
AutoRemove: true,
|
||||
Mounts: []mount.Mount{{Source: server.Id, Target: rawImage.Config.WorkingDir, Type: "volume"}},
|
||||
PortBindings: portMapping,
|
||||
ConsoleSize: [2]uint{1000, 1000},
|
||||
},
|
||||
&network.NetworkingConfig{},
|
||||
&v1.Platform{},
|
||||
"",
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = self.client.ContainerStart(ctx, createdContainer.ID, container.StartOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
func (self *InstanceManager) StopServer(ctx context.Context, serverId string) error {
|
||||
runningContainers, err := self.containerList(ctx, ContainerLabels{VolumeId: serverId, Type: Game}, false)
|
||||
|
||||
for _, rawContainer := range runningContainers {
|
||||
err = self.client.ContainerStop(ctx, rawContainer.ID, container.StopOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *InstanceManager) CreateServer(ctx context.Context, image models.Image) (*instancemanager.Server, error) {
|
||||
func (self *InstanceManager) CreateServer(ctx context.Context) (*instancemanager.Server, error) {
|
||||
labels, err := convertLabelsToMap(VolumeLabels{
|
||||
Type: Game,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
volume, err := self.client.VolumeCreate(ctx, volume.CreateOptions{
|
||||
Labels: *labels,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &instancemanager.Server{
|
||||
Id: volume.Name,
|
||||
Running: false,
|
||||
RunningImage: nil,
|
||||
RunningCommand: "",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (self *InstanceManager) DeleteServer(ctx context.Context, serverId string) error {
|
||||
server, err := self.GetServer(ctx, serverId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if server.Running {
|
||||
err = self.StopServer(ctx, server.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = self.StopFileBrowser(ctx, server.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = self.client.VolumeRemove(ctx, server.Id, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Terminal
|
||||
|
||||
// Read Only
|
||||
func (self *InstanceManager) GetLogs(ctx context.Context, serverId string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Status Changing
|
||||
func (self *InstanceManager) InteractiveTerminal(ctx context.Context, serverId string) (*net.Conn, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (self *InstanceManager) RunCommand(ctx context.Context, serverId string, command string) (string, error) {
|
||||
server, err := self.GetServer(ctx, serverId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return "", nil
|
||||
if !server.Running {
|
||||
return nil, fmt.Errorf("Server %s not running", server.Id)
|
||||
}
|
||||
|
||||
rawContainers, err := self.containerList(ctx, ContainerLabels{VolumeId: serverId, Type: Game}, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(rawContainers) == 0 {
|
||||
return nil, fmt.Errorf("Server %s not running and wasn't caught", server.Id)
|
||||
}
|
||||
|
||||
rawContainer := rawContainers[0]
|
||||
|
||||
attach, err := self.client.ContainerAttach(ctx,
|
||||
rawContainer.ID,
|
||||
container.AttachOptions{Stream: true,
|
||||
Stdin: true,
|
||||
Stdout: true,
|
||||
Stderr: true,
|
||||
Logs: true,
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &attach.Conn, nil
|
||||
}
|
||||
|
||||
func (self *InstanceManager) ResizeTerminal(ctx context.Context, serverId string, width uint, height uint) error {
|
||||
containers, err := self.containerList(ctx, ContainerLabels{VolumeId: serverId, Type: Game}, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(containers) == 0 {
|
||||
return fmt.Errorf("Server %s not running", serverId)
|
||||
}
|
||||
|
||||
err = self.client.ContainerResize(context.TODO(), containers[0].ID, container.ResizeOptions{Height: height, Width: width})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// File Browser
|
||||
|
||||
// Read Only
|
||||
func (self *InstanceManager) GetFileBrowser(ctx context.Context, serverId string) (*models.FileBrowser, error) {
|
||||
return nil, nil
|
||||
containers, err := self.containerList(ctx, ContainerLabels{VolumeId: serverId, Type: FileBrowser}, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(containers) == 0 {
|
||||
return nil, fmt.Errorf("File Browser for server %s is not running", serverId)
|
||||
}
|
||||
|
||||
rawContainer := containers[0]
|
||||
|
||||
containerLabels, err := convertContainerLabelsToStruct(rawContainer.Labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &models.FileBrowser{
|
||||
Url: containerLabels.VolumeId[:12] + "." + self.config.BrowsersDomain,
|
||||
Id: rawContainer.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (self *InstanceManager) ListFileBrowsers(ctx context.Context) ([]models.FileBrowser, error) {
|
||||
return nil, nil
|
||||
containers, err := self.containerList(ctx, ContainerLabels{Type: FileBrowser}, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fileBrowsers := make([]models.FileBrowser, len(containers))
|
||||
|
||||
for i, rawContainer := range containers {
|
||||
containerLabels, err := convertContainerLabelsToStruct(rawContainer.Labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fileBrowsers[i] = models.FileBrowser{
|
||||
Url: containerLabels.VolumeId[:12] + "." + self.config.BrowsersDomain,
|
||||
Id: rawContainer.ID,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return fileBrowsers, nil
|
||||
}
|
||||
|
||||
// Status Changing
|
||||
func (self *InstanceManager) StartFileBrowser(ctx context.Context, serverId string) (*models.FileBrowser, error) {
|
||||
return nil, nil
|
||||
server, err := self.GetServer(ctx, serverId)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
labelId := serverId[:12]
|
||||
|
||||
browserLabels := make(map[string]string)
|
||||
browserLabels["traefik.enable"] = "true"
|
||||
browserLabels[fmt.Sprintf("traefik.http.routers.%s.rule", labelId)] = fmt.Sprintf("Host(`%s.browsers.%s`)", labelId, self.config.BrowsersDomain)
|
||||
browserLabels[fmt.Sprintf("traefik.http.routers.%s.entrypoints", labelId)] = "websecure"
|
||||
browserLabels[fmt.Sprintf("traefik.http.routers.%s.middlewares", labelId)] = "games@docker"
|
||||
browserLabels[fmt.Sprintf("traefik.http.routers.%s.tls.domains[0].main", labelId)] = fmt.Sprintf("%s.%s", "browsers", self.config.BrowsersDomain)
|
||||
browserLabels[fmt.Sprintf("traefik.http.routers.%s.tls.domains[0].sans", labelId)] = fmt.Sprintf("*.%s.%s", "browsers", self.config.BrowsersDomain)
|
||||
browserLabels[fmt.Sprintf("traefik.http.routers.%s.tls.certresolver", labelId)] = "myresolver"
|
||||
|
||||
containerConfig, err := convertLabelsToMap(ContainerLabels{VolumeId: serverId, Type: FileBrowser})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for key, value := range *containerConfig {
|
||||
browserLabels[key] = value
|
||||
}
|
||||
|
||||
command := self.config.FileBrowser.Command
|
||||
|
||||
if command == "" {
|
||||
command = "--noauth -r /tmp/data"
|
||||
}
|
||||
|
||||
splitCommand, err := shellwords.Split(command)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ContainerResponse, err := self.client.ContainerCreate(
|
||||
context.TODO(),
|
||||
&container.Config{
|
||||
Cmd: splitCommand,
|
||||
Image: fmt.Sprintf("%s:%s", self.config.FileBrowser.Image.Registry, self.config.FileBrowser.Image.Tag),
|
||||
Labels: browserLabels,
|
||||
Tty: true,
|
||||
},
|
||||
&container.HostConfig{
|
||||
Mounts: []mount.Mount{{Source: server.Id, Target: "/tmp/data", Type: "volume"}},
|
||||
AutoRemove: true,
|
||||
ConsoleSize: [2]uint{1000, 1000},
|
||||
},
|
||||
&network.NetworkingConfig{
|
||||
EndpointsConfig: map[string]*network.EndpointSettings{"browsers": {
|
||||
NetworkID: self.config.FileBrowser.Network,
|
||||
}},
|
||||
},
|
||||
&v1.Platform{},
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = self.client.ContainerStart(context.TODO(), ContainerResponse.ID, container.StartOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &models.FileBrowser{
|
||||
Url: serverId[:12] + "." + self.config.BrowsersDomain,
|
||||
Id: ContainerResponse.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (self *InstanceManager) StopFileBrowser(ctx context.Context, serverId string) error {
|
||||
containers, err := self.containerList(ctx, ContainerLabels{Type: FileBrowser}, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, rawContainer := range containers {
|
||||
err := self.client.ContainerStop(ctx, rawContainer.ID, container.StopOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -8,16 +8,18 @@ const (
|
||||
)
|
||||
|
||||
type ContainerLabels struct {
|
||||
OwnerId string `json:"user_id,omitempty"`
|
||||
ImageId string `json:"image_id,omitempty"`
|
||||
VolumeId string `json:"volume_id,omitempty"`
|
||||
Type ContainerType `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
type BrowserLabels struct {
|
||||
ContainerLabels
|
||||
UrlRule string
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
type VolumeLabels struct {
|
||||
OwnerId string `json:"user_id,omitempty"`
|
||||
ImageId string `json:"image_id,omitempty"`
|
||||
Type ContainerType `json:"type,omitempty"`
|
||||
Type ContainerType `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
type ImageLabels struct {
|
||||
|
@ -5,51 +5,54 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
instancemanager "git.acooldomain.co/server-manager/backend-kubernetes-go/instance_manager"
|
||||
"git.acooldomain.co/server-manager/backend-kubernetes-go/models"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/go-connections/nat"
|
||||
)
|
||||
|
||||
func convertLabelsToFilter(labels any) (*filters.Args, error) {
|
||||
args := filters.NewArgs()
|
||||
raw, err := json.Marshal(labels)
|
||||
|
||||
labelMap, err := convertLabelsToMap(labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var unflattenedMap map[string]any
|
||||
|
||||
err = json.Unmarshal(raw, &unflattenedMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
flatMap := flattenMap(unflattenedMap)
|
||||
|
||||
for key, value := range flatMap {
|
||||
args.Add(key, value)
|
||||
for key, value := range *labelMap {
|
||||
args.Add("label", fmt.Sprintf("%s=%s", key, value))
|
||||
}
|
||||
|
||||
return &args, nil
|
||||
}
|
||||
|
||||
func flattenMap(m map[string]any, previous ...string) map[string]string {
|
||||
flattenedMap := make(map[string]string)
|
||||
for key, value := range m {
|
||||
v := reflect.ValueOf(value)
|
||||
switch v.Kind() {
|
||||
case reflect.Map:
|
||||
inner := flattenMap(v.Interface().(map[string]any), append(previous, key)...)
|
||||
for key, value := range inner {
|
||||
flattenedMap[key] = value
|
||||
}
|
||||
func convertLabelsToMap(labels any) (*map[string]string, error) {
|
||||
|
||||
default:
|
||||
flattenedMap[key] = fmt.Sprintf("%v", value)
|
||||
}
|
||||
raw, err := json.Marshal(labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return flattenedMap
|
||||
var rawMap map[string]any
|
||||
|
||||
err = json.Unmarshal(raw, &rawMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stringifiedMap := stringifyMap(rawMap)
|
||||
|
||||
return &stringifiedMap, nil
|
||||
}
|
||||
|
||||
func stringifyMap(m map[string]any) map[string]string {
|
||||
stringifiedMap := make(map[string]string)
|
||||
for key, value := range m {
|
||||
stringifiedMap[key] = fmt.Sprintf("%v", value)
|
||||
}
|
||||
|
||||
return stringifiedMap
|
||||
}
|
||||
|
||||
func convertContainerPortsToPorts(ports []types.Port) []models.Port {
|
||||
@ -87,3 +90,75 @@ func convertContainerImageToImage(image string) models.Image {
|
||||
Tag: imageTag,
|
||||
}
|
||||
}
|
||||
|
||||
func convertContainerLabelsToStruct(labels map[string]string) (*ContainerLabels, error) {
|
||||
var containerLabels ContainerLabels
|
||||
|
||||
rawLabels, err := json.Marshal(labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(rawLabels, &labels)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &containerLabels, nil
|
||||
}
|
||||
|
||||
func convertVolumeLabelsToStruct(labels map[string]string) (*VolumeLabels, error) {
|
||||
var volumeLabels VolumeLabels
|
||||
|
||||
rawLabels, err := json.Marshal(labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(rawLabels, &labels)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &volumeLabels, nil
|
||||
}
|
||||
|
||||
func convertImageLabelsToStruct(labels map[string]string) (*ImageLabels, error) {
|
||||
var imageLabels ImageLabels
|
||||
|
||||
rawLabels, err := json.Marshal(labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(rawLabels, &labels)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &imageLabels, nil
|
||||
}
|
||||
|
||||
func convertImagePortsToPorts(rawPorts nat.PortSet) []instancemanager.Port {
|
||||
ports := make([]instancemanager.Port, len(rawPorts))
|
||||
i := 0
|
||||
for imagePort := range rawPorts {
|
||||
portNumber := imagePort.Int()
|
||||
var protocol models.PortProtocol
|
||||
switch imagePort.Proto() {
|
||||
case "TCP":
|
||||
protocol = models.TCP
|
||||
case "UDP":
|
||||
protocol = models.UDP
|
||||
default:
|
||||
log.Default().Println(fmt.Sprintf("Unknown port protocol %s using TCP", imagePort.Proto()))
|
||||
protocol = models.TCP
|
||||
}
|
||||
ports[i] = instancemanager.Port{
|
||||
Number: uint16(portNumber),
|
||||
Protocol: protocol,
|
||||
}
|
||||
i++
|
||||
}
|
||||
return ports
|
||||
}
|
||||
|
@ -35,20 +35,17 @@ type InstanceManager interface {
|
||||
ListServers(ctx context.Context) ([]Server, error)
|
||||
|
||||
// State Changing
|
||||
StartServer(ctx context.Context, serverId string, command string, ports []models.Port) error
|
||||
StartServer(ctx context.Context, serverId string, image Image, command string, ports []models.Port) error
|
||||
StopServer(ctx context.Context, serverId string) error
|
||||
|
||||
CreateServer(ctx context.Context, image models.Image) (*Server, error)
|
||||
CreateServer(ctx context.Context) (*Server, error)
|
||||
DeleteServer(ctx context.Context, serverId string) error
|
||||
|
||||
// Terminal
|
||||
|
||||
// Read Only
|
||||
GetLogs(ctx context.Context, serverId string) (string, error)
|
||||
|
||||
// Status Changing
|
||||
InteractiveTerminal(ctx context.Context, serverId string) (*net.Conn, error)
|
||||
RunCommand(ctx context.Context, serverId string, command string) (string, error)
|
||||
ResizeTerminal(ctx context.Context, serverId string, width uint, height uint) error
|
||||
|
||||
// File Browser
|
||||
|
||||
|
@ -42,7 +42,19 @@ type UsersDatabaseConfig struct {
|
||||
Mongo *MongoDBConfig `yaml:"mongo"`
|
||||
}
|
||||
|
||||
type ServersInstanceManagerConfig struct {
|
||||
type FileBrowserConfig struct {
|
||||
Image Image `yaml:"image"`
|
||||
Command string `yaml:"command"`
|
||||
Network string `yaml:"network"`
|
||||
}
|
||||
|
||||
type DockerInstanceManagerConfig struct {
|
||||
BrowsersDomain string `yaml:"browsers_domain"`
|
||||
CertificateResolver string `yaml:"certificate_resolver"`
|
||||
FileBrowser FileBrowserConfig `yaml:"file_browser"`
|
||||
}
|
||||
|
||||
type InstanceManagerConfig struct {
|
||||
Type InstanceManagerType
|
||||
}
|
||||
|
||||
@ -58,10 +70,11 @@ type ServersAuthorizationDatabaseConfig struct {
|
||||
|
||||
type GlobalConfig struct {
|
||||
// Features Configs
|
||||
Email EmailConfig `yaml:"email"`
|
||||
Domain string `yaml:"domain"`
|
||||
Signing SigningConfig `yaml:"signing"`
|
||||
Authentication AuthenticationConfig `yaml:"authentication"`
|
||||
Email EmailConfig `yaml:"email"`
|
||||
Domain string `yaml:"domain"`
|
||||
Signing SigningConfig `yaml:"signing"`
|
||||
Authentication AuthenticationConfig `yaml:"authentication"`
|
||||
InstanceManager InstanceManagerConfig `yaml:"instance_manager"`
|
||||
|
||||
// Database Configs
|
||||
ServersDatabase ServersDatabaseConfig `yaml:"servers_database"`
|
||||
|
Loading…
x
Reference in New Issue
Block a user