From 8b74b73704b855f4872a4a600665c8edd4d31534 Mon Sep 17 00:00:00 2001 From: ACoolName Date: Wed, 2 Apr 2025 22:19:42 +0300 Subject: [PATCH] added browser support --- instancemanager/docker/instance_manager.go | 173 ++++++++++----------- 1 file changed, 86 insertions(+), 87 deletions(-) diff --git a/instancemanager/docker/instance_manager.go b/instancemanager/docker/instance_manager.go index 907c1c4..5237293 100644 --- a/instancemanager/docker/instance_manager.go +++ b/instancemanager/docker/instance_manager.go @@ -30,13 +30,13 @@ type InstanceManager struct { siteDomain string } -func (self *InstanceManager) containerList(ctx context.Context, labels ContainerLabels, all bool) ([]container.Summary, error) { +func (im *InstanceManager) containerList(ctx context.Context, labels ContainerLabels, all bool) ([]container.Summary, error) { filters, err := convertLabelsToFilter(labels) if err != nil { return nil, err } - containers, err := self.client.ContainerList(ctx, container.ListOptions{Filters: *filters, All: all}) + containers, err := im.client.ContainerList(ctx, container.ListOptions{Filters: *filters, All: all}) if err != nil { return nil, err } @@ -44,8 +44,8 @@ func (self *InstanceManager) containerList(ctx context.Context, labels Container return containers, nil } -func (self *InstanceManager) getVolume(ctx context.Context, serverId string) (*volume.Volume, error) { - volume, err := self.client.VolumeInspect(ctx, serverId) +func (im *InstanceManager) getVolume(ctx context.Context, serverId string) (*volume.Volume, error) { + volume, err := im.client.VolumeInspect(ctx, serverId) if err != nil { return nil, err } @@ -56,7 +56,7 @@ func (self *InstanceManager) getVolume(ctx context.Context, serverId string) (*v } if labels.Type != Game { - return nil, fmt.Errorf("Server not found") + return nil, fmt.Errorf("server not found") } return &volume, err @@ -64,8 +64,8 @@ func (self *InstanceManager) getVolume(ctx context.Context, serverId string) (*v // General // Read Only -func (self *InstanceManager) GetImage(ctx context.Context, imageId string) (*instancemanager.Image, error) { - imageInspect, err := self.client.ImageInspect(ctx, imageId) +func (im *InstanceManager) GetImage(ctx context.Context, imageId string) (*instancemanager.Image, error) { + imageInspect, err := im.client.ImageInspect(ctx, imageId) if err != nil { return nil, err } @@ -82,23 +82,22 @@ func (self *InstanceManager) GetImage(ctx context.Context, imageId string) (*ins image := convertImageInspectToInstanceImage(imageInspect) return &image, nil - } -func (self *InstanceManager) ListImages(ctx context.Context) ([]instancemanager.Image, error) { +func (im *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{ + rawImages, err := im.client.ImageList(ctx, image.ListOptions{ Filters: *imageFilters, }) images := make([]instancemanager.Image, len(rawImages)) for i, rawImage := range rawImages { - imageInspect, err := self.client.ImageInspect(ctx, rawImage.ID) + imageInspect, err := im.client.ImageInspect(ctx, rawImage.ID) if err != nil { return nil, err } @@ -109,12 +108,12 @@ func (self *InstanceManager) ListImages(ctx context.Context) ([]instancemanager. return images, nil } -func (self *InstanceManager) GetServer(ctx context.Context, serverId string) (*instancemanager.Server, error) { - volume, err := self.getVolume(ctx, serverId) +func (im *InstanceManager) GetServer(ctx context.Context, serverId string) (*instancemanager.Server, error) { + volume, err := im.getVolume(ctx, serverId) if err != nil { return nil, err } - serverContainers, err := self.containerList( + serverContainers, err := im.containerList( ctx, ContainerLabels{ VolumeId: serverId, @@ -132,7 +131,7 @@ func (self *InstanceManager) GetServer(ctx context.Context, serverId string) (*i RunningCommand: "", RunningImage: nil, Ports: nil, - Domain: self.siteDomain, + Domain: im.siteDomain, }, nil } @@ -149,17 +148,17 @@ func (self *InstanceManager) GetServer(ctx context.Context, serverId string) (*i RunningCommand: runningCommand, Ports: convertContainerPortsToPorts(serverContainer.Ports), RunningImage: &image, - Domain: self.siteDomain, + Domain: im.siteDomain, }, nil } -func (self *InstanceManager) ListServers(ctx context.Context) ([]instancemanager.Server, error) { +func (im *InstanceManager) ListServers(ctx context.Context) ([]instancemanager.Server, error) { volumeFilter, err := convertLabelsToFilter(VolumeLabels{Type: Game}) if err != nil { return nil, err } - volumes, err := self.client.VolumeList(ctx, volume.ListOptions{Filters: *volumeFilter}) + volumes, err := im.client.VolumeList(ctx, volume.ListOptions{Filters: *volumeFilter}) if err != nil { return nil, err } @@ -173,11 +172,11 @@ func (self *InstanceManager) ListServers(ctx context.Context) ([]instancemanager RunningCommand: "", Ports: nil, RunningImage: nil, - Domain: self.siteDomain, + Domain: im.siteDomain, } } - containers, err := self.containerList(ctx, ContainerLabels{Type: Game}, false) + containers, err := im.containerList(ctx, ContainerLabels{Type: Game}, false) for _, container := range containers { rawLabels, err := json.Marshal(container.Labels) @@ -215,13 +214,13 @@ func (self *InstanceManager) ListServers(ctx context.Context) ([]instancemanager } // State Changing -func (self *InstanceManager) StartServer(ctx context.Context, +func (im *InstanceManager) StartServer(ctx context.Context, serverId string, imageId string, command string, ports []models.Port, ) error { - server, err := self.GetServer(ctx, serverId) + server, err := im.GetServer(ctx, serverId) if err != nil { return err } @@ -238,7 +237,7 @@ func (self *InstanceManager) StartServer(ctx context.Context, volumes := make(map[string]struct{}) var portMapping nat.PortMap = make(nat.PortMap) - image, err := self.GetImage(ctx, imageId) + image, err := im.GetImage(ctx, imageId) if err != nil { return err } @@ -281,7 +280,7 @@ func (self *InstanceManager) StartServer(ctx context.Context, return err } - createdContainer, err := self.client.ContainerCreate( + createdContainer, err := im.client.ContainerCreate( context.TODO(), &container.Config{ AttachStdin: true, @@ -306,23 +305,23 @@ func (self *InstanceManager) StartServer(ctx context.Context, &v1.Platform{}, "", ) - if err != nil { return err } - err = self.client.ContainerStart(ctx, createdContainer.ID, container.StartOptions{}) + err = im.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) + +func (im *InstanceManager) StopServer(ctx context.Context, serverId string) error { + runningContainers, err := im.containerList(ctx, ContainerLabels{VolumeId: serverId, Type: Game}, false) for _, rawContainer := range runningContainers { - err = self.client.ContainerStop(ctx, rawContainer.ID, container.StopOptions{}) + err = im.client.ContainerStop(ctx, rawContainer.ID, container.StopOptions{}) if err != nil { return err } @@ -331,22 +330,21 @@ func (self *InstanceManager) StopServer(ctx context.Context, serverId string) er return nil } -func (self *InstanceManager) createVolume(ctx context.Context, volumeLabels VolumeLabels) (volume.Volume, error) { +func (im *InstanceManager) createVolume(ctx context.Context, volumeLabels VolumeLabels) (volume.Volume, error) { labels, err := convertLabelsToMap(volumeLabels) if err != nil { return volume.Volume{}, err } - volume, err := self.client.VolumeCreate(ctx, volume.CreateOptions{ + volume, err := im.client.VolumeCreate(ctx, volume.CreateOptions{ Labels: *labels, }) return volume, err } -func (self *InstanceManager) CreateServer(ctx context.Context) (*instancemanager.Server, error) { - volume, err := self.createVolume(ctx, VolumeLabels{Type: Game}) - +func (im *InstanceManager) CreateServer(ctx context.Context) (*instancemanager.Server, error) { + volume, err := im.createVolume(ctx, VolumeLabels{Type: Game}) if err != nil { return nil, err } @@ -356,29 +354,29 @@ func (self *InstanceManager) CreateServer(ctx context.Context) (*instancemanager Running: false, RunningImage: nil, RunningCommand: "", - Domain: self.siteDomain, + Domain: im.siteDomain, }, nil } -func (self *InstanceManager) DeleteServer(ctx context.Context, serverId string) error { - server, err := self.GetServer(ctx, serverId) +func (im *InstanceManager) DeleteServer(ctx context.Context, serverId string) error { + server, err := im.GetServer(ctx, serverId) if err != nil { return err } if server.Running { - err = self.StopServer(ctx, server.Id) + err = im.StopServer(ctx, server.Id) if err != nil { return err } } - err = self.StopFileBrowser(ctx, server.Id) + err = im.StopFileBrowser(ctx, server.Id) if err != nil { return err } - err = self.client.VolumeRemove(ctx, server.Id, true) + err = im.client.VolumeRemove(ctx, server.Id, true) if err != nil { return err } @@ -388,8 +386,8 @@ func (self *InstanceManager) DeleteServer(ctx context.Context, serverId string) // Terminal // Status Changing -func (self *InstanceManager) InteractiveTerminal(ctx context.Context, serverId string) (*net.Conn, error) { - server, err := self.GetServer(ctx, serverId) +func (im *InstanceManager) InteractiveTerminal(ctx context.Context, serverId string) (*net.Conn, error) { + server, err := im.GetServer(ctx, serverId) if err != nil { return nil, err } @@ -398,7 +396,7 @@ func (self *InstanceManager) InteractiveTerminal(ctx context.Context, serverId s return nil, fmt.Errorf("Server %s not running", server.Id) } - rawContainers, err := self.containerList(ctx, ContainerLabels{VolumeId: serverId, Type: Game}, false) + rawContainers, err := im.containerList(ctx, ContainerLabels{VolumeId: serverId, Type: Game}, false) if err != nil { return nil, err } @@ -409,16 +407,16 @@ func (self *InstanceManager) InteractiveTerminal(ctx context.Context, serverId s rawContainer := rawContainers[0] - attach, err := self.client.ContainerAttach(ctx, + attach, err := im.client.ContainerAttach(ctx, rawContainer.ID, - container.AttachOptions{Stream: true, + container.AttachOptions{ + Stream: true, Stdin: true, Stdout: true, Stderr: true, Logs: true, }, ) - if err != nil { return nil, err } @@ -426,8 +424,8 @@ func (self *InstanceManager) InteractiveTerminal(ctx context.Context, serverId s 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) +func (im *InstanceManager) ResizeTerminal(ctx context.Context, serverId string, width uint, height uint) error { + containers, err := im.containerList(ctx, ContainerLabels{VolumeId: serverId, Type: Game}, false) if err != nil { return err } @@ -436,7 +434,7 @@ func (self *InstanceManager) ResizeTerminal(ctx context.Context, serverId string return fmt.Errorf("Server %s not running", serverId) } - err = self.client.ContainerResize(context.TODO(), containers[0].ID, container.ResizeOptions{Height: height, Width: width}) + err = im.client.ContainerResize(context.TODO(), containers[0].ID, container.ResizeOptions{Height: height, Width: width}) return err } @@ -444,8 +442,8 @@ func (self *InstanceManager) ResizeTerminal(ctx context.Context, serverId string // File Browser // Read Only -func (self *InstanceManager) GetFileBrowser(ctx context.Context, serverId string) (*models.FileBrowser, error) { - containers, err := self.containerList(ctx, ContainerLabels{VolumeId: serverId, Type: FileBrowser}, false) +func (im *InstanceManager) GetFileBrowser(ctx context.Context, serverId string) (*models.FileBrowser, error) { + containers, err := im.containerList(ctx, ContainerLabels{VolumeId: serverId, Type: FileBrowser}, false) if err != nil { return nil, err } @@ -462,14 +460,14 @@ func (self *InstanceManager) GetFileBrowser(ctx context.Context, serverId string } return &models.FileBrowser{ - Url: fmt.Sprintf("%s/browsers/%s/", self.siteDomain, containerLabels.VolumeId), + Url: fmt.Sprintf("%s/browsers/%s/", im.siteDomain, containerLabels.VolumeId), ServerId: containerLabels.VolumeId, Id: rawContainer.ID, }, nil } -func (self *InstanceManager) ListFileBrowsers(ctx context.Context) ([]models.FileBrowser, error) { - containers, err := self.containerList(ctx, ContainerLabels{Type: FileBrowser}, false) +func (im *InstanceManager) ListFileBrowsers(ctx context.Context) ([]models.FileBrowser, error) { + containers, err := im.containerList(ctx, ContainerLabels{Type: FileBrowser}, false) if err != nil { return nil, err } @@ -483,7 +481,7 @@ func (self *InstanceManager) ListFileBrowsers(ctx context.Context) ([]models.Fil } fileBrowsers[i] = models.FileBrowser{ - Url: fmt.Sprintf("%s/browsers/%s/", self.siteDomain, containerLabels.VolumeId), + Url: fmt.Sprintf("%s/browsers/%s/", im.siteDomain, containerLabels.VolumeId), ServerId: containerLabels.VolumeId, Id: rawContainer.ID, } @@ -494,9 +492,8 @@ func (self *InstanceManager) ListFileBrowsers(ctx context.Context) ([]models.Fil } // Status Changing -func (self *InstanceManager) StartFileBrowser(ctx context.Context, serverId string) (*models.FileBrowser, error) { - server, err := self.GetServer(ctx, serverId) - +func (im *InstanceManager) StartFileBrowser(ctx context.Context, serverId string) (*models.FileBrowser, error) { + server, err := im.GetServer(ctx, serverId) if err != nil { return nil, err } @@ -507,31 +504,35 @@ func (self *InstanceManager) StartFileBrowser(ctx context.Context, serverId stri VolumeId: server.Id, } - containers, err := self.containerList(ctx, ContainerLabels{VolumeId: serverId, Type: FileBrowser}, false) + containers, err := im.containerList(ctx, ContainerLabels{VolumeId: serverId, Type: FileBrowser}, false) + if err != nil { + return nil, err + } if len(containers) > 0 { - return &models.FileBrowser{ - Url: fmt.Sprintf("%s/browsers/%s/", self.siteDomain, server.Id), + Url: fmt.Sprintf("%s/browsers/%s/", im.siteDomain, server.Id), ServerId: server.Id, Id: containers[0].ID, }, nil } - volume, err := self.createVolume(ctx, volumeLabels) - - containerConfig, err := convertLabelsToMap(ContainerLabels{VolumeId: serverId, Type: FileBrowser}) - + volume, err := im.createVolume(ctx, volumeLabels) if err != nil { return nil, err } - PrepareDatabaseContainer, err := self.client.ContainerCreate( + containerConfig, err := convertLabelsToMap(ContainerLabels{VolumeId: serverId, Type: FileBrowser}) + if err != nil { + return nil, err + } + + PrepareDatabaseContainer, err := im.client.ContainerCreate( ctx, &container.Config{ Entrypoint: []string{"/bin/sh"}, Cmd: []string{"-c", "/filebrowser config init -d /tmp/database/database.db && /filebrowser config set -d /tmp/database/database.db --auth.method=proxy --auth.header=X-Auth-Username"}, - Image: fmt.Sprintf("%s:%s", self.config.FileBrowser.Image.Registry, self.config.FileBrowser.Image.Tag), + Image: fmt.Sprintf("%s:%s", im.config.FileBrowser.Image.Registry, im.config.FileBrowser.Image.Tag), Labels: *containerConfig, }, &container.HostConfig{ @@ -542,28 +543,26 @@ func (self *InstanceManager) StartFileBrowser(ctx context.Context, serverId stri &v1.Platform{}, "", ) - if err != nil { return nil, err } - err = self.client.ContainerStart(ctx, PrepareDatabaseContainer.ID, container.StartOptions{}) - + err = im.client.ContainerStart(ctx, PrepareDatabaseContainer.ID, container.StartOptions{}) if err != nil { log.Printf("Failed to wait %s", err) } - responseChan, _ := self.client.ContainerWait(ctx, PrepareDatabaseContainer.ID, container.WaitConditionNotRunning) + responseChan, _ := im.client.ContainerWait(ctx, PrepareDatabaseContainer.ID, container.WaitConditionNotRunning) response := <-responseChan log.Printf("%#v\n", response) browserLabels := make(map[string]string) browserLabels["traefik.enable"] = "true" - browserLabels[fmt.Sprintf("traefik.http.routers.%s.rule", labelId)] = fmt.Sprintf("Host(`%s`) && PathPrefix(`/browsers/%s/`)", self.siteDomain, labelId) - browserLabels[fmt.Sprintf("traefik.http.routers.%s.entrypoints", labelId)] = self.config.FileBrowser.ReverseProxy.Entrypoint - browserLabels[fmt.Sprintf("traefik.http.routers.%s.middlewares", labelId)] = strings.Join(self.config.FileBrowser.ReverseProxy.Middlewares, ",") - if self.config.FileBrowser.ReverseProxy.Tls { - browserLabels[fmt.Sprintf("traefik.http.routers.%s.tls.certresolver", labelId)] = self.config.FileBrowser.ReverseProxy.TlsResolver + browserLabels[fmt.Sprintf("traefik.http.routers.%s.rule", labelId)] = fmt.Sprintf("Host(`%s`) && PathPrefix(`/browsers/%s/`)", im.siteDomain, labelId) + browserLabels[fmt.Sprintf("traefik.http.routers.%s.entrypoints", labelId)] = im.config.FileBrowser.ReverseProxy.Entrypoint + browserLabels[fmt.Sprintf("traefik.http.routers.%s.middlewares", labelId)] = strings.Join(im.config.FileBrowser.ReverseProxy.Middlewares, ",") + if im.config.FileBrowser.ReverseProxy.Tls { + browserLabels[fmt.Sprintf("traefik.http.routers.%s.tls.certresolver", labelId)] = im.config.FileBrowser.ReverseProxy.TlsResolver } if err != nil { @@ -572,7 +571,7 @@ func (self *InstanceManager) StartFileBrowser(ctx context.Context, serverId stri maps.Copy(browserLabels, *containerConfig) - command := self.config.FileBrowser.Command + command := im.config.FileBrowser.Command command += fmt.Sprintf("-d /tmp/database/database.db -r /tmp/data -b /browsers/%s/", labelId) @@ -581,11 +580,11 @@ func (self *InstanceManager) StartFileBrowser(ctx context.Context, serverId stri return nil, err } - ContainerResponse, err := self.client.ContainerCreate( + ContainerResponse, err := im.client.ContainerCreate( ctx, &container.Config{ Cmd: splitCommand, - Image: fmt.Sprintf("%s:%s", self.config.FileBrowser.Image.Registry, self.config.FileBrowser.Image.Tag), + Image: fmt.Sprintf("%s:%s", im.config.FileBrowser.Image.Registry, im.config.FileBrowser.Image.Tag), Labels: browserLabels, Tty: true, }, @@ -596,7 +595,7 @@ func (self *InstanceManager) StartFileBrowser(ctx context.Context, serverId stri }, &network.NetworkingConfig{ EndpointsConfig: map[string]*network.EndpointSettings{"browsers": { - NetworkID: self.config.FileBrowser.Network, + NetworkID: im.config.FileBrowser.Network, }}, }, &v1.Platform{}, @@ -606,34 +605,34 @@ func (self *InstanceManager) StartFileBrowser(ctx context.Context, serverId stri return nil, err } - err = self.client.ContainerStart(ctx, ContainerResponse.ID, container.StartOptions{}) + err = im.client.ContainerStart(ctx, ContainerResponse.ID, container.StartOptions{}) if err != nil { return nil, err } return &models.FileBrowser{ - Url: fmt.Sprintf("%s/browsers/%s/", self.siteDomain, server.Id), + Url: fmt.Sprintf("%s/browsers/%s/", im.siteDomain, server.Id), ServerId: server.Id, Id: volume.Name, }, nil } -func (self *InstanceManager) StopFileBrowser(ctx context.Context, serverId string) error { - containers, err := self.containerList(ctx, ContainerLabels{Type: FileBrowser}, false) +func (im *InstanceManager) StopFileBrowser(ctx context.Context, serverId string) error { + containers, err := im.containerList(ctx, ContainerLabels{Type: FileBrowser}, false) if err != nil { return err } for _, rawContainer := range containers { - stopChan, _ := self.client.ContainerWait(ctx, rawContainer.ID, container.WaitConditionRemoved) - err := self.client.ContainerStop(ctx, rawContainer.ID, container.StopOptions{}) + stopChan, _ := im.client.ContainerWait(ctx, rawContainer.ID, container.WaitConditionRemoved) + err := im.client.ContainerStop(ctx, rawContainer.ID, container.StopOptions{}) if err != nil { return err } <-stopChan for _, mount := range rawContainer.Mounts { if mount.Destination == "/tmp/database" { - err := self.client.VolumeRemove(ctx, mount.Name, true) + err := im.client.VolumeRemove(ctx, mount.Name, true) if err != nil { return err }