Skip to main content

S3

Struct S3 

Source
pub struct S3 { /* private fields */ }
Expand description

An object in S3, as a configuration source.

Implementations§

Source§

impl S3

Source

pub async fn new( bucket: impl Into<String>, key: impl Into<Keys>, ) -> Result<Self, Error>

The object key in bucket, with credentials from the environment.

key is a key — "prod/db.json" — or a Keys, for the several-objects and prefix forms.

The format is taken from the key’s extension — prod/db.json is JSON. A key without one, and every prefix, needs with_format.

This resolves credentials, which may read a file or call the instance metadata service — the one constructor in this family that does I/O, because the credential chain is what it is.

Source

pub fn with_config( config: &SdkConfig, bucket: impl Into<String>, key: impl Into<Keys>, ) -> Self

Uses an SdkConfig the program already built.

For a caller that already talks to AWS, and for anything that is not AWS: MinIO, Ceph, R2 and B2 all speak this API, and all of them need an endpoint override the environment cannot express.

let config = aws_config::from_env()
    .endpoint_url("http://minio.internal:9000")
    .load()
    .await;

let s3 = S3::with_config(&config, "myapp-config", "prod/db.json");
Source

pub fn with_tls( config: &SdkConfig, bucket: impl Into<String>, key: impl Into<Keys>, tls: &TlsConfig, ) -> Result<Self, Error>

As with_config, with a private certificate authority.

The same vocabulary as the other six store crates, spelled as data — nothing here names an SDK or a rustls type:

let config = aws_config::from_env()
    .endpoint_url("https://minio.internal:9000")
    .load()
    .await;

let s3 = S3::with_tls(
    &config,
    "myapp-config",
    "prod/db.json",
    &TlsConfig::new().with_ca_certificate_file("/etc/ssl/private-ca.pem"),
)?;

This is for the S3-compatible servers, which is where a private authority actually turns up: MinIO, Ceph and a company’s own gateway all present certificates AWS’ public chain has never heard of.

§What S3 cannot express

A client certificate. The SDK reaches TLS through aws-smithy-http-client, whose TlsContext has a trust store and nothing else — there is no client-certificate slot to fill, at any version this crate can depend on. So with_client_certificate_files and with_client_certificate_pem are refused here, naming the call and pointing at from_client — not ignored, because a caller who asked to present a certificate and did not would discover it as an authentication failure a long way from the cause.

A caller who needs mTLS to an S3-compatible server builds the connector themselves and hands over the finished Client. That is what the escape hatch is for, and it is untouched.

The CA replaces the platform trust store rather than adding to it, which is what naming a private authority means. A deployment that needs both puts both in the file.

There is no way to turn verification off; TlsConfig’s own documentation argues that one, and the SDK’s TLS context offers no such switch to forward even if this crate wanted to.

§Errors

If the configuration names a client certificate, if a PEM file cannot be read, or if the TLS context will not build.

Source

pub fn from_client( client: Client, bucket: impl Into<String>, key: impl Into<Keys>, ) -> Self

Uses a client the program already has.

The escape hatch, and it stays one: a connector this crate has no spelling for — mTLS, a proxy, a DNS resolver — is built here and handed over finished.

Source

pub fn with_format(self, format: Format) -> Self

States the format, for a key whose name does not.

Required for Keys::Prefix — a prefix has no extension — and it also settles a list whose keys name two different formats.

Source

pub fn reporting_to(self, sink: RemoteSink) -> Self

Reports this source’s watch failures to sink.

A poll loop is the half of a store dynamic-config cannot see. A delivery keeps RemoteStatus current because RemoteSink::apply records one — but a poll that keeps failing delivers nothing and would otherwise say nothing: an expired credential, a bucket policy that changed under the process, a gateway that went away. dynamic_config_remote_up would report the last delivery rather than the last attempt, and a bucket that stopped answering an hour ago would look healthy until something called refresh_remote_async().

// Taken once, where the loop is wired: a sink captures the generation
// of the source installed at that moment, which is what stops a loop
// winding down from charging its failures to its replacement.
let sink = DbConfig::remote_sink();

let watcher = S3::new("myapp-config", "prod/db.json").await?.reporting_to(sink);

A failure moves the failure streak and nothing else. The fetch count and the clock are left alone, so dynamic_config_remote_last_fetch_seconds keeps ageing while dynamic_config_remote_up goes to zero — the pair an alert wants. Only the failure’s kind and key path are recorded; a bucket, an endpoint and a key never reach a RemoteStatus.

It changes nothing about what watch returns, and nothing about fetch, which already records itself through refresh_remote_async().

Source

pub fn with_timeout(self, timeout: Duration) -> Self

How long a single fetch attempt may take before it is given up on.

The deadline for one attempt, excluding retries the underlying client performs — the sentence every store in this family answers to, and the one place in the family where the exclusion is not a technicality.

