318 lines
7.5 KiB
Go
318 lines
7.5 KiB
Go
package docker
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"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/container"
|
|
"github.com/docker/docker/api/types/filters"
|
|
"github.com/docker/docker/api/types/image"
|
|
"github.com/docker/docker/api/types/volume"
|
|
"github.com/docker/docker/client"
|
|
)
|
|
|
|
type InstanceManager struct {
|
|
instancemanager.InstanceManager
|
|
client client.Client
|
|
}
|
|
|
|
func flattenMap(m map[string]any, previous ...string) map[string]string {
|
|
var flattenedMap 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
|
|
}
|
|
|
|
default:
|
|
flattenedMap[key] = fmt.Sprintf("%v", value)
|
|
}
|
|
}
|
|
return flattenedMap
|
|
}
|
|
|
|
func convertLabelsToFilter(labels any) (*filters.Args, error) {
|
|
args := filters.NewArgs()
|
|
raw, err := json.Marshal(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)
|
|
}
|
|
|
|
return &args, nil
|
|
}
|
|
|
|
func convertContainerPortsToPorts(ports []types.Port) []models.Port {
|
|
containerPorts := make([]models.Port, len(ports))
|
|
logger := log.Default()
|
|
for i, port := range ports {
|
|
var portProtocol models.PortProtocol
|
|
switch port.Type {
|
|
case "TCP":
|
|
portProtocol = models.TCP
|
|
case "UDP":
|
|
portProtocol = models.UDP
|
|
default:
|
|
logger.Println(fmt.Sprintf("Unkown Port Protocol %s assuming TCP", port.Type))
|
|
portProtocol = models.TCP
|
|
}
|
|
containerPorts[i] = models.Port{
|
|
PublicPort: port.PublicPort,
|
|
ContainerPort: port.PrivatePort,
|
|
Protocol: portProtocol,
|
|
}
|
|
}
|
|
|
|
return containerPorts
|
|
}
|
|
|
|
func convertContainerImageToImage(image string) models.Image {
|
|
imageSegments := strings.Split(image, ":")
|
|
imageRegistry := imageSegments[0]
|
|
imageTag := imageSegments[1]
|
|
|
|
return models.Image{
|
|
Registry: imageRegistry,
|
|
Tag: imageTag,
|
|
}
|
|
}
|
|
|
|
func convertImagePortsToPorts(types.Port) *models.Port {
|
|
return nil
|
|
}
|
|
|
|
// General
|
|
// Read Only
|
|
func (self *InstanceManager) ListImages(ctx context.Context) (*instancemanager.Image, error) {
|
|
imageFilters, err := convertLabelsToFilter(ImageLabels{Type: Game})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
rawImages, err := self.client.ImageList(ctx, image.ListOptions{
|
|
Filters: *imageFilters,
|
|
})
|
|
|
|
images := make([]instancemanager.Image, len(rawImages))
|
|
|
|
for i, rawImage := range rawImages {
|
|
imageInspect, _, err := self.client.ImageInspectWithRaw(ctx, rawImage.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
func (self *InstanceManager) GetServer(ctx context.Context, serverId string) (*instancemanager.Server, error) {
|
|
volume, err := self.client.VolumeInspect(ctx, serverId)
|
|
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)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if labels.Type != Game {
|
|
return nil, fmt.Errorf("Server not found")
|
|
}
|
|
|
|
filterArgs, err := convertLabelsToFilter(ContainerLabels{
|
|
VolumeId: volume.Name,
|
|
Type: Game,
|
|
})
|
|
|
|
serverContainers, err := self.client.ContainerList(
|
|
ctx,
|
|
container.ListOptions{
|
|
Filters: *filterArgs,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(serverContainers) == 0 {
|
|
return &instancemanager.Server{
|
|
Id: volume.Name,
|
|
Running: false,
|
|
RunningCommand: "",
|
|
RunningImage: nil,
|
|
Ports: nil,
|
|
}, nil
|
|
}
|
|
|
|
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
|
|
image := convertContainerImageToImage(serverContainer.Image)
|
|
|
|
return &instancemanager.Server{
|
|
Id: volume.Name,
|
|
Running: running,
|
|
RunningCommand: runningCommand,
|
|
Ports: convertContainerPortsToPorts(serverContainer.Ports),
|
|
RunningImage: &image,
|
|
}, nil
|
|
}
|
|
|
|
func (self *InstanceManager) ListServers(ctx context.Context) ([]instancemanager.Server, error) {
|
|
volumeFilter, err := convertLabelsToFilter(VolumeLabels{Type: Game})
|
|
if err != nil {
|
|
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
|
|
}
|
|
|
|
serverStatus := make(map[string]*instancemanager.Server)
|
|
|
|
for _, volume := range volumes.Volumes {
|
|
serverStatus[volume.Name] = &instancemanager.Server{
|
|
Id: volume.Name,
|
|
Running: false,
|
|
RunningCommand: "",
|
|
Ports: nil,
|
|
RunningImage: nil,
|
|
}
|
|
}
|
|
|
|
containers, err := self.client.ContainerList(ctx, container.ListOptions{Filters: *containerFilters})
|
|
|
|
for _, container := range containers {
|
|
rawLabels, err := json.Marshal(container.Labels)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var containerLabels ContainerLabels
|
|
err = json.Unmarshal(rawLabels, &containerLabels)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if container.State != "running" {
|
|
continue
|
|
}
|
|
|
|
image := convertContainerImageToImage(container.Image)
|
|
|
|
serverStatus[containerLabels.VolumeId].Ports = convertContainerPortsToPorts(container.Ports)
|
|
serverStatus[containerLabels.VolumeId].Running = true
|
|
serverStatus[containerLabels.VolumeId].RunningImage = &image
|
|
serverStatus[containerLabels.VolumeId].RunningCommand = container.Command
|
|
}
|
|
|
|
servers := make([]instancemanager.Server, len(serverStatus))
|
|
|
|
i := 0
|
|
for _, value := range serverStatus {
|
|
servers[i] = *value
|
|
i++
|
|
}
|
|
|
|
return servers, nil
|
|
}
|
|
|
|
// State Changing
|
|
func (self *InstanceManager) StartServer(ctx context.Context, serverId string, command string, ports []models.Port) error {
|
|
return nil
|
|
}
|
|
func (self *InstanceManager) StopServer(ctx context.Context, serverId string) error {
|
|
return nil
|
|
}
|
|
|
|
func (self *InstanceManager) CreateServer(ctx context.Context, image models.Image) (*instancemanager.Server, error) {
|
|
|
|
return nil, nil
|
|
}
|
|
func (self *InstanceManager) DeleteServer(ctx context.Context, serverId string) error {
|
|
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) {
|
|
|
|
return "", nil
|
|
}
|
|
|
|
// File Browser
|
|
|
|
// Read Only
|
|
func (self *InstanceManager) GetFileBrowser(ctx context.Context, serverId string) (*models.FileBrowser, error) {
|
|
return nil, nil
|
|
}
|
|
func (self *InstanceManager) ListFileBrowsers(ctx context.Context) ([]models.FileBrowser, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
// Status Changing
|
|
func (self *InstanceManager) StartFileBrowser(ctx context.Context, serverId string) (*models.FileBrowser, error) {
|
|
return nil, nil
|
|
}
|
|
func (self *InstanceManager) StopFileBrowser(ctx context.Context, serverId string) error {
|
|
return nil
|
|
}
|