feat: add configurable default ETag for files without metadata

When versitygw serves files that were placed on the filesystem outside
of the gateway, those files have no stored etag attribute and are
served with an empty ETag. This causes problems for S3 clients that
rely on ETags being non empty.

The new --default-etag flag (VGW_DEFAULT_ETAG) lets operators specify
a fallback ETag value returned for any object that lacks a stored etag
attribute, making pre-existing filesystem data behave more predictably
under S3 workloads without requiring a metadata migration.
This commit is contained in:
Ben McClelland
2026-07-02 18:09:27 -07:00
parent 6b2380853f
commit 9db2c9c702
6 changed files with 62 additions and 10 deletions
+8
View File
@@ -34,6 +34,7 @@ var (
forceNoTmpFile bool
forceNoCopyFileRange bool
actionsConcurrency int
defaultEtag string
)
func posixCommand() *cli.Command {
@@ -115,6 +116,12 @@ will be translated into the file /mnt/fs/gwroot/mybucket/a/b/c/myobject`,
EnvVars: []string{"VGW_DISABLE_COPY_FILE_RANGE"},
Destination: &forceNoCopyFileRange,
},
&cli.StringFlag{
Name: "default-etag",
Usage: "default ETag value returned for objects that do not have a stored etag attribute (e.g. files placed on the filesystem outside of versitygw)",
EnvVars: []string{"VGW_DEFAULT_ETAG"},
Destination: &defaultEtag,
},
},
}
}
@@ -149,6 +156,7 @@ func runPosix(ctx *cli.Context) error {
ValidateBucketNames: disableStrictBucketNames,
Concurrency: actionsConcurrency,
CopyObjectThreshold: copyObjectThreshold,
DefaultEtag: defaultEtag,
}
var ms meta.MetadataStorer
+7
View File
@@ -106,6 +106,12 @@ move interfaces as well as support for tiered filesystems.`,
Value: 5000,
Destination: &actionsConcurrency,
},
&cli.StringFlag{
Name: "default-etag",
Usage: "default ETag value returned for objects that do not have a stored etag attribute (e.g. files placed on the filesystem outside of versitygw)",
EnvVars: []string{"VGW_DEFAULT_ETAG"},
Destination: &defaultEtag,
},
},
}
}
@@ -135,6 +141,7 @@ func runScoutfs(ctx *cli.Context) error {
opts.SetProjectID = setProjectID
opts.Concurrency = actionsConcurrency
opts.CopyObjectThreshold = copyObjectThreshold
opts.DefaultEtag = defaultEtag
be, err := scoutfs.New(ctx.Args().Get(0), opts)
if err != nil {