Skip to main content

Consul

Struct Consul 

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

A key in Consul’s KV store, as a configuration source.

Not Clone: the session holds the current token, and two clones logging in separately would double the login traffic. Wrap it in an Arc if two places need one.

Implementations§

Source§

impl Consul

Source

pub fn new(address: impl Into<String>, keys: impl Into<Keys>) -> Self

The key keys, served by the Consul agent at address.

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

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

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 with_token(self, token: impl Into<String>) -> Self

The ACL token to authenticate with.

Shorthand for with_auth(Auth::token(..)). A token that stops working cannot be replaced, because there are no credentials here to log in again with; Auth::kubernetes and Auth::jwt can.

Source

pub fn with_auth(self, auth: Auth) -> Self

How to obtain an ACL token.

// In Kubernetes, with no secret to distribute at all.
let consul = Consul::new("http://consul:8500", "myapp/db.json")
    .with_auth(Auth::kubernetes("kubernetes"));

// Or whatever the operator put in the environment.
let consul = Consul::new("http://consul:8500", "myapp/db.json")
    .with_auth(Auth::from_environment());

Logging in is lazy: this reaches nothing, and the first read does it.

Source

pub fn with_agent(self, agent: Agent) -> Self

Uses an HTTP client the program already has.

For a caller with its own proxy settings, a private CA, a client certificate, or a connection pool it would rather not have a second copy of. The agent’s own timeout applies instead of with_timeout — including for the long blocking query watch issues, so an agent used for watching needs a timeout above with_wait.

The escape hatch, and it stays one: with_tls covers a private CA and a client certificate, and everything else — a proxy, a connection pool, an option this crate has never heard of — still lives here. Setting both is refused rather than resolved; see with_tls.

Source

pub fn with_tls(self, tls: TlsConfig) -> Self

A private certificate authority, a client certificate, or both.

The same three settings, spelled the same way, in all seven store crates — and spelled as data, so nothing here names a ureq type:

let consul = Consul::new("https://consul.internal:8501", "myapp/db.json")
    .with_tls(
        TlsConfig::new()
            .with_ca_certificate_file("/etc/consul.d/consul-agent-ca.pem")
            .with_client_certificate_files(
                "/etc/consul.d/client.crt",
                "/etc/consul.d/client.key",
            ),
    );

Consul expresses all of it: a CA from a file or from bytes, and a client certificate from either. A CA replaces the platform trust store rather than adding to it — naming a private authority is saying the public ones do not apply to this host — so a deployment that needs both puts both in the file. Consul’s own agent CA is exactly this case: consul tls ca create mints an authority no public store has heard of.

There is no way to turn verification off; TlsConfig’s own documentation argues that one.

Nothing is read here. The files are opened when a request builds its client, so a missing CA is an error naming the path rather than a panic in a builder chain.

§With with_agent

Setting both is refused, at the first request, naming both calls. An agent already carries a complete TLS configuration, so “apply this too” has no meaning that is not a guess — and the guess that loses silently discards a CA, which is the failure this whole surface exists to prevent. Put the CA on the agent, or drop the agent.

Source

pub fn with_datacenter(self, datacenter: impl Into<String>) -> Self

The datacenter to read from, when it is not the agent’s own.

Source

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

How long a single fetch may take before it is given up on. Ten seconds by default.

The deadline for one fetch attempt, excluding retries the underlying client performs — the same sentence every store in this family answers to. ureq performs none of its own, so here the deadline is the whole story.

The blocking query watch issues is the exception, and deliberately so: it is one fetch that is meant to be held open, so its client-side timeout is sized from with_wait plus this value plus the jitter Consul adds.

Source

pub fn with_wait(self, wait: Duration) -> Self

How long a blocking query may hold the connection open, when watch is used. One minute by default.

This is also how long a stopped watch can take to notice, so it trades one against the other: longer means fewer requests, and a slower exit. Consul’s own ceiling is ten minutes, so anything above it is clamped there — the agent would cap it silently anyway, and this way the client-side timeout stays sized to what the agent will actually do.

Source

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

Reports the watch loop’s failed attempts to sink.

A watch loop is the half of a store dynamic-config cannot otherwise see. RemoteSink::apply records a delivery, so a working watch keeps RemoteStatus current — but a loop whose blocking query is erroring, whose key was deleted or whose ACL token was refused delivers nothing, and without this says nothing: dynamic_config_remote_up would report the last delivery rather than the last attempt, and an agent that stopped answering an hour ago would look healthy until something called refresh_remote.

let sink = DbConfig::remote_sink();

Consul::new(address, "myapp/db.json")
    .reporting_to(sink)
    .watch(&watching, move |document| sink.apply(document))

One sink serves both halves, and it is taken once, where the loop is wired: a sink is Copy, and the generation it captures there is what fences a loop winding down after its source was replaced from charging its failures to the replacement.

A failure to report a failure never reaches the loop — reporting is infallible and silent — and what it moves is deliberately narrow: the failure streak and the last failure, never the fetch clock. So dynamic_config_remote_last_fetch_seconds keeps ageing while dynamic_config_remote_up goes to zero, which is the pair that says both the store is not answering and how stale what it last said has become.

A fetch needs none of this: a fetch records itself, through the Remote that performed it.

Source

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

Calls on_change whenever what this source reads changes.

Uses Consul’s blocking queries: each request carries the index the last one returned, and the agent holds it open until that index moves or with_wait expires. So this is change-driven, not a poll — the callback runs when the value actually moves.

One key or a prefix. A prefix watch is the cheapest correct watch on a set anywhere in this family, because it needs no re-read at all: a recursive blocking query’s answer is the subtree at one index, so the document handed to on_change is folded from the very bytes the agent blocked to send. There is no window between “the set changed” and “read the set” for a second write to land in. A named list is refused; the reason is on Keys::Several.

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, which it usually does:

sink.apply(consul.fetch()?)?;
consul.watch(&watching, move |document| sink.apply(document))

A failed query does not end the watch: the agent restarting, a network blip, or a key that does not exist yet are all exactly what a watch is supposed to survive. It pauses briefly and tries again, and gives up only when watching says to. A document identical to the last one is not reported — Consul bumps the index on every write, including one that changed nothing.

Surviving a failure quietly is not the same as hiding it: reporting_to hands each failed attempt to a RemoteSink, so a loop that has been erroring for an hour stops reporting the store as healthy.

§Errors

If on_change returns an error, which ends the watch — so a caller that wants to survive a bad document should log it and return Ok. Transport failures do not surface here; they are retried.

Under a prefix, also if the subtree cannot be folded into a document: two keys supplying the same path, a key the agent answered with that is not under the prefix, or more keys than the budget. None of those is a blip a retry cures, and retrying them forever with nothing said would leave the configuration frozen and silent — the failure this crate’s watch loops are shaped to avoid.

Trait Implementations§

Source§

impl Debug for Consul

Source§

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

Formats the value using the given formatter. Read more
Source§

impl RemoteSource for Consul

Source§

fn fetch(&self) -> Result<Fetched, Error>

Reads the current document. Read more
Source§

fn describe(&self) -> String

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

Auto Trait Implementations§

§

impl !Freeze for Consul

§

impl !RefUnwindSafe for Consul

§

impl !UnwindSafe for Consul

§

impl Send for Consul

§

impl Sync for Consul

§

impl Unpin for Consul

§

impl UnsafeUnpin for Consul

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> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> 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, 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.