diff --git a/instance_manager/docker/instance_manager.go b/instance_manager/docker/instance_manager.go index 6178071..46c3870 100644 --- a/instance_manager/docker/instance_manager.go +++ b/instance_manager/docker/instance_manager.go @@ -6,17 +6,15 @@ import ( "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" + "github.com/docker/go-connections/nat" ) type InstanceManager struct { @@ -24,111 +22,7 @@ type InstanceManager struct { 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) { +func (self *InstanceManager) getVolume(ctx context.Context, serverId string) (*volume.Volume, error) { volume, err := self.client.VolumeInspect(ctx, serverId) if err != nil { return nil, err @@ -149,6 +43,72 @@ func (self *InstanceManager) GetServer(ctx context.Context, serverId string) (*i return nil, fmt.Errorf("Server not found") } + 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) { + 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 + } + + ports := convertImagePortsToPorts(imageInspect.Config.ExposedPorts) + imageId := convertContainerImageToImage(rawImage.RepoTags[0]) + images[i] = instancemanager.Image{ + Registry: imageId.Registry, + Tag: imageId.Tag, + Ports: ports, + Command: strings.Join(imageInspect.Config.Cmd, " "), + } + } + + return images, nil +} + +func (self *InstanceManager) GetServer(ctx context.Context, serverId string) (*instancemanager.Server, error) { + volume, err := self.getVolume(ctx, serverId) + if err != nil { + return nil, err + } + filterArgs, err := convertLabelsToFilter(ContainerLabels{ VolumeId: volume.Name, Type: Game, @@ -268,6 +228,7 @@ 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 { + return nil } func (self *InstanceManager) StopServer(ctx context.Context, serverId string) error { diff --git a/instance_manager/docker/utils.go b/instance_manager/docker/utils.go new file mode 100644 index 0000000..a8a747c --- /dev/null +++ b/instance_manager/docker/utils.go @@ -0,0 +1,89 @@ +package docker + +import ( + "encoding/json" + "fmt" + "log" + "reflect" + + "git.acooldomain.co/server-manager/backend-kubernetes-go/models" + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" +) + +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 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 + } + + default: + flattenedMap[key] = fmt.Sprintf("%v", value) + } + } + + return flattenedMap +} + +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, + } +} diff --git a/instance_manager/instance_manager.go b/instance_manager/instance_manager.go index a0ef335..fc88554 100644 --- a/instance_manager/instance_manager.go +++ b/instance_manager/instance_manager.go @@ -30,7 +30,7 @@ type Image struct { type InstanceManager interface { //General // Read Only - ListImages(ctx context.Context) (*Image, error) + ListImages(ctx context.Context) ([]Image, error) GetServer(ctx context.Context, serverId string) (*Server, error) ListServers(ctx context.Context) ([]Server, error)