The AWS SDK retries on its own. So this maps onto operation_attempt_timeout, which is per attempt, and a fetch can take this multiplied by the attempt count — three, by default. That is documented rather than tuned away: the SDK’s retry policy is a deployment’s decision, and silently disabling it here would be this crate overruling it. Set operation_timeout on the SdkConfig for a ceiling on the whole call, or a retry policy for a different multiplier.

The SDK has no timeout set at all by default, so this is additive: nothing that worked before starts failing, and a fetch that used to hang now stops.

Source

pub async fn watch<F>( &self, watching: &Watching, interval: Duration, on_change: F, ) -> Result<(), Error>
where F: FnMut(Fetched) -> Result<(), Error> + Send,

Calls on_change when the object’s ETag moves, checking every interval.

Polling, because S3 offers nothing better without a notification pipeline — and ETag polling, because downloading an object every thirty seconds to discover it has not changed is a poor thing to do to a bucket that charges per gigabyte. Each tick is a HEAD; only a new ETag costs a GET.

The current value is not delivered at startup, for the same reason a file watcher does not report an edit when it starts. Fetch first if the starting value matters.

A failed check does not end the watch — an expired credential, a network blip, a bucket briefly unreachable — it waits out the interval and tries again. stop is noticed within a quarter second whatever interval is.

§What a failing loop reports

Nothing, unless reporting_to was given a sink. With one, both failures inside the loop are reported to the RemoteStatus as they happen: a HEAD that did not answer, and a GET that did not answer after the ETag moved. Surviving a failure is exactly what makes this necessary — a loop that retries forever is a loop that reports nothing forever, and a poll silently failing since Tuesday is indistinguishable from a configuration nobody has changed.

The refusals at the door — no format, several keys — are not reported: they are returned to the caller by this very call, before there is a loop to be silent in, and they are deployment mistakes rather than a store that stopped answering.

§Errors

If the key names no format and none was stated — a watch that cannot parse what it fetches would poll forever and deliver nothing, so it refuses at the start instead. If the source reads several keys: an ETag belongs to an object, and a set of objects has none. Or if on_change returns an error, which ends the watch. Transport failures do not surface here; they are retried.

Trait Implementations§

Source§

impl AsyncRemoteSource for S3

Source§

fn fetch( &self, ) -> Pin<Box<dyn Future<Output = Result<Fetched, Error>> + Send + '_>>

Reads the current document. Read more
Source§

fn describe(&self) -> String

How to name this source in an error or a report.
Source§

impl Debug for S3

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for S3

§

impl !UnwindSafe for S3

§

impl Freeze for S3

§

impl Send for S3

§

impl Sync for S3

§

impl Unpin for S3

§

impl UnsafeUnpin for S3

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

Source§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
Source§

impl<T> MaybeSendSync for T

Source§

impl<T> Paint for T
where T: ?Sized,

Source§

fn fg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the foreground set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like red() and green(), which have the same functionality but are pithier.

§Example

Set foreground color to white using fg():

use yansi::{Paint, Color};

painted.fg(Color::White);

Set foreground color to white using white().

use yansi::Paint;

painted.white();
Source§

fn primary(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Primary].

§Example
println!("{}", value.primary());
Source§

fn fixed(&self, color: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Fixed].

§Example
println!("{}", value.fixed(color));
Source§

fn rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Rgb].

§Example
println!("{}", value.rgb(r, g, b));
Source§

fn black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Black].

§Example
println!("{}", value.black());
Source§

fn red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Red].

§Example
println!("{}", value.red());
Source§

fn green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Green].

§Example
println!("{}", value.green());
Source§

fn yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Yellow].

§Example
println!("{}", value.yellow());
Source§

fn blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Blue].

§Example
println!("{}", value.blue());
Source§

fn magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Magenta].

§Example
println!("{}", value.magenta());
Source§

fn cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Cyan].

§Example
println!("{}", value.cyan());
Source§

fn white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: White].

§Example
println!("{}", value.white());
Source§

fn bright_black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlack].

§Example
println!("{}", value.bright_black());
Source§

fn bright_red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightRed].

§Example
println!("{}", value.bright_red());
Source§

fn bright_green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightGreen].

§Example
println!("{}", value.bright_green());
Source§

fn bright_yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightYellow].

§Example
println!("{}", value.bright_yellow());
Source§

fn bright_blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlue].

§Example
println!("{}", value.bright_blue());
Source§

fn bright_magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.bright_magenta());
Source§

fn bright_cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightCyan].

§Example
println!("{}", value.bright_cyan());
Source§

fn bright_white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightWhite].

§Example
println!("{}", value.bright_white());
Source§

fn bg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the background set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like on_red() and on_green(), which have the same functionality but are pithier.

§Example

Set background color to red using fg():

