Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "genin"
version = "0.5.3"
version = "0.5.4"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
383 changes: 365 additions & 18 deletions README.md

Large diffs are not rendered by default.

520 changes: 429 additions & 91 deletions README.ru.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ pub fn run_v2() -> Result<(), Box<dyn Error>> {
State::from_latest(args)?.into()
} else {
match args.get_one::<String>("old") {
Some(old_path) if old_path.ends_with(".tgz") => {
Some(old_path) if old_path.ends_with(".gz") => {
State::try_from(&PathBuf::from(old_path))?.into()
}
Some(old_path) => Cluster::try_from(&PathBuf::from(old_path))?,
Expand Down
34 changes: 20 additions & 14 deletions src/task/cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ use crate::task::utils::create_file_or_copy;
use crate::task::vars::InvalidVars;

use super::state::Change;
use super::{TypeError, DICT};

/// Cluster is a `genin` specific configuration file
/// ```rust
Expand Down Expand Up @@ -202,7 +203,7 @@ impl<'a> TryFrom<&'a ArgMatches> for Cluster {

fn try_from(args: &'a ArgMatches) -> Result<Self, Self::Error> {
match args.try_get_one::<String>("source") {
Ok(Some(path)) if path.ends_with(".tgz") => {
Ok(Some(path)) if path.ends_with(".gz") => {
debug!("Restoring the cluster distribution from the state file {path}");
Ok(Cluster {
metadata: ClusterMetadata {
Expand Down Expand Up @@ -470,9 +471,14 @@ impl<'de> Deserialize<'de> for Cluster {
},
}
.spread()),
ClusterHelper::InvalidCluster(_) => Err(serde::de::Error::custom(
"Cluster configuration contains errors",
)),
ClusterHelper::InvalidCluster(value) => {
println!(
"Cluster configuration contains errors: {:?}",
serde_yaml::from_value::<InvalidCluster>(value)
.expect("can't fail because the value is parsed and not validated")
);
Err(serde::de::Error::custom("Invalid cluster configuration"))
}
})
}
}
Expand Down Expand Up @@ -810,7 +816,7 @@ impl Cluster {
let path: String = if let Ok(Some(path)) = args.try_get_one::<String>("export-state") {
path.into()
} else {
format!("{state_dir}/latest.tgz")
format!("{state_dir}/latest.gz")
};

// if args != export-state -> try open latest
Expand Down Expand Up @@ -923,7 +929,6 @@ impl HostV2Helper {
}
}

#[allow(unused)]
struct TopologyMemberV1 {
name: Name,
count: usize,
Expand Down Expand Up @@ -979,16 +984,12 @@ impl<'de> Deserialize<'de> for TopologyMemberV1 {
}
}

#[allow(unused)]
#[derive(Deserialize, Default)]
#[serde(default)]
pub struct InvalidCluster {
#[serde(default)]
topology: Value,
#[serde(default)]
hosts: Value,
#[serde(default)]
failover: Value,
#[serde(default)]
vars: Value,
}

Expand Down Expand Up @@ -1058,7 +1059,10 @@ impl std::fmt::Debug for InvalidCluster {
))?;
}
_ => {
formatter.write_str("Failover must be a mapping".as_error().as_str())?;
formatter.write_fmt(format_args!(
"\nfailover: {}",
self.failover.type_error(DICT).as_error()
))?;
}
}

Expand All @@ -1072,8 +1076,10 @@ impl std::fmt::Debug for InvalidCluster {
))?;
}
_ => {
formatter.write_str("\nvars: ")?;
formatter.write_str("Vars must be a mapping".as_error().as_str())?;
formatter.write_fmt(format_args!(
"\nvars: {}",
self.vars.type_error(DICT).as_error()
))?;
}
}

Expand Down
19 changes: 7 additions & 12 deletions src/task/cluster/hst/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1088,15 +1088,12 @@ impl<'a> From<DomainMember> for Cow<'a, str> {
#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq)]
pub struct IPSubnet(Vec<IpAddr>);

#[derive(Deserialize)]
#[derive(Deserialize, Default)]
#[serde(default)]
pub struct InvalidHostV2 {
#[serde(skip)]
pub offset: String,
#[serde(default)]
name: Value,
#[serde(default)]
config: Value,
#[serde(default)]
hosts: Value,
}

Expand Down Expand Up @@ -1177,19 +1174,15 @@ impl fmt::Debug for InvalidHostV2 {
}
}

