Skip to content

Commit

Permalink
[fix] #4292, #4327: Docker follow-up on configuration update (#4367)
Browse files Browse the repository at this point in the history
* [fix]: implement reading of `SUMERAGI_TRUSTED_PEERS`

Signed-off-by: Dmitry Balashov <[email protected]>

* [build]: update Dockerfile(s)

Signed-off-by: Dmitry Balashov <[email protected]>

* [build]: revert `CONFIG_DIR`

Signed-off-by: Dmitry Balashov <[email protected]>

---------

Signed-off-by: Dmitry Balashov <[email protected]>
  • Loading branch information
0x009922 authored Mar 19, 2024
1 parent c380c8b commit ac872b2
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 54 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 3 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=/x86_64-linux-musl-native/bin/
# builder stage
WORKDIR /iroha
COPY . .
# FIXME: shouldn't it only build `iroha`, `iroha_client_cli`, and `kagami`?
# FIXME: consider building only `iroha`, `iroha_client_cli`, and `kagami`?
RUN cargo build --target x86_64-unknown-linux-musl --profile deploy


Expand All @@ -41,10 +41,8 @@ ARG TARGET_DIR=/iroha/target/x86_64-unknown-linux-musl/deploy
ENV BIN_PATH=/usr/local/bin/
ENV CONFIG_DIR=/config

# FIXME: these are obsolete
ENV IROHA2_CONFIG_PATH=$CONFIG_DIR/config.json
ENV IROHA2_GENESIS_PATH=$CONFIG_DIR/genesis.json
ENV KURA_BLOCK_STORE_PATH=$STORAGE
ENV KURA_STORE_DIR=$STORAGE
ENV SNAPSHOT_STORE_DIR=$STORAGE/snapshot

ENV WASM_DIRECTORY=/app/.cache/wasmtime
ENV USER=iroha
Expand Down
5 changes: 2 additions & 3 deletions Dockerfile.glibc
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ ARG STORAGE=/storage
ARG TARGET_DIR=/iroha/target/x86_64-unknown-linux-gnu/${PROFILE}
ENV BIN_PATH=/usr/local/bin/
ENV CONFIG_DIR=/config
ENV IROHA2_CONFIG_PATH=$CONFIG_DIR/config.json
ENV IROHA2_GENESIS_PATH=$CONFIG_DIR/genesis.json
ENV KURA_BLOCK_STORE_PATH=$STORAGE
ENV KURA_STORE_DIR=$STORAGE
ENV SNAPSHOT_STORE_DIR=$STORAGE/snapshot
ENV WASM_DIRECTORY=/app/.cache/wasmtime
ENV USER=iroha
ENV UID=1001
Expand Down
4 changes: 2 additions & 2 deletions config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ license.workspace = true
workspace = true

[dependencies]
iroha_config_base = { workspace = true }
iroha_config_base = { workspace = true, features = ["json"] }
iroha_data_model = { workspace = true }
iroha_primitives = { workspace = true }
iroha_crypto = { workspace = true }
Expand All @@ -32,7 +32,7 @@ displaydoc = { workspace = true }
derive_more = { workspace = true }
cfg-if = { workspace = true }
once_cell = { workspace = true }
nonzero_ext = { workspace = true }
nonzero_ext = { workspace = true }
toml = { workspace = true }
merge = "0.1.0"

Expand Down
6 changes: 6 additions & 0 deletions config/base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ license.workspace = true
[lints]
workspace = true

[features]
# enables some JSON-related features
json = ["serde_json"]

[dependencies]
merge = "0.1.0"
drop_bomb = { workspace = true }
Expand All @@ -20,5 +24,7 @@ serde_with = { workspace = true, features = ["macros", "std"] }
thiserror = { workspace = true }
num-traits = "0.2.17"

serde_json = { version = "1", optional = true }

[dev-dependencies]
toml = { workspace = true }
99 changes: 84 additions & 15 deletions config/base/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::{
use eyre::{eyre, Report, WrapErr};
pub use merge::Merge;
pub use serde;
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Deserialize, Serialize};

/// [`Duration`], but can parse a human-readable string.
/// TODO: currently deserializes just as [`Duration`]
Expand Down Expand Up @@ -114,7 +114,7 @@ pub struct Emitter<T: Debug> {
bomb: drop_bomb::DropBomb,
}

