feat: wip implement port forwarding

This commit is contained in:
2024-11-20 21:05:31 +00:00
parent fb5e708fd8
commit 6e6fb06351
13 changed files with 790 additions and 356 deletions

View File

@@ -4,13 +4,16 @@ import (
"context"
"database/sql"
"errors"
"fmt"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/google/uuid"
"github.com/uptrace/bun"
"net/url"
"regexp"
"sync"
"tesseract/internal/docker"
"tesseract/internal/reverseproxy"
"tesseract/internal/service"
)
@@ -31,6 +34,18 @@ type workspace struct {
SSHPort int `bun:"-" json:"sshPort,omitempty"`
Status status `bun:"-" json:"status"`
PortMappings []portMapping `bun:"rel:has-many,join:id=workspace_id" json:"ports,omitempty"`
}
type portMapping struct {
bun.BaseModel `bun:"table:port_mappings,alias:port_mapping"`
WorkspaceID uuid.UUID `bun:",type:uuid,pk" json:"-"`
ContainerPort int `json:"port"`
Subdomain string `json:"subdomain"`
Workspace workspace `bun:"rel:belongs-to,join:workspace_id=id"`
}
// status represents the status of a workspace.
@@ -122,5 +137,66 @@ func SyncAll(ctx context.Context, services service.Services) error {
return err
}
if err = initializeHTTPProxies(ctx, services.Database, services.DockerClient, services.ReverseProxy); err != nil {
return err
}
return nil
}
func initializeHTTPProxies(ctx context.Context, db *bun.DB, dockerClient *client.Client, proxy *reverseproxy.ReverseProxy) error {
var mappings []portMapping
if err := db.NewSelect().
Model(&mappings).
Relation("Workspace", func(q *bun.SelectQuery) *bun.SelectQuery {
return q.Column("container_id")
}).
Scan(ctx); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil
}
return err
}
if len(mappings) == 0 {
return nil
}
var wg sync.WaitGroup
var errs []error
var mu sync.Mutex
for _, m := range mappings {
m := m
wg.Add(1)
go func() {
var err error
defer wg.Done()
defer func() {
mu.Lock()
errs = append(errs, err)
mu.Unlock()
}()
inspect, err := dockerClient.ContainerInspect(ctx, m.Workspace.ContainerID)
if err != nil {
return
}
u, err := url.Parse(fmt.Sprintf("http://%s:%d", inspect.NetworkSettings.IPAddress, m.ContainerPort))
if err != nil {
return
}
proxy.AddEntry(m.Subdomain, u)
}()
}
wg.Wait()
if err := errors.Join(errs...); err != nil {
return err
}
return nil
}