mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-07-26 07:58:14 +00:00
Merge branch 'main-v1' into merge-v1
This commit is contained in:
@@ -12,32 +12,32 @@ when:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: check formatting
|
- name: check formatting
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
commands:
|
commands:
|
||||||
- nix-shell --attr devShell --run "cargo fmt -- --check"
|
- nix-build -j4 --attr flakePackages.fmt
|
||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
commands:
|
commands:
|
||||||
- nix-build -j4 --attr flakePackages.dev
|
- nix-build -j4 --attr flakePackages.dev
|
||||||
|
|
||||||
- name: unit + func tests (lmdb)
|
- name: unit + func tests (lmdb)
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
commands:
|
commands:
|
||||||
- nix-build -j4 --attr flakePackages.tests-lmdb
|
- nix-build -j4 --attr flakePackages.tests-lmdb
|
||||||
|
|
||||||
- name: unit + func tests (sqlite)
|
- name: unit + func tests (sqlite)
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
commands:
|
commands:
|
||||||
- nix-build -j4 --attr flakePackages.tests-sqlite
|
- nix-build -j4 --attr flakePackages.tests-sqlite
|
||||||
|
|
||||||
- name: unit + func tests (fjall)
|
- name: unit + func tests (fjall)
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
commands:
|
commands:
|
||||||
- nix-build -j4 --attr flakePackages.tests-fjall
|
- nix-build -j4 --attr flakePackages.tests-fjall
|
||||||
|
|
||||||
- name: integration tests
|
- name: integration tests
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
commands:
|
commands:
|
||||||
- nix-build -j4 --attr flakePackages.dev
|
- nix-build -j4 --attr flakePackages.dev
|
||||||
- nix-shell --attr ci --run ./script/test-smoke.sh || (cat /tmp/garage.log; false)
|
- nix-shell --attr ci --run ./script/test-smoke.sh || (cat /tmp/garage.log; false)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ depends_on:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: refresh-index
|
- name: refresh-index
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
environment:
|
environment:
|
||||||
AWS_ACCESS_KEY_ID:
|
AWS_ACCESS_KEY_ID:
|
||||||
from_secret: garagehq_aws_access_key_id
|
from_secret: garagehq_aws_access_key_id
|
||||||
@@ -22,7 +22,7 @@ steps:
|
|||||||
- nix-shell --attr ci --run "refresh_index"
|
- nix-shell --attr ci --run "refresh_index"
|
||||||
|
|
||||||
- name: multiarch-docker
|
- name: multiarch-docker
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
environment:
|
environment:
|
||||||
DOCKER_AUTH:
|
DOCKER_AUTH:
|
||||||
from_secret: docker_auth
|
from_secret: docker_auth
|
||||||
|
|||||||
@@ -19,17 +19,17 @@ matrix:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: build
|
- name: build
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
commands:
|
commands:
|
||||||
- nix-build --attr releasePackages.${ARCH} --argstr git_version ${CI_COMMIT_TAG:-$CI_COMMIT_SHA}
|
- nix-build --attr releasePackages.${ARCH} --argstr git_version ${CI_COMMIT_TAG:-$CI_COMMIT_SHA}
|
||||||
|
|
||||||
- name: check is static binary
|
- name: check is static binary
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
commands:
|
commands:
|
||||||
- nix-shell --attr ci --run "./script/not-dynamic.sh result/bin/garage"
|
- nix-shell --attr ci --run "./script/not-dynamic.sh result/bin/garage"
|
||||||
|
|
||||||
- name: integration tests
|
- name: integration tests
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
commands:
|
commands:
|
||||||
- nix-shell --attr ci --run ./script/test-smoke.sh || (cat /tmp/garage.log; false)
|
- nix-shell --attr ci --run ./script/test-smoke.sh || (cat /tmp/garage.log; false)
|
||||||
when:
|
when:
|
||||||
@@ -39,7 +39,7 @@ steps:
|
|||||||
ARCH: i386
|
ARCH: i386
|
||||||
|
|
||||||
- name: upgrade tests from v1.0.0
|
- name: upgrade tests from v1.0.0
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
commands:
|
commands:
|
||||||
- nix-shell --attr ci --run "./script/test-upgrade.sh v1.0.0 x86_64-unknown-linux-musl" || (cat /tmp/garage.log; false)
|
- nix-shell --attr ci --run "./script/test-upgrade.sh v1.0.0 x86_64-unknown-linux-musl" || (cat /tmp/garage.log; false)
|
||||||
when:
|
when:
|
||||||
@@ -47,7 +47,7 @@ steps:
|
|||||||
ARCH: amd64
|
ARCH: amd64
|
||||||
|
|
||||||
- name: upgrade tests from v0.8.4
|
- name: upgrade tests from v0.8.4
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
commands:
|
commands:
|
||||||
- nix-shell --attr ci --run "./script/test-upgrade.sh v0.8.4 x86_64-unknown-linux-musl" || (cat /tmp/garage.log; false)
|
- nix-shell --attr ci --run "./script/test-upgrade.sh v0.8.4 x86_64-unknown-linux-musl" || (cat /tmp/garage.log; false)
|
||||||
when:
|
when:
|
||||||
@@ -55,7 +55,7 @@ steps:
|
|||||||
ARCH: amd64
|
ARCH: amd64
|
||||||
|
|
||||||
- name: push static binary
|
- name: push static binary
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
environment:
|
environment:
|
||||||
TARGET: "${TARGET}"
|
TARGET: "${TARGET}"
|
||||||
AWS_ACCESS_KEY_ID:
|
AWS_ACCESS_KEY_ID:
|
||||||
@@ -66,7 +66,7 @@ steps:
|
|||||||
- nix-shell --attr ci --run "to_s3"
|
- nix-shell --attr ci --run "to_s3"
|
||||||
|
|
||||||
- name: docker build and publish
|
- name: docker build and publish
|
||||||
image: nixpkgs/nix:nixos-22.05
|
image: nixpkgs/nix:nixos-24.05
|
||||||
environment:
|
environment:
|
||||||
DOCKER_PLATFORM: "linux/${ARCH}"
|
DOCKER_PLATFORM: "linux/${ARCH}"
|
||||||
CONTAINER_NAME: "dxflrs/${ARCH}_garage"
|
CONTAINER_NAME: "dxflrs/${ARCH}_garage"
|
||||||
|
|||||||
@@ -15,9 +15,10 @@ Alpine Linux repositories (available since v3.17):
|
|||||||
apk add garage
|
apk add garage
|
||||||
```
|
```
|
||||||
|
|
||||||
The default configuration file is installed to `/etc/garage.toml`. You can run
|
The default configuration file is installed to `/etc/garage/garage.toml`. You can run
|
||||||
Garage using: `rc-service garage start`. If you don't specify `rpc_secret`, it
|
Garage using: `rc-service garage start`.
|
||||||
will be automatically replaced with a random string on the first start.
|
|
||||||
|
If you don't specify `rpc_secret`, it will be automatically replaced with a random string on the first start.
|
||||||
|
|
||||||
Please note that this package is built without Consul discovery, Kubernetes
|
Please note that this package is built without Consul discovery, Kubernetes
|
||||||
discovery, OpenTelemetry exporter, and K2V features (K2V will be enabled once
|
discovery, OpenTelemetry exporter, and K2V features (K2V will be enabled once
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ db_engine = "lmdb"
|
|||||||
block_size = "1M"
|
block_size = "1M"
|
||||||
block_ram_buffer_max = "256MiB"
|
block_ram_buffer_max = "256MiB"
|
||||||
block_max_concurrent_reads = 16
|
block_max_concurrent_reads = 16
|
||||||
|
block_max_concurrent_writes_per_request =10
|
||||||
lmdb_map_size = "1T"
|
lmdb_map_size = "1T"
|
||||||
|
|
||||||
compression_level = 1
|
compression_level = 1
|
||||||
@@ -103,6 +103,7 @@ Top-level configuration options, in alphabetical order:
|
|||||||
[`allow_world_readable_secrets`](#allow_world_readable_secrets),
|
[`allow_world_readable_secrets`](#allow_world_readable_secrets),
|
||||||
[`block_max_concurrent_reads`](#block_max_concurrent_reads),
|
[`block_max_concurrent_reads`](#block_max_concurrent_reads),
|
||||||
[`block_ram_buffer_max`](#block_ram_buffer_max),
|
[`block_ram_buffer_max`](#block_ram_buffer_max),
|
||||||
|
[`block_max_concurrent_writes_per_request`](#block_max_concurrent_writes_per_request),
|
||||||
[`block_size`](#block_size),
|
[`block_size`](#block_size),
|
||||||
[`bootstrap_peers`](#bootstrap_peers),
|
[`bootstrap_peers`](#bootstrap_peers),
|
||||||
[`compression_level`](#compression_level),
|
[`compression_level`](#compression_level),
|
||||||
@@ -559,6 +560,14 @@ metric in Prometheus: a non-zero number of such events indicates an I/O
|
|||||||
bottleneck on HDD read speed.
|
bottleneck on HDD read speed.
|
||||||
|
|
||||||
|
|
||||||
|
#### `block_max_concurrent_writes_per_request` (since `v2.1.0`) {#block_max_concurrent_writes_per_request}
|
||||||
|
|
||||||
|
This parameter is designed to adapt to the concurrent write performance of
|
||||||
|
different storage media.Maximum number of parallel block writes per put request
|
||||||
|
Higher values improve throughput but increase memory usage.
|
||||||
|
|
||||||
|
Default: 3, Recommended: 10-30 for NVMe, 3-10 for HDD
|
||||||
|
|
||||||
#### `lmdb_map_size` {#lmdb_map_size}
|
#### `lmdb_map_size` {#lmdb_map_size}
|
||||||
|
|
||||||
This parameters can be used to set the map size used by LMDB,
|
This parameters can be used to set the map size used by LMDB,
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Feel free to open a PR to suggest fixes this table. Minio is missing because the
|
|||||||
|
|
||||||
| Feature | Garage | [Openstack Swift](https://docs.openstack.org/swift/latest/s3_compat.html) | [Ceph Object Gateway](https://docs.ceph.com/en/latest/radosgw/s3/) | [Riak CS](https://docs.riak.com/riak/cs/2.1.1/references/apis/storage/s3/index.html) | [OpenIO](https://docs.openio.io/latest/source/arch-design/s3_compliancy.html) |
|
| Feature | Garage | [Openstack Swift](https://docs.openstack.org/swift/latest/s3_compat.html) | [Ceph Object Gateway](https://docs.ceph.com/en/latest/radosgw/s3/) | [Riak CS](https://docs.riak.com/riak/cs/2.1.1/references/apis/storage/s3/index.html) | [OpenIO](https://docs.openio.io/latest/source/arch-design/s3_compliancy.html) |
|
||||||
|------------------------------|----------------------------------|-----------------|---------------|---------|-----|
|
|------------------------------|----------------------------------|-----------------|---------------|---------|-----|
|
||||||
| [signature v2](https://docs.aws.amazon.com/general/latest/gr/signature-version-2.html) (deprecated) | ❌ Missing | ✅ | ✅ | ✅ | ✅ |
|
| [signature v2](https://docs.aws.amazon.com/AmazonS3/latest/API/Appendix-Sigv2.html) (deprecated) | ❌ Missing | ✅ | ✅ | ✅ | ✅ |
|
||||||
| [signature v4](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html) | ✅ Implemented | ✅ | ✅ | ❌ | ✅ |
|
| [signature v4](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html) | ✅ Implemented | ✅ | ✅ | ❌ | ✅ |
|
||||||
| [URL path-style](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#path-style-access) (eg. `host.tld/bucket/key`) | ✅ Implemented | ✅ | ✅ | ❓| ✅ |
|
| [URL path-style](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#path-style-access) (eg. `host.tld/bucket/key`) | ✅ Implemented | ✅ | ✅ | ❓| ✅ |
|
||||||
| [URL vhost-style](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#virtual-hosted-style-access) URL (eg. `bucket.host.tld/key`) | ✅ Implemented | ❌| ✅| ✅ | ✅ |
|
| [URL vhost-style](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#virtual-hosted-style-access) URL (eg. `bucket.host.tld/key`) | ✅ Implemented | ❌| ✅| ✅ | ✅ |
|
||||||
|
|||||||
Generated
+14
-14
@@ -2,11 +2,11 @@
|
|||||||
"nodes": {
|
"nodes": {
|
||||||
"crane": {
|
"crane": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1737689766,
|
"lastModified": 1768873933,
|
||||||
"narHash": "sha256-ivVXYaYlShxYoKfSo5+y5930qMKKJ8CLcAoIBPQfJ6s=",
|
"narHash": "sha256-CfyzdaeLNGkyAHp3kT5vjvXhA1pVVK7nyDziYxCPsNk=",
|
||||||
"owner": "ipetkov",
|
"owner": "ipetkov",
|
||||||
"repo": "crane",
|
"repo": "crane",
|
||||||
"rev": "6fe74265bbb6d016d663b1091f015e2976c4a527",
|
"rev": "0bda7e7d005ccb5522a76d11ccfbf562b71953ca",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -17,11 +17,11 @@
|
|||||||
},
|
},
|
||||||
"flake-compat": {
|
"flake-compat": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1717312683,
|
"lastModified": 1761640442,
|
||||||
"narHash": "sha256-FrlieJH50AuvagamEvWMIE6D2OAnERuDboFDYAED/dE=",
|
"narHash": "sha256-AtrEP6Jmdvrqiv4x2xa5mrtaIp3OEe8uBYCDZDS+hu8=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "flake-compat",
|
"repo": "flake-compat",
|
||||||
"rev": "38fd3954cf65ce6faf3d0d45cd26059e059f07ea",
|
"rev": "4a56054d8ffc173222d09dad23adf4ba946c8884",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -50,17 +50,17 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1747825515,
|
"lastModified": 1763977559,
|
||||||
"narHash": "sha256-BWpMQymVI73QoKZdcVCxUCCK3GNvr/xa2Dc4DM1o2BE=",
|
"narHash": "sha256-g4MKqsIRy5yJwEsI+fYODqLUnAqIY4kZai0nldAP6EM=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "cd2812de55cf87df88a9e09bf3be1ce63d50c1a6",
|
"rev": "cfe2c7d5b5d3032862254e68c37a6576b633d632",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "cd2812de55cf87df88a9e09bf3be1ce63d50c1a6",
|
"rev": "cfe2c7d5b5d3032862254e68c37a6576b633d632",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -80,17 +80,17 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1738549608,
|
"lastModified": 1763952169,
|
||||||
"narHash": "sha256-GdyT9QEUSx5k/n8kILuNy83vxxdyUfJ8jL5mMpQZWfw=",
|
"narHash": "sha256-+PeDBD8P+NKauH+w7eO/QWCIp8Cx4mCfWnh9sJmy9CM=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "35c6f8c4352f995ecd53896200769f80a3e8f22d",
|
"rev": "ab726555a9a72e6dc80649809147823a813fa95b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "35c6f8c4352f995ecd53896200769f80a3e8f22d",
|
"rev": "ab726555a9a72e6dc80649809147823a813fa95b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
description =
|
description =
|
||||||
"Garage, an S3-compatible distributed object store for self-hosted deployments";
|
"Garage, an S3-compatible distributed object store for self-hosted deployments";
|
||||||
|
|
||||||
# Nixpkgs 25.05 as of 2025-05-22
|
# Nixpkgs 25.05 as of 2025-11-24
|
||||||
inputs.nixpkgs.url =
|
inputs.nixpkgs.url =
|
||||||
"github:NixOS/nixpkgs/cd2812de55cf87df88a9e09bf3be1ce63d50c1a6";
|
"github:NixOS/nixpkgs/cfe2c7d5b5d3032862254e68c37a6576b633d632";
|
||||||
|
|
||||||
# Rust overlay as of 2025-02-03
|
# Rust overlay as of 2025-11-24
|
||||||
inputs.rust-overlay.url =
|
inputs.rust-overlay.url =
|
||||||
"github:oxalica/rust-overlay/35c6f8c4352f995ecd53896200769f80a3e8f22d";
|
"github:oxalica/rust-overlay/ab726555a9a72e6dc80649809147823a813fa95b";
|
||||||
inputs.rust-overlay.inputs.nixpkgs.follows = "nixpkgs";
|
inputs.rust-overlay.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
|
||||||
inputs.crane.url = "github:ipetkov/crane";
|
inputs.crane.url = "github:ipetkov/crane";
|
||||||
@@ -30,6 +30,10 @@
|
|||||||
inherit system nixpkgs crane rust-overlay extraTestEnv;
|
inherit system nixpkgs crane rust-overlay extraTestEnv;
|
||||||
release = false;
|
release = false;
|
||||||
}).garage-test;
|
}).garage-test;
|
||||||
|
lints = (compile {
|
||||||
|
inherit system nixpkgs crane rust-overlay;
|
||||||
|
release = false;
|
||||||
|
});
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
packages = {
|
packages = {
|
||||||
@@ -56,6 +60,10 @@
|
|||||||
tests-fjall = testWith {
|
tests-fjall = testWith {
|
||||||
GARAGE_TEST_INTEGRATION_DB_ENGINE = "fjall";
|
GARAGE_TEST_INTEGRATION_DB_ENGINE = "fjall";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# lints (fmt, clippy)
|
||||||
|
fmt = lints.garage-cargo-fmt;
|
||||||
|
clippy = lints.garage-cargo-clippy;
|
||||||
};
|
};
|
||||||
|
|
||||||
# ---- developpment shell, for making native builds only ----
|
# ---- developpment shell, for making native builds only ----
|
||||||
|
|||||||
+12
-1
@@ -48,7 +48,7 @@ let
|
|||||||
|
|
||||||
inherit (pkgs) lib stdenv;
|
inherit (pkgs) lib stdenv;
|
||||||
|
|
||||||
toolchainFn = (p: p.rust-bin.stable."1.82.0".default.override {
|
toolchainFn = (p: p.rust-bin.stable."1.91.0".default.override {
|
||||||
targets = lib.optionals (target != null) [ rustTarget ];
|
targets = lib.optionals (target != null) [ rustTarget ];
|
||||||
extensions = [
|
extensions = [
|
||||||
"rust-src"
|
"rust-src"
|
||||||
@@ -190,4 +190,15 @@ in rec {
|
|||||||
pkgs.cacert
|
pkgs.cacert
|
||||||
];
|
];
|
||||||
} // extraTestEnv);
|
} // extraTestEnv);
|
||||||
|
|
||||||
|
# ---- source code linting ----
|
||||||
|
|
||||||
|
garage-cargo-fmt = craneLib.cargoFmt (commonArgs // {
|
||||||
|
cargoExtraArgs = "";
|
||||||
|
});
|
||||||
|
|
||||||
|
garage-cargo-clippy = craneLib.cargoClippy (commonArgs // {
|
||||||
|
cargoArtifacts = garage-deps;
|
||||||
|
cargoClippyExtraArgs = "--all-targets -- -D warnings";
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export AWS_ACCESS_KEY_ID=`cat /tmp/garage.s3 |cut -d' ' -f1`
|
export AWS_ACCESS_KEY_ID=`cat /tmp/garage.s3 |cut -d' ' -f1`
|
||||||
export AWS_SECRET_ACCESS_KEY=`cat /tmp/garage.s3 |cut -d' ' -f2`
|
export AWS_SECRET_ACCESS_KEY=`cat /tmp/garage.s3 |cut -d' ' -f2`
|
||||||
export AWS_DEFAULT_REGION='garage'
|
export AWS_DEFAULT_REGION='garage'
|
||||||
|
export AWS_REQUEST_CHECKSUM_CALCULATION='when_required'
|
||||||
# FUTUREWORK: set AWS_ENDPOINT_URL instead, once nixpkgs bumps awscli to >=2.13.0.
|
# FUTUREWORK: set AWS_ENDPOINT_URL instead, once nixpkgs bumps awscli to >=2.13.0.
|
||||||
function aws { command aws --endpoint-url http://127.0.0.1:3911 $@ ; }
|
function aws { command aws --endpoint-url http://127.0.0.1:3911 $@ ; }
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ in
|
|||||||
jq
|
jq
|
||||||
];
|
];
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
|
export AWS_REQUEST_CHECKSUM_CALCULATION='when_required'
|
||||||
|
|
||||||
function to_s3 {
|
function to_s3 {
|
||||||
AWS_REQUEST_CHECKSUM_CALCULATION=WHEN_REQUIRED AWS_RESPONSE_CHECKSUM_VALIDATION=WHEN_REQUIRED \
|
AWS_REQUEST_CHECKSUM_CALCULATION=WHEN_REQUIRED AWS_RESPONSE_CHECKSUM_VALIDATION=WHEN_REQUIRED \
|
||||||
aws \
|
aws \
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ pub enum Error {
|
|||||||
NoSuchAdminToken(String),
|
NoSuchAdminToken(String),
|
||||||
|
|
||||||
/// The API access key does not exist
|
/// The API access key does not exist
|
||||||
#[error("Access key not found: {00}")]
|
#[error("Access key not found: {0}")]
|
||||||
NoSuchAccessKey(String),
|
NoSuchAccessKey(String),
|
||||||
|
|
||||||
/// The requested block does not exist
|
/// The requested block does not exist
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ fn check_standard_signature(
|
|||||||
// Verify that all necessary request headers are included in signed_headers
|
// Verify that all necessary request headers are included in signed_headers
|
||||||
// The following must be included for all signatures:
|
// The following must be included for all signatures:
|
||||||
// - the Host header (mandatory)
|
// - the Host header (mandatory)
|
||||||
// - all x-amz-* headers used in the request
|
// - all x-amz-* headers used in the request (except x-amz-content-sha256)
|
||||||
// AWS also indicates that the Content-Type header should be signed if
|
// AWS also indicates that the Content-Type header should be signed if
|
||||||
// it is used, but Minio client doesn't sign it so we don't check it for compatibility.
|
// it is used, but Minio client doesn't sign it so we don't check it for compatibility.
|
||||||
let signed_headers = split_signed_headers(&authorization)?;
|
let signed_headers = split_signed_headers(&authorization)?;
|
||||||
@@ -152,7 +152,7 @@ fn check_presigned_signature(
|
|||||||
// Verify that all necessary request headers are included in signed_headers
|
// Verify that all necessary request headers are included in signed_headers
|
||||||
// For AWSv4 pre-signed URLs, the following must be included:
|
// For AWSv4 pre-signed URLs, the following must be included:
|
||||||
// - the Host header (mandatory)
|
// - the Host header (mandatory)
|
||||||
// - all x-amz-* headers used in the request
|
// - all x-amz-* headers used in the request (except x-amz-content-sha256)
|
||||||
let signed_headers = split_signed_headers(&authorization)?;
|
let signed_headers = split_signed_headers(&authorization)?;
|
||||||
verify_signed_headers(request.headers(), &signed_headers)?;
|
verify_signed_headers(request.headers(), &signed_headers)?;
|
||||||
|
|
||||||
@@ -269,7 +269,9 @@ fn verify_signed_headers(headers: &HeaderMap, signed_headers: &[HeaderName]) ->
|
|||||||
return Err(Error::bad_request("Header `Host` should be signed"));
|
return Err(Error::bad_request("Header `Host` should be signed"));
|
||||||
}
|
}
|
||||||
for (name, _) in headers.iter() {
|
for (name, _) in headers.iter() {
|
||||||
if name.as_str().starts_with("x-amz-") {
|
// Enforce signature of all x-amz-* headers, except x-amz-content-sh256
|
||||||
|
// because it is included in the canonical request in all cases
|
||||||
|
if name.as_str().starts_with("x-amz-") && name != X_AMZ_CONTENT_SHA256 {
|
||||||
if !signed_headers.contains(name) {
|
if !signed_headers.contains(name) {
|
||||||
return Err(Error::bad_request(format!(
|
return Err(Error::bad_request(format!(
|
||||||
"Header `{}` should be signed",
|
"Header `{}` should be signed",
|
||||||
@@ -475,8 +477,7 @@ impl Authorization {
|
|||||||
|
|
||||||
let date = headers
|
let date = headers
|
||||||
.get(X_AMZ_DATE)
|
.get(X_AMZ_DATE)
|
||||||
.ok_or_bad_request("Missing X-Amz-Date field")
|
.ok_or_bad_request("Missing X-Amz-Date field")?
|
||||||
.map_err(Error::from)?
|
|
||||||
.to_str()?;
|
.to_str()?;
|
||||||
let date = parse_date(date)?;
|
let date = parse_date(date)?;
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -853,7 +853,9 @@ impl PreconditionHeaders {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check(&self, v: &ObjectVersion, etag: &str) -> Result<Option<StatusCode>, Error> {
|
fn check(&self, v: &ObjectVersion, etag: &str) -> Result<Option<StatusCode>, Error> {
|
||||||
let v_date = UNIX_EPOCH + Duration::from_millis(v.timestamp);
|
// we store date with ms precision, but headers are precise to the second: truncate
|
||||||
|
// the timestamp to handle the same-second edge case
|
||||||
|
let v_date = UNIX_EPOCH + Duration::from_secs(v.timestamp / 1000);
|
||||||
|
|
||||||
// Implemented from https://datatracker.ietf.org/doc/html/rfc7232#section-6
|
// Implemented from https://datatracker.ietf.org/doc/html/rfc7232#section-6
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -39,8 +39,6 @@ use crate::encryption::{EncryptionParams, OekDerivationInfo};
|
|||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
use crate::website::X_AMZ_WEBSITE_REDIRECT_LOCATION;
|
use crate::website::X_AMZ_WEBSITE_REDIRECT_LOCATION;
|
||||||
|
|
||||||
const PUT_BLOCKS_MAX_PARALLEL: usize = 3;
|
|
||||||
|
|
||||||
pub(crate) struct SaveStreamResult {
|
pub(crate) struct SaveStreamResult {
|
||||||
pub(crate) version_uuid: Uuid,
|
pub(crate) version_uuid: Uuid,
|
||||||
pub(crate) version_timestamp: u64,
|
pub(crate) version_timestamp: u64,
|
||||||
@@ -507,7 +505,7 @@ pub(crate) async fn read_and_put_blocks<S: Stream<Item = Result<Bytes, Error>> +
|
|||||||
};
|
};
|
||||||
let recv_next = async {
|
let recv_next = async {
|
||||||
// If more than a maximum number of writes are in progress, don't add more for now
|
// If more than a maximum number of writes are in progress, don't add more for now
|
||||||
if currently_running >= PUT_BLOCKS_MAX_PARALLEL {
|
if currently_running >= ctx.garage.config.block_max_concurrent_writes_per_request {
|
||||||
futures::future::pending().await
|
futures::future::pending().await
|
||||||
} else {
|
} else {
|
||||||
block_rx3.recv().await
|
block_rx3.recv().await
|
||||||
|
|||||||
@@ -198,6 +198,7 @@ async fn test_precondition() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
let older_date = DateTime::from_secs_f64(last_modified.as_secs_f64() - 10.0);
|
let older_date = DateTime::from_secs_f64(last_modified.as_secs_f64() - 10.0);
|
||||||
|
let same_date = DateTime::from_secs_f64(last_modified.as_secs_f64());
|
||||||
let newer_date = DateTime::from_secs_f64(last_modified.as_secs_f64() + 10.0);
|
let newer_date = DateTime::from_secs_f64(last_modified.as_secs_f64() + 10.0);
|
||||||
{
|
{
|
||||||
let err = ctx
|
let err = ctx
|
||||||
@@ -212,6 +213,18 @@ async fn test_precondition() {
|
|||||||
matches!(err, Err(SdkError::ServiceError(se)) if se.raw().status().as_u16() == 304)
|
matches!(err, Err(SdkError::ServiceError(se)) if se.raw().status().as_u16() == 304)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let err = ctx
|
||||||
|
.client
|
||||||
|
.get_object()
|
||||||
|
.bucket(&bucket)
|
||||||
|
.key(STD_KEY)
|
||||||
|
.if_modified_since(same_date)
|
||||||
|
.send()
|
||||||
|
.await;
|
||||||
|
assert!(
|
||||||
|
matches!(err, Err(SdkError::ServiceError(se)) if se.raw().status().as_u16() == 304)
|
||||||
|
);
|
||||||
|
|
||||||
let o = ctx
|
let o = ctx
|
||||||
.client
|
.client
|
||||||
.get_object()
|
.get_object()
|
||||||
@@ -236,6 +249,17 @@ async fn test_precondition() {
|
|||||||
matches!(err, Err(SdkError::ServiceError(se)) if se.raw().status().as_u16() == 412)
|
matches!(err, Err(SdkError::ServiceError(se)) if se.raw().status().as_u16() == 412)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let o = ctx
|
||||||
|
.client
|
||||||
|
.get_object()
|
||||||
|
.bucket(&bucket)
|
||||||
|
.key(STD_KEY)
|
||||||
|
.if_unmodified_since(same_date)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(o.e_tag.as_ref().unwrap().as_str(), etag);
|
||||||
|
|
||||||
let o = ctx
|
let o = ctx
|
||||||
.client
|
.client
|
||||||
.get_object()
|
.get_object()
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ pub struct Config {
|
|||||||
)]
|
)]
|
||||||
pub block_size: usize,
|
pub block_size: usize,
|
||||||
|
|
||||||
|
/// Maximum number of parallel block writes per PUT request
|
||||||
|
/// Higher values improve throughput but increase memory usage
|
||||||
|
/// Default: 3, Recommended: 10-30 for NVMe, 3-10 for HDD
|
||||||
|
#[serde(default = "default_block_max_concurrent_writes_per_request")]
|
||||||
|
pub block_max_concurrent_writes_per_request: usize,
|
||||||
/// Number of replicas. Can be any positive integer, but uneven numbers are more favorable.
|
/// Number of replicas. Can be any positive integer, but uneven numbers are more favorable.
|
||||||
/// - 1 for single-node clusters, or to disable replication
|
/// - 1 for single-node clusters, or to disable replication
|
||||||
/// - 3 is the recommended and supported setting.
|
/// - 3 is the recommended and supported setting.
|
||||||
@@ -272,6 +277,9 @@ pub struct KubernetesDiscoveryConfig {
|
|||||||
pub skip_crd: bool,
|
pub skip_crd: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn default_block_max_concurrent_writes_per_request() -> usize {
|
||||||
|
3
|
||||||
|
}
|
||||||
/// Read and parse configuration
|
/// Read and parse configuration
|
||||||
pub fn read_config(config_file: PathBuf) -> Result<Config, Error> {
|
pub fn read_config(config_file: PathBuf) -> Result<Config, Error> {
|
||||||
let config = std::fs::read_to_string(config_file)?;
|
let config = std::fs::read_to_string(config_file)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user