use yansi::{Paint, Color};

painted.bg(Color::Red);

Set background color to red using on_red().

use yansi::Paint;

painted.on_red();
Source§

fn on_primary(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Primary].

§Example
println!("{}", value.on_primary());
Source§

fn on_fixed(&self, color: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Fixed].

§Example
println!("{}", value.on_fixed(color));
Source§

fn on_rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Rgb].

§Example
println!("{}", value.on_rgb(r, g, b));
Source§

fn on_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Black].

§Example
println!("{}", value.on_black());
Source§

fn on_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Red].

§Example
println!("{}", value.on_red());
Source§

fn on_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Green].

§Example
println!("{}", value.on_green());
Source§

fn on_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Yellow].

§Example
println!("{}", value.on_yellow());
Source§

fn on_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Blue].

§Example
println!("{}", value.on_blue());
Source§

fn on_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Magenta].

§Example
println!("{}", value.on_magenta());
Source§

fn on_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Cyan].

§Example
println!("{}", value.on_cyan());
Source§

fn on_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: White].

§Example
println!("{}", value.on_white());
Source§

fn on_bright_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlack].

§Example
println!("{}", value.on_bright_black());
Source§

fn on_bright_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightRed].

§Example
println!("{}", value.on_bright_red());
Source§

fn on_bright_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightGreen].

§Example
println!("{}", value.on_bright_green());
Source§

fn on_bright_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightYellow].

§Example
println!("{}", value.on_bright_yellow());
Source§

fn on_bright_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlue].

§Example
println!("{}", value.on_bright_blue());
Source§

fn on_bright_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.on_bright_magenta());
Source§

fn on_bright_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightCyan].

§Example
println!("{}", value.on_bright_cyan());
Source§

fn on_bright_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightWhite].

§Example
println!("{}", value.on_bright_white());
Source§

fn attr(&self, value: Attribute) -> Painted<&T>

Enables the styling Attribute value.

This method should be used rarely. Instead, prefer to use attribute-specific builder methods like bold() and underline(), which have the same functionality but are pithier.

§Example

Make text bold using attr():

use yansi::{Paint, Attribute};

painted.attr(Attribute::Bold);

Make text bold using using bold().

use yansi::Paint;

painted.bold();
Source§

fn bold(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Bold].

§Example
println!("{}", value.bold());
Source§

fn dim(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Dim].

§Example
println!("{}", value.dim());
Source§

fn italic(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Italic].

§Example
println!("{}", value.italic());
Source§

fn underline(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Underline].

§Example
println!("{}", value.underline());

Returns self with the attr() set to [Attribute :: Blink].

§Example
println!("{}", value.blink());

Returns self with the attr() set to [Attribute :: RapidBlink].

§Example
println!("{}", value.rapid_blink());
Source§

fn invert(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Invert].

§Example
println!("{}", value.invert());
Source§

fn conceal(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Conceal].

§Example
println!("{}", value.conceal());
Source§

fn strike(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Strike].

§Example
println!("{}", value.strike());
Source§

fn quirk(&self, value: Quirk) -> Painted<&T>

Enables the yansi Quirk value.

This method should be used rarely. Instead, prefer to use quirk-specific builder methods like mask() and wrap(), which have the same functionality but are pithier.

§Example

Enable wrapping using .quirk():

use yansi::{Paint, Quirk};

painted.quirk(Quirk::Wrap);

Enable wrapping using wrap().

use yansi::Paint;

painted.wrap();
Source§

fn mask(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Mask].

§Example
println!("{}", value.mask());
Source§

fn wrap(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Wrap].

§Example
println!("{}", value.wrap());
Source§

fn linger(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Linger].

§Example
println!("{}", value.linger());
Source§

fn clear(&self) -> Painted<&T>

👎Deprecated since 1.0.1:

renamed to resetting() due to conflicts with Vec::clear(). The clear() method will be removed in a future release.

Returns self with the quirk() set to [Quirk :: Clear].

§Example
println!("{}", value.clear());
Source§

fn resetting(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Resetting].

§Example
println!("{}", value.resetting());
Source§

fn bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Bright].

§Example
println!("{}", value.bright());
Source§

fn on_bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: OnBright].

§Example
println!("{}", value.on_bright());
Source§

fn whenever(&self, value: Condition) -> Painted<&T>

Conditionally enable styling based on whether the Condition value applies. Replaces any previous condition.

See the crate level docs for more details.

§Example

Enable styling painted only when both stdout and stderr are TTYs:

use yansi::{Paint, Condition};

painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);
Source§

fn new(self) -> Painted<Self>
where Self: Sized,

Create a new Painted with a default Style. Read more
Source§

fn paint<S>(&self, style: S) -> Painted<&Self>
where S: Into<Style>,

Apply a style wholesale to self. Any previous style is replaced. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more