Merge branch 'master' into policies

This commit is contained in:
Miroslav Šedivý
2021-07-27 19:44:26 +02:00
4 changed files with 132 additions and 92 deletions
+5 -22
View File
@@ -13,34 +13,17 @@ import (
) )
func (manager *RoomManagerCtx) containerToEntry(container dockerTypes.Container) (*types.RoomEntry, error) { func (manager *RoomManagerCtx) containerToEntry(container dockerTypes.Container) (*types.RoomEntry, error) {
roomName, ok := container.Labels["m1k1o.neko_rooms.name"] labels, err := manager.extractLabels(container.Labels)
if !ok {
return nil, fmt.Errorf("damaged container labels: name not found")
}
nekoImage, ok := container.Labels["m1k1o.neko_rooms.neko_image"]
if !ok {
// Backward compatibility.
nekoImage = container.Image
//return nil, fmt.Errorf("Damaged container labels: neko_image not found.")
}
URL, ok := container.Labels["m1k1o.neko_rooms.url"]
if !ok {
return nil, fmt.Errorf("damaged container labels: url not found")
}
epr, err := manager.getEprFromLabels(container.Labels)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &types.RoomEntry{ return &types.RoomEntry{
ID: container.ID, ID: container.ID,
URL: URL, URL: labels.URL,
Name: roomName, Name: labels.Name,
NekoImage: nekoImage, NekoImage: labels.NekoImage,
MaxConnections: epr.Max - epr.Min + 1, MaxConnections: labels.Epr.Max - labels.Epr.Min + 1,
Running: container.State == "running", Running: container.State == "running",
Status: container.Status, Status: container.Status,
Created: time.Unix(container.Created, 0), Created: time.Unix(container.Created, 0),
+71
View File
@@ -0,0 +1,71 @@
package room
import (
"fmt"
"strconv"
)
type RoomLabels struct {
Name string
URL string
Epr EprPorts
NekoImage string
}
func (manager *RoomManagerCtx) extractLabels(labels map[string]string) (*RoomLabels, error) {
name, ok := labels["m1k1o.neko_rooms.name"]
if !ok {
return nil, fmt.Errorf("damaged container labels: name not found")
}
url, ok := labels["m1k1o.neko_rooms.url"]
if !ok {
return nil, fmt.Errorf("damaged container labels: url not found")
}
nekoImage, ok := labels["m1k1o.neko_rooms.neko_image"]
if !ok {
return nil, fmt.Errorf("damaged container labels: neko_image not found")
}
eprMinStr, ok := labels["m1k1o.neko_rooms.epr.min"]
if !ok {
return nil, fmt.Errorf("damaged container labels: epr.min not found")
}
eprMin, err := strconv.ParseUint(eprMinStr, 10, 16)
if err != nil {
return nil, err
}
eprMaxStr, ok := labels["m1k1o.neko_rooms.epr.max"]
if !ok {
return nil, fmt.Errorf("damaged container labels: epr.max not found")
}
eprMax, err := strconv.ParseUint(eprMaxStr, 10, 16)
if err != nil {
return nil, err
}
return &RoomLabels{
Name: name,
URL: url,
NekoImage: nekoImage,
Epr: EprPorts{
Min: uint16(eprMin),
Max: uint16(eprMax),
},
}, nil
}
func (manager *RoomManagerCtx) serializeLabels(labels RoomLabels) map[string]string {
return map[string]string{
"m1k1o.neko_rooms.name": labels.Name,
"m1k1o.neko_rooms.url": labels.URL,
"m1k1o.neko_rooms.instance": manager.config.InstanceName,
"m1k1o.neko_rooms.epr.min": fmt.Sprintf("%d", labels.Epr.Min),
"m1k1o.neko_rooms.epr.max": fmt.Sprintf("%d", labels.Epr.Max),
"m1k1o.neko_rooms.neko_image": labels.NekoImage,
}
}
+54 -38
View File
@@ -115,6 +115,10 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro
} }
} }
//
// Allocate ports
//
epr, err := manager.allocatePorts(settings.MaxConnections) epr, err := manager.allocatePorts(settings.MaxConnections)
if err != nil { if err != nil {
return "", err return "", err
@@ -138,8 +142,33 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro
exposedPorts[portKey] = struct{}{} exposedPorts[portKey] = struct{}{}
} }
//
// Set traefik labels
//
containerName := manager.config.InstanceName + "-" + roomName containerName := manager.config.InstanceName + "-" + roomName
traefikLabels := map[string]string{
"traefik.enable": "true",
"traefik.http.services." + containerName + "-frontend.loadbalancer.server.port": fmt.Sprintf("%d", frontendPort),
"traefik.http.routers." + containerName + ".entrypoints": manager.config.TraefikEntrypoint,
"traefik.http.routers." + containerName + ".rule": "Host(`" + manager.config.TraefikDomain + "`) && PathPrefix(`/" + roomName + "`)",
"traefik.http.middlewares." + containerName + "-rdr.redirectregex.regex": "/" + roomName + "$$",
"traefik.http.middlewares." + containerName + "-rdr.redirectregex.replacement": "/" + roomName + "/",
"traefik.http.middlewares." + containerName + "-prf.stripprefix.prefixes": "/" + roomName + "/",
"traefik.http.routers." + containerName + ".middlewares": containerName + "-rdr," + containerName + "-prf",
}
// optional HTTPS
if manager.config.TraefikCertresolver != "" {
traefikLabels["traefik.http.routers."+containerName+".tls"] = "true"
traefikLabels["traefik.http.routers."+containerName+".tls.certresolver"] = manager.config.TraefikCertresolver
}
//
// Set internal labels
//
instanceUrl := manager.config.InstanceUrl instanceUrl := manager.config.InstanceUrl
if instanceUrl == "" { if instanceUrl == "" {
urlProto := "http" urlProto := "http"
@@ -158,31 +187,20 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro
instanceUrl = instanceUrl + "/" instanceUrl = instanceUrl + "/"
} }
labels := map[string]string{ labels := manager.serializeLabels(RoomLabels{
// Set internal labels Name: roomName,
"m1k1o.neko_rooms.name": roomName, URL: instanceUrl + roomName + "/",
"m1k1o.neko_rooms.url": instanceUrl + roomName + "/", Epr: epr,
"m1k1o.neko_rooms.instance": manager.config.InstanceName, NekoImage: settings.NekoImage,
"m1k1o.neko_rooms.epr.min": fmt.Sprintf("%d", epr.Min), })
"m1k1o.neko_rooms.epr.max": fmt.Sprintf("%d", epr.Max),
"m1k1o.neko_rooms.neko_image": settings.NekoImage,
// Set traefik labels for k, v := range traefikLabels {
"traefik.enable": "true", labels[k] = v
"traefik.http.services." + containerName + "-frontend.loadbalancer.server.port": fmt.Sprintf("%d", frontendPort),
"traefik.http.routers." + containerName + ".entrypoints": manager.config.TraefikEntrypoint,
"traefik.http.routers." + containerName + ".rule": "Host(`" + manager.config.TraefikDomain + "`) && PathPrefix(`/" + roomName + "`)",
"traefik.http.middlewares." + containerName + "-rdr.redirectregex.regex": "/" + roomName + "$$",
"traefik.http.middlewares." + containerName + "-rdr.redirectregex.replacement": "/" + roomName + "/",
"traefik.http.middlewares." + containerName + "-prf.stripprefix.prefixes": "/" + roomName + "/",
"traefik.http.routers." + containerName + ".middlewares": containerName + "-rdr," + containerName + "-prf",
} }
// optional HTTPS //
if manager.config.TraefikCertresolver != "" { // Set environment variables
labels["traefik.http.routers."+containerName+".tls"] = "true" //
labels["traefik.http.routers."+containerName+".tls.certresolver"] = manager.config.TraefikCertresolver
}
env := []string{ env := []string{
fmt.Sprintf("NEKO_BIND=:%d", frontendPort), fmt.Sprintf("NEKO_BIND=:%d", frontendPort),
@@ -245,6 +263,10 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro
} }
} }
//
// Set container mounts
//
paths := map[string]bool{} paths := map[string]bool{}
mounts := []dockerMount.Mount{} mounts := []dockerMount.Mount{}
for _, mount := range settings.Mounts { for _, mount := range settings.Mounts {
@@ -319,6 +341,10 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro
paths[mount.ContainerPath] = true paths[mount.ContainerPath] = true
} }
//
// Set container configs
//
config := &container.Config{ config := &container.Config{
// Hostname // Hostname
Hostname: containerName, Hostname: containerName,
@@ -417,22 +443,12 @@ func (manager *RoomManagerCtx) GetSettings(id string) (*types.RoomSettings, erro
return nil, err return nil, err
} }
roomName, ok := container.Config.Labels["m1k1o.neko_rooms.name"] labels, err := manager.extractLabels(container.Config.Labels)
if !ok {
return nil, fmt.Errorf("damaged container labels: name not found")
}
nekoImage, ok := container.Config.Labels["m1k1o.neko_rooms.neko_image"]
if !ok {
return nil, fmt.Errorf("damaged container labels: neko_image not found")
}
epr, err := manager.getEprFromLabels(container.Config.Labels)
if err != nil { if err != nil {
return nil, err return nil, err
} }
privateStorageRoot := path.Join(manager.config.StorageExternal, privateStoragePath, roomName) privateStorageRoot := path.Join(manager.config.StorageExternal, privateStoragePath, labels.Name)
templateStorageRoot := path.Join(manager.config.StorageExternal, templateStoragePath) templateStorageRoot := path.Join(manager.config.StorageExternal, templateStoragePath)
mounts := []types.RoomMount{} mounts := []types.RoomMount{}
@@ -456,7 +472,7 @@ func (manager *RoomManagerCtx) GetSettings(id string) (*types.RoomSettings, erro
} }
var policiesData *types.Policies var policiesData *types.Policies
policyConfig := policies.GetConfig(nekoImage) policyConfig := policies.GetConfig(labels.NekoImage)
if policyConfig != nil { if policyConfig != nil {
var policyMount *types.RoomMount var policyMount *types.RoomMount
for _, mount := range mounts { for _, mount := range mounts {
@@ -480,9 +496,9 @@ func (manager *RoomManagerCtx) GetSettings(id string) (*types.RoomSettings, erro
} }
settings := types.RoomSettings{ settings := types.RoomSettings{
Name: roomName, Name: labels.Name,
NekoImage: nekoImage, NekoImage: labels.NekoImage,
MaxConnections: epr.Max - epr.Min + 1, MaxConnections: labels.Epr.Max - labels.Epr.Min + 1,
Mounts: mounts, Mounts: mounts,
Policies: policiesData, Policies: policiesData,
} }
+2 -32
View File
@@ -3,7 +3,6 @@ package room
import ( import (
"fmt" "fmt"
"sort" "sort"
"strconv"
) )
type EprPorts struct { type EprPorts struct {
@@ -51,12 +50,12 @@ func (manager *RoomManagerCtx) getUsedPorts() ([]EprPorts, error) {
result := []EprPorts{} result := []EprPorts{}
for _, container := range containers { for _, container := range containers {
epr, err := manager.getEprFromLabels(container.Labels) labels, err := manager.extractLabels(container.Labels)
if err != nil { if err != nil {
return nil, err return nil, err
} }
result = append(result, epr) result = append(result, labels.Epr)
} }
sort.SliceStable(result, func(i, j int) bool { sort.SliceStable(result, func(i, j int) bool {
@@ -65,32 +64,3 @@ func (manager *RoomManagerCtx) getUsedPorts() ([]EprPorts, error) {
return result, nil return result, nil
} }
func (manager *RoomManagerCtx) getEprFromLabels(labels map[string]string) (EprPorts, error) {
var err error
epr := EprPorts{}
eprMinStr, ok := labels["m1k1o.neko_rooms.epr.min"]
if !ok {
return epr, fmt.Errorf("damaged container labels: epr.min not found")
}
eprMin, err := strconv.ParseUint(eprMinStr, 10, 16)
if err != nil {
return epr, err
}
eprMaxStr, ok := labels["m1k1o.neko_rooms.epr.max"]
if !ok {
return epr, fmt.Errorf("damaged container labels: epr.max not found")
}
eprMax, err := strconv.ParseUint(eprMaxStr, 10, 16)
if err != nil {
return epr, err
}
epr.Min = uint16(eprMin)
epr.Max = uint16(eprMax)
return epr, nil
}