pub struct HetznerDriver { /* private fields */ }Expand description
Hetzner Cloud + Object Storage driver for Phase-1 mirror bootstrap.
Cloud operations (server lifecycle) use HETZNER_API_TOKEN.
Bucket operations use the Hetzner Object Storage S3-compat API
(HETZNER_S3_ACCESS_KEY + HETZNER_S3_SECRET_KEY).
Run yah cloud secrets for the canonical contract (vault slots + env).
Implementations§
Source§impl HetznerDriver
impl HetznerDriver
Sourcepub fn new(token: impl Into<String>) -> Self
pub fn new(token: impl Into<String>) -> Self
Build with a Cloud API token only. Bucket operations will fail until
S3 credentials are added via [with_storage].
Sourcepub fn with_storage(
self,
access_key: impl Into<String>,
secret_key: impl Into<String>,
) -> Self
pub fn with_storage( self, access_key: impl Into<String>, secret_key: impl Into<String>, ) -> Self
Attach Hetzner Object Storage S3 credentials.
Sourcepub fn with_s3_endpoint(self, endpoint: impl Into<String>) -> Self
pub fn with_s3_endpoint(self, endpoint: impl Into<String>) -> Self
Override the S3 base endpoint (e.g. "http://localhost:9000" for MinIO in tests).
Sourcepub fn from_env() -> Result<Self>
pub fn from_env() -> Result<Self>
Build from environment variables.
Required: HETZNER_API_TOKEN.
Optional: HETZNER_S3_ACCESS_KEY + HETZNER_S3_SECRET_KEY (needed for create_bucket).
Sourcepub fn from_default_sources() -> Result<Self>
pub fn from_default_sources() -> Result<Self>
Build from the shared keys vault first, then fall back to env vars.
Slot ↔ env mapping:
hetzner-api-token↔HETZNER_API_TOKEN(required)hetzner-s3-access-key↔HETZNER_S3_ACCESS_KEY(optional pair)hetzner-s3-secret-key↔HETZNER_S3_SECRET_KEY(optional pair)
The vault path is the production-default for yah callers; env is
kept as a fallback so CI / one-shot scripts (and hosts that don’t
have a vault yet) keep working. The two are checked per-key, so a
vault-stored API token combined with env-supplied S3 creds is fine.
Vault open errors (missing machine.key, etc.) are swallowed — they
just mean “no vault here, try env.”
Trait Implementations§
Source§impl Clone for HetznerDriver
impl Clone for HetznerDriver
Source§impl MachineProvider for HetznerDriver
impl MachineProvider for HetznerDriver
Source§fn ensure_project<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<ProjectId>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn ensure_project<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<ProjectId>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn create_server<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_project: &'life1 ProjectId,
spec: &'life2 ServerSpec,
user_data: &'life3 str,
) -> Pin<Box<dyn Future<Output = Result<ServerId>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn create_server<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_project: &'life1 ProjectId,
spec: &'life2 ServerSpec,
user_data: &'life3 str,
) -> Pin<Box<dyn Future<Output = Result<ServerId>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
user_data string.Source§fn server_status<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 ServerId,
) -> Pin<Box<dyn Future<Output = Result<ServerStatus>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn server_status<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 ServerId,
) -> Pin<Box<dyn Future<Output = Result<ServerStatus>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn find_server_by_name<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<ServerSummary>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn find_server_by_name<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<ServerSummary>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Ok(None) means the API
responded but no server with that name exists; Err(_) means the
API call itself failed.Source§fn bucket_exists<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
location: Location,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn bucket_exists<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
location: Location,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
location. Ok(true) = HEAD 200,
Ok(false) = HEAD 404. Auth failures (403) propagate as Err so
the caller can distinguish “missing” from “can’t tell”.Source§fn destroy_server<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 ServerId,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn destroy_server<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 ServerId,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Ok(()) if already deleted.Source§fn delete_bucket<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
location: Location,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn delete_bucket<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
location: Location,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Ok(()) if the bucket was already gone (404
on the final DELETE). Auth/transport failures propagate as Err.Source§fn create_bucket<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
location: Location,
) -> Pin<Box<dyn Future<Output = Result<BucketRef>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn create_bucket<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
location: Location,
) -> Pin<Box<dyn Future<Output = Result<BucketRef>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn set_bucket_acl<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
location: Location,
acl: BucketAcl,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn set_bucket_acl<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
location: Location,
acl: BucketAcl,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
PUT /<bucket>?acl. Read moreAuto Trait Implementations§
impl !RefUnwindSafe for HetznerDriver
impl !UnwindSafe for HetznerDriver
impl Freeze for HetznerDriver
impl Send for HetznerDriver
impl Sync for HetznerDriver
impl Unpin for HetznerDriver
impl UnsafeUnpin for HetznerDriver
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<T> ErasedDestructor for Twhere
T: 'static,
impl<T> Fruit for T
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more