Compare commits
4 Commits
v2023.3.28
...
v2023.3.29
Author | SHA1 | Date | |
---|---|---|---|
351f22e216 | |||
854a6ae41b | |||
a48c2ebe14 | |||
cdd78e4031 |
2
go.mod
2
go.mod
@ -4,6 +4,7 @@ go 1.19
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
forge.cadoles.com/arcad/edge v0.0.0-20230328183829-d8ce2901d2ab
|
forge.cadoles.com/arcad/edge v0.0.0-20230328183829-d8ce2901d2ab
|
||||||
|
github.com/Masterminds/sprig/v3 v3.2.3
|
||||||
github.com/alecthomas/participle/v2 v2.0.0-beta.5
|
github.com/alecthomas/participle/v2 v2.0.0-beta.5
|
||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
|
||||||
github.com/btcsuite/btcd/btcutil v1.1.3
|
github.com/btcsuite/btcd/btcutil v1.1.3
|
||||||
@ -31,7 +32,6 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
|
||||||
github.com/barnybug/go-cast v0.0.0-20201201064555-a87ccbc26692 // indirect
|
github.com/barnybug/go-cast v0.0.0-20201201064555-a87ccbc26692 // indirect
|
||||||
github.com/dop251/goja_nodejs v0.0.0-20230320130059-dcf93ba651dd // indirect
|
github.com/dop251/goja_nodejs v0.0.0-20230320130059-dcf93ba651dd // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.1 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.1 // indirect
|
||||||
|
4
go.sum
4
go.sum
@ -54,10 +54,6 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
|||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
forge.cadoles.com/arcad/edge v0.0.0-20230322170544-cf8a3f8ac077 h1:vsYcNHZevZrs0VeOTasvJoqvPynb8OvH+MMpIUvNT6Q=
|
|
||||||
forge.cadoles.com/arcad/edge v0.0.0-20230322170544-cf8a3f8ac077/go.mod h1:ONd6vyQ0IM0vHi1i+bmZBRc1Fd0BoXMuDdY/+0sZefw=
|
|
||||||
forge.cadoles.com/arcad/edge v0.0.0-20230328081549-e09de0b0a4f4 h1:ZBBOOKqCEt6F9/Ikkwc2xwYDr7JpLybvxtoRJwXt7Gw=
|
|
||||||
forge.cadoles.com/arcad/edge v0.0.0-20230328081549-e09de0b0a4f4/go.mod h1:ONd6vyQ0IM0vHi1i+bmZBRc1Fd0BoXMuDdY/+0sZefw=
|
|
||||||
forge.cadoles.com/arcad/edge v0.0.0-20230328183829-d8ce2901d2ab h1:xOtzLAYOUcKd/VBx/PzL2riC0zNuQ/cxxf5r3AmEvJE=
|
forge.cadoles.com/arcad/edge v0.0.0-20230328183829-d8ce2901d2ab h1:xOtzLAYOUcKd/VBx/PzL2riC0zNuQ/cxxf5r3AmEvJE=
|
||||||
forge.cadoles.com/arcad/edge v0.0.0-20230328183829-d8ce2901d2ab/go.mod h1:ONd6vyQ0IM0vHi1i+bmZBRc1Fd0BoXMuDdY/+0sZefw=
|
forge.cadoles.com/arcad/edge v0.0.0-20230328183829-d8ce2901d2ab/go.mod h1:ONd6vyQ0IM0vHi1i+bmZBRc1Fd0BoXMuDdY/+0sZefw=
|
||||||
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
|
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
|
||||||
|
@ -51,10 +51,8 @@ func (c *Controller) getHandlerOptions(ctx context.Context, appKey string, specs
|
|||||||
bundles = append(bundles, path)
|
bundles = append(bundles, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
getAppURL := createGetAppURL(specs)
|
|
||||||
|
|
||||||
bus := memory.NewBus()
|
bus := memory.NewBus()
|
||||||
modules := getAppModules(bus, db, specs, keySet, getAppURL, bundles)
|
modules := c.getAppModules(bus, db, specs, keySet)
|
||||||
|
|
||||||
options := []edgeHTTP.HandlerOptionFunc{
|
options := []edgeHTTP.HandlerOptionFunc{
|
||||||
edgeHTTP.WithBus(bus),
|
edgeHTTP.WithBus(bus),
|
||||||
@ -148,7 +146,7 @@ func createGetAppURL(specs *spec.Spec) GetURLFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAppModules(bus bus.Bus, db *sql.DB, spec *appSpec.Spec, keySet jwk.Set, getAppURL GetURLFunc, bundles []string) []app.ServerModuleFactory {
|
func (c *Controller) getAppModules(bus bus.Bus, db *sql.DB, spec *appSpec.Spec, keySet jwk.Set) []app.ServerModuleFactory {
|
||||||
ds := sqlite.NewDocumentStoreWithDB(db)
|
ds := sqlite.NewDocumentStoreWithDB(db)
|
||||||
bs := sqlite.NewBlobStoreWithDB(db)
|
bs := sqlite.NewBlobStoreWithDB(db)
|
||||||
|
|
||||||
@ -185,6 +183,6 @@ func getAppModules(bus bus.Bus, db *sql.DB, spec *appSpec.Spec, keySet jwk.Set,
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
appModule.ModuleFactory(NewAppRepository(getAppURL, bundles...)),
|
appModule.ModuleFactory(c.appRepository),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"forge.cadoles.com/arcad/edge/pkg/app"
|
"forge.cadoles.com/arcad/edge/pkg/app"
|
||||||
"forge.cadoles.com/arcad/edge/pkg/bundle"
|
"forge.cadoles.com/arcad/edge/pkg/bundle"
|
||||||
@ -15,10 +16,14 @@ type GetURLFunc func(context.Context, *app.Manifest) (string, error)
|
|||||||
type AppRepository struct {
|
type AppRepository struct {
|
||||||
getURL GetURLFunc
|
getURL GetURLFunc
|
||||||
bundles []string
|
bundles []string
|
||||||
|
mutex sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get implements app.Repository
|
// Get implements app.Repository
|
||||||
func (r *AppRepository) Get(ctx context.Context, id app.ID) (*app.Manifest, error) {
|
func (r *AppRepository) Get(ctx context.Context, id app.ID) (*app.Manifest, error) {
|
||||||
|
r.mutex.RLock()
|
||||||
|
defer r.mutex.RUnlock()
|
||||||
|
|
||||||
manifest, err := r.findManifest(ctx, id)
|
manifest, err := r.findManifest(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStack(err)
|
||||||
@ -29,6 +34,9 @@ func (r *AppRepository) Get(ctx context.Context, id app.ID) (*app.Manifest, erro
|
|||||||
|
|
||||||
// GetURL implements app.Repository
|
// GetURL implements app.Repository
|
||||||
func (r *AppRepository) GetURL(ctx context.Context, id app.ID) (string, error) {
|
func (r *AppRepository) GetURL(ctx context.Context, id app.ID) (string, error) {
|
||||||
|
r.mutex.RLock()
|
||||||
|
defer r.mutex.RUnlock()
|
||||||
|
|
||||||
manifest, err := r.findManifest(ctx, id)
|
manifest, err := r.findManifest(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.WithStack(err)
|
return "", errors.WithStack(err)
|
||||||
@ -44,6 +52,9 @@ func (r *AppRepository) GetURL(ctx context.Context, id app.ID) (string, error) {
|
|||||||
|
|
||||||
// List implements app.Repository
|
// List implements app.Repository
|
||||||
func (r *AppRepository) List(ctx context.Context) ([]*app.Manifest, error) {
|
func (r *AppRepository) List(ctx context.Context) ([]*app.Manifest, error) {
|
||||||
|
r.mutex.RLock()
|
||||||
|
defer r.mutex.RUnlock()
|
||||||
|
|
||||||
manifests := make([]*app.Manifest, 0)
|
manifests := make([]*app.Manifest, 0)
|
||||||
|
|
||||||
for _, path := range r.bundles {
|
for _, path := range r.bundles {
|
||||||
@ -69,6 +80,14 @@ func (r *AppRepository) List(ctx context.Context) ([]*app.Manifest, error) {
|
|||||||
return manifests, nil
|
return manifests, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *AppRepository) Update(getURL GetURLFunc, bundles []string) {
|
||||||
|
r.mutex.Lock()
|
||||||
|
defer r.mutex.Unlock()
|
||||||
|
|
||||||
|
r.getURL = getURL
|
||||||
|
r.bundles = bundles
|
||||||
|
}
|
||||||
|
|
||||||
func (r *AppRepository) findManifest(ctx context.Context, id app.ID) (*app.Manifest, error) {
|
func (r *AppRepository) findManifest(ctx context.Context, id app.ID) (*app.Manifest, error) {
|
||||||
for _, path := range r.bundles {
|
for _, path := range r.bundles {
|
||||||
bundleCtx := logger.With(ctx, logger.F("path", path))
|
bundleCtx := logger.With(ctx, logger.F("path", path))
|
||||||
@ -97,8 +116,13 @@ func (r *AppRepository) findManifest(ctx context.Context, id app.ID) (*app.Manif
|
|||||||
return nil, errors.WithStack(appModule.ErrNotFound)
|
return nil, errors.WithStack(appModule.ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAppRepository(getURL GetURLFunc, bundles ...string) *AppRepository {
|
func NewAppRepository() *AppRepository {
|
||||||
return &AppRepository{getURL, bundles}
|
return &AppRepository{
|
||||||
|
getURL: func(ctx context.Context, m *app.Manifest) (string, error) {
|
||||||
|
return "", errors.New("unavailable")
|
||||||
|
},
|
||||||
|
bundles: []string{},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ appModule.Repository = &AppRepository{}
|
var _ appModule.Repository = &AppRepository{}
|
||||||
|
@ -16,7 +16,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type serverEntry struct {
|
type serverEntry struct {
|
||||||
SpecHash uint64
|
AppDefHash uint64
|
||||||
Server *Server
|
Server *Server
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,6 +25,7 @@ type Controller struct {
|
|||||||
downloadDir string
|
downloadDir string
|
||||||
dataDir string
|
dataDir string
|
||||||
servers map[string]*serverEntry
|
servers map[string]*serverEntry
|
||||||
|
appRepository *AppRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name implements node.Controller.
|
// Name implements node.Controller.
|
||||||
@ -95,7 +96,9 @@ func (c *Controller) updateApps(ctx context.Context, specs *spec.Spec) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// (Re)start apps
|
c.updateAppRepository(ctx, specs)
|
||||||
|
|
||||||
|
// (Re)start apps if necessary
|
||||||
for appKey := range specs.Apps {
|
for appKey := range specs.Apps {
|
||||||
appCtx := logger.With(ctx, logger.F("appKey", appKey))
|
appCtx := logger.With(ctx, logger.F("appKey", appKey))
|
||||||
|
|
||||||
@ -106,10 +109,35 @@ func (c *Controller) updateApps(ctx context.Context, specs *spec.Spec) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Controller) updateAppRepository(ctx context.Context, specs *spec.Spec) {
|
||||||
|
bundles := make([]string, 0, len(specs.Apps))
|
||||||
|
for appKey, app := range specs.Apps {
|
||||||
|
path := c.getAppBundlePath(appKey, app.Format)
|
||||||
|
bundles = append(bundles, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
getURL := createGetAppURL(specs)
|
||||||
|
|
||||||
|
c.appRepository.Update(getURL, bundles)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Controller) updateApp(ctx context.Context, specs *spec.Spec, appKey string) (err error) {
|
func (c *Controller) updateApp(ctx context.Context, specs *spec.Spec, appKey string) (err error) {
|
||||||
appEntry := specs.Apps[appKey]
|
appEntry := specs.Apps[appKey]
|
||||||
|
|
||||||
newAppSpecHash, err := hashstructure.Hash(appEntry, hashstructure.FormatV2, nil)
|
var auth *spec.Auth
|
||||||
|
if specs.Config != nil {
|
||||||
|
auth = specs.Config.Auth
|
||||||
|
}
|
||||||
|
|
||||||
|
appDef := struct {
|
||||||
|
App spec.AppEntry
|
||||||
|
Auth *spec.Auth
|
||||||
|
}{
|
||||||
|
App: appEntry,
|
||||||
|
Auth: auth,
|
||||||
|
}
|
||||||
|
|
||||||
|
newAppDefHash, err := hashstructure.Hash(appDef, hashstructure.FormatV2, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
@ -149,19 +177,19 @@ func (c *Controller) updateApp(ctx context.Context, specs *spec.Spec, appKey str
|
|||||||
|
|
||||||
server = &serverEntry{
|
server = &serverEntry{
|
||||||
Server: NewServer(bundle, auth, options...),
|
Server: NewServer(bundle, auth, options...),
|
||||||
SpecHash: 0,
|
AppDefHash: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
c.servers[appKey] = server
|
c.servers[appKey] = server
|
||||||
}
|
}
|
||||||
|
|
||||||
specChanged := newAppSpecHash != server.SpecHash
|
defChanged := newAppDefHash != server.AppDefHash
|
||||||
|
|
||||||
if server.Server.Running() && !specChanged {
|
if server.Server.Running() && !defChanged {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if specChanged && server.SpecHash != 0 {
|
if defChanged && server.AppDefHash != 0 {
|
||||||
logger.Info(
|
logger.Info(
|
||||||
ctx, "restarting app",
|
ctx, "restarting app",
|
||||||
logger.F("address", appEntry.Address),
|
logger.F("address", appEntry.Address),
|
||||||
@ -179,7 +207,7 @@ func (c *Controller) updateApp(ctx context.Context, specs *spec.Spec, appKey str
|
|||||||
return errors.Wrap(err, "could not start app")
|
return errors.Wrap(err, "could not start app")
|
||||||
}
|
}
|
||||||
|
|
||||||
server.SpecHash = newAppSpecHash
|
server.AppDefHash = newAppDefHash
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -298,6 +326,7 @@ func NewController(funcs ...OptionFunc) *Controller {
|
|||||||
downloadDir: opts.DownloadDir,
|
downloadDir: opts.DownloadDir,
|
||||||
dataDir: opts.DataDir,
|
dataDir: opts.DataDir,
|
||||||
servers: make(map[string]*serverEntry),
|
servers: make(map[string]*serverEntry),
|
||||||
|
appRepository: NewAppRepository(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,11 +3,13 @@ package app
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec"
|
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec"
|
||||||
appSpec "forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec"
|
appSpec "forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec"
|
||||||
|
"forge.cadoles.com/Cadoles/emissary/internal/proxy/wildcard"
|
||||||
edgeHTTP "forge.cadoles.com/arcad/edge/pkg/http"
|
edgeHTTP "forge.cadoles.com/arcad/edge/pkg/http"
|
||||||
authHTTP "forge.cadoles.com/arcad/edge/pkg/module/auth/http"
|
authHTTP "forge.cadoles.com/arcad/edge/pkg/module/auth/http"
|
||||||
"gitlab.com/wpetit/goweb/logger"
|
"gitlab.com/wpetit/goweb/logger"
|
||||||
@ -109,7 +111,7 @@ func (s *Server) Stop() error {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
if err := s.server.Close(); err != nil {
|
if err := s.server.Close(); err != nil {
|
||||||
panic(errors.WithStack(err))
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -140,6 +142,10 @@ func (s *Server) configureAuth(router chi.Router, auth *spec.Auth) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.auth.Local.CookieDomain != "" {
|
||||||
|
router.Use(invalidCookieDomainRedirect(s.auth.Local.CookieDomain))
|
||||||
|
}
|
||||||
|
|
||||||
router.Handle("/auth/*", authHTTP.NewLocalHandler(
|
router.Handle("/auth/*", authHTTP.NewLocalHandler(
|
||||||
jwa.HS256, key,
|
jwa.HS256, key,
|
||||||
authHTTP.WithRoutePrefix("/auth"),
|
authHTTP.WithRoutePrefix("/auth"),
|
||||||
@ -158,3 +164,33 @@ func NewServer(bundle bundle.Bundle, auth *appSpec.Auth, handlerOptions ...edgeH
|
|||||||
handlerOptions: handlerOptions,
|
handlerOptions: handlerOptions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func invalidCookieDomainRedirect(cookieDomain string) func(http.Handler) http.Handler {
|
||||||
|
domain := strings.TrimPrefix(cookieDomain, ".")
|
||||||
|
hostPattern := "*" + domain
|
||||||
|
|
||||||
|
return func(h http.Handler) http.Handler {
|
||||||
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
hostParts := strings.SplitN(r.Host, ":", 2)
|
||||||
|
|
||||||
|
if !wildcard.Match(hostParts[0], hostPattern) {
|
||||||
|
url := r.URL
|
||||||
|
|
||||||
|
newHost := domain
|
||||||
|
if len(hostParts) > 1 {
|
||||||
|
newHost += ":" + hostParts[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
url.Host = newHost
|
||||||
|
|
||||||
|
http.Redirect(w, r, url.String(), http.StatusTemporaryRedirect)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
h.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
return http.HandlerFunc(fn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,6 +17,12 @@
|
|||||||
"sha256sum": "e97b7b79159bb5d6a13b05644c091272b02a1a3cbb1b613dd5eda37e1eb84623",
|
"sha256sum": "e97b7b79159bb5d6a13b05644c091272b02a1a3cbb1b613dd5eda37e1eb84623",
|
||||||
"address": "127.0.0.1:8084",
|
"address": "127.0.0.1:8084",
|
||||||
"format": "zip"
|
"format": "zip"
|
||||||
|
},
|
||||||
|
"diffusion": {
|
||||||
|
"url": "https://emissary.cadol.es/files/apps/arcad.diffusion_v2023.3.29-5b3fab4.zip",
|
||||||
|
"sha256sum": "1282e75719beedbc7c7e67879389d0f3e11c86d3d2c37cf13da624a66faaeb58",
|
||||||
|
"address": "127.0.0.1:8085",
|
||||||
|
"format": "zip"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
"hostPattern": "test.arcad.local:*",
|
"hostPattern": "test.arcad.local:*",
|
||||||
"target": "http://localhost:8084"
|
"target": "http://localhost:8084"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"hostPattern": "diffusion.arcad.local:*",
|
||||||
|
"target": "http://localhost:8085"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"hostPattern": "*",
|
"hostPattern": "*",
|
||||||
"target": "http://localhost:8082"
|
"target": "http://localhost:8082"
|
||||||
|
Reference in New Issue
Block a user