#[derive(Deserialize)]
#[derive(Deserialize, Default)]
#[serde(default)]
pub struct InvalidHostV2Config {
#[serde(skip)]
offset: String,
#[serde(default)]
pub http_port: Value,
#[serde(default)]
pub binary_port: Value,
#[serde(default)]
pub address: Value,
#[serde(default)]
pub distance: Value,
#[serde(default)]
pub additional_config: Value,
}

Expand Down Expand Up @@ -1244,7 +1237,9 @@ impl fmt::Debug for InvalidHostV2Config {

// address: String
match &self.address {
Value::Null => {}
Value::Null => {

}
Value::String(address) => {
formatter.write_fmt(format_args!("{}address: {}", self.offset, address))?;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
source: src/task/cluster/test.rs
expression: uncolorize(result)
---
Err(Cluster configuration contains errors(Ok(
Err(Invalid cluster configuration(Ok(
---
topology: "Missing field 'topology'"
hosts:
Expand All @@ -14,5 +14,5 @@ hosts:
hosts:
- name: server-10
- name: server-11
vars: "Vars must be a mapping"
vars: "Expected type Dict got Null"
)))
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
source: src/task/cluster/test.rs
expression: uncolorize(result)
---
Err(Cluster configuration contains errors(Ok(
Err(Invalid cluster configuration(Ok(
---
topology: "Missing field 'topology'"
hosts: "Missing field 'hosts'"
vars: "Vars must be a mapping"
vars: "Expected type Dict got Null"
)))
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
source: src/task/cluster/test.rs
expression: uncolorize(result)
---
Err(Cluster configuration contains errors(Ok(
Err(Invalid cluster configuration(Ok(
---
topology:
- name: "Missing field 'name'"
Expand All @@ -28,5 +28,5 @@ topology:
roles:
- value
hosts: "Missing field 'hosts'"
vars: "Vars must be a mapping"
vars: "Expected type Dict got Null"
)))
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
source: src/task/cluster/test.rs
expression: uncolorize(result)
---
Err(Cluster configuration contains errors(Err(
Err(Invalid cluster configuration(Err(

---
topology:
Expand Down
2 changes: 1 addition & 1 deletion src/task/cluster/topology.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ impl std::fmt::Debug for InvalidTopologySet {
}
_ => {
formatter.write_fmt(format_args!(
" replication_factor: {}",
"\n replication_factor: {}",
self.replication_factor.type_error(NUMBER).as_error()
))?;
}
Expand Down
56 changes: 40 additions & 16 deletions src/task/flv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
DEFAULT_STATEBOARD_PORT,
};

use super::{cluster::hst::v2::Address, AsError};
use super::{cluster::hst::v2::Address, AsError, TypeError, LIST, NUMBER, STRING};

#[derive(Serialize, Clone, Debug, PartialEq, Eq)]
/// Failover enum
Expand Down Expand Up @@ -718,16 +718,22 @@ pub struct InvalidETCD2 {

impl fmt::Debug for InvalidETCD2 {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("\n prefix: ")?;
match &self.prefix {
Value::Null => {
formatter.write_str("Missing field 'prefix'".as_error().as_str())?;
formatter.write_fmt(format_args!(
"\n prefix: {}",
"Missing field 'prefix'".as_error()
))?;
}
Value::String(prefix) => {
formatter.write_str("\n prefix: ")?;
formatter.write_str(prefix)?;
}
_ => {
formatter.write_str("Field 'prefix' must be a String".as_error().as_str())?;
formatter.write_fmt(format_args!(
"\n prefix: {}",
self.prefix.type_error(STRING).as_error()
))?;
}
}

Expand All @@ -737,17 +743,22 @@ impl fmt::Debug for InvalidETCD2 {
formatter.write_str(lock_delay.to_string().as_str())?;
}
_ => {
formatter.write_str("\n lock_delay: ")?;
formatter.write_str("Field 'lock_delay' must be a Number".as_error().as_str())?;
formatter.write_fmt(format_args!(
"\n lock_delay: {}",
self.lock_delay.type_error(NUMBER).as_error()
))?;
}
}

formatter.write_str("\n endpoints:")?;
match &self.endpoints {
Value::Null => {
formatter.write_str("Missing field 'endpoints'".as_error().as_str())?;
formatter.write_fmt(format_args!(
"\n endpoints: {}",
"Missing field 'endpoints'".as_error().as_str()
))?;
}
Value::Sequence(seq) => {
formatter.write_str("\n endpoints:")?;
for endpoint in seq {
if let Ok(uri) = serde_yaml::from_value::<UriWithProtocol>(endpoint.clone()) {
formatter.write_str(format!("\n - {uri}").as_str())?;
Expand All @@ -758,7 +769,10 @@ impl fmt::Debug for InvalidETCD2 {
}
}
_ => {
formatter.write_str("Field 'lock_delay' must be a Sequence".as_error().as_str())?;
formatter.write_fmt(format_args!(
"\n endpoints: {}",
self.endpoints.type_error(LIST).as_error()
))?;
}
}

Expand All @@ -768,8 +782,10 @@ impl fmt::Debug for InvalidETCD2 {
formatter.write_str(username)?;
}
_ => {
formatter.write_str("\n username: ")?;
formatter.write_str("Field 'username' must be a String".as_error().as_str())?;
formatter.write_fmt(format_args!(
"\n username: {}",
self.username.type_error(STRING).as_error()
))?;
}
}

Expand All @@ -779,8 +795,10 @@ impl fmt::Debug for InvalidETCD2 {
formatter.write_str(password)?;
}
_ => {
formatter.write_str("\n password: ")?;
formatter.write_str("Field 'password' must be a String".as_error().as_str())?;
formatter.write_fmt(format_args!(
"\n password: {}",
self.username.type_error(STRING).as_error()
))?;
}
}
Ok(())
Expand All @@ -802,16 +820,22 @@ impl fmt::Debug for InvalidStateboardParams {
formatter.write_str("Invalid Uri".as_error().as_str())?;
}

formatter.write_str("\n password: ")?;
match &self.password {
Value::Null => {
formatter.write_str("Missing field 'password'".as_error().as_str())?;
formatter.write_fmt(format_args!(
"\n password: {}",
"Missing field 'password'".as_error()
))?;
}
Value::String(password) => {
formatter.write_str("\n password: ")?;
formatter.write_str(password)?;
}
_ => {
formatter.write_str("Field 'password' must be a String".as_error().as_str())?;
formatter.write_fmt(format_args!(
"\n password: {}",
self.password.type_error(STRING).as_error()
))?;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ expression: uncolorize(invalid_v1)
state_provider: etcd2
etcd2_params:
prefix: /cartridge
lock_delay: "Field 'lock_delay' must be a Number"
lock_delay: "Expected type Number got String"
endpoints:
- http://172.20.73.12:2379
- "InvalidUri"
username: "Field 'username' must be a String"
password: "Field 'password' must be a String"
username: "Expected type String got Number"
password: "Expected type String got Number"
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ expression: uncolorize(invalid_v1)
state_provider: stateboard
stateboard_params:
uri: 192.168.16.11:4401
password: "Field 'password' must be a String"
password: "Expected type String got Number"
4 changes: 2 additions & 2 deletions src/task/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,12 @@ impl State {
}

pub fn dump_by_uid(&mut self, state_dir: &str) -> Result<(), io::Error> {
self.dump_by_path(&format!("{state_dir}/{}.tgz", &self.uid))
self.dump_by_path(&format!("{state_dir}/{}.gz", &self.uid))
}

pub fn from_latest(args: &ArgMatches) -> Result<Self, StateError> {
let path = format!(
"{}/latest.tgz",
"{}/latest.gz",
args.get_one::<String>("state-dir")
.cloned()
.unwrap_or(".geninstate".into())
Expand Down
Loading