backend/instancemanager/kubernetes/instance_manager.go
2025-04-05 23:37:29 +03:00

230 lines
6.1 KiB
Go

package kubernetes
import (
"context"
"net"
"strings"
"git.acooldomain.co/server-manager/backend/instancemanager"
"git.acooldomain.co/server-manager/backend/models"
servermanagerv1 "git.acooldomain.co/server-manager/kubernetes-operator/api/v1alpha1"
"github.com/buildkite/shellwords"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
)
type InstanceManager struct {
instancemanager.InstanceManager
Config models.KubernetesInstanceManagerConfig
client client.Client
}
func convertServerManagerImage(image *servermanagerv1.Image) *instancemanager.Image {
ports := make([]instancemanager.Port, len(image.Spec.Ports))
for i, port := range image.Spec.Ports {
ports[i] = instancemanager.Port{
Number: uint16(port.Port),
Protocol: models.PortProtocol(port.Protocol),
}
}
return &instancemanager.Image{
Registry: image.Spec.Name,
Tag: image.Spec.Tag,
Id: image.Name,
Ports: ports,
WorkingDir: image.Spec.WorkingDir,
Command: strings.Join(image.Spec.Args, " "),
}
}
// General
// Read Only
func (i *InstanceManager) GetImage(ctx context.Context, imageId string) (*instancemanager.Image, error) {
image := &servermanagerv1.Image{}
err := i.client.Get(ctx, client.ObjectKey{Name: imageId, Namespace: i.Config.Namespace}, image)
if err != nil {
return nil, err
}
return convertServerManagerImage(image), nil
}
func (i *InstanceManager) ListImages(ctx context.Context) ([]instancemanager.Image, error) {
images := &servermanagerv1.ImageList{}
err := i.client.List(ctx, images, &client.ListOptions{Namespace: i.Config.Namespace})
if err != nil {
return nil, err
}
imImages := make([]instancemanager.Image, len(images.Items))
for i, image := range images.Items {
imImages[i] = *convertServerManagerImage(&image)
}
return imImages, nil
}
func (i *InstanceManager) GetServer(ctx context.Context, serverId string) (*instancemanager.Server, error) {
serverManager := &servermanagerv1.ServerManager{}
err := i.client.Get(ctx, client.ObjectKey{Namespace: i.Config.Namespace, Name: serverId}, serverManager)
if err != nil {
return nil, err
}
image, err := i.GetImage(ctx, serverManager.Spec.Server.Image)
if err != nil {
return nil, err
}
return &instancemanager.Server{
Id: serverManager.Name,
Running: serverManager.Spec.Server.On,
RunningCommand: strings.Join(serverManager.Status.Server.Args, " "),
RunningImage: &models.Image{
Registry: image.Registry,
Tag: image.Tag,
Id: image.Id,
},
}, nil
}
func (i *InstanceManager) ListServers(ctx context.Context) ([]instancemanager.Server, error) {
serverManagers := &servermanagerv1.ServerManagerList{}
err := i.client.List(ctx, serverManagers, &client.ListOptions{Namespace: i.Config.Namespace})
if err != nil {
return nil, err
}
servers := make([]instancemanager.Server, len(serverManagers.Items))
for index, serverManager := range serverManagers.Items {
image, err := i.GetImage(ctx, serverManager.Spec.Server.Image)
if err != nil {
return nil, err
}
servers[index] = instancemanager.Server{
Id: serverManager.Name,
Running: serverManager.Spec.Server.On,
RunningCommand: strings.Join(serverManager.Status.Server.Args, " "),
RunningImage: &models.Image{
Registry: image.Registry,
Tag: image.Tag,
Id: image.Id,
},
}
}
return servers, nil
}
// State Changing
func (i *InstanceManager) StartServer(ctx context.Context, serverId string, imageId string, command string, ports []models.Port) error {
image := &servermanagerv1.Image{}
err := i.client.Get(ctx, client.ObjectKey{Name: imageId, Namespace: i.Config.Namespace}, image)
if err != nil {
return err
}
serverManager := &servermanagerv1.ServerManager{}
err = i.client.Get(ctx, client.ObjectKey{Name: serverId, Namespace: i.Config.Namespace}, serverManager)
if err != nil {
return err
}
serverManager.Spec.Server.Image = image.Name
serverManager.Spec.Server.On = true
serverManager.Spec.Server.Args, err = shellwords.Split(command)
if err != nil {
return err
}
err = i.client.Update(ctx, serverManager)
if err != nil {
return err
}
return nil
}
func (i *InstanceManager) StopServer(ctx context.Context, serverId string) error {
serverManager := &servermanagerv1.ServerManager{}
err := i.client.Get(ctx, client.ObjectKey{Name: serverId, Namespace: i.Config.Namespace}, serverManager)
if err != nil {
return err
}
serverManager.Spec.Server.On = false
err = i.client.Update(ctx, serverManager)
if err != nil {
return err
}
return nil
}
func (i *InstanceManager) CreateServer(ctx context.Context) (*instancemanager.Server, error) {
return nil, nil
}
func (i *InstanceManager) DeleteServer(ctx context.Context, serverId string) error {
return nil
}
// Terminal
// Status Changing
func (i *InstanceManager) InteractiveTerminal(ctx context.Context, serverId string) (*net.Conn, error) {
return nil, nil
}
func (i *InstanceManager) ResizeTerminal(ctx context.Context, serverId string, width uint, height uint) error {
return nil
}
// File Browser
// Read Only
func (i *InstanceManager) GetFileBrowser(ctx context.Context, serverId string) (*models.FileBrowser, error) {
return nil, nil
}
func (i *InstanceManager) ListFileBrowsers(ctx context.Context) ([]models.FileBrowser, error) {
return nil, nil
}
// Status Changing
func (i *InstanceManager) StartFileBrowser(ctx context.Context, serverId string) (*models.FileBrowser, error) {
return nil, nil
}
func (i *InstanceManager) StopFileBrowser(ctx context.Context, serverId string) error {
return nil
}
func NewInstanceManager(config models.KubernetesInstanceManagerConfig) (*InstanceManager, error) {
c, err := rest.InClusterConfig()
if err != nil {
return nil, err
}
scheme := runtime.NewScheme()
clientgoscheme.AddToScheme(scheme)
servermanagerv1.AddToScheme(scheme)
client, err := client.New(c, client.Options{Scheme: scheme})
if err != nil {
return nil, err
}
if err != nil {
return nil, err
}
return &InstanceManager{client: client}, nil
}