working state
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"maps"
|
||||
"net"
|
||||
"strings"
|
||||
@@ -23,8 +24,10 @@ import (
|
||||
|
||||
type InstanceManager struct {
|
||||
instancemanager.InstanceManager
|
||||
client *client.Client
|
||||
config models.DockerInstanceManagerConfig
|
||||
client *client.Client
|
||||
config models.DockerInstanceManagerConfig
|
||||
browsersSubDomain string
|
||||
siteDomain string
|
||||
}
|
||||
|
||||
func (self *InstanceManager) containerList(ctx context.Context, labels ContainerLabels, all bool) ([]container.Summary, error) {
|
||||
@@ -129,7 +132,7 @@ func (self *InstanceManager) GetServer(ctx context.Context, serverId string) (*i
|
||||
RunningCommand: "",
|
||||
RunningImage: nil,
|
||||
Ports: nil,
|
||||
Domain: self.config.GamesDomain,
|
||||
Domain: self.siteDomain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -146,7 +149,7 @@ func (self *InstanceManager) GetServer(ctx context.Context, serverId string) (*i
|
||||
RunningCommand: runningCommand,
|
||||
Ports: convertContainerPortsToPorts(serverContainer.Ports),
|
||||
RunningImage: &image,
|
||||
Domain: self.config.GamesDomain,
|
||||
Domain: self.siteDomain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -170,7 +173,7 @@ func (self *InstanceManager) ListServers(ctx context.Context) ([]instancemanager
|
||||
RunningCommand: "",
|
||||
Ports: nil,
|
||||
RunningImage: nil,
|
||||
Domain: self.config.GamesDomain,
|
||||
Domain: self.siteDomain,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,18 +331,22 @@ func (self *InstanceManager) StopServer(ctx context.Context, serverId string) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *InstanceManager) CreateServer(ctx context.Context) (*instancemanager.Server, error) {
|
||||
labels, err := convertLabelsToMap(VolumeLabels{
|
||||
Type: Game,
|
||||
})
|
||||
func (self *InstanceManager) createVolume(ctx context.Context, volumeLabels VolumeLabels) (volume.Volume, error) {
|
||||
labels, err := convertLabelsToMap(volumeLabels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return volume.Volume{}, err
|
||||
}
|
||||
|
||||
volume, err := self.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})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -349,7 +356,7 @@ func (self *InstanceManager) CreateServer(ctx context.Context) (*instancemanager
|
||||
Running: false,
|
||||
RunningImage: nil,
|
||||
RunningCommand: "",
|
||||
Domain: self.config.GamesDomain,
|
||||
Domain: self.siteDomain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -455,8 +462,9 @@ func (self *InstanceManager) GetFileBrowser(ctx context.Context, serverId string
|
||||
}
|
||||
|
||||
return &models.FileBrowser{
|
||||
Url: containerLabels.VolumeId[:12] + "." + self.config.BrowsersDomain,
|
||||
Id: rawContainer.ID,
|
||||
Url: fmt.Sprintf("%s/browsers/%s/", self.siteDomain, containerLabels.VolumeId),
|
||||
ServerId: containerLabels.VolumeId,
|
||||
Id: rawContainer.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -475,8 +483,9 @@ func (self *InstanceManager) ListFileBrowsers(ctx context.Context) ([]models.Fil
|
||||
}
|
||||
|
||||
fileBrowsers[i] = models.FileBrowser{
|
||||
Url: containerLabels.VolumeId[:12] + "." + self.config.BrowsersDomain,
|
||||
Id: rawContainer.ID,
|
||||
Url: fmt.Sprintf("%s/browsers/%s/", self.siteDomain, containerLabels.VolumeId),
|
||||
ServerId: containerLabels.VolumeId,
|
||||
Id: rawContainer.ID,
|
||||
}
|
||||
|
||||
}
|
||||
@@ -492,20 +501,71 @@ func (self *InstanceManager) StartFileBrowser(ctx context.Context, serverId stri
|
||||
return nil, err
|
||||
}
|
||||
|
||||
labelId := serverId[:12]
|
||||
labelId := server.Id
|
||||
volumeLabels := VolumeLabels{
|
||||
Type: FileBrowser,
|
||||
VolumeId: server.Id,
|
||||
}
|
||||
|
||||
containers, err := self.containerList(ctx, ContainerLabels{VolumeId: serverId, Type: FileBrowser}, false)
|
||||
|
||||
if len(containers) > 0 {
|
||||
|
||||
return &models.FileBrowser{
|
||||
Url: fmt.Sprintf("%s/browsers/%s/", self.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})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
PrepareDatabaseContainer, err := self.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),
|
||||
Labels: *containerConfig,
|
||||
},
|
||||
&container.HostConfig{
|
||||
Mounts: []mount.Mount{{Source: volume.Name, Target: "/tmp/database", Type: mount.TypeVolume}},
|
||||
AutoRemove: true,
|
||||
},
|
||||
&network.NetworkingConfig{},
|
||||
&v1.Platform{},
|
||||
"",
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = self.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)
|
||||
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.browsers.%s`)", labelId, self.config.BrowsersDomain)
|
||||
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.domains[0].main", labelId)] = self.config.BrowsersDomain
|
||||
browserLabels[fmt.Sprintf("traefik.http.routers.%s.tls.domains[0].sans", labelId)] = fmt.Sprintf("*.%s", self.config.BrowsersDomain)
|
||||
browserLabels[fmt.Sprintf("traefik.http.routers.%s.tls.certresolver", labelId)] = self.config.FileBrowser.ReverseProxy.TlsResolver
|
||||
}
|
||||
|
||||
containerConfig, err := convertLabelsToMap(ContainerLabels{VolumeId: serverId, Type: FileBrowser})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -514,9 +574,7 @@ func (self *InstanceManager) StartFileBrowser(ctx context.Context, serverId stri
|
||||
|
||||
command := self.config.FileBrowser.Command
|
||||
|
||||
if command == "" {
|
||||
command = "--noauth -r /tmp/data"
|
||||
}
|
||||
command += fmt.Sprintf("-d /tmp/database/database.db -r /tmp/data -b /browsers/%s/", labelId)
|
||||
|
||||
splitCommand, err := shellwords.Split(command)
|
||||
if err != nil {
|
||||
@@ -524,7 +582,7 @@ func (self *InstanceManager) StartFileBrowser(ctx context.Context, serverId stri
|
||||
}
|
||||
|
||||
ContainerResponse, err := self.client.ContainerCreate(
|
||||
context.TODO(),
|
||||
ctx,
|
||||
&container.Config{
|
||||
Cmd: splitCommand,
|
||||
Image: fmt.Sprintf("%s:%s", self.config.FileBrowser.Image.Registry, self.config.FileBrowser.Image.Tag),
|
||||
@@ -532,7 +590,7 @@ func (self *InstanceManager) StartFileBrowser(ctx context.Context, serverId stri
|
||||
Tty: true,
|
||||
},
|
||||
&container.HostConfig{
|
||||
Mounts: []mount.Mount{{Source: server.Id, Target: "/tmp/data", Type: "volume"}},
|
||||
Mounts: []mount.Mount{{Source: server.Id, Target: "/tmp/data", Type: "volume"}, {Source: volume.Name, Target: "/tmp/database/", Type: mount.TypeVolume}},
|
||||
AutoRemove: true,
|
||||
ConsoleSize: [2]uint{1000, 1000},
|
||||
},
|
||||
@@ -548,14 +606,15 @@ func (self *InstanceManager) StartFileBrowser(ctx context.Context, serverId stri
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = self.client.ContainerStart(context.TODO(), ContainerResponse.ID, container.StartOptions{})
|
||||
err = self.client.ContainerStart(ctx, ContainerResponse.ID, container.StartOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &models.FileBrowser{
|
||||
Url: serverId[:12] + "." + self.config.BrowsersDomain,
|
||||
Id: ContainerResponse.ID,
|
||||
Url: fmt.Sprintf("%s/browsers/%s/", self.siteDomain, server.Id),
|
||||
ServerId: server.Id,
|
||||
Id: volume.Name,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -566,16 +625,26 @@ func (self *InstanceManager) StopFileBrowser(ctx context.Context, serverId strin
|
||||
}
|
||||
|
||||
for _, rawContainer := range containers {
|
||||
stopChan, _ := self.client.ContainerWait(ctx, rawContainer.ID, container.WaitConditionRemoved)
|
||||
err := self.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)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewInstanceManager(config models.DockerInstanceManagerConfig) (*InstanceManager, error) {
|
||||
func NewInstanceManager(config models.DockerInstanceManagerConfig, siteDomain string) (*InstanceManager, error) {
|
||||
apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -584,7 +653,8 @@ func NewInstanceManager(config models.DockerInstanceManagerConfig) (*InstanceMan
|
||||
defer apiClient.Close()
|
||||
|
||||
return &InstanceManager{
|
||||
config: config,
|
||||
client: apiClient,
|
||||
config: config,
|
||||
client: apiClient,
|
||||
siteDomain: siteDomain,
|
||||
}, nil
|
||||
}
|
||||
|
@@ -19,7 +19,8 @@ type BrowserLabels struct {
|
||||
}
|
||||
|
||||
type VolumeLabels struct {
|
||||
Type ContainerType `json:"type,omitempty"`
|
||||
Type ContainerType `json:"type,omitempty"`
|
||||
VolumeId string `json:"volume_id,omitempty"`
|
||||
}
|
||||
|
||||
type ImageLabels struct {
|
||||
|
Reference in New Issue
Block a user