Compare commits

...

4 commits

Author SHA1 Message Date
8e950d1cf4 Release v0.32.8
All checks were successful
/ DCO (pull_request) Successful in 29s
/ Vulncheck (pull_request) Successful in 1m5s
/ Builds (pull_request) Successful in 1m35s
/ OCI image (pull_request) Successful in 2m8s
/ Lint (pull_request) Successful in 2m25s
/ Tests (pull_request) Successful in 1m9s
/ OCI image (push) Successful in 2m13s
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2025-02-11 11:37:12 +03:00
2faadc0057 [#635] Bump go version in vulncheck
go1.23.5 triggers GO-2025-3447 but this is applicable
only for ppc64le platform.

Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2025-02-11 11:37:11 +03:00
b1cc53056e [#626] Fix ALREADY REMOVED response status code
All checks were successful
/ DCO (pull_request) Successful in 30s
/ Vulncheck (pull_request) Successful in 1m8s
/ Builds (pull_request) Successful in 1m36s
/ OCI image (pull_request) Successful in 2m36s
/ Lint (pull_request) Successful in 2m46s
/ Tests (pull_request) Successful in 1m12s
/ OCI image (push) Successful in 1m46s
Signed-off-by: Pavel Pogodaev <p.pogodaev@yadro.com>
2025-02-10 16:09:45 +03:00
901893a6fc [#627] Add tree_stream_timeout config parameter
All checks were successful
/ DCO (pull_request) Successful in 1m18s
/ Vulncheck (pull_request) Successful in 1m15s
/ Builds (pull_request) Successful in 1m51s
/ OCI image (pull_request) Successful in 2m9s
/ Lint (pull_request) Successful in 2m38s
/ Tests (pull_request) Successful in 1m43s
/ OCI image (push) Successful in 2m16s
Signed-off-by: Marina Biryukova <m.biryukova@yadro.com>
2025-02-07 12:45:03 +03:00
10 changed files with 58 additions and 16 deletions

View file

@ -16,7 +16,7 @@ jobs:
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: '1.23' go-version: '1.23.6'
- name: Install govulncheck - name: Install govulncheck
run: go install golang.org/x/vuln/cmd/govulncheck@latest run: go install golang.org/x/vuln/cmd/govulncheck@latest

View file

@ -4,15 +4,23 @@ This document outlines major changes between releases.
## [Unreleased] ## [Unreleased]
## [0.32.8] - 2025-02-11
### Fixed
- Return 404 instead of 500 when object is missing in object storage and available in the tree (#626)
### Added
- `tree_stream_timeout` configuration parameter (#627)
## [0.32.7] - 2025-02-06 ## [0.32.7] - 2025-02-06
### Fixed ### Fixed
- Corrct passing copies number during multipart upload (#623) - Correct passing copies number during multipart upload (#623)
## [0.32.6] - 2025-02-05 ## [0.32.6] - 2025-02-05
### Fixed ### Fixed
- Connection leak when `feature.tree_pool_netmap_support` is enabled. - Connection leak when `feature.tree_pool_netmap_support` is enabled (#622)
## [0.32.5] - 2025-02-04 ## [0.32.5] - 2025-02-04
@ -436,5 +444,6 @@ To see CHANGELOG for older versions, refer to https://github.com/nspcc-dev/neofs
[0.32.4]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.32.3...v0.32.4 [0.32.4]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.32.3...v0.32.4
[0.32.5]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.32.4...v0.32.5 [0.32.5]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.32.4...v0.32.5
[0.32.6]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.32.5...v0.32.6 [0.32.6]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.32.5...v0.32.6
[0.32.6]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.32.6...v0.32.7 [0.32.7]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.32.6...v0.32.7
[Unreleased]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.32.7...master [0.32.8]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.32.7...v0.32.8
[Unreleased]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.32.8...master

View file

@ -1 +1 @@
v0.32.7 v0.32.8

View file

@ -197,6 +197,33 @@ func TestGetObject(t *testing.T) {
getObjectAssertS3Error(hc, bktName, objName, emptyVersion, apierr.ErrNoSuchKey) getObjectAssertS3Error(hc, bktName, objName, emptyVersion, apierr.ErrNoSuchKey)
} }
func TestGetDeletedObject(t *testing.T) {
hc := prepareHandlerContextWithMinCache(t)
bktName, objName := "bucket", "obj"
bktInfo, objInfo := createVersionedBucketAndObject(hc.t, hc, bktName, objName)
putObject(hc, bktName, objName)
checkFound(hc.t, hc, bktName, objName, objInfo.VersionID())
checkFound(hc.t, hc, bktName, objName, emptyVersion)
addr := getAddressOfLastVersion(hc, bktInfo, objName)
t.Run("not found error", func(_ *testing.T) {
hc.tp.SetObjectError(addr, &apistatus.ObjectNotFound{})
hc.tp.SetObjectError(objInfo.Address(), &apistatus.ObjectNotFound{})
getObjectAssertS3Error(hc, bktName, objName, objInfo.VersionID(), apierr.ErrNoSuchVersion)
getObjectAssertS3Error(hc, bktName, objName, emptyVersion, apierr.ErrNoSuchKey)
})
t.Run("already removed error", func(_ *testing.T) {
hc.tp.SetObjectError(addr, &apistatus.ObjectAlreadyRemoved{})
hc.tp.SetObjectError(objInfo.Address(), &apistatus.ObjectAlreadyRemoved{})
getObjectAssertS3Error(hc, bktName, objName, objInfo.VersionID(), apierr.ErrNoSuchVersion)
getObjectAssertS3Error(hc, bktName, objName, emptyVersion, apierr.ErrNoSuchKey)
})
}
func TestGetObjectEnabledMD5(t *testing.T) { func TestGetObjectEnabledMD5(t *testing.T) {
hc := prepareHandlerContext(t) hc := prepareHandlerContext(t)
bktName, objName := "bucket", "obj" bktName, objName := "bucket", "obj"

View file

@ -410,7 +410,7 @@ func (n *Layer) headLastVersionIfNotDeleted(ctx context.Context, bkt *data.Bucke
meta, err := n.objectHead(ctx, bkt, node.OID) meta, err := n.objectHead(ctx, bkt, node.OID)
if err != nil { if err != nil {
if client.IsErrObjectNotFound(err) { if client.IsErrObjectNotFound(err) || client.IsErrObjectAlreadyRemoved(err) {
return nil, fmt.Errorf("%w: %s; %s", apierr.GetAPIError(apierr.ErrNoSuchKey), err.Error(), node.OID.EncodeToString()) return nil, fmt.Errorf("%w: %s; %s", apierr.GetAPIError(apierr.ErrNoSuchKey), err.Error(), node.OID.EncodeToString())
} }
return nil, err return nil, err
@ -467,7 +467,7 @@ func (n *Layer) headVersion(ctx context.Context, bkt *data.BucketInfo, p *HeadOb
meta, err := n.objectHead(ctx, bkt, foundVersion.OID) meta, err := n.objectHead(ctx, bkt, foundVersion.OID)
if err != nil { if err != nil {
if client.IsErrObjectNotFound(err) { if client.IsErrObjectNotFound(err) || client.IsErrObjectAlreadyRemoved(err) {
return nil, fmt.Errorf("%w: %s", apierr.GetAPIError(apierr.ErrNoSuchVersion), err.Error()) return nil, fmt.Errorf("%w: %s", apierr.GetAPIError(apierr.ErrNoSuchVersion), err.Error())
} }
return nil, err return nil, err

View file

@ -779,9 +779,8 @@ func (a *App) initPools(ctx context.Context) {
prm.SetNodeDialTimeout(connTimeout) prm.SetNodeDialTimeout(connTimeout)
prmTree.SetNodeDialTimeout(connTimeout) prmTree.SetNodeDialTimeout(connTimeout)
streamTimeout := fetchStreamTimeout(a.cfg) prm.SetNodeStreamTimeout(fetchStreamTimeout(a.cfg, cfgStreamTimeout))
prm.SetNodeStreamTimeout(streamTimeout) prmTree.SetNodeStreamTimeout(fetchStreamTimeout(a.cfg, cfgTreeStreamTimeout))
prmTree.SetNodeStreamTimeout(streamTimeout)
healthCheckTimeout := fetchHealthCheckTimeout(a.cfg) healthCheckTimeout := fetchHealthCheckTimeout(a.cfg)
prm.SetHealthcheckTimeout(healthCheckTimeout) prm.SetHealthcheckTimeout(healthCheckTimeout)

View file

@ -122,6 +122,7 @@ const ( // Settings.
// Pool config. // Pool config.
cfgConnectTimeout = "connect_timeout" cfgConnectTimeout = "connect_timeout"
cfgStreamTimeout = "stream_timeout" cfgStreamTimeout = "stream_timeout"
cfgTreeStreamTimeout = "tree_stream_timeout"
cfgHealthcheckTimeout = "healthcheck_timeout" cfgHealthcheckTimeout = "healthcheck_timeout"
cfgRebalanceInterval = "rebalance_interval" cfgRebalanceInterval = "rebalance_interval"
cfgPoolErrorThreshold = "pool_error_threshold" cfgPoolErrorThreshold = "pool_error_threshold"
@ -319,8 +320,8 @@ func fetchReconnectInterval(cfg *viper.Viper) time.Duration {
return reconnect return reconnect
} }
func fetchStreamTimeout(cfg *viper.Viper) time.Duration { func fetchStreamTimeout(cfg *viper.Viper, cfgEntry string) time.Duration {
streamTimeout := cfg.GetDuration(cfgStreamTimeout) streamTimeout := cfg.GetDuration(cfgEntry)
if streamTimeout <= 0 { if streamTimeout <= 0 {
streamTimeout = defaultStreamTimeout streamTimeout = defaultStreamTimeout
} }

View file

@ -80,8 +80,10 @@ S3_GW_PROMETHEUS_ADDRESS=localhost:8086
# Timeout to connect to a node # Timeout to connect to a node
S3_GW_CONNECT_TIMEOUT=10s S3_GW_CONNECT_TIMEOUT=10s
# Timeout for individual operations in streaming RPC. # Timeout for individual operations in object pool streaming RPC.
S3_GW_STREAM_TIMEOUT=10s S3_GW_STREAM_TIMEOUT=10s
# Timeout for individual operations in tree pool streaming RPC.
S3_GW_TREE_STREAM_TIMEOUT=10s
# Timeout to check node health during rebalance. # Timeout to check node health during rebalance.
S3_GW_HEALTHCHECK_TIMEOUT=15s S3_GW_HEALTHCHECK_TIMEOUT=15s
# Interval to check node health # Interval to check node health

View file

@ -100,8 +100,10 @@ tracing:
# Timeout to connect to a node # Timeout to connect to a node
connect_timeout: 10s connect_timeout: 10s
# Timeout for individual operations in streaming RPC. # Timeout for individual operations in object pool streaming RPC.
stream_timeout: 10s stream_timeout: 10s
# Timeout for individual operations in tree pool streaming RPC.
tree_stream_timeout: 10s
# Timeout to check node health during rebalance # Timeout to check node health during rebalance
healthcheck_timeout: 15s healthcheck_timeout: 15s
# Interval to check node health # Interval to check node health

View file

@ -213,6 +213,7 @@ resolve_order:
connect_timeout: 10s connect_timeout: 10s
stream_timeout: 10s stream_timeout: 10s
tree_stream_timeout: 10s
healthcheck_timeout: 15s healthcheck_timeout: 15s
rebalance_interval: 60s rebalance_interval: 60s
pool_error_threshold: 100 pool_error_threshold: 100
@ -235,7 +236,8 @@ source_ip_header: "Source-Ip"
| `rpc_endpoint` | `string` | no | | The address of the RPC host to which the gateway connects to resolve bucket names and interact with frostfs contracts (required to use the `nns` resolver and `frostfsid` contract). | | `rpc_endpoint` | `string` | no | | The address of the RPC host to which the gateway connects to resolve bucket names and interact with frostfs contracts (required to use the `nns` resolver and `frostfsid` contract). |
| `resolve_order` | `[]string` | yes | `[dns]` | Order of bucket name resolvers to use. Available resolvers: `dns`, `nns`. | | `resolve_order` | `[]string` | yes | `[dns]` | Order of bucket name resolvers to use. Available resolvers: `dns`, `nns`. |
| `connect_timeout` | `duration` | no | `10s` | Timeout to connect to a node. | | `connect_timeout` | `duration` | no | `10s` | Timeout to connect to a node. |
| `stream_timeout` | `duration` | no | `10s` | Timeout for individual operations in streaming RPC. | | `stream_timeout` | `duration` | no | `10s` | Timeout for individual operations in object pool streaming RPC. |
| `tree_stream_timeout` | `duration` | no | `10s` | Timeout for individual operations in tree pool streaming RPC. |
| `healthcheck_timeout` | `duration` | no | `15s` | Timeout to check node health during rebalance. | | `healthcheck_timeout` | `duration` | no | `15s` | Timeout to check node health during rebalance. |
| `rebalance_interval` | `duration` | no | `60s` | Interval to check node health. | | `rebalance_interval` | `duration` | no | `60s` | Interval to check node health. |
| `pool_error_threshold` | `uint32` | no | `100` | The number of errors on connection after which node is considered as unhealthy. | | `pool_error_threshold` | `uint32` | no | `100` | The number of errors on connection after which node is considered as unhealthy. |