This is an automated email from the ASF dual-hosted git repository.
hanahmily pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-banyandb.git
The following commit(s) were added to refs/heads/main by this push:
new 40ea444f2 Support relative paths in configuration (#996)
40ea444f2 is described below
commit 40ea444f2a7edd407a3c127034b806b0e064b168
Author: Ali Yasir NaƧ <[email protected]>
AuthorDate: Tue Mar 10 17:27:18 2026 +0300
Support relative paths in configuration (#996)
* feat: introduce path utility to resolve service root and data paths to
absolute paths.
* added banyandbpath support to restore.go and backup.go, and documented it
in configuration.md.
---------
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Gao Hongtao <[email protected]>
---
CHANGES.md | 1 +
banyand/backup/backup.go | 19 ++++++
banyand/backup/restore.go | 18 ++++++
banyand/liaison/grpc/server.go | 24 +++++++
banyand/measure/svc_data.go | 18 ++++--
banyand/measure/svc_liaison.go | 10 +++
banyand/measure/svc_standalone.go | 18 ++++--
banyand/metadata/client.go | 35 +++++++++++
banyand/metadata/schema/schemaserver/service.go | 5 ++
banyand/metadata/service/server.go | 6 ++
banyand/property/gossip/service.go | 18 ++++++
banyand/property/service.go | 7 ++-
banyand/queue/sub/server.go | 7 +++
banyand/stream/svc_liaison.go | 10 +++
banyand/stream/svc_standalone.go | 16 ++++-
banyand/trace/svc_liaison.go | 14 ++++-
banyand/trace/svc_standalone.go | 10 ++-
docs/operation/configuration.md | 2 +
pkg/path/path.go | 34 ++++++++++
pkg/path/path_test.go | 83 +++++++++++++++++++++++++
20 files changed, 340 insertions(+), 15 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 0275b4129..cacf66f52 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -25,6 +25,7 @@ Release Notes.
- Add a generic snapshot coordination package for atomic snapshot transitions
across trace and sidx.
- Support map-reduce aggregation for measure queries: map phase (partial
aggregation on data nodes) and reduce phase (final aggregation on liaison).
- Add eBPF-based KTM I/O monitor for FODC agent.
+- Support relative paths in configuration.
### Bug Fixes
diff --git a/banyand/backup/backup.go b/banyand/backup/backup.go
index 2054127b4..fd7079d66 100644
--- a/banyand/backup/backup.go
+++ b/banyand/backup/backup.go
@@ -44,6 +44,7 @@ import (
"github.com/apache/skywalking-banyandb/pkg/fs/remote/gcp"
"github.com/apache/skywalking-banyandb/pkg/fs/remote/local"
"github.com/apache/skywalking-banyandb/pkg/logger"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/timestamp"
"github.com/apache/skywalking-banyandb/pkg/version"
)
@@ -151,6 +152,24 @@ func backupAction(options backupOptions) error {
if options.dest == "" {
return errors.New("dest is required")
}
+ var err error
+ options.streamRoot, err = banyandbpath.Get(options.streamRoot)
+ if err != nil {
+ return err
+ }
+ options.measureRoot, err = banyandbpath.Get(options.measureRoot)
+ if err != nil {
+ return err
+ }
+ options.propertyRoot, err = banyandbpath.Get(options.propertyRoot)
+ if err != nil {
+ return err
+ }
+ options.traceRoot, err = banyandbpath.Get(options.traceRoot)
+ if err != nil {
+ return err
+ }
+
fs, err := newFS(options.dest, &options.fsConfig)
if err != nil {
return err
diff --git a/banyand/backup/restore.go b/banyand/backup/restore.go
index 0cc3e0bc0..d021a57cb 100644
--- a/banyand/backup/restore.go
+++ b/banyand/backup/restore.go
@@ -36,6 +36,7 @@ import (
"github.com/apache/skywalking-banyandb/pkg/fs/remote"
remoteconfig
"github.com/apache/skywalking-banyandb/pkg/fs/remote/config"
"github.com/apache/skywalking-banyandb/pkg/logger"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/version"
)
@@ -85,6 +86,23 @@ func newRunCommand() *cobra.Command {
if source == "" {
return errors.New("source is required")
}
+
+ cleanPaths := func(paths ...*string) error {
+ for _, p := range paths {
+ if *p != "" {
+ var err error
+ if *p, err =
banyandbpath.Get(*p); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+ }
+
+ if err := cleanPaths(&streamRoot, &measureRoot,
&propertyRoot, &traceRoot); err != nil {
+ return err
+ }
+
fs, err := newFS(source, &fsConfig)
if err != nil {
return err
diff --git a/banyand/liaison/grpc/server.go b/banyand/liaison/grpc/server.go
index 589e9393d..5fb4b2c1b 100644
--- a/banyand/liaison/grpc/server.go
+++ b/banyand/liaison/grpc/server.go
@@ -54,6 +54,7 @@ import (
"github.com/apache/skywalking-banyandb/pkg/bydbql"
"github.com/apache/skywalking-banyandb/pkg/logger"
"github.com/apache/skywalking-banyandb/pkg/partition"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/run"
pkgtls "github.com/apache/skywalking-banyandb/pkg/tls"
)
@@ -218,6 +219,29 @@ func NewServer(_ context.Context, tir1Client, tir2Client,
broadcaster queue.Clie
func (s *server) PreRun(ctx context.Context) error {
s.log = logger.GetLogger("liaison-grpc")
s.initCurrentNode(ctx)
+
+ var err error
+ if s.accessLogRootPath != "" {
+ if s.accessLogRootPath, err =
banyandbpath.Get(s.accessLogRootPath); err != nil {
+ return err
+ }
+ }
+ if s.certFile != "" {
+ if s.certFile, err = banyandbpath.Get(s.certFile); err != nil {
+ return err
+ }
+ }
+ if s.keyFile != "" {
+ if s.keyFile, err = banyandbpath.Get(s.keyFile); err != nil {
+ return err
+ }
+ }
+ if s.authConfigFile != "" {
+ if s.authConfigFile, err = banyandbpath.Get(s.authConfigFile);
err != nil {
+ return err
+ }
+ }
+
s.streamSVC.setLogger(s.log.Named("stream-t1"))
s.measureSVC.setLogger(s.log)
s.traceSVC.setLogger(s.log.Named("trace"))
diff --git a/banyand/measure/svc_data.go b/banyand/measure/svc_data.go
index 61a69e777..bf7c9fedf 100644
--- a/banyand/measure/svc_data.go
+++ b/banyand/measure/svc_data.go
@@ -45,6 +45,7 @@ import (
"github.com/apache/skywalking-banyandb/pkg/fs"
"github.com/apache/skywalking-banyandb/pkg/logger"
"github.com/apache/skywalking-banyandb/pkg/meter/native"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/run"
resourceSchema "github.com/apache/skywalking-banyandb/pkg/schema"
"github.com/apache/skywalking-banyandb/pkg/timestamp"
@@ -233,6 +234,15 @@ func (s *dataSVC) PreRun(ctx context.Context) error {
s.l = logger.GetLogger(s.Name())
s.l.Info().Msg("memory protector is initialized in PreRun")
s.lfs = fs.NewLocalFileSystemWithLoggerAndLimit(s.l, s.pm.GetLimit())
+ var err error
+ if s.root, err = banyandbpath.Get(s.root); err != nil {
+ return err
+ }
+ if s.dataPath != "" {
+ if s.dataPath, err = banyandbpath.Get(s.dataPath); err != nil {
+ return err
+ }
+ }
path := path.Join(s.root, s.Name())
s.snapshotDir = filepath.Join(path, storage.SnapshotsDir)
obsservice.UpdatePath(path)
@@ -266,21 +276,21 @@ func (s *dataSVC) PreRun(ctx context.Context) error {
return fmt.Errorf("failed to subscribe to collect data info
topic: %w", subscribeErr)
}
- if err := s.createDataNativeObservabilityGroup(ctx); err != nil {
+ if err = s.createDataNativeObservabilityGroup(ctx); err != nil {
return err
}
- if err := s.pipeline.Subscribe(data.TopicSnapshot,
&dataSnapshotListener{s: s}); err != nil {
+ if err = s.pipeline.Subscribe(data.TopicSnapshot,
&dataSnapshotListener{s: s}); err != nil {
return err
}
- if err := s.pipeline.Subscribe(data.TopicMeasureDeleteExpiredSegments,
&dataDeleteStreamSegmentsListener{s: s}); err != nil {
+ if err = s.pipeline.Subscribe(data.TopicMeasureDeleteExpiredSegments,
&dataDeleteStreamSegmentsListener{s: s}); err != nil {
return err
}
s.pipeline.RegisterChunkedSyncHandler(data.TopicMeasurePartSync,
setUpChunkedSyncCallback(s.l, s.schemaRepo))
s.pipeline.RegisterChunkedSyncHandler(data.TopicMeasureSeriesSync,
setUpSyncSeriesCallback(s.l, s.schemaRepo))
- err := s.pipeline.Subscribe(data.TopicMeasureSeriesIndexInsert,
setUpIndexCallback(s.l, s.schemaRepo, data.TopicMeasureSeriesIndexInsert))
+ err = s.pipeline.Subscribe(data.TopicMeasureSeriesIndexInsert,
setUpIndexCallback(s.l, s.schemaRepo, data.TopicMeasureSeriesIndexInsert))
if err != nil {
return err
}
diff --git a/banyand/measure/svc_liaison.go b/banyand/measure/svc_liaison.go
index aa6dbea8d..6e946aba5 100644
--- a/banyand/measure/svc_liaison.go
+++ b/banyand/measure/svc_liaison.go
@@ -41,6 +41,7 @@ import (
"github.com/apache/skywalking-banyandb/pkg/fs"
"github.com/apache/skywalking-banyandb/pkg/logger"
"github.com/apache/skywalking-banyandb/pkg/node"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/run"
resourceSchema "github.com/apache/skywalking-banyandb/pkg/schema"
"github.com/apache/skywalking-banyandb/pkg/timestamp"
@@ -141,6 +142,15 @@ func (s *liaison) PreRun(ctx context.Context) error {
s.l = logger.GetLogger(s.Name())
s.l.Info().Msg("memory protector is initialized in PreRun")
s.lfs = fs.NewLocalFileSystemWithLoggerAndLimit(s.l, s.pm.GetLimit())
+ var err error
+ if s.root, err = banyandbpath.Get(s.root); err != nil {
+ return err
+ }
+ if s.dataPath != "" {
+ if s.dataPath, err = banyandbpath.Get(s.dataPath); err != nil {
+ return err
+ }
+ }
path := path.Join(s.root, s.Name())
obsservice.UpdatePath(path)
val := ctx.Value(common.ContextNodeKey)
diff --git a/banyand/measure/svc_standalone.go
b/banyand/measure/svc_standalone.go
index 06f6a8a6e..97e65e9b7 100644
--- a/banyand/measure/svc_standalone.go
+++ b/banyand/measure/svc_standalone.go
@@ -39,6 +39,7 @@ import (
"github.com/apache/skywalking-banyandb/banyand/queue"
"github.com/apache/skywalking-banyandb/pkg/fs"
"github.com/apache/skywalking-banyandb/pkg/logger"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/run"
resourceSchema "github.com/apache/skywalking-banyandb/pkg/schema"
"github.com/apache/skywalking-banyandb/pkg/timestamp"
@@ -240,6 +241,15 @@ func (s *standalone) PreRun(ctx context.Context) error {
s.l = logger.GetLogger(s.Name())
s.l.Info().Msg("memory protector is initialized in PreRun")
s.lfs = fs.NewLocalFileSystemWithLoggerAndLimit(s.l, s.pm.GetLimit())
+ var err error
+ if s.root, err = banyandbpath.Get(s.root); err != nil {
+ return err
+ }
+ if s.dataPath != "" {
+ if s.dataPath, err = banyandbpath.Get(s.dataPath); err != nil {
+ return err
+ }
+ }
path := path.Join(s.root, s.Name())
s.snapshotDir = filepath.Join(path, storage.SnapshotsDir)
obsservice.UpdatePath(path)
@@ -273,11 +283,11 @@ func (s *standalone) PreRun(ctx context.Context) error {
return nil
}
- if err := s.createNativeObservabilityGroup(ctx); err != nil {
+ if err = s.createNativeObservabilityGroup(ctx); err != nil {
return err
}
- if err := s.pipeline.Subscribe(data.TopicSnapshot, &snapshotListener{s:
s}); err != nil {
+ if err = s.pipeline.Subscribe(data.TopicSnapshot, &snapshotListener{s:
s}); err != nil {
return err
}
@@ -289,12 +299,12 @@ func (s *standalone) PreRun(ctx context.Context) error {
writeListener := setUpWriteCallback(s.l, s.schemaRepo,
int(s.retentionConfig.HighWatermark))
// only subscribe metricPipeline for data node
if s.metricPipeline != nil {
- err := s.metricPipeline.Subscribe(data.TopicMeasureWrite,
writeListener)
+ err = s.metricPipeline.Subscribe(data.TopicMeasureWrite,
writeListener)
if err != nil {
return err
}
}
- err := s.pipeline.Subscribe(data.TopicMeasureWrite, writeListener)
+ err = s.pipeline.Subscribe(data.TopicMeasureWrite, writeListener)
if err != nil {
return err
}
diff --git a/banyand/metadata/client.go b/banyand/metadata/client.go
index 8258840e8..20fbdb6dd 100644
--- a/banyand/metadata/client.go
+++ b/banyand/metadata/client.go
@@ -39,6 +39,7 @@ import (
"github.com/apache/skywalking-banyandb/banyand/observability"
"github.com/apache/skywalking-banyandb/pkg/bus"
"github.com/apache/skywalking-banyandb/pkg/logger"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/run"
)
@@ -263,6 +264,40 @@ func (s *clientService) PreRun(ctx context.Context) error {
}
}()
+ var err error
+ if s.etcdTLSCAFile != "" {
+ if s.etcdTLSCAFile, err = banyandbpath.Get(s.etcdTLSCAFile);
err != nil {
+ return errors.Wrapf(err, "failed to resolve path for
etcdTLSCAFile %q", s.etcdTLSCAFile)
+ }
+ }
+ if s.etcdTLSCertFile != "" {
+ if s.etcdTLSCertFile, err =
banyandbpath.Get(s.etcdTLSCertFile); err != nil {
+ return errors.Wrapf(err, "failed to resolve path for
etcdTLSCertFile %q", s.etcdTLSCertFile)
+ }
+ }
+ if s.etcdTLSKeyFile != "" {
+ if s.etcdTLSKeyFile, err = banyandbpath.Get(s.etcdTLSKeyFile);
err != nil {
+ return errors.Wrapf(err, "failed to resolve path for
etcdTLSKeyFile %q", s.etcdTLSKeyFile)
+ }
+ }
+ if s.propertySchemaClientCACert != "" {
+ if s.propertySchemaClientCACert, err =
banyandbpath.Get(s.propertySchemaClientCACert); err != nil {
+ return errors.Wrapf(err, "failed to resolve path for
propertySchemaClientCACert %q", s.propertySchemaClientCACert)
+ }
+ }
+ if s.filePath != "" {
+ if s.filePath, err = banyandbpath.Get(s.filePath); err != nil {
+ return errors.Wrapf(err, "failed to resolve path for
filePath %q", s.filePath)
+ }
+ }
+ for i, certPath := range s.dnsCACertPaths {
+ if certPath != "" {
+ if s.dnsCACertPaths[i], err =
banyandbpath.Get(certPath); err != nil {
+ return err
+ }
+ }
+ }
+
// initialize etcd registry when needed for node discovery or etcd
schema mode
if s.nodeDiscoveryMode == NodeDiscoveryModeEtcd || s.schemaRegistryMode
== RegistryModeEtcd {
initErr := s.initEtcdRegistry(l, stopCh)
diff --git a/banyand/metadata/schema/schemaserver/service.go
b/banyand/metadata/schema/schemaserver/service.go
index 8944d93db..7fce8b9ad 100644
--- a/banyand/metadata/schema/schemaserver/service.go
+++ b/banyand/metadata/schema/schemaserver/service.go
@@ -47,6 +47,7 @@ import (
"github.com/apache/skywalking-banyandb/banyand/property/gossip"
"github.com/apache/skywalking-banyandb/pkg/fs"
"github.com/apache/skywalking-banyandb/pkg/logger"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/run"
pkgtls "github.com/apache/skywalking-banyandb/pkg/tls"
)
@@ -183,6 +184,10 @@ func (s *server) Validate() error {
func (s *server) PreRun(_ context.Context) error {
s.l = logger.GetLogger("schema-server")
+ var err error
+ if s.root, err = banyandbpath.Get(s.root); err != nil {
+ return err
+ }
s.lfs = fs.NewLocalFileSystem()
s.watchers = newWatcherManager(s.l)
diff --git a/banyand/metadata/service/server.go
b/banyand/metadata/service/server.go
index e90c98a60..eeeb63172 100644
--- a/banyand/metadata/service/server.go
+++ b/banyand/metadata/service/server.go
@@ -38,6 +38,7 @@ import (
"github.com/apache/skywalking-banyandb/banyand/observability"
"github.com/apache/skywalking-banyandb/banyand/queue"
"github.com/apache/skywalking-banyandb/pkg/logger"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/run"
"github.com/apache/skywalking-banyandb/pkg/timestamp"
)
@@ -174,6 +175,11 @@ func (s *server) Validate() error {
func (s *server) PreRun(ctx context.Context) error {
needEtcd := s.schemaRegistryMode == schemaTypeEtcd ||
s.nodeDiscoveryMode == metadata.NodeDiscoveryModeEtcd
if s.embedded && needEtcd {
+ var err error
+ s.rootDir, err = banyandbpath.Get(s.rootDir)
+ if err != nil {
+ return err
+ }
etcdServer, startErr :=
embeddedetcd.NewServer(embeddedetcd.RootDir(s.rootDir),
embeddedetcd.ConfigureListener(s.listenClientURL, s.listenPeerURL),
embeddedetcd.AutoCompactionMode(s.autoCompactionMode),
embeddedetcd.AutoCompactionRetention(s.autoCompactionRetention),
embeddedetcd.QuotaBackendBytes(int64(s.quotaBackendBytes)))
diff --git a/banyand/property/gossip/service.go
b/banyand/property/gossip/service.go
index 962a455e9..91000c0f0 100644
--- a/banyand/property/gossip/service.go
+++ b/banyand/property/gossip/service.go
@@ -44,6 +44,7 @@ import (
"github.com/apache/skywalking-banyandb/pkg/logger"
"github.com/apache/skywalking-banyandb/pkg/node"
"github.com/apache/skywalking-banyandb/pkg/partition"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/run"
)
@@ -182,6 +183,23 @@ func (s *service) FlagSet() *run.FlagSet {
}
func (s *service) Validate() error {
+ var err error
+ if s.caCertPath != "" {
+ if s.caCertPath, err = banyandbpath.Get(s.caCertPath); err !=
nil {
+ return err
+ }
+ }
+ if s.certFile != "" {
+ if s.certFile, err = banyandbpath.Get(s.certFile); err != nil {
+ return err
+ }
+ }
+ if s.keyFile != "" {
+ if s.keyFile, err = banyandbpath.Get(s.keyFile); err != nil {
+ return err
+ }
+ }
+
// client side tls validation
if s.tls && s.caCertPath == "" {
return fmt.Errorf("CA certificate path must be provided when
TLS is enabled")
diff --git a/banyand/property/service.go b/banyand/property/service.go
index 5cb66b011..c7bded2c3 100644
--- a/banyand/property/service.go
+++ b/banyand/property/service.go
@@ -43,6 +43,7 @@ import (
"github.com/apache/skywalking-banyandb/pkg/bus"
"github.com/apache/skywalking-banyandb/pkg/fs"
"github.com/apache/skywalking-banyandb/pkg/logger"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/run"
)
@@ -133,6 +134,11 @@ func (s *service) Role() databasev1.Role {
func (s *service) PreRun(ctx context.Context) error {
s.l = logger.GetLogger(s.Name())
s.lfs = fs.NewLocalFileSystemWithLoggerAndLimit(s.l, s.pm.GetLimit())
+ var err error
+ s.root, err = banyandbpath.Get(s.root)
+ if err != nil {
+ return err
+ }
path := path.Join(s.root, s.Name())
s.snapshotDir = filepath.Join(path, storage.SnapshotsDir)
s.repairDir = filepath.Join(path, storage.RepairDir)
@@ -144,7 +150,6 @@ func (s *service) PreRun(ctx context.Context) error {
node := val.(common.Node)
s.nodeID = node.NodeID
- var err error
snapshotLis := &snapshotListener{s: s}
s.db, err = db.OpenDB(ctx, db.Config{
Location: filepath.Join(path, storage.DataDir),
diff --git a/banyand/queue/sub/server.go b/banyand/queue/sub/server.go
index 01a3a004f..2f36afa8d 100644
--- a/banyand/queue/sub/server.go
+++ b/banyand/queue/sub/server.go
@@ -52,6 +52,7 @@ import (
"github.com/apache/skywalking-banyandb/pkg/healthcheck"
"github.com/apache/skywalking-banyandb/pkg/logger"
"github.com/apache/skywalking-banyandb/pkg/meter"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/run"
pkgtls "github.com/apache/skywalking-banyandb/pkg/tls"
)
@@ -139,6 +140,12 @@ func (s *server) PreRun(ctx context.Context) error {
// Initialize TLS reloader if TLS is enabled
if s.tls {
var err error
+ if s.certFile, err = banyandbpath.Get(s.certFile); err != nil {
+ return errors.Wrap(err, "failed to get absolute path
for certFile")
+ }
+ if s.keyFile, err = banyandbpath.Get(s.keyFile); err != nil {
+ return errors.Wrap(err, "failed to get absolute path
for keyFile")
+ }
s.tlsReloader, err = pkgtls.NewReloader(s.certFile, s.keyFile,
s.log)
if err != nil {
return errors.Wrap(err, "failed to initialize TLS
reloader for queue server")
diff --git a/banyand/stream/svc_liaison.go b/banyand/stream/svc_liaison.go
index 25a3ec86e..e0247347d 100644
--- a/banyand/stream/svc_liaison.go
+++ b/banyand/stream/svc_liaison.go
@@ -41,6 +41,7 @@ import (
"github.com/apache/skywalking-banyandb/pkg/fs"
"github.com/apache/skywalking-banyandb/pkg/logger"
"github.com/apache/skywalking-banyandb/pkg/node"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/run"
resourceSchema "github.com/apache/skywalking-banyandb/pkg/schema"
"github.com/apache/skywalking-banyandb/pkg/timestamp"
@@ -148,6 +149,15 @@ func (s *liaison) PreRun(ctx context.Context) error {
s.l = logger.GetLogger(s.Name())
s.l.Info().Msg("memory protector is initialized in PreRun")
s.lfs = fs.NewLocalFileSystemWithLoggerAndLimit(s.l, s.pm.GetLimit())
+ var err error
+ if s.root, err = banyandbpath.Get(s.root); err != nil {
+ return err
+ }
+ if s.dataPath != "" {
+ if s.dataPath, err = banyandbpath.Get(s.dataPath); err != nil {
+ return err
+ }
+ }
path := path.Join(s.root, s.Name())
obsservice.UpdatePath(path)
val := ctx.Value(common.ContextNodeKey)
diff --git a/banyand/stream/svc_standalone.go b/banyand/stream/svc_standalone.go
index eea34da8e..7174ae6ab 100644
--- a/banyand/stream/svc_standalone.go
+++ b/banyand/stream/svc_standalone.go
@@ -41,6 +41,7 @@ import (
"github.com/apache/skywalking-banyandb/pkg/bus"
"github.com/apache/skywalking-banyandb/pkg/fs"
"github.com/apache/skywalking-banyandb/pkg/logger"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/run"
resourceSchema "github.com/apache/skywalking-banyandb/pkg/schema"
"github.com/apache/skywalking-banyandb/pkg/timestamp"
@@ -227,6 +228,15 @@ func (s *standalone) PreRun(ctx context.Context) error {
s.l = logger.GetLogger(s.Name())
s.l.Info().Msg("memory protector is initialized in PreRun")
s.lfs = fs.NewLocalFileSystemWithLoggerAndLimit(s.l, s.pm.GetLimit())
+ var err error
+ if s.root, err = banyandbpath.Get(s.root); err != nil {
+ return err
+ }
+ if s.dataPath != "" {
+ if s.dataPath, err = banyandbpath.Get(s.dataPath); err != nil {
+ return err
+ }
+ }
path := path.Join(s.root, s.Name())
s.snapshotDir = filepath.Join(path, storage.SnapshotsDir)
obsservice.UpdatePath(path)
@@ -256,10 +266,10 @@ func (s *standalone) PreRun(ctx context.Context) error {
}
s.localPipeline = queue.Local()
- if err := s.pipeline.Subscribe(data.TopicSnapshot, &snapshotListener{s:
s}); err != nil {
+ if err = s.pipeline.Subscribe(data.TopicSnapshot, &snapshotListener{s:
s}); err != nil {
return err
}
- if err := s.pipeline.Subscribe(data.TopicDeleteExpiredStreamSegments,
&deleteStreamSegmentsListener{s: s}); err != nil {
+ if err = s.pipeline.Subscribe(data.TopicDeleteExpiredStreamSegments,
&deleteStreamSegmentsListener{s: s}); err != nil {
return err
}
@@ -269,7 +279,7 @@ func (s *standalone) PreRun(ctx context.Context) error {
// For now, keep the original write throttling behavior based on high
watermark
writeListener := setUpWriteCallback(s.l, &s.schemaRepo,
int(s.retentionConfig.HighWatermark))
- err := s.pipeline.Subscribe(data.TopicStreamWrite, writeListener)
+ err = s.pipeline.Subscribe(data.TopicStreamWrite, writeListener)
if err != nil {
return err
}
diff --git a/banyand/trace/svc_liaison.go b/banyand/trace/svc_liaison.go
index 2ed967c1e..9ea23d179 100644
--- a/banyand/trace/svc_liaison.go
+++ b/banyand/trace/svc_liaison.go
@@ -43,6 +43,7 @@ import (
"github.com/apache/skywalking-banyandb/pkg/fs"
"github.com/apache/skywalking-banyandb/pkg/logger"
"github.com/apache/skywalking-banyandb/pkg/node"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/run"
resourceSchema "github.com/apache/skywalking-banyandb/pkg/schema"
"github.com/apache/skywalking-banyandb/pkg/timestamp"
@@ -162,6 +163,15 @@ func (l *liaison) PreRun(ctx context.Context) error {
l.l = logger.GetLogger(l.Name())
l.l.Info().Msg("memory protector is initialized in PreRun")
l.lfs = fs.NewLocalFileSystemWithLoggerAndLimit(l.l, l.pm.GetLimit())
+ var err error
+ if l.root, err = banyandbpath.Get(l.root); err != nil {
+ return err
+ }
+ if l.dataPath != "" {
+ if l.dataPath, err = banyandbpath.Get(l.dataPath); err != nil {
+ return err
+ }
+ }
path := path.Join(l.root, l.Name())
obsservice.UpdatePath(path)
val := ctx.Value(common.ContextNodeKey)
@@ -218,7 +228,8 @@ func (l *liaison) PreRun(ctx context.Context) error {
}
ctx, cancel :=
context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
- groupSchema, err :=
l.metadata.GroupRegistry().GetGroup(ctx, group)
+ var groupSchema *commonv1.Group
+ groupSchema, err =
l.metadata.GroupRegistry().GetGroup(ctx, group)
if err != nil {
return nil, err
}
@@ -244,7 +255,6 @@ func (l *liaison) PreRun(ctx context.Context) error {
return nodes, nil
}
- var err error
// nolint:contextcheck
l.handoffCtrl, err = newHandoffController(l.lfs, l.dataPath,
l.option.tire2Client, l.dataNodeList, maxSizeBytes, l.l, resolveAssignments)
if err != nil {
diff --git a/banyand/trace/svc_standalone.go b/banyand/trace/svc_standalone.go
index 7183832f8..0e42b5c5b 100644
--- a/banyand/trace/svc_standalone.go
+++ b/banyand/trace/svc_standalone.go
@@ -45,6 +45,7 @@ import (
"github.com/apache/skywalking-banyandb/pkg/bus"
"github.com/apache/skywalking-banyandb/pkg/fs"
"github.com/apache/skywalking-banyandb/pkg/logger"
+ banyandbpath "github.com/apache/skywalking-banyandb/pkg/path"
"github.com/apache/skywalking-banyandb/pkg/run"
resourceSchema "github.com/apache/skywalking-banyandb/pkg/schema"
"github.com/apache/skywalking-banyandb/pkg/timestamp"
@@ -136,6 +137,13 @@ func (s *standalone) PreRun(ctx context.Context) error {
s.l = logger.GetLogger(s.Name())
s.l.Info().Msg("memory protector is initialized in PreRun")
s.lfs = fs.NewLocalFileSystemWithLoggerAndLimit(s.l, s.pm.GetLimit())
+ var err error
+ if s.root, err = banyandbpath.Get(s.root); err != nil {
+ return err
+ }
+ if s.dataPath, err = banyandbpath.Get(s.dataPath); err != nil {
+ return err
+ }
path := path.Join(s.root, s.Name())
s.snapshotDir = filepath.Join(path, storage.SnapshotsDir)
obsservice.UpdatePath(path)
@@ -169,7 +177,7 @@ func (s *standalone) PreRun(ctx context.Context) error {
// Set up write callback handler. For now, keep the original write
throttling behavior based on high watermark
writeListener := setUpWriteCallback(s.l, &s.schemaRepo,
int(s.retentionConfig.HighWatermark))
- err := s.pipeline.Subscribe(data.TopicTraceWrite, writeListener)
+ err = s.pipeline.Subscribe(data.TopicTraceWrite, writeListener)
if err != nil {
return err
}
diff --git a/docs/operation/configuration.md b/docs/operation/configuration.md
index 537830be9..7c7b38a50 100644
--- a/docs/operation/configuration.md
+++ b/docs/operation/configuration.md
@@ -2,6 +2,8 @@
BanyanD is the BanyanDB server. There are two ways to configure BanyanD: using
a bootstrap flag or using environment variables. The environment variable name
has a prefix `BYDB_` followed by the flag name in uppercase. For example, the
flag `--port` can be set using the environment variable `BYDB_PORT`.
+> BanyanDB supports both absolute and relative paths for directory and file
configurations (such as data directories, TLS certificates, keys, etc.).
Relative paths are resolved against the current working directory where the
BanyanD process is started.
+
## Commands
### Bootstrap commands
diff --git a/pkg/path/path.go b/pkg/path/path.go
new file mode 100644
index 000000000..6cb49c1ed
--- /dev/null
+++ b/pkg/path/path.go
@@ -0,0 +1,34 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// Package path provides utilities to resolve relative paths to absolute paths.
+package path
+
+import (
+ "path/filepath"
+)
+
+// Get resolves the given path to an absolute path.
+// If the path is empty, it returns an empty string.
+// If the path is already absolute, it returns the cleaned path.
+// Otherwise, it returns the absolute path relative to the current working
directory.
+func Get(p string) (string, error) {
+ if p == "" {
+ return "", nil
+ }
+ return filepath.Abs(p)
+}
diff --git a/pkg/path/path_test.go b/pkg/path/path_test.go
new file mode 100644
index 000000000..472b85af0
--- /dev/null
+++ b/pkg/path/path_test.go
@@ -0,0 +1,83 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package path
+
+import (
+ "os"
+ "path/filepath"
+ "testing"
+)
+
+func TestGet(t *testing.T) {
+ wd, err := os.Getwd()
+ if err != nil {
+ t.Fatalf("failed to get working directory: %v", err)
+ }
+ absPath := filepath.Join(t.TempDir(), "test")
+
+ tests := []struct {
+ name string
+ input string
+ want string
+ wantErr bool
+ }{
+ {
+ name: "empty string",
+ input: "",
+ want: "",
+ wantErr: false,
+ },
+ {
+ name: "absolute path",
+ input: absPath,
+ want: filepath.Clean(absPath),
+ wantErr: false,
+ },
+ {
+ name: "relative path",
+ input: "test/dir",
+ want: filepath.Join(wd, "test/dir"),
+ wantErr: false,
+ },
+ {
+ name: "relative path with dot",
+ input: "./test/dir",
+ want: filepath.Join(wd, "test/dir"),
+ wantErr: false,
+ },
+ {
+ name: "relative path with parent",
+ input: "../test/dir",
+ want: filepath.Join(filepath.Dir(wd), "test/dir"),
+ wantErr: false,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ got, err := Get(test.input)
+ if (err != nil) != test.wantErr {
+ t.Errorf("Get() error = %v, wantErr %v", err,
test.wantErr)
+ return
+ }
+ if got != test.want {
+ t.Errorf("Get() = %v, want %v", got, test.want)
+ }
+ })
+ }
+}