feat: wip implement port forwarding
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user