added more stuff including some of docker support
This commit is contained in:
3
instance_manager/docker/go.mod
Normal file
3
instance_manager/docker/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module git.acooldomain.co/server-manager/backend-kubernetes-go/instance_manager/docker
|
||||
|
||||
go 1.22.0
|
317
instance_manager/docker/instance_manager.go
Normal file
317
instance_manager/docker/instance_manager.go
Normal file
@@ -0,0 +1,317 @@
|
||||
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
|
||||
}
|
25
instance_manager/docker/labels.go
Normal file
25
instance_manager/docker/labels.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package docker
|
||||
|
||||
type ContainerType string
|
||||
|
||||
const (
|
||||
Game ContainerType = "GAME"
|
||||
FileBrowser = "FILE_BROWSER"
|
||||
)
|
||||
|
||||
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 VolumeLabels struct {
|
||||
OwnerId string `json:"user_id,omitempty"`
|
||||
ImageId string `json:"image_id,omitempty"`
|
||||
Type ContainerType `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
type ImageLabels struct {
|
||||
Type ContainerType `json:"type,omitempty"`
|
||||
}
|
3
instance_manager/go.mod
Normal file
3
instance_manager/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module git.acooldomain.co/server-manager/backend-kubernetes-go/instance_manager
|
||||
|
||||
go 1.22.0
|
62
instance_manager/instance_manager.go
Normal file
62
instance_manager/instance_manager.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package instancemanager
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"git.acooldomain.co/server-manager/backend-kubernetes-go/models"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
Id string
|
||||
Running bool
|
||||
RunningCommand string
|
||||
RunningImage *models.Image
|
||||
Ports []models.Port
|
||||
}
|
||||
|
||||
type Port struct {
|
||||
Number uint16
|
||||
Protocol models.PortProtocol
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
Registry string
|
||||
Tag string
|
||||
Command string
|
||||
Ports []Port
|
||||
}
|
||||
|
||||
type InstanceManager interface {
|
||||
//General
|
||||
// Read Only
|
||||
ListImages(ctx context.Context) (*Image, error)
|
||||
GetServer(ctx context.Context, serverId string) (*Server, error)
|
||||
ListServers(ctx context.Context) ([]Server, error)
|
||||
|
||||
// State Changing
|
||||
StartServer(ctx context.Context, serverId string, command string, ports []models.Port) error
|
||||
StopServer(ctx context.Context, serverId string) error
|
||||
|
||||
CreateServer(ctx context.Context, image models.Image) (*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)
|
||||
|
||||
// File Browser
|
||||
|
||||
// Read Only
|
||||
GetFileBrowser(ctx context.Context, serverId string) (*models.FileBrowser, error)
|
||||
ListFileBrowsers(ctx context.Context) ([]models.FileBrowser, error)
|
||||
|
||||
// Status Changing
|
||||
StartFileBrowser(ctx context.Context, serverId string) (*models.FileBrowser, error)
|
||||
StopFileBrowser(ctx context.Context, serverId string) error
|
||||
}
|
3
instance_manager/kubernetes/go.mod
Normal file
3
instance_manager/kubernetes/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module git.acooldomain.co/server-manager/backend-kubernetes-go/instance_manager/kubernetes
|
||||
|
||||
go 1.22.0
|
73
instance_manager/kubernetes/instance_manager.go
Normal file
73
instance_manager/kubernetes/instance_manager.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"git.acooldomain.co/server-manager/backend-kubernetes-go/instance_manager"
|
||||
"git.acooldomain.co/server-manager/backend-kubernetes-go/models"
|
||||
)
|
||||
|
||||
type InstanceManager struct {
|
||||
instancemanager.InstanceManager
|
||||
}
|
||||
|
||||
// General
|
||||
// Read Only
|
||||
func (self *InstanceManager) GetServer(ctx context.Context, serverId string) (*instancemanager.Server, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (self *InstanceManager) ListServers(ctx context.Context) ([]instancemanager.Server, error) {
|
||||
return nil, 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
|
||||
}
|
Reference in New Issue
Block a user