feat: rename gateway spec to proxy
This commit is contained in:
parent
fa36d55163
commit
fbcd3ca806
8
go.mod
8
go.mod
@ -3,12 +3,13 @@ module forge.cadoles.com/Cadoles/emissary
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230310133312-fd12d2ba42fa
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230320204239-1f4f795d43ff
|
||||
github.com/alecthomas/participle/v2 v2.0.0-beta.5
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
|
||||
github.com/btcsuite/btcd/btcutil v1.1.3
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/denisbrodbeck/machineid v1.0.1
|
||||
github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c
|
||||
github.com/evanphx/json-patch/v5 v5.6.0
|
||||
github.com/go-chi/chi v4.1.2+incompatible
|
||||
github.com/go-chi/cors v1.2.1
|
||||
@ -17,6 +18,7 @@ require (
|
||||
github.com/jedib0t/go-pretty/v6 v6.4.4
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.8
|
||||
github.com/lithammer/shortuuid/v4 v4.0.0
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/qri-io/jsonschema v0.2.1
|
||||
@ -29,7 +31,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/barnybug/go-cast v0.0.0-20201201064555-a87ccbc26692 // indirect
|
||||
github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c // indirect
|
||||
github.com/dop251/goja_nodejs v0.0.0-20230226152057-060fa99b809f // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.1 // indirect
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||
@ -40,7 +41,6 @@ require (
|
||||
github.com/hashicorp/mdns v1.0.5 // indirect
|
||||
github.com/igm/sockjs-go/v3 v3.0.2 // indirect
|
||||
github.com/miekg/dns v1.1.51 // indirect
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
|
||||
github.com/oklog/ulid/v2 v2.1.0 // indirect
|
||||
github.com/orcaman/concurrent-map v1.0.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
@ -107,3 +107,5 @@ require (
|
||||
modernc.org/strutil v1.1.3 // indirect
|
||||
modernc.org/token v1.1.0 // indirect
|
||||
)
|
||||
|
||||
// replace forge.cadoles.com/arcad/edge => ../edge
|
||||
|
18
go.sum
18
go.sum
@ -54,10 +54,10 @@ 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.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=
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230303153719-6399196fe5c9 h1:dleaaf/rV2GWtGvrPunRakjrKVDfXoANxAy8/1ctMVs=
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230303153719-6399196fe5c9/go.mod h1:pl9EMtSLSVr4wbDgQBDjr4aizwtmwasE686dm5arYPw=
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230310133312-fd12d2ba42fa h1:dk0rNaBuCx0SxWTZBodg/y655tBaRtgLcW2hDqZRdxg=
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230310133312-fd12d2ba42fa/go.mod h1:pl9EMtSLSVr4wbDgQBDjr4aizwtmwasE686dm5arYPw=
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230320204239-1f4f795d43ff h1:dT7cZQWzSYfW3dVDOSe6OACBGBQNvn0wo32BIvDEowE=
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230320204239-1f4f795d43ff/go.mod h1:ONd6vyQ0IM0vHi1i+bmZBRc1Fd0BoXMuDdY/+0sZefw=
|
||||
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
@ -448,8 +448,6 @@ github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZ
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
||||
github.com/dop251/goja v0.0.0-20221118162653-d4bf6fde1b86/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs=
|
||||
github.com/dop251/goja v0.0.0-20230226152633-7c93113e17ac h1:NGu46Adk2oPN3tinGFItahy4W9l+9uhEf03ZxbwmdVE=
|
||||
github.com/dop251/goja v0.0.0-20230226152633-7c93113e17ac/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs=
|
||||
github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c h1:/utv6nmTctV6OVgfk5+O6lEMEWL+6KJy4h9NZ5fnkQQ=
|
||||
github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
|
||||
@ -696,7 +694,6 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||
github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg=
|
||||
github.com/google/pprof v0.0.0-20230309165930-d61513b1440d h1:um9/pc7tKMINFfP1eE7Wv6PRGXlcCSJkVajF7KJw3uQ=
|
||||
github.com/google/pprof v0.0.0-20230309165930-d61513b1440d/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk=
|
||||
@ -1028,7 +1025,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA
|
||||
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU=
|
||||
github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
|
||||
@ -1389,8 +1385,6 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@ -1519,8 +1513,6 @@ golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@ -1686,8 +1678,6 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
@ -1697,8 +1687,6 @@ golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuX
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -1713,8 +1701,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/spec/app"
|
||||
"forge.cadoles.com/arcad/edge/pkg/bundle"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/sqlite"
|
||||
"github.com/lestrrat-go/jwx/v2/jwk"
|
||||
"github.com/mitchellh/hashstructure/v2"
|
||||
"github.com/pkg/errors"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
@ -96,18 +97,32 @@ func (c *Controller) updateApps(ctx context.Context, spec *app.Spec) {
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
key jwk.Key
|
||||
err error
|
||||
)
|
||||
|
||||
if spec.Auth != nil {
|
||||
key, err = jwk.FromRaw(spec.Auth.Key)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not parse authentication key", logger.E(errors.WithStack(err)))
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// (Re)start apps
|
||||
for appID, appSpec := range spec.Apps {
|
||||
appCtx := logger.With(ctx, logger.F("appID", appID))
|
||||
|
||||
if err := c.updateApp(ctx, appID, appSpec); err != nil {
|
||||
if err := c.updateApp(ctx, appID, appSpec, key); err != nil {
|
||||
logger.Error(appCtx, "could not update app", logger.E(errors.WithStack(err)))
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) updateApp(ctx context.Context, appID string, appSpec app.AppEntry) (err error) {
|
||||
func (c *Controller) updateApp(ctx context.Context, appID string, appSpec app.AppEntry, key jwk.Key) (err error) {
|
||||
newAppSpecHash, err := hashstructure.Hash(appSpec, hashstructure.FormatV2, nil)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
@ -150,7 +165,7 @@ func (c *Controller) updateApp(ctx context.Context, appID string, appSpec app.Ap
|
||||
}
|
||||
|
||||
entry = &serverEntry{
|
||||
Server: NewServer(bundle, db),
|
||||
Server: NewServer(bundle, db, key),
|
||||
SpecHash: 0,
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"github.com/dop251/goja"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/lestrrat-go/jwx/v2/jwk"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@ -30,6 +31,7 @@ type Server struct {
|
||||
db *sql.DB
|
||||
server *http.Server
|
||||
serverMutex sync.RWMutex
|
||||
key jwk.Key
|
||||
}
|
||||
|
||||
func (s *Server) Start(ctx context.Context, addr string) (err error) {
|
||||
@ -129,7 +131,9 @@ func (s *Server) getAppModules(bus bus.Bus, ds storage.DocumentStore, bs storage
|
||||
module.StoreModuleFactory(ds),
|
||||
module.BlobModuleFactory(bus, bs),
|
||||
module.Extends(
|
||||
auth.ModuleFactory(),
|
||||
auth.ModuleFactory(
|
||||
auth.WithJWT(s.getJWTKeySet),
|
||||
),
|
||||
func(o *goja.Object) {
|
||||
if err := o.Set("CLAIM_ROLE", "role"); err != nil {
|
||||
panic(errors.New("could not set 'CLAIM_ROLE' property"))
|
||||
@ -143,9 +147,20 @@ func (s *Server) getAppModules(bus bus.Bus, ds storage.DocumentStore, bs storage
|
||||
}
|
||||
}
|
||||
|
||||
func NewServer(bundle bundle.Bundle, db *sql.DB) *Server {
|
||||
func (s *Server) getJWTKeySet() (jwk.Set, error) {
|
||||
set := jwk.NewSet()
|
||||
|
||||
if err := set.AddKey(s.key); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return set, nil
|
||||
}
|
||||
|
||||
func NewServer(bundle bundle.Bundle, db *sql.DB, key jwk.Key) *Server {
|
||||
return &Server{
|
||||
bundle: bundle,
|
||||
db: db,
|
||||
key: key,
|
||||
}
|
||||
}
|
||||
|
@ -1,124 +0,0 @@
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/spec/gateway"
|
||||
"github.com/pkg/errors"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
proxies map[gateway.ID]*ReverseProxy
|
||||
currentSpecRevision int
|
||||
}
|
||||
|
||||
// Name implements node.Controller.
|
||||
func (c *Controller) Name() string {
|
||||
return "gateway-controller"
|
||||
}
|
||||
|
||||
// Reconcile implements node.Controller.
|
||||
func (c *Controller) Reconcile(ctx context.Context, state *agent.State) error {
|
||||
gatewaySpec := gateway.NewSpec()
|
||||
|
||||
if err := state.GetSpec(gateway.NameGateway, gatewaySpec); err != nil {
|
||||
if errors.Is(err, agent.ErrSpecNotFound) {
|
||||
logger.Info(ctx, "could not find gateway spec, stopping all remaining proxies")
|
||||
|
||||
c.stopAllProxies(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
logger.Info(ctx, "retrieved spec", logger.F("spec", gatewaySpec.SpecName()), logger.F("revision", gatewaySpec.SpecRevision()))
|
||||
|
||||
if c.currentSpecRevision == gatewaySpec.SpecRevision() {
|
||||
logger.Info(ctx, "spec revision did not change, doing nothing")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
c.updateProxies(ctx, gatewaySpec)
|
||||
|
||||
c.currentSpecRevision = gatewaySpec.SpecRevision()
|
||||
logger.Info(ctx, "updating current spec revision", logger.F("revision", c.currentSpecRevision))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) stopAllProxies(ctx context.Context) {
|
||||
for gatewayID, proxy := range c.proxies {
|
||||
logger.Info(ctx, "stopping proxy", logger.F("gatewayID", gatewayID))
|
||||
|
||||
if err := proxy.Stop(); err != nil {
|
||||
logger.Error(
|
||||
ctx, "error while stopping proxy",
|
||||
logger.F("gatewayID", gatewayID),
|
||||
logger.E(errors.WithStack(err)),
|
||||
)
|
||||
|
||||
delete(c.proxies, gatewayID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) updateProxies(ctx context.Context, spec *gateway.Spec) {
|
||||
// Stop and remove obsolete gateways
|
||||
for gatewayID, proxy := range c.proxies {
|
||||
if _, exists := spec.Gateways[gatewayID]; exists {
|
||||
continue
|
||||
}
|
||||
|
||||
logger.Info(ctx, "stopping proxy", logger.F("gatewayID", gatewayID))
|
||||
|
||||
if err := proxy.Stop(); err != nil {
|
||||
logger.Error(
|
||||
ctx, "error while stopping proxy",
|
||||
logger.F("gatewayID", gatewayID),
|
||||
logger.E(errors.WithStack(err)),
|
||||
)
|
||||
|
||||
delete(c.proxies, gatewayID)
|
||||
}
|
||||
}
|
||||
|
||||
// (Re)start gateways
|
||||
for gatewayID, gatewaySpec := range spec.Gateways {
|
||||
proxy, exists := c.proxies[gatewayID]
|
||||
if !exists {
|
||||
proxy = NewReverseProxy()
|
||||
c.proxies[gatewayID] = proxy
|
||||
}
|
||||
|
||||
logger.Info(
|
||||
ctx, "starting proxy",
|
||||
logger.F("gatewayID", gatewayID),
|
||||
logger.F("addr", gatewaySpec.Address),
|
||||
logger.F("target", gatewaySpec.Target),
|
||||
)
|
||||
|
||||
if err := proxy.Start(ctx, gatewaySpec.Address, gatewaySpec.Target); err != nil {
|
||||
logger.Error(
|
||||
ctx, "error while starting proxy",
|
||||
logger.F("gatewayID", gatewayID),
|
||||
logger.E(errors.WithStack(err)),
|
||||
)
|
||||
|
||||
delete(c.proxies, gatewayID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewController() *Controller {
|
||||
return &Controller{
|
||||
proxies: make(map[gateway.ID]*ReverseProxy),
|
||||
currentSpecRevision: -1,
|
||||
}
|
||||
}
|
||||
|
||||
var _ agent.Controller = &Controller{}
|
124
internal/agent/controller/proxy/controller.go
Normal file
124
internal/agent/controller/proxy/controller.go
Normal file
@ -0,0 +1,124 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/spec/proxy"
|
||||
"github.com/pkg/errors"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
proxies map[proxy.ID]*ReverseProxy
|
||||
currentSpecRevision int
|
||||
}
|
||||
|
||||
// Name implements node.Controller.
|
||||
func (c *Controller) Name() string {
|
||||
return "proxy-controller"
|
||||
}
|
||||
|
||||
// Reconcile implements node.Controller.
|
||||
func (c *Controller) Reconcile(ctx context.Context, state *agent.State) error {
|
||||
proxySpec := proxy.NewSpec()
|
||||
|
||||
if err := state.GetSpec(proxy.NameProxy, proxySpec); err != nil {
|
||||
if errors.Is(err, agent.ErrSpecNotFound) {
|
||||
logger.Info(ctx, "could not find proxy spec, stopping all remaining proxies")
|
||||
|
||||
c.stopAllProxies(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
logger.Info(ctx, "retrieved spec", logger.F("spec", proxySpec.SpecName()), logger.F("revision", proxySpec.SpecRevision()))
|
||||
|
||||
if c.currentSpecRevision == proxySpec.SpecRevision() {
|
||||
logger.Info(ctx, "spec revision did not change, doing nothing")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
c.updateProxies(ctx, proxySpec)
|
||||
|
||||
c.currentSpecRevision = proxySpec.SpecRevision()
|
||||
logger.Info(ctx, "updating current spec revision", logger.F("revision", c.currentSpecRevision))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) stopAllProxies(ctx context.Context) {
|
||||
for proxyID, proxy := range c.proxies {
|
||||
logger.Info(ctx, "stopping proxy", logger.F("proxyID", proxyID))
|
||||
|
||||
if err := proxy.Stop(); err != nil {
|
||||
logger.Error(
|
||||
ctx, "error while stopping proxy",
|
||||
logger.F("proxyID", proxyID),
|
||||
logger.E(errors.WithStack(err)),
|
||||
)
|
||||
|
||||
delete(c.proxies, proxyID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) updateProxies(ctx context.Context, spec *proxy.Spec) {
|
||||
// Stop and remove obsolete proxys
|
||||
for proxyID, proxy := range c.proxies {
|
||||
if _, exists := spec.Proxies[proxyID]; exists {
|
||||
continue
|
||||
}
|
||||
|
||||
logger.Info(ctx, "stopping proxy", logger.F("proxyID", proxyID))
|
||||
|
||||
if err := proxy.Stop(); err != nil {
|
||||
logger.Error(
|
||||
ctx, "error while stopping proxy",
|
||||
logger.F("proxyID", proxyID),
|
||||
logger.E(errors.WithStack(err)),
|
||||
)
|
||||
|
||||
delete(c.proxies, proxyID)
|
||||
}
|
||||
}
|
||||
|
||||
// (Re)start proxys
|
||||
for proxyID, proxySpec := range spec.Proxies {
|
||||
proxy, exists := c.proxies[proxyID]
|
||||
if !exists {
|
||||
proxy = NewReverseProxy()
|
||||
c.proxies[proxyID] = proxy
|
||||
}
|
||||
|
||||
logger.Info(
|
||||
ctx, "starting proxy",
|
||||
logger.F("proxyID", proxyID),
|
||||
logger.F("addr", proxySpec.Address),
|
||||
logger.F("target", proxySpec.Target),
|
||||
)
|
||||
|
||||
if err := proxy.Start(ctx, proxySpec.Address, proxySpec.Target); err != nil {
|
||||
logger.Error(
|
||||
ctx, "error while starting proxy",
|
||||
logger.F("proxyID", proxyID),
|
||||
logger.E(errors.WithStack(err)),
|
||||
)
|
||||
|
||||
delete(c.proxies, proxyID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewController() *Controller {
|
||||
return &Controller{
|
||||
proxies: make(map[proxy.ID]*ReverseProxy),
|
||||
currentSpecRevision: -1,
|
||||
}
|
||||
}
|
||||
|
||||
var _ agent.Controller = &Controller{}
|
@ -1,4 +1,4 @@
|
||||
package gateway
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
@ -5,9 +5,9 @@ import (
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/gateway"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/openwrt"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/persistence"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/proxy"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/spec"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/metadata"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/metadata/collector/buildinfo"
|
||||
@ -49,8 +49,8 @@ func RunCommand() *cli.Command {
|
||||
controllers = append(controllers, spec.NewController())
|
||||
}
|
||||
|
||||
if ctrlConf.Gateway.Enabled {
|
||||
controllers = append(controllers, gateway.NewController())
|
||||
if ctrlConf.Proxy.Enabled {
|
||||
controllers = append(controllers, proxy.NewController())
|
||||
}
|
||||
|
||||
if ctrlConf.UCI.Enabled {
|
||||
|
@ -16,7 +16,7 @@ import (
|
||||
|
||||
// Import specs
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/app"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/gateway"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/proxy"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/uci"
|
||||
)
|
||||
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
// Spec validation
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/gateway"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/proxy"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/uci"
|
||||
)
|
||||
|
||||
|
@ -17,7 +17,7 @@ type ShellCollectorConfig struct {
|
||||
type ControllersConfig struct {
|
||||
Persistence PersistenceControllerConfig `yaml:"persistence"`
|
||||
Spec SpecControllerConfig `yaml:"spec"`
|
||||
Gateway GatewayControllerConfig `yaml:"gateway"`
|
||||
Proxy ProxyControllerConfig `yaml:"proxy"`
|
||||
UCI UCIControllerConfig `yaml:"uci"`
|
||||
App AppControllerConfig `yaml:"app"`
|
||||
}
|
||||
@ -30,7 +30,7 @@ type PersistenceControllerConfig struct {
|
||||
type SpecControllerConfig struct {
|
||||
Enabled InterpolatedBool `yaml:"enabled"`
|
||||
}
|
||||
type GatewayControllerConfig struct {
|
||||
type ProxyControllerConfig struct {
|
||||
Enabled InterpolatedBool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ func NewDefaultAgentConfig() AgentConfig {
|
||||
Enabled: true,
|
||||
StateFile: "state.json",
|
||||
},
|
||||
Gateway: GatewayControllerConfig{
|
||||
Proxy: ProxyControllerConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
UCI: UCIControllerConfig{
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
|
||||
// Import specs
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/app"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/gateway"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/proxy"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/uci"
|
||||
)
|
||||
|
||||
|
@ -29,6 +29,15 @@
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"key": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": ["key"]
|
||||
}
|
||||
},
|
||||
"required": ["apps"],
|
||||
|
@ -7,8 +7,9 @@ import (
|
||||
const NameApp spec.Name = "app.emissary.cadoles.com"
|
||||
|
||||
type Spec struct {
|
||||
Revision int `json:"revisions"`
|
||||
Apps map[string]AppEntry
|
||||
Revision int `json:"revisions"`
|
||||
Apps map[string]AppEntry `json:"apps"`
|
||||
Auth *Auth `json:"auth"`
|
||||
}
|
||||
|
||||
type AppEntry struct {
|
||||
@ -18,6 +19,10 @@ type AppEntry struct {
|
||||
Format string `json:"format"`
|
||||
}
|
||||
|
||||
type Auth struct {
|
||||
Key any `json:"key"`
|
||||
}
|
||||
|
||||
func (s *Spec) SpecName() spec.Name {
|
||||
return NameApp
|
||||
}
|
||||
@ -29,6 +34,7 @@ func (s *Spec) SpecRevision() int {
|
||||
func (s *Spec) SpecData() map[string]any {
|
||||
return map[string]any{
|
||||
"apps": s.Apps,
|
||||
"auth": s.Auth,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package gateway
|
||||
package proxy
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
@ -11,7 +11,7 @@ import (
|
||||
var schema []byte
|
||||
|
||||
func init() {
|
||||
if err := spec.Register(NameGateway, schema); err != nil {
|
||||
if err := spec.Register(NameProxy, schema); err != nil {
|
||||
panic(errors.WithStack(err))
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://gateway.emissary.cadoles.com/spec.json",
|
||||
"title": "GatewaySpec",
|
||||
"description": "Emissary 'Gateway' specification",
|
||||
"$id": "https://proxy.emissary.cadoles.com/spec.json",
|
||||
"title": "ProxySpec",
|
||||
"description": "Emissary 'Proxy' specification",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"gateways": {
|
||||
"proxies": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".*": {
|
||||
@ -24,6 +24,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["gateways"],
|
||||
"required": ["proxies"],
|
||||
"additionalProperties": false
|
||||
}
|
@ -1,23 +1,23 @@
|
||||
package gateway
|
||||
package proxy
|
||||
|
||||
import "forge.cadoles.com/Cadoles/emissary/internal/spec"
|
||||
|
||||
const NameGateway spec.Name = "gateway.emissary.cadoles.com"
|
||||
const NameProxy spec.Name = "proxy.emissary.cadoles.com"
|
||||
|
||||
type ID string
|
||||
|
||||
type Spec struct {
|
||||
Revision int `json:"revision"`
|
||||
Gateways map[ID]GatewayEntry `json:"gateways"`
|
||||
Revision int `json:"revision"`
|
||||
Proxies map[ID]ProxyEntry `json:"proxies"`
|
||||
}
|
||||
|
||||
type GatewayEntry struct {
|
||||
type ProxyEntry struct {
|
||||
Address string `json:"address"`
|
||||
Target string `json:"target"`
|
||||
}
|
||||
|
||||
func (s *Spec) SpecName() spec.Name {
|
||||
return NameGateway
|
||||
return NameProxy
|
||||
}
|
||||
|
||||
func (s *Spec) SpecRevision() int {
|
||||
@ -26,14 +26,14 @@ func (s *Spec) SpecRevision() int {
|
||||
|
||||
func (s *Spec) SpecData() map[string]any {
|
||||
return map[string]any{
|
||||
"gateways": s.Gateways,
|
||||
"proxies": s.Proxies,
|
||||
}
|
||||
}
|
||||
|
||||
func NewSpec() *Spec {
|
||||
return &Spec{
|
||||
Revision: -1,
|
||||
Gateways: make(map[ID]GatewayEntry),
|
||||
Proxies: make(map[ID]ProxyEntry),
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "gateway.emissary.cadoles.com",
|
||||
"name": "proxy.emissary.cadoles.com",
|
||||
"data": {
|
||||
"gateways": {
|
||||
"proxies": {
|
||||
"cadoles.com": {
|
||||
"address": ":3003",
|
||||
"target": "https://www.cadoles.com",
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "gateway.emissary.cadoles.com",
|
||||
"name": "proxy.emissary.cadoles.com",
|
||||
"data": {
|
||||
"gateways": {
|
||||
"proxies": {
|
||||
"cadoles.com": {
|
||||
"address": ":3003"
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "gateway.emissary.cadoles.com",
|
||||
"name": "proxy.emissary.cadoles.com",
|
||||
"data": {
|
||||
"gateways": {
|
||||
"proxies": {
|
||||
"cadoles.com": {
|
||||
"address": ":3003",
|
||||
"target": "https://www.cadoles.com"
|
@ -1,4 +1,4 @@
|
||||
package gateway
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -38,7 +38,7 @@ func TestValidator(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
validator := spec.NewValidator()
|
||||
if err := validator.Register(NameGateway, schema); err != nil {
|
||||
if err := validator.Register(NameProxy, schema); err != nil {
|
||||
t.Fatalf("+%v", errors.WithStack(err))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user