From 7d478d997620c0af41a6ffb8b3f29dc6dda2cb98 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Mon, 20 Sep 2021 15:00:31 +0200 Subject: [PATCH 1/3] Stricter Rust formating rules and build in the CI --- .drone.yml | 17 +++++---- .rustfmt.toml | 73 ++++++++++++++++++++++++++++++++++++++ src/config/options.rs | 4 +-- src/config/options_test.rs | 3 +- src/config/runtime.rs | 17 ++++----- src/consul.rs | 11 +++--- src/consul_actor.rs | 25 +++++++------ src/diplonat.rs | 11 +++--- src/fw.rs | 6 ++-- src/fw_actor.rs | 12 +++---- src/igd_actor.rs | 15 ++++---- src/messages.rs | 2 +- 12 files changed, 133 insertions(+), 63 deletions(-) diff --git a/.drone.yml b/.drone.yml index 34200b7..8c1663a 100644 --- a/.drone.yml +++ b/.drone.yml @@ -7,18 +7,17 @@ workspace: steps: - name: code style - image: rust:1.47 + image: rustlang/rust:nightly-slim commands: - - rustup component add rustfmt - - cargo fmt --all -- --check + - rustup component add rustfmt --toolchain nightly + - cargo +nightly fmt --all -- --check # - name: code quality # image: rust:1.47 # commands: # - cargo clippy -- --deny warnings -# - name: test -# image: rust:1.47 -# commands: -# - cargo build --verbose --all -# - cargo test --verbose --all +- name: test + image: rust:1.47 + commands: + - cargo build --verbose --all + - cargo test --verbose --all - \ No newline at end of file diff --git a/.rustfmt.toml b/.rustfmt.toml index f0fa07f..37dfe2c 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,2 +1,75 @@ +unstable_features = true + +array_width = 60 +attr_fn_like_width = 70 +binop_separator = "Front" +blank_lines_lower_bound = 0 +blank_lines_upper_bound = 1 +brace_style = "SameLineWhere" +chain_width = 60 +color = "Auto" +combine_control_expr = true +comment_width = 80 +condense_wildcard_suffixes = true +control_brace_style = "AlwaysSameLine" +disable_all_formatting = false +empty_item_single_line = true +enum_discrim_align_threshold = 0 +error_on_line_overflow = true +error_on_unformatted = true +fn_args_layout = "Tall" +fn_call_width = 60 +fn_single_line = true +force_explicit_abi = true +force_multiline_blocks = false +format_code_in_doc_comments = true +# format_generated_files = true +format_macro_matchers = true +format_macro_bodies = true +format_strings = true hard_tabs = false +#hex_literal_case = "Lower" +hide_parse_errors = false +ignore = [] +imports_indent = "Block" +imports_layout = "Mixed" +indent_style = "Block" +inline_attribute_width = 0 +license_template_path = "" +match_arm_blocks = true +match_arm_leading_pipes = "Never" +match_block_trailing_comma = false +max_width = 100 +merge_derives = true +imports_granularity = "Crate" +newline_style = "Unix" +normalize_comments = true +normalize_doc_attributes = true +overflow_delimited_expr = false +remove_nested_parens = true +reorder_impl_items = true +reorder_imports = true +group_imports = "StdExternalCrate" +reorder_modules = true +report_fixme = "Unnumbered" +report_todo = "Unnumbered" +required_version = "1.4.37" +skip_children = false +single_line_if_else_max_width = 50 +space_after_colon = true +space_before_colon = false +#space_around_ranges = false +struct_field_align_threshold = 0 +struct_lit_single_line = true +struct_lit_width = 18 +struct_variant_width = 35 tab_spaces = 2 +trailing_comma = "Vertical" +trailing_semicolon = false +type_punctuation_density = "Wide" +use_field_init_shorthand = false +use_small_heuristics = "Off" +use_try_shorthand = true +version = "Two" +where_single_line = true +wrap_comments = true diff --git a/src/config/options.rs b/src/config/options.rs index f62d14c..b8dccf7 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -62,9 +62,7 @@ impl ConfigOpts { // Currently only used in tests #[allow(dead_code)] pub fn from_iter(iter: Iter) -> Result - where - Iter: IntoIterator, - { + where Iter: IntoIterator { let base: ConfigOptsBase = envy::prefixed("DIPLONAT_").from_iter(iter.clone())?; let consul: ConfigOptsConsul = envy::prefixed("DIPLONAT_CONSUL_").from_iter(iter.clone())?; let acme: ConfigOptsAcme = envy::prefixed("DIPLONAT_ACME_").from_iter(iter.clone())?; diff --git a/src/config/options_test.rs b/src/config/options_test.rs index c0c7367..790a14e 100644 --- a/src/config/options_test.rs +++ b/src/config/options_test.rs @@ -1,5 +1,4 @@ -use std::collections::HashMap; -use std::time::Duration; +use std::{collections::HashMap, time::Duration}; use crate::config::*; diff --git a/src/config/runtime.rs b/src/config/runtime.rs index 0d52b15..eeb34f6 100644 --- a/src/config/runtime.rs +++ b/src/config/runtime.rs @@ -6,8 +6,8 @@ use crate::config::{ConfigOpts, ConfigOptsAcme, ConfigOptsBase, ConfigOptsConsul // This code is inspired by the Trunk crate (https://github.com/thedodd/trunk) -// In this file, we take ConfigOpts and transform them into ready-to-use RuntimeConfig. -// We apply default values and business logic. +// In this file, we take ConfigOpts and transform them into ready-to-use +// RuntimeConfig. We apply default values and business logic. #[derive(Debug)] pub struct RuntimeConfigAcme { @@ -59,12 +59,11 @@ impl RuntimeConfig { impl RuntimeConfigAcme { pub fn new(opts: ConfigOptsAcme) -> Result> { if !opts.enable { - return Ok(None); + return Ok(None) } let email = opts.email.expect( - "'DIPLONAT_ACME_EMAIL' environment variable is required \ - if 'DIPLONAT_ACME_ENABLE' == 'true'", + "'DIPLONAT_ACME_EMAIL' environment variable is required if 'DIPLONAT_ACME_ENABLE' == 'true'", ); Ok(Some(Self { email })) @@ -105,9 +104,11 @@ impl RuntimeConfigIgd { if refresh_time.as_secs() * 2 > expiration_time.as_secs() { return Err(anyhow!( - "IGD expiration time (currently: {}s) must be at least twice bigger than refresh time (currently: {}s)", - expiration_time.as_secs(), - refresh_time.as_secs())); + "IGD expiration time (currently: {}s) must be at least twice bigger than refresh time \ + (currently: {}s)", + expiration_time.as_secs(), + refresh_time.as_secs() + )) } Ok(Self { diff --git a/src/consul.rs b/src/consul.rs index 1123996..4e6fe5d 100644 --- a/src/consul.rs +++ b/src/consul.rs @@ -1,6 +1,7 @@ +use std::collections::HashMap; + use anyhow::{anyhow, Result}; use serde::{Deserialize, Serialize}; -use std::collections::HashMap; #[derive(Serialize, Deserialize, Debug)] pub struct ServiceEntry { @@ -24,12 +25,10 @@ impl Consul { client: reqwest::Client::new(), url: url.to_string(), idx: None, - }; + } } - pub fn watch_node_reset(&mut self) -> () { - self.idx = None; - } + pub fn watch_node_reset(&mut self) -> () { self.idx = None; } pub async fn watch_node(&mut self, host: &str) -> Result { let url = match self.idx { @@ -44,6 +43,6 @@ impl Consul { }; let resp: CatalogNode = http.json().await?; - return Ok(resp); + return Ok(resp) } } diff --git a/src/consul_actor.rs b/src/consul_actor.rs index d66f7fd..b111f09 100644 --- a/src/consul_actor.rs +++ b/src/consul_actor.rs @@ -1,14 +1,12 @@ -use crate::consul; -use crate::messages; +use std::{cmp, collections::HashSet, time::Duration}; + use anyhow::Result; use log::*; use serde::{Deserialize, Serialize}; use serde_lexpr::{error, from_str}; -use std::cmp; -use std::collections::HashSet; -use std::time::Duration; -use tokio::sync::watch; -use tokio::time::delay_for; +use tokio::{sync::watch, time::delay_for}; + +use crate::{consul, messages}; #[derive(Serialize, Deserialize, Debug)] pub enum DiplonatParameter { @@ -32,11 +30,12 @@ pub struct ConsulActor { fn retry_to_time(retries: u32, max_time: Duration) -> Duration { // 1.2^x seems to be a good value to exponentially increase time at a good pace - // eg. 1.2^32 = 341 seconds ~= 5 minutes - ie. after 32 retries we wait 5 minutes + // eg. 1.2^32 = 341 seconds ~= 5 minutes - ie. after 32 retries we wait 5 + // minutes return Duration::from_secs(cmp::min( max_time.as_secs(), 1.2f64.powf(retries as f64) as u64, - )); + )) } fn to_parameters(catalog: &consul::CatalogNode) -> Vec { @@ -52,7 +51,7 @@ fn to_parameters(catalog: &consul::CatalogNode) -> Vec { } } - return r; + return r } fn to_open_ports(params: &Vec) -> messages::PublicExposedPorts { @@ -71,7 +70,7 @@ fn to_open_ports(params: &Vec) -> messages::PublicExposedPorts { } } - return op; + return op } impl ConsulActor { @@ -87,7 +86,7 @@ impl ConsulActor { tx_open_ports: tx, node: node.to_string(), retries: 0, - }; + } } pub async fn listen(&mut self) -> Result<()> { @@ -104,7 +103,7 @@ impl ConsulActor { e ); delay_for(will_retry_in).await; - continue; + continue } }; self.retries = 0; diff --git a/src/diplonat.rs b/src/diplonat.rs index a17bdc0..496f0ab 100644 --- a/src/diplonat.rs +++ b/src/diplonat.rs @@ -1,10 +1,9 @@ use anyhow::Result; use tokio::try_join; -use crate::config::ConfigOpts; -use crate::consul_actor::ConsulActor; -use crate::fw_actor::FirewallActor; -use crate::igd_actor::IgdActor; +use crate::{ + config::ConfigOpts, consul_actor::ConsulActor, fw_actor::FirewallActor, igd_actor::IgdActor, +}; pub struct Diplonat { consul: ConsulActor, @@ -35,7 +34,7 @@ impl Diplonat { firewall: fw, }; - return Ok(ctx); + return Ok(ctx) } pub async fn listen(&mut self) -> Result<()> { @@ -45,6 +44,6 @@ impl Diplonat { self.firewall.listen() )?; - return Ok(()); + return Ok(()) } } diff --git a/src/fw.rs b/src/fw.rs index 0b07a12..e18a301 100644 --- a/src/fw.rs +++ b/src/fw.rs @@ -1,9 +1,11 @@ -use crate::messages; +use std::collections::HashSet; + use anyhow::{Context, Result}; use iptables; use log::*; use regex::Regex; -use std::collections::HashSet; + +use crate::messages; pub fn setup(ipt: &iptables::IPTables) -> Result<()> { // ensure we start from a clean state without any rule already set diff --git a/src/fw_actor.rs b/src/fw_actor.rs index 5147a9c..0fa6e64 100644 --- a/src/fw_actor.rs +++ b/src/fw_actor.rs @@ -1,4 +1,7 @@ +use std::collections::HashSet; + use anyhow::Result; +use iptables; use log::*; use tokio::{ select, @@ -6,10 +9,7 @@ use tokio::{ time::{self, Duration}, }; -use crate::fw; -use crate::messages; -use iptables; -use std::collections::HashSet; +use crate::{fw, messages}; pub struct FirewallActor { pub ipt: iptables::IPTables, @@ -32,7 +32,7 @@ impl FirewallActor { fw::setup(&ctx.ipt)?; - return Ok(ctx); + return Ok(ctx) } pub async fn listen(&mut self) -> Result<()> { @@ -81,6 +81,6 @@ impl FirewallActor { fw::open_ports(&self.ipt, ports_to_open)?; - return Ok(()); + return Ok(()) } } diff --git a/src/igd_actor.rs b/src/igd_actor.rs index 4ff5f53..bb9099e 100644 --- a/src/igd_actor.rs +++ b/src/igd_actor.rs @@ -1,15 +1,16 @@ -use crate::messages; -use anyhow::{Context, Result}; -use igd::aio::*; -use igd::PortMappingProtocol; -use log::*; use std::net::SocketAddrV4; + +use anyhow::{Context, Result}; +use igd::{aio::*, PortMappingProtocol}; +use log::*; use tokio::{ select, sync::watch, time::{self, Duration}, }; +use crate::messages; + pub struct IgdActor { last_ports: messages::PublicExposedPorts, rx_ports: watch::Receiver, @@ -40,7 +41,7 @@ impl IgdActor { last_ports: messages::PublicExposedPorts::new(), }; - return Ok(ctx); + return Ok(ctx) } pub async fn listen(&mut self) -> Result<()> { @@ -92,6 +93,6 @@ impl IgdActor { } } - return Ok(()); + return Ok(()) } } diff --git a/src/messages.rs b/src/messages.rs index 63f16b0..b622be1 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -11,6 +11,6 @@ impl PublicExposedPorts { return Self { tcp_ports: HashSet::new(), udp_ports: HashSet::new(), - }; + } } } From fd3a153103029cf7b740e3feeb27eadf5fa4eefc Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Mon, 20 Sep 2021 15:18:49 +0200 Subject: [PATCH 2/3] Fix the CONTRIBUTING doc for the new formatting --- CONTRIBUTING.md | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f8de6cc..01e1e12 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,12 +8,13 @@ #### Installing rustfmt -You can run `rustfmt` with Rust 1.24 and above. +You must install a very recent version of `rustfmt` through rust nightly To install: ``` -rustup component add rustfmt +rustup toolchain install nightly-x86_64-unknown-linux-gnu +rustup component add rustfmt --toolchain nightly ``` #### Usage @@ -21,14 +22,24 @@ rustup component add rustfmt To run on Diplonat, launch the following in the root directory: ``` -cargo fmt --all +cargo +nightly fmt ``` -This will format the whole repository using the settigs defined in [`.rustfmt.toml`](./.rustfmt.toml): soft tabs of 2 spaces. +This will format the whole repository using the settigs defined in [`.rustfmt.toml`](./.rustfmt.toml). #### Auto-format code You can automate formatting in a number of ways: -* [Setup your IDE to use `rustfmt`](https://github.com/rust-lang/rustfmt#running-rustfmt-from-your-editor). -* Setup a git hook to run `rustfmt` before each commit. +[Setup your IDE to use `rustfmt`](https://github.com/rust-lang/rustfmt#running-rustfmt-from-your-editor). + +Setup a git hook to run `rustfmt` before each commit: + +```bash +cat < .git/hooks/pre-commit +#!/bin/bash + +cargo +nightly fmt +EOF +chmod +x .git/hooks/pre-commit +``` From 68cb4d5482649baca3a79d3fd0e3449a6af0533b Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Mon, 20 Sep 2021 15:59:52 +0200 Subject: [PATCH 3/3] Use the official rust image --- .drone.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 8c1663a..f431761 100644 --- a/.drone.yml +++ b/.drone.yml @@ -7,8 +7,9 @@ workspace: steps: - name: code style - image: rustlang/rust:nightly-slim + image: rust:1.47 commands: + - rustup toolchain install nightly-x86_64-unknown-linux-gnu - rustup component add rustfmt --toolchain nightly - cargo +nightly fmt --all -- --check # - name: code quality