diff --git a/functional-tests/admin_tests/change_checker.sh b/functional-tests/admin_tests/change_checker.sh new file mode 100755 index 0000000..84dd271 --- /dev/null +++ b/functional-tests/admin_tests/change_checker.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +set -eo xtrace + +ADMIN_URL=${ADMIN_URL:-"http://localhost:9080"} +PROXY_URL=${PROXY_URL:-"http://localhost"} + +DIR="$( cd "$( dirname "$0" )" && pwd )" + +export DGATE_ADMIN_API=$ADMIN_URL + +dgate-cli namespace create \ + name=change_checker-ns + +dgate-cli domain create \ + name=change_checker-dm \ + patterns:='["change_checker.com"]' \ + namespace=change_checker-ns + +dgate-cli module create name=change_checker-mod \ + payload@=$DIR/change_checker_1.ts \ + namespace=change_checker-ns + +dgate-cli route create \ + name=base_rt paths:='["/", "/{id}"]' \ + modules:='["change_checker-mod"]' \ + methods:='["GET","POST"]' \ + stripPath:=true \ + preserveHost:=true \ + namespace=change_checker-ns + +MODID1=$(curl -sG -H Host:change_checker.com ${PROXY_URL}/ | jq -r '.mod') + +if [ "$MODID1" != "module1" ]; then + echo "Initial assert failed" + exit 1 +fi + + +dgate-cli module create name=change_checker-mod \ + payload@=$DIR/change_checker_2.ts \ + namespace=change_checker-ns + +# dgate-cli r.ker-ns + +MODID2=$(curl -sG -H Host:change_checker.com ${PROXY_URL}/ | jq -r '.mod') + +if [ "$MODID2" != "module2" ]; then + echo "module update failed" + exit 1 +fi \ No newline at end of file diff --git a/functional-tests/admin_tests/change_checker_1.ts b/functional-tests/admin_tests/change_checker_1.ts new file mode 100644 index 0000000..08a7a18 --- /dev/null +++ b/functional-tests/admin_tests/change_checker_1.ts @@ -0,0 +1,6 @@ + +export const requestHandler = async (ctx: any) => { + ctx.response().status(201).json({ + mod: "module1", + }); +} \ No newline at end of file diff --git a/functional-tests/admin_tests/change_checker_2.ts b/functional-tests/admin_tests/change_checker_2.ts new file mode 100644 index 0000000..a48cac5 --- /dev/null +++ b/functional-tests/admin_tests/change_checker_2.ts @@ -0,0 +1,6 @@ + +export const requestHandler = async (ctx: any) => { + ctx.response().status(201).json({ + mod: "module2", + }); +}; \ No newline at end of file diff --git a/functional-tests/admin_tests/modify_request.ts b/functional-tests/admin_tests/modify_request.ts index 111a58f..a781477 100644 --- a/functional-tests/admin_tests/modify_request.ts +++ b/functional-tests/admin_tests/modify_request.ts @@ -1,4 +1,6 @@ +// @ts-ignore import { fetch } from "dgate/http"; +// @ts-ignore import { getCache, setCache } from "dgate/storage"; export const requestModifier = async (ctx) => { @@ -23,9 +25,10 @@ export const requestModifier = async (ctx) => { console.error(JSON.stringify(georesp)); throw new Error(("IP API: " + geodata?.message) ?? "Failed to fetch geodata"); } - setCache('geodata:'+remoteAddr, geodata, { - ttl: 3600, - }); + + // setCache('geodata:'+remoteAddr, geodata, { + // ttl: 3600, + // }); } req.headers.set("X-Geo-Country", geodata.country); diff --git a/functional-tests/admin_tests/performance_test_prep.ts b/functional-tests/admin_tests/performance_test_prep.ts index f279604..41dfdc7 100644 --- a/functional-tests/admin_tests/performance_test_prep.ts +++ b/functional-tests/admin_tests/performance_test_prep.ts @@ -1,3 +1,4 @@ +// @ts-ignore import { sleep } from "dgate"; export const fetchUpstream = async (ctx) => diff --git a/functional-tests/admin_tests/url_shortener.ts b/functional-tests/admin_tests/url_shortener.ts index 32ffc66..cca863a 100644 --- a/functional-tests/admin_tests/url_shortener.ts +++ b/functional-tests/admin_tests/url_shortener.ts @@ -13,7 +13,7 @@ export const requestHandler = (ctx: any) => { return; } // get the document with the ID from the collection - return getDocument("short_link", pathId) + return getDocument(pathId, "short_link") .then((doc: any) => { // check if the document contains the URL if (!doc?.data?.url) { diff --git a/functional-tests/raft_tests/test1.yaml b/functional-tests/raft_tests/test1.yaml index 2bb8f42..5c18c1c 100644 --- a/functional-tests/raft_tests/test1.yaml +++ b/functional-tests/raft_tests/test1.yaml @@ -1,5 +1,4 @@ version: v1 -debug: true log_level: info tags: diff --git a/functional-tests/raft_tests/test2.yaml b/functional-tests/raft_tests/test2.yaml index f1bd592..973ad67 100644 --- a/functional-tests/raft_tests/test2.yaml +++ b/functional-tests/raft_tests/test2.yaml @@ -1,5 +1,4 @@ version: v1 -debug: true log_level: info tags: - "dev" diff --git a/internal/admin/admin_raft.go b/internal/admin/admin_raft.go index e31f4dd..9aed54a 100644 --- a/internal/admin/admin_raft.go +++ b/internal/admin/admin_raft.go @@ -30,7 +30,6 @@ func setupRaft( adminConfig := conf.AdminConfig var sstore raft.StableStore var lstore raft.LogStore - snapstore := raft.NewInmemSnapshotStore() switch conf.Storage.StorageType { case config.StorageTypeMemory: sstore = raft.NewInmemStore() @@ -55,6 +54,9 @@ func setupRaft( panic(fmt.Errorf("invalid storage type: %s", conf.Storage.StorageType)) } raftId := adminConfig.Replication.RaftID + if raftId == "" { + raftId = conf.NodeId + } raftConfig := adminConfig.Replication.LoadRaftConfig( &raft.Config{ @@ -90,7 +92,7 @@ func setupRaft( ) raftNode, err := raft.NewRaft( raftConfig, newDGateAdminFSM(logger.Named("fsm"), cs), - lstore, sstore, snapstore, transport, + lstore, sstore, raft.NewInmemSnapshotStore(), transport, ) if err != nil { panic(err) diff --git a/internal/admin/routes/collection_routes.go b/internal/admin/routes/collection_routes.go index 3418cb7..255433d 100644 --- a/internal/admin/routes/collection_routes.go +++ b/internal/admin/routes/collection_routes.go @@ -48,7 +48,10 @@ func ConfigureCollectionAPI(server chi.Router, logger *zap.Logger, cs changestat if oldCollection, ok := rm.GetCollection(collection.Name, collection.NamespaceName); ok { if oldCollection.Type == spec.CollectionTypeDocument { docs, err := dm.GetDocuments( - collection.NamespaceName, collection.Name, 0, 0) + collection.Name, + collection.NamespaceName, + 0, 0, + ) if err != nil { util.JsonError(w, http.StatusInternalServerError, err.Error()) return @@ -142,7 +145,7 @@ func ConfigureCollectionAPI(server chi.Router, logger *zap.Logger, cs changestat util.JsonError(w, http.StatusBadRequest, "offset must be an integer") return } - docs, err := dm.GetDocuments(namespaceName, collectionName, offset, limit) + docs, err := dm.GetDocuments(collectionName, namespaceName, offset, limit) if err != nil { util.JsonError(w, http.StatusInternalServerError, err.Error()) return @@ -194,7 +197,7 @@ func ConfigureCollectionAPI(server chi.Router, logger *zap.Logger, cs changestat return } - document, err := dm.GetDocumentByID(namespaceName, collectionName, documentId) + document, err := dm.GetDocumentByID(documentId, collectionName, namespaceName) if err != nil { util.JsonError(w, http.StatusNotFound, err.Error()) return @@ -348,7 +351,7 @@ func ConfigureCollectionAPI(server chi.Router, logger *zap.Logger, cs changestat util.JsonError(w, http.StatusBadRequest, "document_id is required") return } - document, err := dm.GetDocumentByID(namespaceName, collectionName, documentId) + document, err := dm.GetDocumentByID(documentId, collectionName, namespaceName) if err != nil { util.JsonError(w, http.StatusNotFound, err.Error()) return @@ -386,7 +389,10 @@ func ConfigureCollectionAPI(server chi.Router, logger *zap.Logger, cs changestat } if collection.Type == spec.CollectionTypeDocument { docs, err := dm.GetDocuments( - namespaceName, collectionName, 0, 1) + collectionName, + namespaceName, + 1, 1, + ) if err != nil { util.JsonError(w, http.StatusInternalServerError, err.Error()) return diff --git a/internal/admin/routes/module_routes_test.go b/internal/admin/routes/module_routes_test.go index ed1383d..74db074 100644 --- a/internal/admin/routes/module_routes_test.go +++ b/internal/admin/routes/module_routes_test.go @@ -22,7 +22,7 @@ import ( func TestAdminRoutes_Module(t *testing.T) { namespaces := []string{"default", "test"} for _, ns := range namespaces { - config := configtest.NewTest3DGateConfig() + config := configtest.NewTest4DGateConfig() ps := proxy.NewProxyState(zap.NewNop(), config) mux := chi.NewMux() mux.Route("/api/v1", func(r chi.Router) { diff --git a/internal/admin/routes/service_routes_test.go b/internal/admin/routes/service_routes_test.go index 2e808a1..555959f 100644 --- a/internal/admin/routes/service_routes_test.go +++ b/internal/admin/routes/service_routes_test.go @@ -21,7 +21,7 @@ import ( func TestAdminRoutes_Service(t *testing.T) { namespaces := []string{"default", "test"} for _, ns := range namespaces { - config := configtest.NewTest3DGateConfig() + config := configtest.NewTest4DGateConfig() ps := proxy.NewProxyState(zap.NewNop(), config) mux := chi.NewMux() mux.Route("/api/v1", func(r chi.Router) { diff --git a/internal/config/config.go b/internal/config/config.go index 32e244a..1dcd90e 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -226,6 +226,8 @@ func (conf *DGateConfig) GetLogger() (*zap.Logger, error) { if conf.Logging.ZapConfig == nil { config := zap.NewProductionConfig() config.Level = level + config.DisableCaller = true + config.DisableStacktrace = true config.Development = conf.Debug config.EncoderConfig.EncodeTime = zapcore.RFC3339TimeEncoder config.OutputPaths = []string{"stdout"} diff --git a/internal/config/configtest/dgate_configs.go b/internal/config/configtest/dgate_configs.go index ae5a673..36956f3 100644 --- a/internal/config/configtest/dgate_configs.go +++ b/internal/config/configtest/dgate_configs.go @@ -107,6 +107,23 @@ func NewTest3DGateConfig() *config.DGateConfig { return conf } +func NewTest4DGateConfig() *config.DGateConfig { + conf := NewTestDGateConfig() + conf.DisableDefaultNamespace = false + conf.ProxyConfig = config.DGateProxyConfig{ + Host: "localhost", + Port: 16436, + InitResources: &config.DGateResources{ + Namespaces: []spec.Namespace{ + { + Name: "test", + }, + }, + }, + } + return conf +} + func NewTestDGateConfig_DomainAndNamespaces() *config.DGateConfig { conf := NewTestDGateConfig() conf.ProxyConfig.InitResources.Namespaces = []spec.Namespace{ diff --git a/internal/proxy/change_log.go b/internal/proxy/change_log.go index 207fd8d..5a2ab94 100644 --- a/internal/proxy/change_log.go +++ b/internal/proxy/change_log.go @@ -86,7 +86,7 @@ func (ps *ProxyState) processChangeLog(cl *spec.ChangeLog, reload, store bool) ( } } if reload { - if cl.Cmd.Resource().IsRelatedTo(spec.Routes) || cl.Cmd.IsNoop() { + if cl.Cmd.IsNoop() || cl.Cmd.Resource().IsRelatedTo(spec.Routes) { ps.logger.Debug("Registering change log", zap.Stringer("cmd", cl.Cmd)) err = ps.reconfigureState(false, cl) if err != nil { diff --git a/internal/proxy/dynamic_proxy.go b/internal/proxy/dynamic_proxy.go index 5484022..8b6bcb0 100644 --- a/internal/proxy/dynamic_proxy.go +++ b/internal/proxy/dynamic_proxy.go @@ -11,7 +11,6 @@ import ( "github.com/dgate-io/dgate/pkg/modules/extractors" "github.com/dgate-io/dgate/pkg/spec" "github.com/dgate-io/dgate/pkg/typescript" - "github.com/dgate-io/dgate/pkg/util/tree/avl" "github.com/dop251/goja" "go.uber.org/zap" "golang.org/x/net/http2" @@ -103,48 +102,48 @@ func (ps *ProxyState) setupModules() error { func (ps *ProxyState) setupRoutes() (err error) { ps.logger.Debug("Setting up routes") - reqCtxProviders := avl.NewTree[string, *RequestContextProvider]() + // reqCtxProviders := avl.NewTree[string, *RequestContextProvider]() for namespaceName, routes := range ps.rm.GetRouteNamespaceMap() { mux := router.NewMux() - for _, r := range routes { - reqCtxProvider := NewRequestContextProvider(r, ps) - reqCtxProviders.Insert(r.Namespace.Name+"/"+r.Name, reqCtxProvider) - if len(r.Modules) > 0 { - modPool, err := NewModulePool( - 256, 1024, reqCtxProvider, - ps.createModuleExtractorFunc(r), - ) - if err != nil { + for _, rt := range routes { + reqCtxProvider := NewRequestContextProvider(rt, ps) + if len(rt.Modules) > 0 { + modExtFunc := ps.createModuleExtractorFunc(rt) + if modPool, err := NewModulePool( + 256, 1024, reqCtxProvider, modExtFunc, + ); err != nil { ps.logger.Error("Error creating module buffer", zap.Error(err)) return err + } else { + reqCtxProvider.SetModulePool(modPool) } - reqCtxProvider.SetModulePool(modPool) } - err = func() (err error) { + ps.providers.Insert(rt.Namespace.Name+"/"+rt.Name, reqCtxProvider) + err = func(rt *spec.DGateRoute) (err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("%v", r) } }() - for _, path := range r.Paths { - if len(r.Methods) > 0 && r.Methods[0] == "*" { - if len(r.Methods) > 1 { + for _, path := range rt.Paths { + if len(rt.Methods) > 0 && rt.Methods[0] == "*" { + if len(rt.Methods) > 1 { return errors.New("route methods cannot have other methods with *") } mux.Handle(path, ps.HandleRoute(reqCtxProvider, path)) } else { - if len(r.Methods) == 0 { + if len(rt.Methods) == 0 { return errors.New("route must have at least one method") - } else if err = ValidateMethods(r.Methods); err != nil { + } else if err = ValidateMethods(rt.Methods); err != nil { return err } - for _, method := range r.Methods { + for _, method := range rt.Methods { mux.Method(method, path, ps.HandleRoute(reqCtxProvider, path)) } } } return nil - }() + }(rt) } ps.logger.Debug("Routes have changed, reloading") @@ -158,18 +157,18 @@ func (ps *ProxyState) setupRoutes() (err error) { return } -func (ps *ProxyState) createModuleExtractorFunc(r *spec.DGateRoute) ModuleExtractorFunc { +func (ps *ProxyState) createModuleExtractorFunc(rt *spec.DGateRoute) ModuleExtractorFunc { return func(reqCtx *RequestContextProvider) (_ ModuleExtractor, err error) { - if len(r.Modules) == 0 { - return nil, fmt.Errorf("no modules found for route: %s/%s", r.Name, r.Namespace.Name) + if len(rt.Modules) == 0 { + return nil, fmt.Errorf("no modules found for route: %s/%s", rt.Name, rt.Namespace.Name) } // TODO: Perhaps have some entrypoint flag to determine which module to use - m := r.Modules[0] - if program, ok := ps.modPrograms.Find(m.Name + "/" + r.Namespace.Name); !ok { + m := rt.Modules[0] + if program, ok := ps.modPrograms.Find(m.Name + "/" + rt.Namespace.Name); !ok { ps.logger.Error("Error getting module program: invalid state", zap.Error(err)) - return nil, fmt.Errorf("cannot find module program: %s/%s", m.Name, r.Namespace.Name) + return nil, fmt.Errorf("cannot find module program: %s/%s", m.Name, rt.Namespace.Name) } else { - rtCtx := NewRuntimeContext(ps, r, r.Modules...) + rtCtx := NewRuntimeContext(ps, rt, rt.Modules...) if err := extractors.SetupModuleEventLoop(ps.printer, rtCtx, program); err != nil { ps.logger.Error("Error creating runtime for route", zap.String("route", reqCtx.route.Name), diff --git a/internal/proxy/proxy_documents.go b/internal/proxy/proxy_documents.go index b67c641..c75d031 100644 --- a/internal/proxy/proxy_documents.go +++ b/internal/proxy/proxy_documents.go @@ -15,19 +15,19 @@ func (ps *ProxyState) GetDocuments(collection, namespace string, limit, offset i if _, ok := ps.rm.GetNamespace(namespace); !ok { return nil, spec.ErrNamespaceNotFound(namespace) } - if _, ok := ps.rm.GetCollection(namespace, collection); !ok { + if _, ok := ps.rm.GetCollection(collection, namespace); !ok { return nil, spec.ErrCollectionNotFound(collection) } return ps.store.FetchDocuments(namespace, collection, limit, offset) } // GetDocumentByID is a function that returns a document in a collection by its ID. -func (ps *ProxyState) GetDocumentByID(namespace, collection, docId string) (*spec.Document, error) { +func (ps *ProxyState) GetDocumentByID(docId, collection, namespace string) (*spec.Document, error) { if _, ok := ps.rm.GetNamespace(namespace); !ok { return nil, spec.ErrNamespaceNotFound(namespace) } if _, ok := ps.rm.GetCollection(collection, namespace); !ok { return nil, spec.ErrCollectionNotFound(collection) } - return ps.store.FetchDocument(namespace, collection, docId) + return ps.store.FetchDocument(docId, collection, namespace) } diff --git a/internal/proxy/proxy_handler.go b/internal/proxy/proxy_handler.go index eba264a..b6bb6fa 100644 --- a/internal/proxy/proxy_handler.go +++ b/internal/proxy/proxy_handler.go @@ -38,21 +38,22 @@ func proxyHandler(ps *ProxyState, reqCtx *RequestContext) { var modExt ModuleExtractor if len(reqCtx.route.Modules) != 0 { runtimeStart := time.Now() - if reqCtx.provider.modPool == nil { + if modPool := reqCtx.provider.ModulePool(); modPool == nil { ps.logger.Error("Error getting module buffer: invalid state") util.WriteStatusCodeError(reqCtx.rw, http.StatusInternalServerError) return + } else { + if modExt = modPool.Borrow(); modExt == nil { + ps.metrics.MeasureModuleDuration( + reqCtx, "module_extract", runtimeStart, + errors.New("error borrowing module"), + ) + ps.logger.Error("Error borrowing module") + util.WriteStatusCodeError(reqCtx.rw, http.StatusInternalServerError) + return + } + defer modPool.Return(modExt) } - if modExt = reqCtx.provider.modPool.Borrow(); modExt == nil { - ps.metrics.MeasureModuleDuration( - reqCtx, "module_extract", - runtimeStart, errors.New("error borrowing module"), - ) - ps.logger.Error("Error borrowing module") - util.WriteStatusCodeError(reqCtx.rw, http.StatusInternalServerError) - return - } - defer reqCtx.provider.modPool.Return(modExt) modExt.Start(reqCtx) defer modExt.Stop(true) diff --git a/internal/proxy/proxy_handler_test.go b/internal/proxy/proxy_handler_test.go index cacd8c7..de38c67 100644 --- a/internal/proxy/proxy_handler_test.go +++ b/internal/proxy/proxy_handler_test.go @@ -65,6 +65,7 @@ func TestProxyHandler_ReverseProxy(t *testing.T) { modBuf := NewMockModulePool() modBuf.On("Borrow").Return(modExt).Once() modBuf.On("Return", modExt).Return().Once() + modBuf.On("Close").Return().Once() reqCtxProvider.SetModulePool(modBuf) modPool := NewMockModulePool() @@ -178,7 +179,6 @@ func TestProxyHandler_ProxyHandlerError(t *testing.T) { modPool := NewMockModulePool() modPool.On("Borrow").Return(modExt).Once() modPool.On("Return", modExt).Return().Once() - reqCtxProvider := proxy.NewRequestContextProvider(rt, ps) reqCtxProvider.SetModulePool(modPool) reqCtx := reqCtxProvider.CreateRequestContext( diff --git a/internal/proxy/proxy_state.go b/internal/proxy/proxy_state.go index b0acc25..383055a 100644 --- a/internal/proxy/proxy_state.go +++ b/internal/proxy/proxy_state.go @@ -104,7 +104,6 @@ func NewProxyState(logger *zap.Logger, conf *config.DGateConfig) *ProxyState { replicationEnabled = true } state := &ProxyState{ - version: "unknown", startTime: time.Now(), raftReady: atomic.Bool{}, logger: logger, diff --git a/internal/proxy/proxy_state_test.go b/internal/proxy/proxy_state_test.go index 0a3d27d..8b26709 100644 --- a/internal/proxy/proxy_state_test.go +++ b/internal/proxy/proxy_state_test.go @@ -267,14 +267,14 @@ func TestProcessChangeLog_Route(t *testing.T) { } func TestProcessChangeLog_Service(t *testing.T) { - conf := configtest.NewTestDGateConfig() + conf := configtest.NewTest4DGateConfig() ps := proxy.NewProxyState(zap.NewNop(), conf) if err := ps.Store().InitStore(); err != nil { t.Fatal(err) } s := &spec.Service{ - Name: "test", + Name: "test123", NamespaceName: "test", URLs: []string{"http://localhost:8080"}, Tags: []string{"test"}, @@ -302,14 +302,14 @@ func TestProcessChangeLog_Service(t *testing.T) { } func TestProcessChangeLog_Module(t *testing.T) { - conf := configtest.NewTestDGateConfig() + conf := configtest.NewTest4DGateConfig() ps := proxy.NewProxyState(zap.NewNop(), conf) if err := ps.Store().InitStore(); err != nil { t.Fatal(err) } m := &spec.Module{ - Name: "test", + Name: "test123", NamespaceName: "test", Payload: "", Tags: []string{"test"}, @@ -337,7 +337,7 @@ func TestProcessChangeLog_Module(t *testing.T) { } func TestProcessChangeLog_Namespace(t *testing.T) { - ps := proxy.NewProxyState(zap.NewNop(), configtest.NewTestDGateConfig()) + ps := proxy.NewProxyState(zap.NewNop(), configtest.NewTest4DGateConfig()) if err := ps.Store().InitStore(); err != nil { t.Fatal(err) } @@ -351,28 +351,30 @@ func TestProcessChangeLog_Namespace(t *testing.T) { if !assert.Nil(t, err, "error should be nil") { return } - namespaces := ps.ResourceManager().GetNamespaces() - assert.Equal(t, 2, len(namespaces), "should have 2 items") - assert.Equal(t, n.Name, namespaces[1].Name, "should have the same name") + ns, ok := ps.ResourceManager().GetNamespace(n.Name) + if !assert.True(t, ok, "should be true") { + return + } + assert.Equal(t, n.Name, ns.Name, "should have the same name") cl = spec.NewChangeLog(n, n.Name, spec.DeleteNamespaceCommand) err = ps.ProcessChangeLog(cl, false) if !assert.Nil(t, err, "error should be nil") { return } - namespaces = ps.ResourceManager().GetNamespaces() - assert.Equal(t, 1, len(namespaces), "should have 0 item") + _, ok = ps.ResourceManager().GetNamespace(n.Name) + assert.False(t, ok, "should be false") } func TestProcessChangeLog_Collection(t *testing.T) { - conf := configtest.NewTestDGateConfig() + conf := configtest.NewTest4DGateConfig() ps := proxy.NewProxyState(zap.NewNop(), conf) if err := ps.Store().InitStore(); err != nil { t.Fatal(err) } c := &spec.Collection{ - Name: "test", + Name: "test123", NamespaceName: "test", // Type: spec.CollectionTypeDocument, Visibility: spec.CollectionVisibilityPrivate, @@ -409,11 +411,11 @@ func TestProcessChangeLog_Document(t *testing.T) { } c := &spec.Collection{ - Name: "test", + Name: "test123", NamespaceName: "test", - // Type: spec.CollectionTypeDocument, - Visibility: spec.CollectionVisibilityPrivate, - Tags: []string{"test"}, + Type: spec.CollectionTypeDocument, + Visibility: spec.CollectionVisibilityPrivate, + Tags: []string{"test"}, } cl := spec.NewChangeLog(c, c.NamespaceName, spec.AddCollectionCommand) @@ -423,9 +425,9 @@ func TestProcessChangeLog_Document(t *testing.T) { } d := &spec.Document{ - ID: "test", + ID: "test123", + CollectionName: "test123", NamespaceName: "test", - CollectionName: "test", Data: "", } @@ -435,7 +437,7 @@ func TestProcessChangeLog_Document(t *testing.T) { return } documents, err := ps.DocumentManager().GetDocuments( - "test", "test", 999, 0, + d.CollectionName, d.NamespaceName, 999, 0, ) if !assert.Nil(t, err, "error should be nil") { return @@ -452,7 +454,7 @@ func TestProcessChangeLog_Document(t *testing.T) { return } documents, err = ps.DocumentManager().GetDocuments( - "test", "test", 999, 0, + d.CollectionName, d.NamespaceName, 999, 0, ) if !assert.Nil(t, err, "error should be nil") { return diff --git a/internal/proxy/proxystore/proxy_store.go b/internal/proxy/proxystore/proxy_store.go index 430d3c5..d55eb9a 100644 --- a/internal/proxy/proxystore/proxy_store.go +++ b/internal/proxy/proxystore/proxy_store.go @@ -92,12 +92,12 @@ func (store *ProxyStore) DeleteChangeLogs(logs []*spec.ChangeLog) (int, error) { return removed, nil } -func createDocumentKey(nsName, colName, docId string) string { +func createDocumentKey(docId, colName, nsName string) string { return "doc/" + nsName + "/" + colName + "/" + docId } -func (store *ProxyStore) FetchDocument(nsName, colName, docId string) (*spec.Document, error) { - docBytes, err := store.storage.Get(createDocumentKey(nsName, colName, docId)) +func (store *ProxyStore) FetchDocument(docId, colName, nsName string) (*spec.Document, error) { + docBytes, err := store.storage.Get(createDocumentKey(docId, colName, nsName)) if err != nil { if err == storage.ErrStoreLocked { return nil, err @@ -119,7 +119,7 @@ func (store *ProxyStore) FetchDocuments( limit, offset int, ) ([]*spec.Document, error) { docs := make([]*spec.Document, 0) - docPrefix := createDocumentKey(namespaceName, collectionName, "") + docPrefix := createDocumentKey("", collectionName, namespaceName) err := store.storage.IterateValuesPrefix(docPrefix, func(key string, val []byte) error { if offset -= 1; offset > 0 { return nil @@ -145,7 +145,7 @@ func (store *ProxyStore) StoreDocument(doc *spec.Document) error { return err } store.logger.Debug("storing document") - err = store.storage.Set(createDocumentKey(doc.NamespaceName, doc.CollectionName, doc.ID), docBytes) + err = store.storage.Set(createDocumentKey(doc.ID, doc.CollectionName, doc.NamespaceName), docBytes) if err != nil { return err } @@ -153,7 +153,7 @@ func (store *ProxyStore) StoreDocument(doc *spec.Document) error { } func (store *ProxyStore) DeleteDocument(id, colName, nsName string) error { - err := store.storage.Delete(createDocumentKey(nsName, colName, id)) + err := store.storage.Delete(createDocumentKey(id, colName, nsName)) if err != nil { if err == badger.ErrKeyNotFound { return nil @@ -164,7 +164,7 @@ func (store *ProxyStore) DeleteDocument(id, colName, nsName string) error { } func (store *ProxyStore) DeleteDocuments(doc *spec.Document) error { - err := store.storage.IterateTxnPrefix(createDocumentKey(doc.NamespaceName, doc.CollectionName, ""), + err := store.storage.IterateTxnPrefix(createDocumentKey("", doc.CollectionName, doc.NamespaceName), func(txn storage.StorageTxn, key string) error { return txn.Delete(key) }) diff --git a/internal/proxy/request_context.go b/internal/proxy/request_context.go index 7e2b911..0f01dd9 100644 --- a/internal/proxy/request_context.go +++ b/internal/proxy/request_context.go @@ -5,6 +5,7 @@ import ( "crypto/tls" "net" "net/http" + "sync" "github.com/dgate-io/chi-router" "github.com/dgate-io/dgate/internal/proxy/reverse_proxy" @@ -14,10 +15,11 @@ import ( type S string type RequestContextProvider struct { - ctx context.Context - route *spec.DGateRoute - rpb reverse_proxy.Builder - modPool ModulePool + ctx context.Context + route *spec.DGateRoute + rpb reverse_proxy.Builder + mtx *sync.Mutex + modBuf ModulePool } type RequestContext struct { @@ -73,11 +75,23 @@ func NewRequestContextProvider(route *spec.DGateRoute, ps *ProxyState) *RequestC ctx: ctx, route: route, rpb: rpb, + mtx: &sync.Mutex{}, } } func (reqCtxProvider *RequestContextProvider) SetModulePool(mb ModulePool) { - reqCtxProvider.modPool = mb + reqCtxProvider.mtx.Lock() + defer reqCtxProvider.mtx.Unlock() + if reqCtxProvider.modBuf != nil { + reqCtxProvider.modBuf.Close() + } + reqCtxProvider.modBuf = mb +} + +func (reqCtxProvider *RequestContextProvider) ModulePool() ModulePool { + reqCtxProvider.mtx.Lock() + defer reqCtxProvider.mtx.Unlock() + return reqCtxProvider.modBuf } func (reqCtxProvider *RequestContextProvider) CreateRequestContext( diff --git a/internal/router/router.go b/internal/router/router.go index a7412e4..bd4f5b6 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -21,13 +21,6 @@ func NewRouterWithMux(mux *chi.Mux) *DynamicRouter { func NewMux() *chi.Mux { return chi.NewRouter() } - -func (r *DynamicRouter) ModifyMux(fn func(*chi.Mux)) { - r.lock.Lock() - defer r.lock.Unlock() - fn(r.router) -} - // ReplaceRouter replaces the router func (r *DynamicRouter) ReplaceMux(router *chi.Mux) { r.lock.Lock() diff --git a/pkg/modules/dgate/state/state_mod.go b/pkg/modules/dgate/state/state_mod.go index b8fa250..44ed32b 100644 --- a/pkg/modules/dgate/state/state_mod.go +++ b/pkg/modules/dgate/state/state_mod.go @@ -23,8 +23,8 @@ func (hp *ResourcesModule) Exports() *modules.Exports { return &modules.Exports{ Named: map[string]any{ "getCollection": hp.fetchCollection, - "getDocument": hp.fetchDocument, - "getDocuments": hp.fetchDocuments, + "getDocument": hp.getDocument, + "getDocuments": hp.getDocuments, "addCollection": writeFunc[*spec.Collection](hp, spec.AddCollectionCommand), "addDocument": writeFunc[*spec.Document](hp, spec.AddDocumentCommand), "deleteCollection": writeFunc[*spec.Collection](hp, spec.DeleteCollectionCommand), @@ -48,7 +48,7 @@ func (hp *ResourcesModule) fetchCollection(name string) *goja.Promise { )) return } - collection, ok := rm.GetCollection(namespace.(string), name) + collection, ok := rm.GetCollection(name, namespace.(string)) if !ok { reject(goja.Null()) return @@ -58,7 +58,7 @@ func (hp *ResourcesModule) fetchCollection(name string) *goja.Promise { return docPromise } -func (hp *ResourcesModule) fetchDocument(collection, docId string) *goja.Promise { +func (hp *ResourcesModule) getDocument(docId, collection string) *goja.Promise { ctx := hp.modCtx.Context() state := hp.modCtx.State() loop := hp.modCtx.EventLoop() @@ -71,7 +71,7 @@ func (hp *ResourcesModule) fetchDocument(collection, docId string) *goja.Promise return } doc, err := state.DocumentManager(). - GetDocumentByID(namespace.(string), collection, docId) + GetDocumentByID(docId, collection, namespace.(string)) if err != nil { reject(rt.NewGoError(err)) return @@ -81,25 +81,20 @@ func (hp *ResourcesModule) fetchDocument(collection, docId string) *goja.Promise return docPromise } -func (hp *ResourcesModule) fetchDocuments(args goja.FunctionCall) (*goja.Promise, error) { +type FetchDocumentsPayload struct { + Collection string `json:"collection"` + Limit int `json:"limit"` + Offset int `json:"offset"` +} + +func (hp *ResourcesModule) getDocuments(payload FetchDocumentsPayload) (*goja.Promise, error) { ctx := hp.modCtx.Context() state := hp.modCtx.State() loop := hp.modCtx.EventLoop() rt := hp.modCtx.Runtime() - collection_name := "" - if args.Argument(0) == goja.Undefined() { + if payload.Collection == "" { return nil, errors.New("collection name is required") - } else { - collection_name = args.Argument(0).String() - } - limit := 0 - if args.Argument(1) != goja.Undefined() { - limit = int(args.Argument(1).ToInteger()) - } - offset := 0 - if args.Argument(2) != goja.Undefined() { - offset = int(args.Argument(2).ToInteger()) } namespaceVal := ctx.Value(spec.Name("namespace")) @@ -111,7 +106,12 @@ func (hp *ResourcesModule) fetchDocuments(args goja.FunctionCall) (*goja.Promise docPromise, resolve, reject := rt.NewPromise() loop.RunOnLoop(func(rt *goja.Runtime) { doc, err := state.DocumentManager(). - GetDocuments(namespace, collection_name, limit, offset) + GetDocuments( + payload.Collection, + namespace, + payload.Limit, + payload.Offset, + ) if err != nil { reject(rt.NewGoError(err)) return diff --git a/pkg/modules/types/request.go b/pkg/modules/types/request.go index 99d27dd..de27edb 100644 --- a/pkg/modules/types/request.go +++ b/pkg/modules/types/request.go @@ -19,7 +19,7 @@ type RequestWrapper struct { loop *eventloop.EventLoop Method string - URL string + Path string Headers http.Header Query url.Values Host string @@ -40,7 +40,7 @@ func NewRequestWrapper( loop: loop, req: req, Query: req.URL.Query(), - URL: req.URL.String(), + Path: req.URL.Path, Host: req.Host, Proto: req.Proto, diff --git a/pkg/resources/document_manager.go b/pkg/resources/document_manager.go index c765215..51417c5 100644 --- a/pkg/resources/document_manager.go +++ b/pkg/resources/document_manager.go @@ -5,6 +5,6 @@ import ( ) type DocumentManager interface { - GetDocumentByID(namespace, collection, id string) (*spec.Document, error) + GetDocumentByID(id, collection, namespace string) (*spec.Document, error) GetDocuments(collection, namespace string, limit, offset int) ([]*spec.Document, error) } diff --git a/pkg/resources/resource_manager.go b/pkg/resources/resource_manager.go index 8c96112..cee0d69 100644 --- a/pkg/resources/resource_manager.go +++ b/pkg/resources/resource_manager.go @@ -157,17 +157,38 @@ func (rm *ResourceManager) GetRoute(name, namespace string) (*spec.DGateRoute, b func (rm *ResourceManager) getRoute(name, namespace string) (*spec.DGateRoute, bool) { if lk, ok := rm.routes.Find(name + "/" + namespace); ok { - return lk.Item().Read(), true + return rm.updateRouteRef(lk), true } return nil, false } +func (rm *ResourceManager) updateRouteRef( + lk *linker.Link[string, safe.Ref[spec.DGateRoute]], +) *spec.DGateRoute { + rt := lk.Item().Read() + rt.Modules = []*spec.DGateModule{} + lk.Each("modules", func(_ string, lk linker.Linker[string]) { + mdLk := linker.NamedVertexWithVertex[string, safe.Ref[spec.DGateModule]](lk) + rt.Modules = append(rt.Modules, mdLk.Item().Read()) + }) + if mods, ok := rm.getRouteModules(rt.Name, rt.Namespace.Name); ok { + rt.Modules = mods + } + if rt.Service != nil { + svcKey := rt.Service.Name + "/" + rt.Namespace.Name + if svc, ok := rm.services.Find(svcKey); ok { + rt.Service = svc.Item().Read() + } + } + return rt +} + // GetRoutes returns a list of all routes func (rm *ResourceManager) GetRoutes() []*spec.DGateRoute { defer rm.mutex.RLockMain()() var routes []*spec.DGateRoute rm.routes.Each(func(_ string, rtlk *linker.Link[string, safe.Ref[spec.DGateRoute]]) bool { - routes = append(routes, rtlk.Item().Read()) + routes = append(routes, rm.updateRouteRef(rtlk)) return true }) return routes @@ -179,8 +200,8 @@ func (rm *ResourceManager) GetRoutesByNamespace(namespace string) []*spec.DGateR var routes []*spec.DGateRoute if nsLk, ok := rm.namespaces.Find(namespace); ok { nsLk.Each("routes", func(_ string, lk linker.Linker[string]) { - rtLk := linker.NamedVertexWithVertex[string, safe.Ref[spec.DGateRoute]](lk) - routes = append(routes, rtLk.Item().Read()) + rtlk := linker.NamedVertexWithVertex[string, safe.Ref[spec.DGateRoute]](lk) + routes = append(routes, rm.updateRouteRef(rtlk)) }) } return routes @@ -193,8 +214,8 @@ func (rm *ResourceManager) GetRouteNamespaceMap() map[string][]*spec.DGateRoute rm.namespaces.Each(func(ns string, lk *linker.Link[string, safe.Ref[spec.DGateNamespace]]) bool { routes := []*spec.DGateRoute{} lk.Each("routes", func(_ string, lk linker.Linker[string]) { - rtLk := linker.NamedVertexWithVertex[string, safe.Ref[spec.DGateRoute]](lk) - routes = append(routes, rtLk.Item().Read()) + rtlk := linker.NamedVertexWithVertex[string, safe.Ref[spec.DGateRoute]](lk) + routes = append(routes, rm.updateRouteRef(rtlk)) }) if len(routes) > 0 { routeMap[ns] = routes @@ -374,15 +395,20 @@ func (rm *ResourceManager) AddService(service *spec.Service) (*spec.DGateService if err != nil { return nil, err } - rw := safe.NewRef(svc) - svcLk := linker.NewNamedVertexWithValue(rw, "routes", "namespaces") - if nsLk, ok := rm.namespaces.Find(service.NamespaceName); ok { - svcLk.LinkOneMany("namespaces", service.NamespaceName, nsLk) - nsLk.LinkOneMany("services", service.Name, svcLk) - rm.services.Insert(service.Name+"/"+service.NamespaceName, svcLk) - return rw.Read(), nil + if svcLk, ok := rm.services.Find(service.Name + "/" + service.NamespaceName); ok { + svcLk.Item().Replace(svc) + return svc, nil } else { - return nil, ErrNamespaceNotFound(service.NamespaceName) + rw := safe.NewRef(svc) + svcLk = linker.NewNamedVertexWithValue(rw, "routes", "namespaces") + if nsLk, ok := rm.namespaces.Find(service.NamespaceName); ok { + svcLk.LinkOneMany("namespaces", service.NamespaceName, nsLk) + nsLk.LinkOneMany("services", service.Name, svcLk) + rm.services.Insert(service.Name+"/"+service.NamespaceName, svcLk) + return rw.Read(), nil + } else { + return nil, ErrNamespaceNotFound(service.NamespaceName) + } } } @@ -493,13 +519,18 @@ func (rm *ResourceManager) AddDomain(domain *spec.Domain) (*spec.DGateDomain, er if err != nil { return nil, err } - rw := safe.NewRef(dm) - dmLk := linker.NewNamedVertexWithValue(rw, "namespace") - if nsLk, ok := rm.namespaces.Find(domain.NamespaceName); ok { - nsLk.LinkOneMany("domains", domain.Name, dmLk) - dmLk.LinkOneOne("namespace", domain.NamespaceName, nsLk) - rm.domains.Insert(domain.Name+"/"+domain.NamespaceName, dmLk) - return rw.Read(), nil + if dmLk, ok := rm.domains.Find(domain.Name + "/" + domain.NamespaceName); ok { + dmLk.Item().Replace(dm) + return dm, nil + } else { + rw := safe.NewRef(dm) + dmLk = linker.NewNamedVertexWithValue(rw, "namespace") + if nsLk, ok := rm.namespaces.Find(domain.NamespaceName); ok { + nsLk.LinkOneMany("domains", domain.Name, dmLk) + dmLk.LinkOneOne("namespace", domain.NamespaceName, nsLk) + rm.domains.Insert(domain.Name+"/"+domain.NamespaceName, dmLk) + return rw.Read(), nil + } } return nil, ErrNamespaceNotFound(domain.NamespaceName) } @@ -566,18 +597,24 @@ func (rm *ResourceManager) GetModules() []*spec.DGateModule { // GetRouteModules returns a list of all modules in a route func (rm *ResourceManager) GetRouteModules(name, namespace string) ([]*spec.DGateModule, bool) { defer rm.mutex.RLock(namespace)() - route, ok := rm.getRoute(name, namespace) - if !ok { + return rm.getRouteModules(name, namespace) +} + +// getRouteModules returns a list of all modules in a route +func (rm *ResourceManager) getRouteModules(name, namespace string) ([]*spec.DGateModule, bool) { + if lk, ok := rm.routes.Find(name + "/" + namespace); ok { + rt := lk.Item().Read() + var modules []*spec.DGateModule + if rtLk, ok := rm.routes.Find(rt.Name + "/" + rt.Namespace.Name); ok { + rtLk.Each("modules", func(_ string, lk linker.Linker[string]) { + mdLk := linker.NamedVertexWithVertex[string, safe.Ref[spec.DGateModule]](lk) + modules = append(modules, mdLk.Item().Read()) + }) + } + return modules, true + } else { return nil, false } - var modules []*spec.DGateModule - if rtLk, ok := rm.routes.Find(route.Name + "/" + route.Namespace.Name); ok { - rtLk.Each("modules", func(_ string, lk linker.Linker[string]) { - mdLk := linker.NamedVertexWithVertex[string, safe.Ref[spec.DGateModule]](lk) - modules = append(modules, mdLk.Item().Read()) - }) - } - return modules, true } // GetModulesByNamespace returns a list of all modules in a namespace @@ -595,19 +632,22 @@ func (rm *ResourceManager) GetModulesByNamespace(namespace string) []*spec.DGate func (rm *ResourceManager) AddModule(module *spec.Module) (*spec.DGateModule, error) { defer rm.mutex.Lock(module.NamespaceName)() - md, err := rm.transformModule(module) - if err != nil { + if md, err := rm.transformModule(module); err != nil { return nil, err - } - rw := safe.NewRef(md) - modLk := linker.NewNamedVertexWithValue(rw, "namespace", "routes") - if nsLk, ok := rm.namespaces.Find(module.NamespaceName); ok { - nsLk.LinkOneMany("modules", module.Name, modLk) - modLk.LinkOneOne("namespace", module.NamespaceName, nsLk) - rm.modules.Insert(module.Name+"/"+module.NamespaceName, modLk) - return rw.Read(), nil + } else if modLk, ok := rm.modules.Find(module.Name + "/" + module.NamespaceName); ok { + modLk.Item().Replace(md) + return md, nil } else { - return nil, ErrNamespaceNotFound(module.NamespaceName) + rw := safe.NewRef(md) + modLk = linker.NewNamedVertexWithValue(rw, "namespace", "routes") + if nsLk, ok := rm.namespaces.Find(module.NamespaceName); ok { + nsLk.LinkOneMany("modules", module.Name, modLk) + modLk.LinkOneOne("namespace", module.NamespaceName, nsLk) + rm.modules.Insert(module.Name+"/"+module.NamespaceName, modLk) + return rw.Read(), nil + } else { + return nil, ErrNamespaceNotFound(module.NamespaceName) + } } } @@ -683,15 +723,20 @@ func (rm *ResourceManager) AddCollection(collection *spec.Collection) (*spec.DGa if err != nil { return nil, err } - rw := safe.NewRef(cl) - colLk := linker.NewNamedVertexWithValue(rw, "namespace") - if nsLk, ok := rm.namespaces.Find(collection.NamespaceName); ok { - nsLk.LinkOneMany("collections", collection.Name, colLk) - colLk.LinkOneOne("namespace", collection.NamespaceName, nsLk) - rm.collections.Insert(collection.Name+"/"+collection.NamespaceName, colLk) - return rw.Read(), nil + if clLk, ok := rm.collections.Find(collection.Name + "/" + collection.NamespaceName); ok { + clLk.Item().Replace(cl) + return cl, nil } else { - return nil, ErrNamespaceNotFound(collection.NamespaceName) + rw := safe.NewRef(cl) + colLk := linker.NewNamedVertexWithValue(rw, "namespace") + if nsLk, ok := rm.namespaces.Find(collection.NamespaceName); ok { + nsLk.LinkOneMany("collections", collection.Name, colLk) + colLk.LinkOneOne("namespace", collection.NamespaceName, nsLk) + rm.collections.Insert(collection.Name+"/"+collection.NamespaceName, colLk) + return rw.Read(), nil + } else { + return nil, ErrNamespaceNotFound(collection.NamespaceName) + } } } @@ -773,19 +818,24 @@ func (rm *ResourceManager) GetSecretsByNamespace(namespace string) []*spec.DGate func (rm *ResourceManager) AddSecret(secret *spec.Secret) (*spec.DGateSecret, error) { defer rm.mutex.Lock(secret.NamespaceName)() - md, err := rm.transformSecret(secret) + sec, err := rm.transformSecret(secret) if err != nil { return nil, err } - rw := safe.NewRef(md) - scrtLk := linker.NewNamedVertexWithValue(rw, "namespace") - if nsLk, ok := rm.namespaces.Find(secret.NamespaceName); ok { - nsLk.LinkOneMany("secrets", secret.Name, scrtLk) - scrtLk.LinkOneOne("namespace", secret.NamespaceName, nsLk) - rm.secrets.Insert(secret.Name+"/"+secret.NamespaceName, scrtLk) - return rw.Read(), nil + if rw, ok := rm.secrets.Find(secret.Name + "/" + secret.NamespaceName); ok { + rw.Item().Replace(sec) + return sec, nil } else { - return nil, ErrNamespaceNotFound(secret.NamespaceName) + rw := safe.NewRef(sec) + scrtLk := linker.NewNamedVertexWithValue(rw, "namespace") + if nsLk, ok := rm.namespaces.Find(secret.NamespaceName); ok { + nsLk.LinkOneMany("secrets", secret.Name, scrtLk) + scrtLk.LinkOneOne("namespace", secret.NamespaceName, nsLk) + rm.secrets.Insert(secret.Name+"/"+secret.NamespaceName, scrtLk) + return rw.Read(), nil + } else { + return nil, ErrNamespaceNotFound(secret.NamespaceName) + } } } diff --git a/pkg/spec/change_log.go b/pkg/spec/change_log.go index b815aec..90d3d26 100644 --- a/pkg/spec/change_log.go +++ b/pkg/spec/change_log.go @@ -119,16 +119,19 @@ func (clc Command) IsRestart() bool { } func (resource1 Resource) IsRelatedTo(resource2 Resource) bool { - if resource1 == resource2 || resource1 == Namespaces || resource2 == Namespaces { + if resource1 == resource2 { return true } + if resource1 == Namespaces || resource2 == Namespaces { + if resource1 != Documents && resource2 != Documents { + return true + } + } switch resource1 { case Routes: return resource2 == Services || resource2 == Modules - case Services: + case Services, Modules: return resource2 == Routes - case Modules: - return resource2 == Namespaces case Collections: return resource2 == Documents case Documents: diff --git a/pkg/util/logadapter/zap2hc.go b/pkg/util/logadapter/zap2hc.go index 2fa81bd..f787311 100644 --- a/pkg/util/logadapter/zap2hc.go +++ b/pkg/util/logadapter/zap2hc.go @@ -2,6 +2,7 @@ package logadapter import ( "context" + "fmt" "io" "log" @@ -39,34 +40,52 @@ func (l *Zap2HCLogAdapter) IsError() bool { return l.logger.Core().Enabled(hc2zapLevel(hclog.Error)) } -func (l *Zap2HCLogAdapter) Trace(format string, args ...interface{}) {} +func (l *Zap2HCLogAdapter) Trace(format string, args ...any) {} -func (l *Zap2HCLogAdapter) Debug(format string, args ...interface{}) { - l.logger.Debug(format) +func prepArgs(args ...any) []zap.Field { + if len(args) == 0 { + return []zap.Field{} + } else if len(args)%2 != 0 { + args = append(args, "MISSING") + } + fields := make([]zap.Field, 0, len(args)/2) + for i := 0; i < len(args); i += 2 { + key, val := args[i].(string), args[i+1] + switch t := val.(type) { + case hclog.Format: + val = fmt.Sprintf(t[0].(string), t[1:]...) + } + fields = append(fields, zap.Any(key, val)) + } + return fields +} + +func (l *Zap2HCLogAdapter) Debug(format string, args ...any) { + l.Log(hclog.Debug, format, args...) } -func (l *Zap2HCLogAdapter) Info(format string, args ...interface{}) { - l.logger.Info(format) +func (l *Zap2HCLogAdapter) Info(format string, args ...any) { + l.Log(hclog.Info, format, args...) } -func (l *Zap2HCLogAdapter) Warn(format string, args ...interface{}) { - l.logger.Warn(format) +func (l *Zap2HCLogAdapter) Warn(format string, args ...any) { + l.Log(hclog.Warn, format, args...) } -func (l *Zap2HCLogAdapter) Error(format string, args ...interface{}) { - l.logger.Error(format) +func (l *Zap2HCLogAdapter) Error(format string, args ...any) { + l.Log(hclog.Error, format, args...) } -func (l *Zap2HCLogAdapter) Log(level hclog.Level, format string, args ...interface{}) { +func (l *Zap2HCLogAdapter) Log(level hclog.Level, format string, args ...any) { switch level { case hclog.Debug: - l.Debug(format, args...) + l.logger.Debug(format, prepArgs(args...)...) case hclog.Info: - l.Info(format, args...) + l.logger.Info(format, prepArgs(args...)...) case hclog.Warn: - l.Warn(format, args...) + l.logger.Warn(format, prepArgs(args...)...) case hclog.Error: - l.Error(format, args...) + l.logger.Error(format, prepArgs(args...)...) } } @@ -100,7 +119,7 @@ func (l *Zap2HCLogAdapter) StandardWriter(opts *hclog.StandardLoggerOptions) io. return l.StandardLogger(opts).Writer() } -func (l *Zap2HCLogAdapter) ImpliedArgs() []interface{} { +func (l *Zap2HCLogAdapter) ImpliedArgs() []any { return nil }