mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-08-13 15:46:53 +00:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a1cec2cd60 | |||
| b66f247580 | |||
| 16f2a32bb7 | |||
| 472444ed8e | |||
| bb03805b58 | |||
| e4f955d672 | |||
| ea9b15f669 | |||
| 2e6bb3f766 | |||
| 375270afd1 | |||
| c783194e8b | |||
| fdcd7dee5a | |||
| 0f0795103d | |||
| c9d26e8c50 | |||
| b925f53dc3 | |||
| 2f495575d8 | |||
| 9e0a9c1c15 | |||
| 9c788059e2 | |||
| 5684e1990c | |||
| 14c50f2f84 | |||
| 0fab9c3b8c | |||
| 75759a163c | |||
| d2deee0b8b | |||
| 8499cd5c21 | |||
| 4ea7983093 | |||
| d5e39d11eb | |||
| 6d3ace1ea9 | |||
| 833cf082da | |||
| 1ecd88c01f | |||
| 5efcdc0de3 | |||
| a16eb7e4b8 | |||
| 6742070517 | |||
| 6894878146 | |||
| 02b0ba5f44 | |||
| fb3bd11dce | |||
| c168383113 | |||
| 04a0063df9 | |||
| a2a35ac7a8 | |||
| f167310f42 | |||
| 66ed0bdd91 | |||
| 11b154b33b |
Generated
+332
-198
File diff suppressed because it is too large
Load Diff
+12
@@ -11,10 +11,22 @@ members = [
|
||||
"src/web",
|
||||
"src/garage",
|
||||
"src/k2v-client",
|
||||
"src/format-table",
|
||||
]
|
||||
|
||||
default-members = ["src/garage"]
|
||||
|
||||
[workspace.dependencies]
|
||||
format_table = { version = "0.1.0", path = "src/format-table" }
|
||||
garage_api = { version = "0.8.2", path = "src/api" }
|
||||
garage_block = { version = "0.8.2", path = "src/block" }
|
||||
garage_db = { version = "0.8.2", path = "src/db", default-features = false }
|
||||
garage_model = { version = "0.8.2", path = "src/model", default-features = false }
|
||||
garage_rpc = { version = "0.8.2", path = "src/rpc" }
|
||||
garage_table = { version = "0.8.2", path = "src/table" }
|
||||
garage_util = { version = "0.8.2", path = "src/util" }
|
||||
garage_web = { version = "0.8.2", path = "src/web" }
|
||||
|
||||
[profile.dev]
|
||||
lto = "off"
|
||||
|
||||
|
||||
+4
-49
@@ -202,56 +202,11 @@ See its usage output for other commands available.
|
||||
## Cyberduck & duck {#cyberduck}
|
||||
|
||||
Both Cyberduck (the GUI) and duck (the CLI) have a concept of "Connection Profiles" that contain some presets for a specific provider.
|
||||
We wrote the following connection profile for Garage:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Protocol</key>
|
||||
<string>s3</string>
|
||||
<key>Vendor</key>
|
||||
<string>garage</string>
|
||||
<key>Scheme</key>
|
||||
<string>https</string>
|
||||
<key>Description</key>
|
||||
<string>GarageS3</string>
|
||||
<key>Default Hostname</key>
|
||||
<string>127.0.0.1</string>
|
||||
<key>Default Port</key>
|
||||
<string>4443</string>
|
||||
<key>Hostname Configurable</key>
|
||||
<false/>
|
||||
<key>Port Configurable</key>
|
||||
<false/>
|
||||
<key>Username Configurable</key>
|
||||
<true/>
|
||||
<key>Username Placeholder</key>
|
||||
<string>Access Key ID (GK...)</string>
|
||||
<key>Password Placeholder</key>
|
||||
<string>Secret Key</string>
|
||||
<key>Properties</key>
|
||||
<array>
|
||||
<string>s3service.disable-dns-buckets=true</string>
|
||||
</array>
|
||||
<key>Region</key>
|
||||
<string>garage</string>
|
||||
<key>Regions</key>
|
||||
<array>
|
||||
<string>garage</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
*Note: If your garage instance is configured with vhost access style, you can remove `s3service.disable-dns-buckets=true`.*
|
||||
|
||||
### Instructions for the GUI
|
||||
|
||||
Copy the connection profile, and save it anywhere as `garage.cyberduckprofile`.
|
||||
Then find this file with your file explorer and double click on it: Cyberduck will open a connection wizard for this profile.
|
||||
Simply follow the wizard and you should be done!
|
||||
Within Cyberduck, a
|
||||
[Garage connection profile](https://docs.cyberduck.io/protocols/s3/garage/) is
|
||||
available within the `Preferences -> Profiles` section. This can enabled and
|
||||
then connections to Garage may be configured.
|
||||
|
||||
### Instuctions for the CLI
|
||||
|
||||
|
||||
@@ -349,5 +349,5 @@ and is covered in the [quick start guide](@/documentation/quick-start/_index.md)
|
||||
Remember also that the CLI is self-documented thanks to the `--help` flag and
|
||||
the `help` subcommand (e.g. `garage help`, `garage key --help`).
|
||||
|
||||
Configuring S3-compatible applicatiosn to interact with Garage
|
||||
Configuring S3-compatible applications to interact with Garage
|
||||
is covered in the [Integrations](@/documentation/connect/_index.md) section.
|
||||
|
||||
@@ -290,13 +290,13 @@ sourcing the right file.*
|
||||
aws s3 ls
|
||||
|
||||
# list objects of a bucket
|
||||
aws s3 ls s3://my_files
|
||||
aws s3 ls s3://nextcloud-bucket
|
||||
|
||||
# copy from your filesystem to garage
|
||||
aws s3 cp /proc/cpuinfo s3://my_files/cpuinfo.txt
|
||||
aws s3 cp /proc/cpuinfo s3://nextcloud-bucket/cpuinfo.txt
|
||||
|
||||
# copy from garage to your filesystem
|
||||
aws s3 cp s3/my_files/cpuinfo.txt /tmp/cpuinfo.txt
|
||||
aws s3 cp s3://nextcloud-bucket/cpuinfo.txt /tmp/cpuinfo.txt
|
||||
```
|
||||
|
||||
Note that you can use `awscli` for more advanced operations like
|
||||
|
||||
Generated
+76
-23
@@ -41,12 +41,15 @@
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1659877975,
|
||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||
"lastModified": 1681202837,
|
||||
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -56,12 +59,15 @@
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1667395993,
|
||||
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
|
||||
"lastModified": 1681202837,
|
||||
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
|
||||
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -72,44 +78,61 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1665657542,
|
||||
"narHash": "sha256-mojxNyzbvmp8NtVtxqiHGhRfjCALLfk9i/Uup68Y5q8=",
|
||||
"lastModified": 1682109806,
|
||||
"narHash": "sha256-d9g7RKNShMLboTWwukM+RObDWWpHKaqTYXB48clBWXI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a3073c49bc0163fea6a121c276f526837672b555",
|
||||
"rev": "2362848adf8def2866fabbffc50462e929d7fffb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1682423271,
|
||||
"narHash": "sha256-WHhl1GiOij1ob4cTLL+yhqr+vFOUH8E5wAX8Ir8fvjE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "94517a501434a627c5d9e72ac6e7f26174b978d3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a3073c49bc0163fea6a121c276f526837672b555",
|
||||
"rev": "94517a501434a627c5d9e72ac6e7f26174b978d3",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"cargo2nix": "cargo2nix",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"cargo2nix",
|
||||
"flake-compat"
|
||||
],
|
||||
"flake-utils": [
|
||||
"cargo2nix",
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"cargo2nix",
|
||||
"nixpkgs"
|
||||
]
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1664247556,
|
||||
"narHash": "sha256-J4vazHU3609ekn7dr+3wfqPo5WGlZVAgV7jfux352L0=",
|
||||
"lastModified": 1682389182,
|
||||
"narHash": "sha256-8t2nmFnH+8V48+IJsf8AK51ebXNlVbOSVYOpiqJKvJE=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "524db9c9ea7bc7743bb74cdd45b6d46ea3fcc2ab",
|
||||
"rev": "74f1a64dd28faeeb85ef081f32cad2989850322c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -117,6 +140,36 @@
|
||||
"repo": "rust-overlay",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
|
||||
@@ -2,16 +2,30 @@
|
||||
description =
|
||||
"Garage, an S3-compatible distributed object store for self-hosted deployments";
|
||||
|
||||
# Nixpkgs unstable as of 2023-04-25, has rustc v1.68
|
||||
inputs.nixpkgs.url =
|
||||
"github:NixOS/nixpkgs/a3073c49bc0163fea6a121c276f526837672b555";
|
||||
"github:NixOS/nixpkgs/94517a501434a627c5d9e72ac6e7f26174b978d3";
|
||||
|
||||
inputs.cargo2nix = {
|
||||
# As of 2022-10-18: two small patches over unstable branch, one for clippy and one to fix feature detection
|
||||
url = "github:Alexis211/cargo2nix/a7a61179b66054904ef6a195d8da736eaaa06c36";
|
||||
|
||||
# As of 2023-04-25:
|
||||
# - my two patches were merged into unstable (one for clippy and one to "fix" feature detection)
|
||||
# - rustc v1.66
|
||||
# url = "github:cargo2nix/cargo2nix/8fb57a670f7993bfc24099c33eb9c5abb51f29a2";
|
||||
|
||||
# Rust overlay as of 2023-04-25
|
||||
inputs.rust-overlay.url =
|
||||
"github:oxalica/rust-overlay/74f1a64dd28faeeb85ef081f32cad2989850322c";
|
||||
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
inputs.flake-utils.url = "github:numtide/flake-utils";
|
||||
|
||||
outputs = { self, nixpkgs, cargo2nix, flake-utils }:
|
||||
inputs.flake-utils.follows = "cargo2nix/flake-utils";
|
||||
inputs.flake-compat.follows = "cargo2nix/flake-compat";
|
||||
|
||||
outputs = { self, nixpkgs, cargo2nix, flake-utils, ... }:
|
||||
let
|
||||
git_version = self.lastModifiedDate;
|
||||
compile = import ./nix/compile.nix;
|
||||
|
||||
+10
-15
@@ -1,19 +1,14 @@
|
||||
rec {
|
||||
# * Fixed dependencies
|
||||
pkgsSrc = fetchTarball {
|
||||
# As of 2022-10-13
|
||||
let
|
||||
lock = builtins.fromJSON (builtins.readFile ../flake.lock);
|
||||
flakeCompatRev = lock.nodes.flake-compat.locked.rev;
|
||||
flakeCompat = fetchTarball {
|
||||
url =
|
||||
"https://github.com/NixOS/nixpkgs/archive/a3073c49bc0163fea6a121c276f526837672b555.zip";
|
||||
sha256 = "1bz632psfbpmicyzjb8b4265y50shylccvfm6ry6mgnv5hvz324s";
|
||||
"https://github.com/edolstra/flake-compat/archive/${flakeCompatRev}.tar.gz";
|
||||
sha256 = lock.nodes.flake-compat.locked.narHash;
|
||||
};
|
||||
cargo2nixSrc = fetchGit {
|
||||
# As of 2022-10-18: two small patches over unstable branch, one for clippy and one to fix feature detection
|
||||
url = "https://github.com/Alexis211/cargo2nix";
|
||||
ref = "custom_unstable";
|
||||
rev = "a7a61179b66054904ef6a195d8da736eaaa06c36";
|
||||
};
|
||||
|
||||
# * Shared objects
|
||||
cargo2nix = import cargo2nixSrc;
|
||||
flake = ((import flakeCompat) { src = ../.; }).defaultNix;
|
||||
in rec {
|
||||
pkgsSrc = flake.inputs.nixpkgs;
|
||||
cargo2nix = flake.inputs.cargo2nix;
|
||||
cargo2nixOverlay = cargo2nix.overlays.default;
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ let
|
||||
*/
|
||||
toolchainOptions = if target == null || target == "x86_64-unknown-linux-musl"
|
||||
|| target == "aarch64-unknown-linux-musl" then {
|
||||
rustVersion = "1.63.0";
|
||||
rustVersion = "1.68.0";
|
||||
extraRustComponents = [ "clippy" ];
|
||||
} else {
|
||||
rustToolchain = pkgs.symlinkJoin {
|
||||
|
||||
+2
-2
@@ -1,13 +1,13 @@
|
||||
pkgs:
|
||||
pkgs.buildGoModule rec {
|
||||
pname = "kaniko";
|
||||
version = "1.6.0";
|
||||
version = "1.9.2";
|
||||
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "GoogleContainerTools";
|
||||
repo = "kaniko";
|
||||
rev = "v${version}";
|
||||
sha256 = "1fnclr556avxay6pvgw5ya3xbxfnf2gv4njq2hr4fd6fcjyslq5h";
|
||||
sha256 = "dXQ0/o1qISv+sjNVIpfF85bkbM9sGOGwqVbWZpMWfMY=";
|
||||
};
|
||||
|
||||
vendorSha256 = null;
|
||||
|
||||
@@ -15,10 +15,10 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.3.0
|
||||
version: 0.4.1
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "v0.7.2.1"
|
||||
appVersion: "v0.8.2"
|
||||
|
||||
@@ -4,9 +4,28 @@
|
||||
|
||||
# Garage configuration. These values go to garage.toml
|
||||
garage:
|
||||
# Can be changed for better performance on certain systems
|
||||
# https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#db-engine-since-v0-8-0
|
||||
dbEngine: "sled"
|
||||
|
||||
# Defaults is 1MB
|
||||
# An increase can result in better performance in certain scenarios
|
||||
# https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#block-size
|
||||
blockSize: "1048576"
|
||||
|
||||
# Tuning parameters for the sled DB engine
|
||||
# https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#sled-cache-capacity
|
||||
sledCacheCapacity: "134217728"
|
||||
sledFlushEveryMs: "2000"
|
||||
|
||||
# Default to 3 replicas, see the replication_mode section at
|
||||
# https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/
|
||||
# https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#replication-mode
|
||||
replicationMode: "3"
|
||||
|
||||
# zstd compression level of stored blocks
|
||||
# https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#compression-level
|
||||
compressionLevel: "1"
|
||||
|
||||
rpcBindAddr: "[::]:3901"
|
||||
# If not given, a random secret will be generated and stored in a Secret object
|
||||
rpcSecret: ""
|
||||
@@ -27,8 +46,19 @@ garage:
|
||||
metadata_dir = "/mnt/meta"
|
||||
data_dir = "/mnt/data"
|
||||
|
||||
db_engine = "{{ .Values.garage.dbEngine }}"
|
||||
|
||||
block_size = {{ .Values.garage.blockSize }}
|
||||
|
||||
{{- if eq .Values.garage.dbEngine "sled"}}
|
||||
sled_cache_capacity = {{ .Values.garage.sledCacheCapacity }}
|
||||
sled_flush_every_ms = {{ .Values.garage.sledFlushEveryMs }}
|
||||
{{- end }}
|
||||
|
||||
replication_mode = "{{ .Values.garage.replicationMode }}"
|
||||
|
||||
compression_level = {{ .Values.garage.compressionLevel }}
|
||||
|
||||
rpc_bind_addr = "{{ .Values.garage.rpcBindAddr }}"
|
||||
# rpc_secret will be populated by the init container from a k8s secret object
|
||||
rpc_secret = "__RPC_SECRET_REPLACE__"
|
||||
@@ -49,7 +79,7 @@ garage:
|
||||
bind_addr = "[::]:3902"
|
||||
root_domain = "{{ .Values.garage.s3.web.rootDomain }}"
|
||||
index = "{{ .Values.garage.s3.web.index }}"
|
||||
|
||||
|
||||
[admin]
|
||||
api_bind_addr = "[::]:3903"
|
||||
{{- if .Values.monitoring.tracing.sink }}
|
||||
@@ -211,4 +241,4 @@ monitoring:
|
||||
scrapeTimeout: 10s
|
||||
relabelings: []
|
||||
tracing:
|
||||
sink: ""
|
||||
sink: ""
|
||||
|
||||
+6
-6
@@ -14,11 +14,11 @@ path = "lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_model = { version = "0.8.2", path = "../model" }
|
||||
garage_table = { version = "0.8.2", path = "../table" }
|
||||
garage_block = { version = "0.8.2", path = "../block" }
|
||||
garage_util = { version = "0.8.2", path = "../util" }
|
||||
garage_rpc = { version = "0.8.2", path = "../rpc" }
|
||||
garage_model.workspace = true
|
||||
garage_table.workspace = true
|
||||
garage_block.workspace = true
|
||||
garage_util.workspace = true
|
||||
garage_rpc.workspace = true
|
||||
|
||||
async-trait = "0.1.7"
|
||||
base64 = "0.21"
|
||||
@@ -51,7 +51,7 @@ roxmltree = "0.14"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_bytes = "0.11"
|
||||
serde_json = "1.0"
|
||||
quick-xml = { version = "0.21", features = [ "serialize" ] }
|
||||
quick-xml = { version = "0.26", features = [ "serialize" ] }
|
||||
url = "2.3"
|
||||
|
||||
opentelemetry = "0.17"
|
||||
|
||||
@@ -105,7 +105,7 @@ impl AdminApiServer {
|
||||
let bucket_id = self
|
||||
.garage
|
||||
.bucket_helper()
|
||||
.resolve_global_bucket_name(&domain)
|
||||
.resolve_global_bucket_name(domain)
|
||||
.await?
|
||||
.ok_or(HelperError::NoSuchBucket(domain.to_string()))?;
|
||||
|
||||
|
||||
@@ -183,8 +183,8 @@ async fn bucket_info_results(
|
||||
}
|
||||
}),
|
||||
keys: relevant_keys
|
||||
.into_iter()
|
||||
.map(|(_, key)| {
|
||||
.into_values()
|
||||
.map(|key| {
|
||||
let p = key.state.as_option().unwrap();
|
||||
GetBucketInfoKey {
|
||||
access_key_id: key.key_id,
|
||||
|
||||
@@ -183,8 +183,8 @@ async fn key_info_results(garage: &Arc<Garage>, key: Key) -> Result<Response<Bod
|
||||
create_bucket: *key_state.allow_create_bucket.get(),
|
||||
},
|
||||
buckets: relevant_buckets
|
||||
.into_iter()
|
||||
.map(|(_, bucket)| {
|
||||
.into_values()
|
||||
.map(|bucket| {
|
||||
let state = bucket.state.as_option().unwrap();
|
||||
KeyInfoBucketResult {
|
||||
id: hex::encode(bucket.id),
|
||||
|
||||
@@ -128,7 +128,7 @@ impl<A: ApiHandler> ApiServer<A> {
|
||||
let uri = req.uri().clone();
|
||||
|
||||
if let Ok(forwarded_for_ip_addr) =
|
||||
forwarded_headers::handle_forwarded_for_headers(&req.headers())
|
||||
forwarded_headers::handle_forwarded_for_headers(req.headers())
|
||||
{
|
||||
info!(
|
||||
"{} (via {}) {} {}",
|
||||
|
||||
@@ -282,8 +282,8 @@ pub(crate) async fn handle_poll_range(
|
||||
if let Some((items, seen_marker)) = resp {
|
||||
let resp = PollRangeResponse {
|
||||
items: items
|
||||
.into_iter()
|
||||
.map(|(_k, i)| ReadBatchResponseItem::from(i))
|
||||
.into_values()
|
||||
.map(ReadBatchResponseItem::from)
|
||||
.collect::<Vec<_>>(),
|
||||
seen_marker,
|
||||
};
|
||||
|
||||
+2
-2
@@ -443,7 +443,7 @@ fn body_from_blocks_range(
|
||||
// block.part_number, which is not the same in the case of a multipart upload)
|
||||
let mut blocks: Vec<(VersionBlock, u64)> = Vec::with_capacity(std::cmp::min(
|
||||
all_blocks.len(),
|
||||
4 + ((end - begin) / std::cmp::max(all_blocks[0].1.size as u64, 1024)) as usize,
|
||||
4 + ((end - begin) / std::cmp::max(all_blocks[0].1.size, 1024)) as usize,
|
||||
));
|
||||
let mut block_offset: u64 = 0;
|
||||
for (_, b) in all_blocks.iter() {
|
||||
@@ -454,7 +454,7 @@ fn body_from_blocks_range(
|
||||
if block_offset < end && block_offset + b.size > begin {
|
||||
blocks.push((*b, block_offset));
|
||||
}
|
||||
block_offset += b.size as u64;
|
||||
block_offset += b.size;
|
||||
}
|
||||
|
||||
let order_stream = OrderTag::stream();
|
||||
|
||||
@@ -14,10 +14,10 @@ path = "lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_db = { version = "0.8.2", path = "../db" }
|
||||
garage_rpc = { version = "0.8.2", path = "../rpc" }
|
||||
garage_util = { version = "0.8.2", path = "../util" }
|
||||
garage_table = { version = "0.8.2", path = "../table" }
|
||||
garage_db.workspace = true
|
||||
garage_rpc.workspace = true
|
||||
garage_util.workspace = true
|
||||
garage_table.workspace = true
|
||||
|
||||
opentelemetry = "0.17"
|
||||
|
||||
@@ -37,7 +37,7 @@ serde_bytes = "0.11"
|
||||
futures = "0.3"
|
||||
futures-util = "0.3"
|
||||
tokio = { version = "1.0", default-features = false, features = ["rt", "rt-multi-thread", "io-util", "net", "time", "macros", "sync", "signal", "fs"] }
|
||||
tokio-util = { version = "0.6", features = ["io"] }
|
||||
tokio-util = { version = "0.7", features = ["io"] }
|
||||
|
||||
[features]
|
||||
system-libs = [ "zstd/pkg-config" ]
|
||||
|
||||
+25
-5
@@ -600,12 +600,32 @@ impl BlockManager {
|
||||
/// Utility: check if block is stored compressed. Error if block is not stored
|
||||
async fn is_block_compressed(&self, hash: &Hash) -> Result<bool, Error> {
|
||||
let mut path = self.block_path(hash);
|
||||
path.set_extension("zst");
|
||||
if fs::metadata(&path).await.is_ok() {
|
||||
return Ok(true);
|
||||
|
||||
// If compression is disabled on node - check for the raw block
|
||||
// first and then a compressed one (as compression may have been
|
||||
// previously enabled).
|
||||
match self.compression_level {
|
||||
None => {
|
||||
if fs::metadata(&path).await.is_ok() {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
path.set_extension("zst");
|
||||
|
||||
fs::metadata(&path).await.map(|_| true).map_err(Into::into)
|
||||
}
|
||||
_ => {
|
||||
path.set_extension("zst");
|
||||
|
||||
if fs::metadata(&path).await.is_ok() {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
path.set_extension("");
|
||||
|
||||
fs::metadata(&path).await.map(|_| false).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
path.set_extension("");
|
||||
fs::metadata(&path).await.map(|_| false).map_err(Into::into)
|
||||
}
|
||||
|
||||
async fn lock_mutate(&self, hash: &Hash) -> MutexGuard<'_, BlockManagerLocked> {
|
||||
|
||||
+16
-12
@@ -220,14 +220,12 @@ fn randomize_next_scrub_run_time(timestamp: u64) -> u64 {
|
||||
// Take SCRUB_INTERVAL and mix in a random interval of 10 days to attempt to
|
||||
// balance scrub load across different cluster nodes.
|
||||
|
||||
let next_run_timestamp = timestamp
|
||||
timestamp
|
||||
+ SCRUB_INTERVAL
|
||||
.saturating_add(Duration::from_secs(
|
||||
rand::thread_rng().gen_range(0..3600 * 24 * 10),
|
||||
))
|
||||
.as_millis() as u64;
|
||||
|
||||
next_run_timestamp
|
||||
.as_millis() as u64
|
||||
}
|
||||
|
||||
impl Default for ScrubWorkerPersisted {
|
||||
@@ -241,18 +239,14 @@ impl Default for ScrubWorkerPersisted {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
enum ScrubWorkerState {
|
||||
Running(BlockStoreIterator),
|
||||
Paused(BlockStoreIterator, u64), // u64 = time when to resume scrub
|
||||
#[default]
|
||||
Finished,
|
||||
}
|
||||
|
||||
impl Default for ScrubWorkerState {
|
||||
fn default() -> Self {
|
||||
ScrubWorkerState::Finished
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ScrubWorkerCommand {
|
||||
Start,
|
||||
@@ -281,6 +275,7 @@ impl ScrubWorker {
|
||||
ScrubWorkerCommand::Start => {
|
||||
self.work = match std::mem::take(&mut self.work) {
|
||||
ScrubWorkerState::Finished => {
|
||||
info!("Scrub worker initializing, now performing datastore scrub");
|
||||
let iterator = BlockStoreIterator::new(&self.manager);
|
||||
ScrubWorkerState::Running(iterator)
|
||||
}
|
||||
@@ -394,12 +389,21 @@ impl Worker for ScrubWorker {
|
||||
.tranquilizer
|
||||
.tranquilize_worker(self.persister.get_with(|p| p.tranquility)))
|
||||
} else {
|
||||
let now = now_msec();
|
||||
let next_scrub_timestamp = randomize_next_scrub_run_time(now);
|
||||
|
||||
self.persister.set_with(|p| {
|
||||
p.time_last_complete_scrub = now_msec();
|
||||
p.time_next_run_scrub = randomize_next_scrub_run_time(now_msec());
|
||||
p.time_last_complete_scrub = now;
|
||||
p.time_next_run_scrub = next_scrub_timestamp;
|
||||
})?;
|
||||
self.work = ScrubWorkerState::Finished;
|
||||
self.tranquilizer.clear();
|
||||
|
||||
info!(
|
||||
"Datastore scrub completed, next scrub scheduled for {}",
|
||||
msec_to_rfc3339(next_scrub_timestamp)
|
||||
);
|
||||
|
||||
Ok(WorkerState::Idle)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,6 +349,6 @@ pub fn recommended_map_size() -> usize {
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub fn recommended_map_size() -> usize {
|
||||
warn!("LMDB is not recommended on 32-bit systems, database size will be limited");
|
||||
tracing::warn!("LMDB is not recommended on 32-bit systems, database size will be limited");
|
||||
1usize << 30
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "format_table"
|
||||
version = "0.1.0"
|
||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||
edition = "2018"
|
||||
license = "AGPL-3.0"
|
||||
description = "Format tables with a stupid API"
|
||||
repository = "https://git.deuxfleurs.fr/Deuxfleurs/garage"
|
||||
readme = "README.md"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
@@ -0,0 +1,13 @@
|
||||
# `format_table`
|
||||
|
||||
Format tables with a stupid API. [Documentation](https://docs.rs/format_table).
|
||||
|
||||
Example:
|
||||
|
||||
```rust
|
||||
let mut table = vec!["product\tquantity\tprice".to_string()];
|
||||
for (p, q, r) in [("tomato", 12, 15), ("potato", 10, 20), ("rice", 5, 12)] {
|
||||
table.push(format!("{}\t{}\t{}", p, q, r));
|
||||
}
|
||||
format_table::format_table(table);
|
||||
```
|
||||
@@ -1,3 +1,19 @@
|
||||
//! Format tables with a stupid API.
|
||||
//!
|
||||
//! Example:
|
||||
//!
|
||||
//! ```rust
|
||||
//! let mut table = vec!["product\tquantity\tprice".to_string()];
|
||||
//! for (p, q, r) in [("tomato", 12, 15), ("potato", 10, 20), ("rice", 5, 12)] {
|
||||
//! table.push(format!("{}\t{}\t{}", p, q, r));
|
||||
//! }
|
||||
//! format_table::format_table(table);
|
||||
//! ```
|
||||
//!
|
||||
//! A table to be formatted is a `Vec<String>`, containing one string per line.
|
||||
//! Table columns in each line are separated by a `\t` character.
|
||||
|
||||
/// Format a table and return the result as a string.
|
||||
pub fn format_table_to_string(data: Vec<String>) -> String {
|
||||
let data = data
|
||||
.iter()
|
||||
@@ -27,6 +43,7 @@ pub fn format_table_to_string(data: Vec<String>) -> String {
|
||||
out
|
||||
}
|
||||
|
||||
/// Format a table and print the result to stdout.
|
||||
pub fn format_table(data: Vec<String>) {
|
||||
print!("{}", format_table_to_string(data));
|
||||
}
|
||||
+11
-9
@@ -21,19 +21,20 @@ path = "tests/lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_db = { version = "0.8.2", path = "../db" }
|
||||
garage_api = { version = "0.8.2", path = "../api" }
|
||||
garage_block = { version = "0.8.2", path = "../block" }
|
||||
garage_model = { version = "0.8.2", path = "../model" }
|
||||
garage_rpc = { version = "0.8.2", path = "../rpc" }
|
||||
garage_table = { version = "0.8.2", path = "../table" }
|
||||
garage_util = { version = "0.8.2", path = "../util" }
|
||||
garage_web = { version = "0.8.2", path = "../web" }
|
||||
format_table.workspace = true
|
||||
garage_db.workspace = true
|
||||
garage_api.workspace = true
|
||||
garage_block.workspace = true
|
||||
garage_model.workspace = true
|
||||
garage_rpc.workspace = true
|
||||
garage_table.workspace = true
|
||||
garage_util.workspace = true
|
||||
garage_web.workspace = true
|
||||
|
||||
backtrace = "0.3"
|
||||
bytes = "1.0"
|
||||
bytesize = "1.1"
|
||||
timeago = "0.4"
|
||||
timeago = { version = "0.4", default-features = false }
|
||||
parse_duration = "2.1"
|
||||
hex = "0.4"
|
||||
tracing = { version = "0.1" }
|
||||
@@ -41,6 +42,7 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
rand = "0.8"
|
||||
async-trait = "0.1.7"
|
||||
sodiumoxide = { version = "0.2.5-0", package = "kuska-sodiumoxide" }
|
||||
git-version = "0.3.4"
|
||||
|
||||
serde = { version = "1.0", default-features = false, features = ["derive", "rc"] }
|
||||
serde_bytes = "0.11"
|
||||
|
||||
+1
-1
@@ -5,11 +5,11 @@ use std::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use format_table::format_table_to_string;
|
||||
use garage_util::background::BackgroundRunner;
|
||||
use garage_util::crdt::*;
|
||||
use garage_util::data::*;
|
||||
use garage_util::error::Error as GarageError;
|
||||
use garage_util::formater::format_table_to_string;
|
||||
use garage_util::time::*;
|
||||
|
||||
use garage_table::replication::*;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::collections::HashSet;
|
||||
use std::time::Duration;
|
||||
|
||||
use format_table::format_table;
|
||||
use garage_util::error::*;
|
||||
use garage_util::formater::format_table;
|
||||
|
||||
use garage_rpc::layout::*;
|
||||
use garage_rpc::system::*;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use format_table::format_table;
|
||||
use garage_util::crdt::Crdt;
|
||||
use garage_util::error::*;
|
||||
use garage_util::formater::format_table;
|
||||
|
||||
use garage_rpc::layout::*;
|
||||
use garage_rpc::system::*;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use format_table::format_table;
|
||||
use garage_util::background::*;
|
||||
use garage_util::crdt::*;
|
||||
use garage_util::data::*;
|
||||
use garage_util::error::*;
|
||||
use garage_util::formater::format_table;
|
||||
use garage_util::time::*;
|
||||
|
||||
use garage_block::manager::BlockResyncErrorInfo;
|
||||
|
||||
@@ -108,6 +108,12 @@ async fn main() {
|
||||
][..];
|
||||
if let Some(git_version) = option_env!("GIT_VERSION") {
|
||||
garage_util::version::init_version(git_version);
|
||||
} else {
|
||||
garage_util::version::init_version(git_version::git_version!(
|
||||
prefix = "git:",
|
||||
cargo_prefix = "cargo:",
|
||||
fallback = "unknown"
|
||||
));
|
||||
}
|
||||
garage_util::version::init_features(features);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "k2v-client"
|
||||
version = "0.1.1"
|
||||
version = "0.0.2"
|
||||
authors = ["Trinity Pointard <trinity.pointard@gmail.com>", "Alex Auvolat <alex@adnab.me>"]
|
||||
edition = "2018"
|
||||
license = "AGPL-3.0"
|
||||
@@ -19,15 +19,15 @@ hyper-rustls = { version = "0.23", default-features = false, features = [ "http1
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
thiserror = "1.0"
|
||||
tokio = "1.24"
|
||||
tokio = { version = "1.0", default-features = false, features = ["rt", "rt-multi-thread", "io-util", "net", "time", "macros", "sync", "signal", "fs"] }
|
||||
|
||||
# cli deps
|
||||
clap = { version = "4.1", optional = true, features = ["derive", "env"] }
|
||||
garage_util = { version = "0.8.2", path = "../util", optional = true }
|
||||
format_table = { workspace = true, optional = true }
|
||||
|
||||
|
||||
[features]
|
||||
cli = ["clap", "tokio/fs", "tokio/io-std", "garage_util"]
|
||||
cli = ["clap", "tokio/fs", "tokio/io-std", "format_table"]
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
@@ -2,9 +2,11 @@ use std::collections::BTreeMap;
|
||||
use std::process::exit;
|
||||
use std::time::Duration;
|
||||
|
||||
use base64::prelude::*;
|
||||
|
||||
use k2v_client::*;
|
||||
|
||||
use garage_util::formater::format_table;
|
||||
use format_table::format_table;
|
||||
|
||||
use rusoto_core::credential::AwsCredentials;
|
||||
use rusoto_core::Region;
|
||||
@@ -155,7 +157,9 @@ impl Value {
|
||||
if let Some(ref text) = self.text {
|
||||
Ok(text.as_bytes().to_vec())
|
||||
} else if let Some(ref b64) = self.b64 {
|
||||
base64::decode(b64).map_err(|_| Error::Message("invalid base64 input".into()))
|
||||
BASE64_STANDARD
|
||||
.decode(b64)
|
||||
.map_err(|_| Error::Message("invalid base64 input".into()))
|
||||
} else if let Some(ref path) = self.file {
|
||||
use tokio::io::AsyncReadExt;
|
||||
if path == "-" {
|
||||
@@ -230,7 +234,7 @@ impl ReadOutputKind {
|
||||
for val in val.value {
|
||||
match val {
|
||||
K2vValue::Value(v) => {
|
||||
println!("{}", base64::encode(&v))
|
||||
println!("{}", BASE64_STANDARD.encode(&v))
|
||||
}
|
||||
K2vValue::Tombstone => {
|
||||
println!();
|
||||
@@ -249,7 +253,7 @@ impl ReadOutputKind {
|
||||
if let Ok(string) = std::str::from_utf8(&v) {
|
||||
println!(" utf-8: {}", string);
|
||||
} else {
|
||||
println!(" base64: {}", base64::encode(&v));
|
||||
println!(" base64: {}", BASE64_STANDARD.encode(&v));
|
||||
}
|
||||
}
|
||||
K2vValue::Tombstone => {
|
||||
@@ -275,7 +279,7 @@ struct BatchOutputKind {
|
||||
impl BatchOutputKind {
|
||||
fn display_human_output(&self, values: BTreeMap<String, CausalValue>) -> ! {
|
||||
for (key, values) in values {
|
||||
println!("key: {}", key);
|
||||
println!("sort_key: {}", key);
|
||||
let causality: String = values.causality.into();
|
||||
println!("causality: {}", causality);
|
||||
for value in values.value {
|
||||
@@ -284,7 +288,7 @@ impl BatchOutputKind {
|
||||
if let Ok(string) = std::str::from_utf8(&v) {
|
||||
println!(" value(utf-8): {}", string);
|
||||
} else {
|
||||
println!(" value(base64): {}", base64::encode(&v));
|
||||
println!(" value(base64): {}", BASE64_STANDARD.encode(&v));
|
||||
}
|
||||
}
|
||||
K2vValue::Tombstone => {
|
||||
@@ -520,7 +524,7 @@ async fn main() -> Result<(), Error> {
|
||||
value
|
||||
.as_object_mut()
|
||||
.unwrap()
|
||||
.insert("sort_key".to_owned(), k.into());
|
||||
.insert("partition_key".to_owned(), k.into());
|
||||
value
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@@ -537,7 +541,7 @@ async fn main() -> Result<(), Error> {
|
||||
}
|
||||
|
||||
let mut to_print = Vec::new();
|
||||
to_print.push(format!("key:\tentries\tconflicts\tvalues\tbytes"));
|
||||
to_print.push(format!("partition_key\tentries\tconflicts\tvalues\tbytes"));
|
||||
for (k, v) in res.items {
|
||||
to_print.push(format!(
|
||||
"{}\t{}\t{}\t{}\t{}",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use base64::prelude::*;
|
||||
use http::header::{ACCEPT, CONTENT_LENGTH, CONTENT_TYPE};
|
||||
use http::status::StatusCode;
|
||||
use http::HeaderMap;
|
||||
@@ -375,7 +376,7 @@ impl K2vClient {
|
||||
.unwrap_or_default();
|
||||
let err_body_str = std::str::from_utf8(&err_body)
|
||||
.map(String::from)
|
||||
.unwrap_or_else(|_| base64::encode(&err_body));
|
||||
.unwrap_or_else(|_| BASE64_STANDARD.encode(&err_body));
|
||||
|
||||
if s.is_client_error() || s.is_server_error() {
|
||||
error!("Error response {}: {}", res.status, err_body_str);
|
||||
@@ -408,7 +409,7 @@ impl K2vClient {
|
||||
"Response body: {}",
|
||||
std::str::from_utf8(&body)
|
||||
.map(String::from)
|
||||
.unwrap_or_else(|_| base64::encode(&body))
|
||||
.unwrap_or_else(|_| BASE64_STANDARD.encode(&body))
|
||||
);
|
||||
|
||||
Ok(Response {
|
||||
@@ -482,9 +483,11 @@ impl<'de> Deserialize<'de> for K2vValue {
|
||||
{
|
||||
let val: Option<&str> = Option::deserialize(d)?;
|
||||
Ok(match val {
|
||||
Some(s) => {
|
||||
K2vValue::Value(base64::decode(s).map_err(|_| DeError::custom("invalid base64"))?)
|
||||
}
|
||||
Some(s) => K2vValue::Value(
|
||||
BASE64_STANDARD
|
||||
.decode(s)
|
||||
.map_err(|_| DeError::custom("invalid base64"))?,
|
||||
),
|
||||
None => K2vValue::Tombstone,
|
||||
})
|
||||
}
|
||||
@@ -498,7 +501,7 @@ impl Serialize for K2vValue {
|
||||
match self {
|
||||
K2vValue::Tombstone => serializer.serialize_none(),
|
||||
K2vValue::Value(v) => {
|
||||
let b64 = base64::encode(v);
|
||||
let b64 = BASE64_STANDARD.encode(v);
|
||||
serializer.serialize_str(&b64)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ path = "lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_db = { version = "0.8.2", default-features = false, path = "../db" }
|
||||
garage_rpc = { version = "0.8.2", path = "../rpc" }
|
||||
garage_table = { version = "0.8.2", path = "../table" }
|
||||
garage_block = { version = "0.8.2", path = "../block" }
|
||||
garage_util = { version = "0.8.2", path = "../util" }
|
||||
garage_db.workspace = true
|
||||
garage_rpc.workspace = true
|
||||
garage_table.workspace = true
|
||||
garage_block.workspace = true
|
||||
garage_util.workspace = true
|
||||
|
||||
async-trait = "0.1.7"
|
||||
arc-swap = "1.0"
|
||||
|
||||
@@ -79,7 +79,7 @@ impl RangeSeenMarker {
|
||||
|
||||
let bytes = nonversioned_encode(&self)?;
|
||||
let bytes = zstd::stream::encode_all(&mut &bytes[..], zstd::DEFAULT_COMPRESSION_LEVEL)?;
|
||||
Ok(BASE64_STANDARD.encode(&bytes))
|
||||
Ok(BASE64_STANDARD.encode(bytes))
|
||||
}
|
||||
|
||||
/// Decode from msgpack+zstd+b64 representation, returns None on error.
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ path = "lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_util = { version = "0.8.2", path = "../util" }
|
||||
garage_util.workspace = true
|
||||
|
||||
arc-swap = "1.0"
|
||||
bytes = "1.0"
|
||||
|
||||
@@ -14,9 +14,9 @@ path = "lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_db = { version = "0.8.2", path = "../db" }
|
||||
garage_rpc = { version = "0.8.2", path = "../rpc" }
|
||||
garage_util = { version = "0.8.2", path = "../util" }
|
||||
garage_db.workspace = true
|
||||
garage_rpc.workspace = true
|
||||
garage_util.workspace = true
|
||||
|
||||
opentelemetry = "0.17"
|
||||
|
||||
|
||||
+8
-8
@@ -44,22 +44,22 @@ pub struct TableData<F: TableSchema, R: TableReplication> {
|
||||
impl<F: TableSchema, R: TableReplication> TableData<F, R> {
|
||||
pub fn new(system: Arc<System>, instance: F, replication: R, db: &db::Db) -> Arc<Self> {
|
||||
let store = db
|
||||
.open_tree(&format!("{}:table", F::TABLE_NAME))
|
||||
.open_tree(format!("{}:table", F::TABLE_NAME))
|
||||
.expect("Unable to open DB tree");
|
||||
|
||||
let merkle_tree = db
|
||||
.open_tree(&format!("{}:merkle_tree", F::TABLE_NAME))
|
||||
.open_tree(format!("{}:merkle_tree", F::TABLE_NAME))
|
||||
.expect("Unable to open DB Merkle tree tree");
|
||||
let merkle_todo = db
|
||||
.open_tree(&format!("{}:merkle_todo", F::TABLE_NAME))
|
||||
.open_tree(format!("{}:merkle_todo", F::TABLE_NAME))
|
||||
.expect("Unable to open DB Merkle TODO tree");
|
||||
|
||||
let insert_queue = db
|
||||
.open_tree(&format!("{}:insert_queue", F::TABLE_NAME))
|
||||
.open_tree(format!("{}:insert_queue", F::TABLE_NAME))
|
||||
.expect("Unable to open insert queue DB tree");
|
||||
|
||||
let gc_todo = db
|
||||
.open_tree(&format!("{}:gc_todo_v2", F::TABLE_NAME))
|
||||
.open_tree(format!("{}:gc_todo_v2", F::TABLE_NAME))
|
||||
.expect("Unable to open GC DB tree");
|
||||
let gc_todo = CountedTree::new(gc_todo).expect("Cannot count gc_todo_v2");
|
||||
|
||||
@@ -90,7 +90,7 @@ impl<F: TableSchema, R: TableReplication> TableData<F, R> {
|
||||
|
||||
pub fn read_entry(&self, p: &F::P, s: &F::S) -> Result<Option<ByteBuf>, Error> {
|
||||
let tree_key = self.tree_key(p, s);
|
||||
if let Some(bytes) = self.store.get(&tree_key)? {
|
||||
if let Some(bytes) = self.store.get(tree_key)? {
|
||||
Ok(Some(ByteBuf::from(bytes.to_vec())))
|
||||
} else {
|
||||
Ok(None)
|
||||
@@ -132,10 +132,10 @@ impl<F: TableSchema, R: TableReplication> TableData<F, R> {
|
||||
}
|
||||
}
|
||||
|
||||
fn read_range_aux<'a>(
|
||||
fn read_range_aux(
|
||||
&self,
|
||||
partition_hash: Hash,
|
||||
range: db::ValueIter<'a>,
|
||||
range: db::ValueIter,
|
||||
filter: &Option<F::Filter>,
|
||||
limit: usize,
|
||||
) -> Result<Vec<Arc<ByteBuf>>, Error> {
|
||||
|
||||
+2
-7
@@ -34,8 +34,9 @@ impl DeletedFilter {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum EnumerationOrder {
|
||||
#[default]
|
||||
Forward,
|
||||
Reverse,
|
||||
}
|
||||
@@ -49,9 +50,3 @@ impl EnumerationOrder {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EnumerationOrder {
|
||||
fn default() -> Self {
|
||||
EnumerationOrder::Forward
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -14,7 +14,7 @@ path = "lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_db = { version = "0.8.2", path = "../db" }
|
||||
garage_db.workspace = true
|
||||
|
||||
arc-swap = "1.0"
|
||||
async-trait = "0.1"
|
||||
@@ -22,7 +22,6 @@ blake2 = "0.10"
|
||||
bytes = "1.0"
|
||||
digest = "0.10"
|
||||
err-derive = "0.3"
|
||||
git-version = "0.3.4"
|
||||
hexdump = "0.1"
|
||||
xxhash-rust = { version = "0.8", default-features = false, features = ["xxh3"] }
|
||||
hex = "0.4"
|
||||
|
||||
+1
-1
@@ -223,7 +223,7 @@ fn secret_from_file(
|
||||
#[cfg(unix)]
|
||||
if std::env::var("GARAGE_ALLOW_WORLD_READABLE_SECRETS").as_deref() != Ok("true") {
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
let metadata = std::fs::metadata(&file_path)?;
|
||||
let metadata = std::fs::metadata(file_path)?;
|
||||
if metadata.mode() & 0o077 != 0 {
|
||||
return Err(format!("File {} is world-readable! (mode: 0{:o}, expected 0600)\nRefusing to start until this is fixed, or environment variable GARAGE_ALLOW_WORLD_READABLE_SECRETS is set to true.", file_path, metadata.mode()).into());
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ pub fn handle_forwarded_for_headers(headers: &HeaderMap<HeaderValue>) -> Result<
|
||||
.to_str()
|
||||
.ok_or_message("Error parsing X-Forwarded-For header")?;
|
||||
|
||||
let client_ip = IpAddr::from_str(&forwarded_for_ip_str)
|
||||
let client_ip = IpAddr::from_str(forwarded_for_ip_str)
|
||||
.ok_or_message("Valid IP address not found in X-Forwarded-For header")?;
|
||||
|
||||
Ok(client_ip.to_string())
|
||||
|
||||
@@ -10,7 +10,6 @@ pub mod crdt;
|
||||
pub mod data;
|
||||
pub mod encode;
|
||||
pub mod error;
|
||||
pub mod formater;
|
||||
pub mod forwarded_headers;
|
||||
pub mod metrics;
|
||||
pub mod migrate;
|
||||
|
||||
+4
-8
@@ -1,18 +1,14 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use arc_swap::{ArcSwap, ArcSwapOption};
|
||||
use arc_swap::ArcSwapOption;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref VERSION: ArcSwap<&'static str> = ArcSwap::new(Arc::new(git_version::git_version!(
|
||||
prefix = "git:",
|
||||
cargo_prefix = "cargo:",
|
||||
fallback = "unknown"
|
||||
)));
|
||||
static ref VERSION: ArcSwapOption<&'static str> = ArcSwapOption::new(None);
|
||||
static ref FEATURES: ArcSwapOption<&'static [&'static str]> = ArcSwapOption::new(None);
|
||||
}
|
||||
|
||||
pub fn garage_version() -> &'static str {
|
||||
&VERSION.load()
|
||||
VERSION.load().as_ref().unwrap()
|
||||
}
|
||||
|
||||
pub fn garage_features() -> Option<&'static [&'static str]> {
|
||||
@@ -20,7 +16,7 @@ pub fn garage_features() -> Option<&'static [&'static str]> {
|
||||
}
|
||||
|
||||
pub fn init_version(version: &'static str) {
|
||||
VERSION.store(Arc::new(version));
|
||||
VERSION.store(Some(Arc::new(version)));
|
||||
}
|
||||
|
||||
pub fn init_features(features: &'static [&'static str]) {
|
||||
|
||||
+4
-4
@@ -14,10 +14,10 @@ path = "lib.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
garage_api = { version = "0.8.2", path = "../api" }
|
||||
garage_model = { version = "0.8.2", path = "../model" }
|
||||
garage_util = { version = "0.8.2", path = "../util" }
|
||||
garage_table = { version = "0.8.2", path = "../table" }
|
||||
garage_api.workspace = true
|
||||
garage_model.workspace = true
|
||||
garage_util.workspace = true
|
||||
garage_table.workspace = true
|
||||
|
||||
err-derive = "0.3"
|
||||
tracing = "0.1"
|
||||
|
||||
@@ -106,7 +106,7 @@ impl WebServer {
|
||||
addr: SocketAddr,
|
||||
) -> Result<Response<Body>, Infallible> {
|
||||
if let Ok(forwarded_for_ip_addr) =
|
||||
forwarded_headers::handle_forwarded_for_headers(&req.headers())
|
||||
forwarded_headers::handle_forwarded_for_headers(req.headers())
|
||||
{
|
||||
info!(
|
||||
"{} (via {}) {} {}",
|
||||
|
||||
Reference in New Issue
Block a user