impl<T: Debug> Emitter<T> {
impl<E: Debug> Emitter<E> {
/// Create a new empty emitter
pub fn new() -> Self {
Self {
Expand All @@ -126,12 +126,12 @@ impl<T: Debug> Emitter<T> {
}

/// Emit a single error
pub fn emit(&mut self, error: T) {
pub fn emit(&mut self, error: E) {
self.errors.push(error);
}

/// Emit a collection of errors
pub fn emit_collection(&mut self, mut errors: ErrorsCollection<T>) {
pub fn emit_collection(&mut self, mut errors: ErrorsCollection<E>) {
self.errors.append(&mut errors.0);
}

Expand All @@ -140,7 +140,7 @@ impl<T: Debug> Emitter<T> {
///
/// # Errors
/// If any errors were emitted.
pub fn finish(mut self) -> Result<(), ErrorsCollection<T>> {
pub fn finish(mut self) -> Result<(), ErrorsCollection<E>> {
self.bomb.defuse();

if self.errors.is_empty() {
Expand All @@ -151,6 +151,27 @@ impl<T: Debug> Emitter<T> {
}
}

impl Emitter<Report> {
/// A shorthand to work with [`FromEnv`].
///
/// # Errors
/// If failed to parse the value from env.
pub fn try_from_env<T, R, RE>(&mut self, env: &R) -> Option<T>
where
T: FromEnv,
R: ReadEnv<RE>,
RE: Error,
{
match FromEnv::from_env(env) {
Ok(parsed) => Some(parsed),
Err(errors) => {
self.emit_collection(errors);
None
}
}
}
}

impl<T: Debug> Default for Emitter<T> {
fn default() -> Self {
Self::new()
Expand Down Expand Up @@ -310,6 +331,28 @@ pub enum ParseEnvResult<T> {
None,
}

impl<'a> ParseEnvResult<Cow<'a, str>> {
fn read_env_only<E: Error>(
emitter: &mut Emitter<Report>,
env: &'a impl ReadEnv<E>,
env_key: impl AsRef<str>,
) -> Self {
// FIXME: errors handling is such a mess now
match env
.read_env(env_key.as_ref())
.map_err(|err| eyre!("{err}"))
.wrap_err_with(|| eyre!("ooops"))
{
Ok(Some(value)) => Self::Value(value),
Ok(None) => Self::None,
Err(report) => {
emitter.emit(report);
Self::Error
}
}
}
}

impl<T> ParseEnvResult<T>
where
T: FromStr,
Expand All @@ -322,21 +365,47 @@ where
env_key: impl AsRef<str>,
field_name: impl AsRef<str>,
) -> Self {
// FIXME: errors handling is such a mess now
let read = match env
.read_env(env_key.as_ref())
.map_err(|err| eyre!("{err}"))
.wrap_err_with(|| eyre!("ooops"))
{
Ok(Some(value)) => value,
Ok(None) => return Self::None,
let read = match ParseEnvResult::read_env_only(emitter, env, env_key.as_ref()) {
ParseEnvResult::Value(x) => x,
ParseEnvResult::None => return Self::None,
ParseEnvResult::Error => return Self::Error,
};

match FromStr::from_str(read.as_ref()).wrap_err_with(|| {
eyre!(
"failed to parse `{}` field from `{}` env variable",
field_name.as_ref(),
env_key.as_ref()
)
}) {
Ok(value) => Self::Value(value),
Err(report) => {
emitter.emit(report);
return Self::Error;
Self::Error
}
}
}
}

impl<T> ParseEnvResult<T>
where
T: DeserializeOwned,
{
/// Treat string data in ENV as JSON
#[cfg(feature = "json")]
pub fn parse_json<E: Error>(
emitter: &mut Emitter<Report>,
env: &impl ReadEnv<E>,
env_key: impl AsRef<str>,
field_name: impl AsRef<str>,
) -> Self {
let read = match ParseEnvResult::read_env_only(emitter, env, env_key.as_ref()) {
ParseEnvResult::Value(x) => x,
ParseEnvResult::None => return Self::None,
ParseEnvResult::Error => return Self::Error,
};

match FromStr::from_str(read.as_ref()).wrap_err_with(|| {
match serde_json::from_str(read.as_ref()).wrap_err_with(|| {
eyre!(
"failed to parse `{}` field from `{}` env variable",
field_name.as_ref(),
Expand Down
64 changes: 37 additions & 27 deletions config/src/parameters/user/boilerplate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{
path::PathBuf,
};

use eyre::{eyre, Report, WrapErr};
use eyre::{eyre, WrapErr};
use iroha_config_base::{
Emitter, ErrorsCollection, ExtendsPaths, FromEnv, FromEnvDefaultFallback, FromEnvResult,
HumanBytes, HumanDuration, Merge, MissingFieldError, ParseEnvResult, ReadEnv, UnwrapPartial,
Expand Down Expand Up @@ -127,21 +127,6 @@ impl UnwrapPartial for RootPartial {

impl FromEnv for RootPartial {
fn from_env<E: Error, R: ReadEnv<E>>(env: &R) -> FromEnvResult<Self> {
fn from_env_nested<T, R, RE>(env: &R, emitter: &mut Emitter<Report>) -> Option<T>
where
T: FromEnv,
R: ReadEnv<RE>,
RE: Error,
{
match FromEnv::from_env(env) {
Ok(parsed) => Some(parsed),
Err(errors) => {
emitter.emit_collection(errors);
None
}
}
}

let mut emitter = Emitter::new();

let chain_id = env
Expand All @@ -163,16 +148,16 @@ impl FromEnv for RootPartial {
user::private_key_from_env(&mut emitter, env, "PRIVATE_KEY", "iroha.private_key")
.into();

let genesis = from_env_nested(env, &mut emitter);
let kura = from_env_nested(env, &mut emitter);
let sumeragi = from_env_nested(env, &mut emitter);
let network = from_env_nested(env, &mut emitter);
let logger = from_env_nested(env, &mut emitter);
let queue = from_env_nested(env, &mut emitter);
let snapshot = from_env_nested(env, &mut emitter);
let telemetry = from_env_nested(env, &mut emitter);
let torii = from_env_nested(env, &mut emitter);
let chain_wide = from_env_nested(env, &mut emitter);
let genesis = emitter.try_from_env(env);
let kura = emitter.try_from_env(env);
let sumeragi = emitter.try_from_env(env);
let network = emitter.try_from_env(env);
let logger = emitter.try_from_env(env);
let queue = emitter.try_from_env(env);
let snapshot = emitter.try_from_env(env);
let telemetry = emitter.try_from_env(env);
let torii = emitter.try_from_env(env);
let chain_wide = emitter.try_from_env(env);

emitter.finish()?;

Expand Down Expand Up @@ -392,7 +377,32 @@ impl UnwrapPartial for SumeragiDebugPartial {
}
}

impl FromEnvDefaultFallback for SumeragiPartial {}
impl FromEnv for SumeragiPartial {
fn from_env<E: Error, R: ReadEnv<E>>(env: &R) -> FromEnvResult<Self>
where
Self: Sized,
{
let mut emitter = Emitter::new();

let trusted_peers = ParseEnvResult::parse_json(
&mut emitter,
env,
"SUMERAGI_TRUSTED_PEERS",
"sumeragi.trusted_peers",
)
.into();
let debug = emitter.try_from_env(env);

emitter.finish()?;

Ok(Self {
trusted_peers,
debug: debug.unwrap(),
})
}
}

impl FromEnvDefaultFallback for SumeragiDebugPartial {}

#[derive(Deserialize, Serialize, Debug, Default, Merge)]
#[serde(deny_unknown_fields, default)]
Expand Down
16 changes: 15 additions & 1 deletion config/tests/fixtures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,21 @@ fn full_envs_set_is_consumed() -> Result<()> {
},
},
sumeragi: SumeragiPartial {
trusted_peers: None,
trusted_peers: Some(
[
PeerId {
address: SocketAddrHost {
host: "iroha2",
port: 1339,
},
public_key: PublicKey(
ed25519(
"ed0120312C1B7B5DE23D366ADCF23CD6DB92CE18B2AA283C7D9F5033B969C2DC2B92F4",
),
),
},
],
),
debug: SumeragiDebugPartial {
force_soft_fork: None,
},
Expand Down
1 change: 1 addition & 0 deletions config/tests/fixtures/full.env
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ LOG_LEVEL=DEBUG
LOG_FORMAT=pretty
SNAPSHOT_MODE=read_write
SNAPSHOT_STORE_DIR=/snapshot/path/from/env
SUMERAGI_TRUSTED_PEERS=[{"address":"iroha2:1339","public_key":"ed0120312C1B7B5DE23D366ADCF23CD6DB92CE18B2AA283C7D9F5033B969C2DC2B92F4"}]
9 changes: 8 additions & 1 deletion tools/swarm/src/compose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,14 @@ mod tests {
genesis_private_key: Some(keypair.private_key().clone()),
p2p_addr: socket_addr!(127.0.0.1:1337),
api_addr: socket_addr!(127.0.0.1:1338),
trusted_peers: BTreeSet::new(),
trusted_peers: {
let mut set = BTreeSet::new();
set.insert(PeerId::new(
socket_addr!(127.0.0.1:8081),
KeyPair::random().into_parts().0,
));
set
},
}
.into();

Expand Down

0 comments on commit ac872b2

Please sign in to comment.