Skip to content

Commit

Permalink
config: add agent timing knobs
Browse files Browse the repository at this point in the history
This adds support for a new config section `agent.timing` to configure
timing-related settings on the agent.
It currently has a single knob `steady_interval_secs` to tweak the refresh
period while in steady state.
  • Loading branch information
lucab committed Feb 10, 2020
1 parent dc3b285 commit a08598b
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 5 deletions.
5 changes: 5 additions & 0 deletions dist/config.d/10-agent.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Configure agent timing.
[agent.timing]

# Pausing interval between updates checks in steady mode, in seconds.
steady_interval_secs = 300
23 changes: 23 additions & 0 deletions src/config/fragments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

use ordered_float::NotNan;
use serde::Deserialize;
use std::num::NonZeroU64;

/// Top-level configuration stanza.
#[derive(Debug, Deserialize, PartialEq, Eq)]
pub(crate) struct ConfigFragment {
/// Agent configuration.
pub(crate) agent: Option<AgentFragment>,
/// Cincinnati client configuration.
pub(crate) cincinnati: Option<CincinnatiFragment>,
/// Agent identity.
Expand All @@ -14,6 +17,21 @@ pub(crate) struct ConfigFragment {
pub(crate) updates: Option<UpdateFragment>,
}

/// Config fragment for agent settings.
#[derive(Debug, Deserialize, PartialEq, Eq)]
pub(crate) struct AgentFragment {
/// Timing settings for the agent.
pub(crate) timing: Option<AgentTiming>,
}

/// Config fragment for agent timing.
#[derive(Debug, Deserialize, PartialEq, Eq)]
pub(crate) struct AgentTiming {
/// Pausing interval between updates checks in steady mode, in seconds (default: 300).
pub(crate) steady_interval_secs: Option<NonZeroU64>,
}

// Config fragment for agent identity.
#[derive(Debug, Deserialize, PartialEq, Eq)]
pub(crate) struct IdentityFragment {
/// Update group for this agent (default: 'default')
Expand Down Expand Up @@ -65,6 +83,11 @@ mod tests {
let cfg: ConfigFragment = toml::from_slice(&content).unwrap();

let expected = ConfigFragment {
agent: Some(AgentFragment {
timing: Some(AgentTiming {
steady_interval_secs: Some(NonZeroU64::new(35).unwrap()),
}),
}),
cincinnati: Some(CincinnatiFragment {
base_url: Some("http://cincinnati.example.com:80/".to_string()),
}),
Expand Down
33 changes: 33 additions & 0 deletions src/config/inputs.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use crate::config::fragments;
use crate::update_agent::DEFAULT_STEADY_INTERVAL_SECS;
use failure::{Fallible, ResultExt};
use log::trace;
use ordered_float::NotNan;
use serde::Serialize;
use std::num::NonZeroU64;

/// Runtime configuration holding environmental inputs.
#[derive(Debug, Serialize)]
pub(crate) struct ConfigInput {
pub(crate) agent: AgentInput,
pub(crate) cincinnati: CincinnatiInput,
pub(crate) updates: UpdateInput,
pub(crate) identity: IdentityInput,
Expand Down Expand Up @@ -46,11 +49,15 @@ impl ConfigInput {

/// Merge multiple fragments into a single configuration.
fn merge_fragments(fragments: Vec<fragments::ConfigFragment>) -> Self {
let mut agents = vec![];
let mut cincinnatis = vec![];
let mut updates = vec![];
let mut identities = vec![];

for snip in fragments {
if let Some(a) = snip.agent {
agents.push(a);
}
if let Some(c) = snip.cincinnati {
cincinnatis.push(c);
}
Expand All @@ -63,13 +70,39 @@ impl ConfigInput {
}

Self {
agent: AgentInput::from_fragments(agents),
cincinnati: CincinnatiInput::from_fragments(cincinnatis),
updates: UpdateInput::from_fragments(updates),
identity: IdentityInput::from_fragments(identities),
}
}
}

/// Config for the agent.
#[derive(Debug, Serialize)]
pub(crate) struct AgentInput {
pub(crate) steady_interval_secs: NonZeroU64,
}

impl AgentInput {
fn from_fragments(fragments: Vec<fragments::AgentFragment>) -> Self {
let mut cfg = Self {
steady_interval_secs: NonZeroU64::new(DEFAULT_STEADY_INTERVAL_SECS)
.expect("non-zero interval"),
};

for snip in fragments {
if let Some(timing) = snip.timing {
if let Some(s) = timing.steady_interval_secs {
cfg.steady_interval_secs = s;
}
}
}

cfg
}
}

#[derive(Clone, Debug, Serialize)]
pub(crate) struct CincinnatiInput {
/// Base URL (template) for the Cincinnati service.
Expand Down
5 changes: 5 additions & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::identity::Identity;
use crate::strategy::UpdateStrategy;
use failure::{Fallible, ResultExt};
use serde::Serialize;
use std::num::NonZeroU64;
use structopt::clap::crate_name;

/// Runtime configuration for the agent.
Expand All @@ -27,6 +28,8 @@ pub(crate) struct Settings {
pub(crate) allow_downgrade: bool,
/// Whether to enable auto-updates logic.
pub(crate) enabled: bool,
/// Agent timing, steady state refresh period.
pub(crate) steady_interval_secs: NonZeroU64,
/// Cincinnati configuration.
pub(crate) cincinnati: Cincinnati,
/// Agent configuration.
Expand All @@ -53,6 +56,7 @@ impl Settings {
fn validate(cfg: inputs::ConfigInput) -> Fallible<Self> {
let allow_downgrade = cfg.updates.allow_downgrade;
let enabled = cfg.updates.enabled;
let steady_interval_secs = cfg.agent.steady_interval_secs;
let identity = Identity::with_config(cfg.identity)
.context("failed to validate agent identity configuration")?;
let strategy = UpdateStrategy::with_config(cfg.updates, &identity)
Expand All @@ -63,6 +67,7 @@ impl Settings {
Ok(Self {
allow_downgrade,
enabled,
steady_interval_secs,
cincinnati,
identity,
strategy,
Expand Down
12 changes: 7 additions & 5 deletions src/update_agent/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use prometheus::IntGauge;
use std::time::Duration;

/// Default tick/refresh period for the state machine (in seconds).
const DEFAULT_REFRESH_PERIOD_SECS: u64 = 5 * 60;
const DEFAULT_REFRESH_PERIOD_SECS: u64 = 300; // 5 minutes.
/// Default refresh interval for steady state (in seconds).
pub(crate) const DEFAULT_STEADY_INTERVAL_SECS: u64 = 300; // 5 minutes.

lazy_static::lazy_static! {
static ref LATEST_STATE_CHANGE: IntGauge = register_int_gauge!(opts!(
Expand Down Expand Up @@ -148,21 +150,21 @@ impl UpdateAgent {
cfg: Settings,
rpm_ostree_addr: Addr<RpmOstreeClient>,
) -> failure::Fallible<Self> {
let steady_secs = cfg.steady_interval_secs.get();
let agent = UpdateAgent {
allow_downgrade: cfg.allow_downgrade,
cincinnati: cfg.cincinnati,
enabled: cfg.enabled,
identity: cfg.identity,
rpm_ostree_actor: rpm_ostree_addr,
// TODO(lucab): consider tweaking this
// * maybe configurable, in minutes?
// * maybe more granular, per-state?
steady_interval: Duration::from_secs(DEFAULT_REFRESH_PERIOD_SECS),
steady_interval: Duration::from_secs(steady_secs),
state: UpdateAgentState::default(),
strategy: cfg.strategy,
state_changed: chrono::Utc::now(),
};

// TODO(lucab): consider adding more metrics here
// (e.g. steady interval, downgrade allowed, etc.)
UPDATES_ENABLED.set(i64::from(cfg.enabled));

Ok(agent)
Expand Down
3 changes: 3 additions & 0 deletions tests/fixtures/00-config-sample.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[agent.timing]
steady_interval_secs = 35

[identity]
group = "workers"
node_uuid = "27e3ac02af3946af995c9940e18b0cce"
Expand Down

0 comments on commit a08598b

Please sign in to comment.