Compare commits
No commits in common. "1243db87f2090a3302c7c8beb386e68ddf9b66b5" and "16aa418e473a5e9ef229060d20f6eb280df272a2" have entirely different histories.
1243db87f2
...
16aa418e47
14 changed files with 36 additions and 213 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -1271,7 +1271,6 @@ dependencies = [
|
||||||
"http-range",
|
"http-range",
|
||||||
"httpdate",
|
"httpdate",
|
||||||
"hyper",
|
"hyper",
|
||||||
"hyperlocal",
|
|
||||||
"idna",
|
"idna",
|
||||||
"md-5",
|
"md-5",
|
||||||
"multer",
|
"multer",
|
||||||
|
@ -1460,10 +1459,8 @@ dependencies = [
|
||||||
"garage_util",
|
"garage_util",
|
||||||
"http",
|
"http",
|
||||||
"hyper",
|
"hyper",
|
||||||
"hyperlocal",
|
|
||||||
"opentelemetry",
|
"opentelemetry",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"tokio",
|
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1773,19 +1770,6 @@ dependencies = [
|
||||||
"tokio-io-timeout",
|
"tokio-io-timeout",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hyperlocal"
|
|
||||||
version = "0.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c"
|
|
||||||
dependencies = [
|
|
||||||
"futures-util",
|
|
||||||
"hex",
|
|
||||||
"hyper",
|
|
||||||
"pin-project",
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iana-time-zone"
|
name = "iana-time-zone"
|
||||||
version = "0.1.57"
|
version = "0.1.57"
|
||||||
|
|
22
Cargo.nix
22
Cargo.nix
|
@ -33,7 +33,7 @@ args@{
|
||||||
ignoreLockHash,
|
ignoreLockHash,
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
nixifiedLockHash = "b73d35e98dc62acc3b01aba2cb825ba6e99217e46781b8c59f8e0ceef34e79d6";
|
nixifiedLockHash = "ab8dba64b487c83fa25ebafbad99538d2f38afa5b53f83e4e031b7909665166b";
|
||||||
workspaceSrc = if args.workspaceSrc == null then ./. else args.workspaceSrc;
|
workspaceSrc = if args.workspaceSrc == null then ./. else args.workspaceSrc;
|
||||||
currentLockHash = builtins.hashFile "sha256" (workspaceSrc + /Cargo.lock);
|
currentLockHash = builtins.hashFile "sha256" (workspaceSrc + /Cargo.lock);
|
||||||
lockHashIgnored = if ignoreLockHash
|
lockHashIgnored = if ignoreLockHash
|
||||||
|
@ -1809,7 +1809,6 @@ in
|
||||||
http_range = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".http-range."0.1.5" { inherit profileName; }).out;
|
http_range = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".http-range."0.1.5" { inherit profileName; }).out;
|
||||||
httpdate = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".httpdate."1.0.3" { inherit profileName; }).out;
|
httpdate = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".httpdate."1.0.3" { inherit profileName; }).out;
|
||||||
hyper = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".hyper."0.14.27" { inherit profileName; }).out;
|
hyper = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".hyper."0.14.27" { inherit profileName; }).out;
|
||||||
hyperlocal = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".hyperlocal."0.8.0" { inherit profileName; }).out;
|
|
||||||
idna = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".idna."0.4.0" { inherit profileName; }).out;
|
idna = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".idna."0.4.0" { inherit profileName; }).out;
|
||||||
md5 = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".md-5."0.10.5" { inherit profileName; }).out;
|
md5 = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".md-5."0.10.5" { inherit profileName; }).out;
|
||||||
multer = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".multer."2.1.0" { inherit profileName; }).out;
|
multer = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".multer."2.1.0" { inherit profileName; }).out;
|
||||||
|
@ -2060,10 +2059,8 @@ in
|
||||||
garage_util = (rustPackages."unknown".garage_util."0.8.4" { inherit profileName; }).out;
|
garage_util = (rustPackages."unknown".garage_util."0.8.4" { inherit profileName; }).out;
|
||||||
http = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".http."0.2.9" { inherit profileName; }).out;
|
http = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".http."0.2.9" { inherit profileName; }).out;
|
||||||
hyper = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".hyper."0.14.27" { inherit profileName; }).out;
|
hyper = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".hyper."0.14.27" { inherit profileName; }).out;
|
||||||
hyperlocal = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".hyperlocal."0.8.0" { inherit profileName; }).out;
|
|
||||||
opentelemetry = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".opentelemetry."0.17.0" { inherit profileName; }).out;
|
opentelemetry = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".opentelemetry."0.17.0" { inherit profileName; }).out;
|
||||||
percent_encoding = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".percent-encoding."2.3.0" { inherit profileName; }).out;
|
percent_encoding = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".percent-encoding."2.3.0" { inherit profileName; }).out;
|
||||||
tokio = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio."1.32.0" { inherit profileName; }).out;
|
|
||||||
tracing = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".tracing."0.1.37" { inherit profileName; }).out;
|
tracing = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".tracing."0.1.37" { inherit profileName; }).out;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -2489,23 +2486,6 @@ in
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
"registry+https://github.com/rust-lang/crates.io-index".hyperlocal."0.8.0" = overridableMkRustCrate (profileName: rec {
|
|
||||||
name = "hyperlocal";
|
|
||||||
version = "0.8.0";
|
|
||||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
|
||||||
src = fetchCratesIo { inherit name version; sha256 = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c"; };
|
|
||||||
features = builtins.concatLists [
|
|
||||||
[ "server" ]
|
|
||||||
];
|
|
||||||
dependencies = {
|
|
||||||
futures_util = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-util."0.3.28" { inherit profileName; }).out;
|
|
||||||
hex = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".hex."0.4.3" { inherit profileName; }).out;
|
|
||||||
hyper = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".hyper."0.14.27" { inherit profileName; }).out;
|
|
||||||
pin_project = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pin-project."1.1.3" { inherit profileName; }).out;
|
|
||||||
tokio = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio."1.32.0" { inherit profileName; }).out;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
"registry+https://github.com/rust-lang/crates.io-index".iana-time-zone."0.1.57" = overridableMkRustCrate (profileName: rec {
|
"registry+https://github.com/rust-lang/crates.io-index".iana-time-zone."0.1.57" = overridableMkRustCrate (profileName: rec {
|
||||||
name = "iana-time-zone";
|
name = "iana-time-zone";
|
||||||
version = "0.1.57";
|
version = "0.1.57";
|
||||||
|
|
|
@ -410,8 +410,6 @@ manually.
|
||||||
The IP and port on which to bind for accepting S3 API calls.
|
The IP and port on which to bind for accepting S3 API calls.
|
||||||
This endpoint does not suport TLS: a reverse proxy should be used to provide it.
|
This endpoint does not suport TLS: a reverse proxy should be used to provide it.
|
||||||
|
|
||||||
Alternatively, since `v0.8.5`, a path can be used to create a unix socket with 0222 mode.
|
|
||||||
|
|
||||||
### `s3_region`
|
### `s3_region`
|
||||||
|
|
||||||
Garage will accept S3 API calls that are targetted to the S3 region defined here.
|
Garage will accept S3 API calls that are targetted to the S3 region defined here.
|
||||||
|
@ -441,8 +439,6 @@ The IP and port on which to bind for accepting HTTP requests to buckets configur
|
||||||
for website access.
|
for website access.
|
||||||
This endpoint does not suport TLS: a reverse proxy should be used to provide it.
|
This endpoint does not suport TLS: a reverse proxy should be used to provide it.
|
||||||
|
|
||||||
Alternatively, since `v0.8.5`, a path can be used to create a unix socket with 0222 mode.
|
|
||||||
|
|
||||||
### `root_domain`
|
### `root_domain`
|
||||||
|
|
||||||
The optional suffix appended to bucket names for the corresponding HTTP Host.
|
The optional suffix appended to bucket names for the corresponding HTTP Host.
|
||||||
|
@ -462,9 +458,6 @@ If specified, Garage will bind an HTTP server to this port and address, on
|
||||||
which it will listen to requests for administration features.
|
which it will listen to requests for administration features.
|
||||||
See [administration API reference](@/documentation/reference-manual/admin-api.md) to learn more about these features.
|
See [administration API reference](@/documentation/reference-manual/admin-api.md) to learn more about these features.
|
||||||
|
|
||||||
Alternatively, since `v0.8.5`, a path can be used to create a unix socket. Note that for security reasons,
|
|
||||||
the socket will have 0220 mode. Make sure to set user and group permissions accordingly.
|
|
||||||
|
|
||||||
### `metrics_token`, `metrics_token_file` or `GARAGE_METRICS_TOKEN` (env)
|
### `metrics_token`, `metrics_token_file` or `GARAGE_METRICS_TOKEN` (env)
|
||||||
|
|
||||||
The token for accessing the Metrics endpoint. If this token is not set, the
|
The token for accessing the Metrics endpoint. If this token is not set, the
|
||||||
|
|
|
@ -45,7 +45,6 @@ http = "0.2"
|
||||||
httpdate = "1.0"
|
httpdate = "1.0"
|
||||||
http-range = "0.1"
|
http-range = "0.1"
|
||||||
hyper = { version = "0.14", features = ["server", "http1", "runtime", "tcp", "stream"] }
|
hyper = { version = "0.14", features = ["server", "http1", "runtime", "tcp", "stream"] }
|
||||||
hyperlocal = { version = "0.8.0", default-features = false, features = ["server"] }
|
|
||||||
multer = "2.0"
|
multer = "2.0"
|
||||||
percent-encoding = "2.1.0"
|
percent-encoding = "2.1.0"
|
||||||
roxmltree = "0.18"
|
roxmltree = "0.18"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::net::SocketAddr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
@ -17,7 +18,6 @@ use prometheus::{Encoder, TextEncoder};
|
||||||
use garage_model::garage::Garage;
|
use garage_model::garage::Garage;
|
||||||
use garage_rpc::system::ClusterHealthStatus;
|
use garage_rpc::system::ClusterHealthStatus;
|
||||||
use garage_util::error::Error as GarageError;
|
use garage_util::error::Error as GarageError;
|
||||||
use garage_util::socket_address::UnixOrTCPSocketAddress;
|
|
||||||
|
|
||||||
use crate::generic_server::*;
|
use crate::generic_server::*;
|
||||||
|
|
||||||
|
@ -61,12 +61,12 @@ impl AdminApiServer {
|
||||||
|
|
||||||
pub async fn run(
|
pub async fn run(
|
||||||
self,
|
self,
|
||||||
bind_addr: UnixOrTCPSocketAddress,
|
bind_addr: SocketAddr,
|
||||||
shutdown_signal: impl Future<Output = ()>,
|
shutdown_signal: impl Future<Output = ()>,
|
||||||
) -> Result<(), GarageError> {
|
) -> Result<(), GarageError> {
|
||||||
let region = self.garage.config.s3_api.s3_region.clone();
|
let region = self.garage.config.s3_api.s3_region.clone();
|
||||||
ApiServer::new(region, self)
|
ApiServer::new(region, self)
|
||||||
.run_server(bind_addr, Some(0o220), shutdown_signal)
|
.run_server(bind_addr, shutdown_signal)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use std::fs::{self, Permissions};
|
use std::net::SocketAddr;
|
||||||
use std::os::unix::fs::PermissionsExt;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
@ -12,10 +11,6 @@ use hyper::service::{make_service_fn, service_fn};
|
||||||
use hyper::{Body, Request, Response, Server};
|
use hyper::{Body, Request, Response, Server};
|
||||||
use hyper::{HeaderMap, StatusCode};
|
use hyper::{HeaderMap, StatusCode};
|
||||||
|
|
||||||
use hyperlocal::UnixServerExt;
|
|
||||||
|
|
||||||
use tokio::net::UnixStream;
|
|
||||||
|
|
||||||
use opentelemetry::{
|
use opentelemetry::{
|
||||||
global,
|
global,
|
||||||
metrics::{Counter, ValueRecorder},
|
metrics::{Counter, ValueRecorder},
|
||||||
|
@ -26,7 +21,6 @@ use opentelemetry::{
|
||||||
use garage_util::error::Error as GarageError;
|
use garage_util::error::Error as GarageError;
|
||||||
use garage_util::forwarded_headers;
|
use garage_util::forwarded_headers;
|
||||||
use garage_util::metrics::{gen_trace_id, RecordDuration};
|
use garage_util::metrics::{gen_trace_id, RecordDuration};
|
||||||
use garage_util::socket_address::UnixOrTCPSocketAddress;
|
|
||||||
|
|
||||||
pub(crate) trait ApiEndpoint: Send + Sync + 'static {
|
pub(crate) trait ApiEndpoint: Send + Sync + 'static {
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
|
@ -97,11 +91,10 @@ impl<A: ApiHandler> ApiServer<A> {
|
||||||
|
|
||||||
pub async fn run_server(
|
pub async fn run_server(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
bind_addr: UnixOrTCPSocketAddress,
|
bind_addr: SocketAddr,
|
||||||
unix_bind_addr_mode: Option<u32>,
|
|
||||||
shutdown_signal: impl Future<Output = ()>,
|
shutdown_signal: impl Future<Output = ()>,
|
||||||
) -> Result<(), GarageError> {
|
) -> Result<(), GarageError> {
|
||||||
let tcp_service = make_service_fn(|conn: &AddrStream| {
|
let service = make_service_fn(|conn: &AddrStream| {
|
||||||
let this = self.clone();
|
let this = self.clone();
|
||||||
|
|
||||||
let client_addr = conn.remote_addr();
|
let client_addr = conn.remote_addr();
|
||||||
|
@ -109,63 +102,28 @@ impl<A: ApiHandler> ApiServer<A> {
|
||||||
Ok::<_, GarageError>(service_fn(move |req: Request<Body>| {
|
Ok::<_, GarageError>(service_fn(move |req: Request<Body>| {
|
||||||
let this = this.clone();
|
let this = this.clone();
|
||||||
|
|
||||||
this.handler(req, client_addr.to_string())
|
this.handler(req, client_addr)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let unix_service = make_service_fn(|_: &UnixStream| {
|
let server = Server::bind(&bind_addr).serve(service);
|
||||||
let this = self.clone();
|
|
||||||
|
|
||||||
let path = bind_addr.to_string();
|
|
||||||
async move {
|
|
||||||
Ok::<_, GarageError>(service_fn(move |req: Request<Body>| {
|
|
||||||
let this = this.clone();
|
|
||||||
|
|
||||||
this.handler(req, path.clone())
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
let graceful = server.with_graceful_shutdown(shutdown_signal);
|
||||||
info!(
|
info!(
|
||||||
"{} API server listening on {}",
|
"{} API server listening on http://{}",
|
||||||
A::API_NAME_DISPLAY,
|
A::API_NAME_DISPLAY,
|
||||||
bind_addr
|
bind_addr
|
||||||
);
|
);
|
||||||
|
|
||||||
match bind_addr {
|
graceful.await?;
|
||||||
UnixOrTCPSocketAddress::TCPSocket(addr) => {
|
|
||||||
Server::bind(&addr)
|
|
||||||
.serve(tcp_service)
|
|
||||||
.with_graceful_shutdown(shutdown_signal)
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
UnixOrTCPSocketAddress::UnixSocket(ref path) => {
|
|
||||||
if path.exists() {
|
|
||||||
fs::remove_file(path)?
|
|
||||||
}
|
|
||||||
|
|
||||||
let bound = Server::bind_unix(path)?;
|
|
||||||
|
|
||||||
fs::set_permissions(
|
|
||||||
path,
|
|
||||||
Permissions::from_mode(unix_bind_addr_mode.unwrap_or(0o222)),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
bound
|
|
||||||
.serve(unix_service)
|
|
||||||
.with_graceful_shutdown(shutdown_signal)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handler(
|
async fn handler(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
req: Request<Body>,
|
req: Request<Body>,
|
||||||
addr: String,
|
addr: SocketAddr,
|
||||||
) -> Result<Response<Body>, GarageError> {
|
) -> Result<Response<Body>, GarageError> {
|
||||||
let uri = req.uri().clone();
|
let uri = req.uri().clone();
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::net::SocketAddr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
@ -8,7 +9,6 @@ use hyper::{Body, Method, Request, Response};
|
||||||
use opentelemetry::{trace::SpanRef, KeyValue};
|
use opentelemetry::{trace::SpanRef, KeyValue};
|
||||||
|
|
||||||
use garage_util::error::Error as GarageError;
|
use garage_util::error::Error as GarageError;
|
||||||
use garage_util::socket_address::UnixOrTCPSocketAddress;
|
|
||||||
|
|
||||||
use garage_model::garage::Garage;
|
use garage_model::garage::Garage;
|
||||||
|
|
||||||
|
@ -37,12 +37,12 @@ pub(crate) struct K2VApiEndpoint {
|
||||||
impl K2VApiServer {
|
impl K2VApiServer {
|
||||||
pub async fn run(
|
pub async fn run(
|
||||||
garage: Arc<Garage>,
|
garage: Arc<Garage>,
|
||||||
bind_addr: UnixOrTCPSocketAddress,
|
bind_addr: SocketAddr,
|
||||||
s3_region: String,
|
s3_region: String,
|
||||||
shutdown_signal: impl Future<Output = ()>,
|
shutdown_signal: impl Future<Output = ()>,
|
||||||
) -> Result<(), GarageError> {
|
) -> Result<(), GarageError> {
|
||||||
ApiServer::new(s3_region, K2VApiServer { garage })
|
ApiServer::new(s3_region, K2VApiServer { garage })
|
||||||
.run_server(bind_addr, None, shutdown_signal)
|
.run_server(bind_addr, shutdown_signal)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::net::SocketAddr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
@ -9,7 +10,6 @@ use hyper::{Body, Request, Response};
|
||||||
use opentelemetry::{trace::SpanRef, KeyValue};
|
use opentelemetry::{trace::SpanRef, KeyValue};
|
||||||
|
|
||||||
use garage_util::error::Error as GarageError;
|
use garage_util::error::Error as GarageError;
|
||||||
use garage_util::socket_address::UnixOrTCPSocketAddress;
|
|
||||||
|
|
||||||
use garage_model::garage::Garage;
|
use garage_model::garage::Garage;
|
||||||
use garage_model::key_table::Key;
|
use garage_model::key_table::Key;
|
||||||
|
@ -44,12 +44,12 @@ pub(crate) struct S3ApiEndpoint {
|
||||||
impl S3ApiServer {
|
impl S3ApiServer {
|
||||||
pub async fn run(
|
pub async fn run(
|
||||||
garage: Arc<Garage>,
|
garage: Arc<Garage>,
|
||||||
addr: UnixOrTCPSocketAddress,
|
addr: SocketAddr,
|
||||||
s3_region: String,
|
s3_region: String,
|
||||||
shutdown_signal: impl Future<Output = ()>,
|
shutdown_signal: impl Future<Output = ()>,
|
||||||
) -> Result<(), GarageError> {
|
) -> Result<(), GarageError> {
|
||||||
ApiServer::new(s3_region, S3ApiServer { garage })
|
ApiServer::new(s3_region, S3ApiServer { garage })
|
||||||
.run_server(addr, None, shutdown_signal)
|
.run_server(addr, shutdown_signal)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ pub async fn run_server(config_file: PathBuf, secrets: Secrets) -> Result<(), Er
|
||||||
"S3 API",
|
"S3 API",
|
||||||
tokio::spawn(S3ApiServer::run(
|
tokio::spawn(S3ApiServer::run(
|
||||||
garage.clone(),
|
garage.clone(),
|
||||||
s3_bind_addr.clone(),
|
*s3_bind_addr,
|
||||||
config.s3_api.s3_region.clone(),
|
config.s3_api.s3_region.clone(),
|
||||||
wait_from(watch_cancel.clone()),
|
wait_from(watch_cancel.clone()),
|
||||||
)),
|
)),
|
||||||
|
@ -94,7 +94,7 @@ pub async fn run_server(config_file: PathBuf, secrets: Secrets) -> Result<(), Er
|
||||||
"K2V API",
|
"K2V API",
|
||||||
tokio::spawn(K2VApiServer::run(
|
tokio::spawn(K2VApiServer::run(
|
||||||
garage.clone(),
|
garage.clone(),
|
||||||
config.k2v_api.as_ref().unwrap().api_bind_addr.clone(),
|
config.k2v_api.as_ref().unwrap().api_bind_addr,
|
||||||
config.s3_api.s3_region.clone(),
|
config.s3_api.s3_region.clone(),
|
||||||
wait_from(watch_cancel.clone()),
|
wait_from(watch_cancel.clone()),
|
||||||
)),
|
)),
|
||||||
|
@ -110,7 +110,7 @@ pub async fn run_server(config_file: PathBuf, secrets: Secrets) -> Result<(), Er
|
||||||
"Web",
|
"Web",
|
||||||
tokio::spawn(WebServer::run(
|
tokio::spawn(WebServer::run(
|
||||||
garage.clone(),
|
garage.clone(),
|
||||||
web_config.bind_addr.clone(),
|
web_config.bind_addr,
|
||||||
web_config.root_domain.clone(),
|
web_config.root_domain.clone(),
|
||||||
wait_from(watch_cancel.clone()),
|
wait_from(watch_cancel.clone()),
|
||||||
)),
|
)),
|
||||||
|
@ -121,9 +121,7 @@ pub async fn run_server(config_file: PathBuf, secrets: Secrets) -> Result<(), Er
|
||||||
info!("Launching Admin API server...");
|
info!("Launching Admin API server...");
|
||||||
servers.push((
|
servers.push((
|
||||||
"Admin",
|
"Admin",
|
||||||
tokio::spawn(
|
tokio::spawn(admin_server.run(*admin_bind_addr, wait_from(watch_cancel.clone()))),
|
||||||
admin_server.run(admin_bind_addr.clone(), wait_from(watch_cancel.clone())),
|
|
||||||
),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ use std::path::PathBuf;
|
||||||
use serde::{de, Deserialize};
|
use serde::{de, Deserialize};
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::socket_address::UnixOrTCPSocketAddress;
|
|
||||||
|
|
||||||
/// Represent the whole configuration
|
/// Represent the whole configuration
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
|
@ -103,7 +102,7 @@ pub struct Config {
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
pub struct S3ApiConfig {
|
pub struct S3ApiConfig {
|
||||||
/// Address and port to bind for api serving
|
/// Address and port to bind for api serving
|
||||||
pub api_bind_addr: Option<UnixOrTCPSocketAddress>,
|
pub api_bind_addr: Option<SocketAddr>,
|
||||||
/// S3 region to use
|
/// S3 region to use
|
||||||
pub s3_region: String,
|
pub s3_region: String,
|
||||||
/// Suffix to remove from domain name to find bucket. If None,
|
/// Suffix to remove from domain name to find bucket. If None,
|
||||||
|
@ -115,14 +114,14 @@ pub struct S3ApiConfig {
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
pub struct K2VApiConfig {
|
pub struct K2VApiConfig {
|
||||||
/// Address and port to bind for api serving
|
/// Address and port to bind for api serving
|
||||||
pub api_bind_addr: UnixOrTCPSocketAddress,
|
pub api_bind_addr: SocketAddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration for serving files as normal web server
|
/// Configuration for serving files as normal web server
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
pub struct WebConfig {
|
pub struct WebConfig {
|
||||||
/// Address and port to bind for web serving
|
/// Address and port to bind for web serving
|
||||||
pub bind_addr: UnixOrTCPSocketAddress,
|
pub bind_addr: SocketAddr,
|
||||||
/// Suffix to remove from domain name to find bucket
|
/// Suffix to remove from domain name to find bucket
|
||||||
pub root_domain: String,
|
pub root_domain: String,
|
||||||
}
|
}
|
||||||
|
@ -131,7 +130,7 @@ pub struct WebConfig {
|
||||||
#[derive(Deserialize, Debug, Clone, Default)]
|
#[derive(Deserialize, Debug, Clone, Default)]
|
||||||
pub struct AdminConfig {
|
pub struct AdminConfig {
|
||||||
/// Address and port to bind for admin API serving
|
/// Address and port to bind for admin API serving
|
||||||
pub api_bind_addr: Option<UnixOrTCPSocketAddress>,
|
pub api_bind_addr: Option<SocketAddr>,
|
||||||
|
|
||||||
/// Bearer token to use to scrape metrics
|
/// Bearer token to use to scrape metrics
|
||||||
pub metrics_token: Option<String>,
|
pub metrics_token: Option<String>,
|
||||||
|
|
|
@ -14,7 +14,6 @@ pub mod forwarded_headers;
|
||||||
pub mod metrics;
|
pub mod metrics;
|
||||||
pub mod migrate;
|
pub mod migrate;
|
||||||
pub mod persister;
|
pub mod persister;
|
||||||
pub mod socket_address;
|
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod tranquilizer;
|
pub mod tranquilizer;
|
||||||
pub mod version;
|
pub mod version;
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
use serde::de::Error;
|
|
||||||
use serde::{Deserialize, Deserializer};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum UnixOrTCPSocketAddress {
|
|
||||||
TCPSocket(SocketAddr),
|
|
||||||
UnixSocket(PathBuf),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for UnixOrTCPSocketAddress {
|
|
||||||
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
UnixOrTCPSocketAddress::TCPSocket(address) => write!(formatter, "http://{}", address),
|
|
||||||
UnixOrTCPSocketAddress::UnixSocket(path) => {
|
|
||||||
write!(formatter, "http+unix://{}", path.to_string_lossy())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for UnixOrTCPSocketAddress {
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let string = String::deserialize(deserializer)?;
|
|
||||||
let string = string.as_str();
|
|
||||||
|
|
||||||
if string.starts_with("/") {
|
|
||||||
Ok(UnixOrTCPSocketAddress::UnixSocket(
|
|
||||||
PathBuf::from_str(string).map_err(Error::custom)?,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Ok(UnixOrTCPSocketAddress::TCPSocket(
|
|
||||||
SocketAddr::from_str(string).map_err(Error::custom)?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -27,8 +27,5 @@ futures = "0.3"
|
||||||
|
|
||||||
http = "0.2"
|
http = "0.2"
|
||||||
hyper = { version = "0.14", features = ["server", "http1", "runtime", "tcp", "stream"] }
|
hyper = { version = "0.14", features = ["server", "http1", "runtime", "tcp", "stream"] }
|
||||||
hyperlocal = { version = "0.8.0", default-features = false, features = ["server"] }
|
|
||||||
|
|
||||||
tokio = { version = "1.0", default-features = false, features = ["net"] }
|
|
||||||
|
|
||||||
opentelemetry = "0.17"
|
opentelemetry = "0.17"
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
use std::fs::{self, Permissions};
|
use std::{convert::Infallible, net::SocketAddr, sync::Arc};
|
||||||
use std::os::unix::prelude::PermissionsExt;
|
|
||||||
use std::{convert::Infallible, sync::Arc};
|
|
||||||
|
|
||||||
use futures::future::Future;
|
use futures::future::Future;
|
||||||
|
|
||||||
|
@ -11,10 +9,6 @@ use hyper::{
|
||||||
Body, Method, Request, Response, Server, StatusCode,
|
Body, Method, Request, Response, Server, StatusCode,
|
||||||
};
|
};
|
||||||
|
|
||||||
use hyperlocal::UnixServerExt;
|
|
||||||
|
|
||||||
use tokio::net::UnixStream;
|
|
||||||
|
|
||||||
use opentelemetry::{
|
use opentelemetry::{
|
||||||
global,
|
global,
|
||||||
metrics::{Counter, ValueRecorder},
|
metrics::{Counter, ValueRecorder},
|
||||||
|
@ -38,7 +32,6 @@ use garage_util::data::Uuid;
|
||||||
use garage_util::error::Error as GarageError;
|
use garage_util::error::Error as GarageError;
|
||||||
use garage_util::forwarded_headers;
|
use garage_util::forwarded_headers;
|
||||||
use garage_util::metrics::{gen_trace_id, RecordDuration};
|
use garage_util::metrics::{gen_trace_id, RecordDuration};
|
||||||
use garage_util::socket_address::UnixOrTCPSocketAddress;
|
|
||||||
|
|
||||||
struct WebMetrics {
|
struct WebMetrics {
|
||||||
request_counter: Counter<u64>,
|
request_counter: Counter<u64>,
|
||||||
|
@ -76,7 +69,7 @@ impl WebServer {
|
||||||
/// Run a web server
|
/// Run a web server
|
||||||
pub async fn run(
|
pub async fn run(
|
||||||
garage: Arc<Garage>,
|
garage: Arc<Garage>,
|
||||||
addr: UnixOrTCPSocketAddress,
|
addr: SocketAddr,
|
||||||
root_domain: String,
|
root_domain: String,
|
||||||
shutdown_signal: impl Future<Output = ()>,
|
shutdown_signal: impl Future<Output = ()>,
|
||||||
) -> Result<(), GarageError> {
|
) -> Result<(), GarageError> {
|
||||||
|
@ -87,7 +80,7 @@ impl WebServer {
|
||||||
root_domain,
|
root_domain,
|
||||||
});
|
});
|
||||||
|
|
||||||
let tcp_service = make_service_fn(|conn: &AddrStream| {
|
let service = make_service_fn(|conn: &AddrStream| {
|
||||||
let web_server = web_server.clone();
|
let web_server = web_server.clone();
|
||||||
|
|
||||||
let client_addr = conn.remote_addr();
|
let client_addr = conn.remote_addr();
|
||||||
|
@ -95,56 +88,23 @@ impl WebServer {
|
||||||
Ok::<_, Error>(service_fn(move |req: Request<Body>| {
|
Ok::<_, Error>(service_fn(move |req: Request<Body>| {
|
||||||
let web_server = web_server.clone();
|
let web_server = web_server.clone();
|
||||||
|
|
||||||
web_server.handle_request(req, client_addr.to_string())
|
web_server.handle_request(req, client_addr)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let unix_service = make_service_fn(|_: &UnixStream| {
|
let server = Server::bind(&addr).serve(service);
|
||||||
let web_server = web_server.clone();
|
let graceful = server.with_graceful_shutdown(shutdown_signal);
|
||||||
|
info!("Web server listening on http://{}", addr);
|
||||||
let path = addr.to_string();
|
|
||||||
async move {
|
|
||||||
Ok::<_, Error>(service_fn(move |req: Request<Body>| {
|
|
||||||
let web_server = web_server.clone();
|
|
||||||
|
|
||||||
web_server.handle_request(req, path.clone())
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
info!("Web server listening on {}", addr);
|
|
||||||
|
|
||||||
match addr {
|
|
||||||
UnixOrTCPSocketAddress::TCPSocket(addr) => {
|
|
||||||
Server::bind(&addr)
|
|
||||||
.serve(tcp_service)
|
|
||||||
.with_graceful_shutdown(shutdown_signal)
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
UnixOrTCPSocketAddress::UnixSocket(ref path) => {
|
|
||||||
if path.exists() {
|
|
||||||
fs::remove_file(path)?
|
|
||||||
}
|
|
||||||
|
|
||||||
let bound = Server::bind_unix(path)?;
|
|
||||||
|
|
||||||
fs::set_permissions(path, Permissions::from_mode(0o222))?;
|
|
||||||
|
|
||||||
bound
|
|
||||||
.serve(unix_service)
|
|
||||||
.with_graceful_shutdown(shutdown_signal)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
graceful.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_request(
|
async fn handle_request(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
req: Request<Body>,
|
req: Request<Body>,
|
||||||
addr: String,
|
addr: SocketAddr,
|
||||||
) -> Result<Response<Body>, Infallible> {
|
) -> Result<Response<Body>, Infallible> {
|
||||||
if let Ok(forwarded_for_ip_addr) =
|
if let Ok(forwarded_for_ip_addr) =
|
||||||
forwarded_headers::handle_forwarded_for_headers(req.headers())
|
forwarded_headers::handle_forwarded_for_headers(req.headers())
|
||||||
|
|
Loading…
Add table
Reference in a new issue