Repository: golemfactory/yagna (language: python)

Issue:
Configuring provider certs and whitelist using `golemsp`



Discussion / hints:

Fix patch:
diff --git a/.github/workflows/binaries-x86-64-hybrid-net.yml b/.github/workflows/binaries-x86-64-hybrid-net.yml
index 8a5211b29c..7de747d398 100644
--- a/.github/workflows/binaries-x86-64-hybrid-net.yml
+++ b/.github/workflows/binaries-x86-64-hybrid-net.yml
@@ -10,6 +10,9 @@ on:
       - master
       - release/*
 
+env:
+  rust_stable: 1.64.0
+
 jobs:
   build:
     name: Build binaries (x86-64) hybrid-net
@@ -26,11 +29,19 @@ jobs:
       - name: Checkout
         uses: actions/checkout@v1
 
-      - name: Install last stable Rust
+      - name: Musl
+        run: |
+          sudo apt-get install musl musl-tools
+
+          musl-gcc -v
+
+      - name: Install Rust ${{ env.rust_stable }}
         uses: actions-rs/toolchain@v1
         with:
-          toolchain: stable
+          toolchain: ${{ env.rust_stable }}
           components: rustfmt, clippy
+          target: x86_64-unknown-linux-musl
+          override: true
 
       - name: Check lockfile
         uses: actions-rs/cargo@v1
@@ -46,17 +57,19 @@ jobs:
           vcpkg integrate install
 
       - name: Build binaries
-        uses: actions-rs/cargo@v1
-        with:
-          command: build
-          args: --workspace
+        run: |
+          cargo build --features static-openssl --target x86_64-unknown-linux-musl
+          (cd core/gftp && cargo build --bin gftp -p gftp --features bin --target x86_64-unknown-linux-musl)
+          (cd golem_cli && cargo build --bin golemsp -p golemsp --target x86_64-unknown-linux-musl)
+          (cd agent/provider && cargo build --bin ya-provider -p ya-provider --target x86_64-unknown-linux-musl)
+          (cd exe-unit && cargo build --bin exe-unit -p ya-exe-unit --features openssl/vendored --target x86_64-unknown-linux-musl)
 
       - name: Copy binaries
         shell: bash
         run: |
           mkdir build
           if [ "$RUNNER_OS" == "Linux" ]; then
-            cp target/debug/{yagna,ya-provider,exe-unit,golemsp,gftp} build
+            cp target/x86_64-unknown-linux-musl/debug/{yagna,ya-provider,exe-unit,golemsp,gftp} build
             strip -x build/*
           elif [ "$RUNNER_OS" == "macOS" ]; then
             cp target/debug/{yagna,gftp} build
diff --git a/.github/workflows/binaries-x86-64.yml b/.github/workflows/binaries-x86-64.yml
index f8b16e7dc6..fe33b8f589 100644
--- a/.github/workflows/binaries-x86-64.yml
+++ b/.github/workflows/binaries-x86-64.yml
@@ -10,6 +10,9 @@ on:
       - master
       - release/*
 
+env:
+  rust_stable: 1.64.0
+
 jobs:
   build:
     name: Build binaries (x86-64)
@@ -26,11 +29,19 @@ jobs:
       - name: Checkout
         uses: actions/checkout@v1
 
-      - name: Install last stable Rust
+      - name: Musl
+        run: |
+          sudo apt-get install musl musl-tools
+
+          musl-gcc -v
+
+      - name: Install Rust ${{ env.rust_stable }}
         uses: actions-rs/toolchain@v1
         with:
-          toolchain: stable
+          toolchain: ${{ env.rust_stable }}
           components: rustfmt, clippy
+          target: x86_64-unknown-linux-musl
+          override: true
 
       - name: Check lockfile
         uses: actions-rs/cargo@v1
@@ -46,17 +57,19 @@ jobs:
           vcpkg integrate install
 
       - name: Build binaries
-        uses: actions-rs/cargo@v1
-        with:
-          command: build
-          args: --workspace --features central-net
+        run: |
+          cargo build --features "static-openssl central-net" --target x86_64-unknown-linux-musl
+          (cd core/gftp && cargo build --bin gftp -p gftp --features bin --target x86_64-unknown-linux-musl)
+          (cd golem_cli && cargo build --bin golemsp -p golemsp --target x86_64-unknown-linux-musl)
+          (cd agent/provider && cargo build --bin ya-provider -p ya-provider --target x86_64-unknown-linux-musl)
+          (cd exe-unit && cargo build --bin exe-unit -p ya-exe-unit --features openssl/vendored --target x86_64-unknown-linux-musl)
 
       - name: Copy binaries
         shell: bash
         run: |
           mkdir build
           if [ "$RUNNER_OS" == "Linux" ]; then
-            cp target/debug/{yagna,ya-provider,exe-unit,golemsp,gftp} build
+            cp target/x86_64-unknown-linux-musl/debug/{yagna,ya-provider,exe-unit,golemsp,gftp} build
             strip -x build/*
           elif [ "$RUNNER_OS" == "macOS" ]; then
             cp target/debug/{yagna,gftp} build
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 05ff456fad..4a1557aa76 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -5,6 +5,9 @@ on:
       - v*
       - pre-rel-*
 
+env:
+  rust_stable: 1.64.0
+
 jobs:
   create-release:
     name: Create release
@@ -86,11 +89,11 @@ jobs:
       - uses: actions-rs/toolchain@v1
         if: matrix.os != 'ubuntu'
         with:
-          toolchain: stable
+          toolchain: ${{ env.rust_stable }}
       - uses: actions-rs/toolchain@v1
         if: matrix.os == 'ubuntu'
         with:
-          toolchain: stable
+          toolchain: ${{ env.rust_stable }}
           target: x86_64-unknown-linux-musl
           override: true
       - name: Build macos
diff --git a/core/market/src/matcher.rs b/core/market/src/matcher.rs
index 7ec50aea0b..f57ce7f58d 100644
--- a/core/market/src/matcher.rs
+++ b/core/market/src/matcher.rs
@@ -28,7 +28,9 @@ use futures::FutureExt;
 use log::debug;
 use resolver::Resolver;
 use store::SubscriptionStore;
-use ya_core_model::net::local::{BroadcastMessage, NewNeighbour, SendBroadcastMessage};
+use ya_core_model::net::local::{
+    BindBroadcastError, BroadcastMessage, NewNeighbour, SendBroadcastMessage,
+};
 use ya_net::bind_broadcast_with_caller;
 
 /// Stores proposal generated from resolver.
@@ -121,7 +123,7 @@ impl Matcher {
         Ok(())
     }
 
-    async fn bind_neighbourhood_bcast(&self, local_prefix: &str) -> anyhow::Result<()> {
+    async fn bind_neighbourhood_bcast(&self, local_prefix: &str) -> Result<(), BindBroadcastError> {
         let bcast_address = format!("{local_prefix}/{}", NewNeighbour::TOPIC);
         let myself = self.clone();
         bind_broadcast_with_caller(
@@ -131,13 +133,11 @@ impl Matcher {
                 async move {
                     debug!("Received new neighbour broadcast from [{}].", &caller);
                     cyclic::bcast_offers_once(myself.clone()).await;
-                    return Ok(());
+                    Ok(())
                 }
             },
         )
-        .await?;
-
-        Ok(())
+        .await
     }
 
     pub async fn bind_expiration_tracker(&self) -> anyhow::Result<()> {
diff --git a/core/market/src/protocol/discovery.rs b/core/market/src/protocol/discovery.rs
index 0b79caf0a2..831eefa854 100644
--- a/core/market/src/protocol/discovery.rs
+++ b/core/market/src/protocol/discovery.rs
@@ -386,14 +386,14 @@ impl Discovery {
 
         // We don't want to get overwhelmed by incoming broadcasts, that's why we drop them,
         // if the queue is full.
-        return match self.inner.offers_receiving_queue.try_send((caller, msg)) {
+        match self.inner.offers_receiving_queue.try_send((caller, msg)) {
             Ok(_) => Ok(()),
             Err(_) => {
                 log::trace!("Already handling to many broadcasts, skipping...");
                 counter!("market.offers.broadcasts.skip", 1);
                 Ok(())
             }
-        };
+        }
     }
 
     async fn on_get_remote_offers(
diff --git a/core/net/src/config.rs b/core/net/src/config.rs
index 61f01c25a6..b105096821 100644
--- a/core/net/src/config.rs
+++ b/core/net/src/config.rs
@@ -4,7 +4,9 @@ use strum::VariantNames;
 use strum::{EnumString, EnumVariantNames, IntoStaticStr};
 use url::Url;
 
-#[derive(StructOpt, EnumString, EnumVariantNames, IntoStaticStr, Copy, Clone, PartialEq, Debug)]
+#[derive(
+    StructOpt, EnumString, EnumVariantNames, IntoStaticStr, Copy, Clone, Eq, PartialEq, Debug,
+)]
 #[strum(serialize_all = "lowercase")]
 pub enum NetType {
     Central,
diff --git a/core/net/src/hybrid/service.rs b/core/net/src/hybrid/service.rs
index 262f60e260..e43ff86e0d 100644
--- a/core/net/src/hybrid/service.rs
+++ b/core/net/src/hybrid/service.rs
@@ -100,10 +100,11 @@ impl Net {
 
     pub async fn shutdown() -> anyhow::Result<()> {
         if let Ok(client) = Self::client().await {
-            if let Err(_) = client
+            if client
                 .shutdown()
                 .timeout(Some(std::time::Duration::from_secs(30)))
                 .await
+                .is_err()
             {
                 log::info!("NET shutdown due to timeout.");
             }
@@ -1147,14 +1148,11 @@ pub async fn send_bcast_new_neighbour() {
     let node_id = crate::service::identities().await.unwrap().0;
 
     let net_type = { *NET_TYPE.read().unwrap() };
-    match net_type {
-        NetType::Hybrid => {
-            log::debug!("Broadcasting new neighbour");
-            if let Err(e) = broadcast(node_id, NewNeighbour {}).await {
-                log::error!("Error broadcasting new neighbour: {e}");
-            }
+    if net_type == NetType::Hybrid {
+        log::debug!("Broadcasting new neighbour");
+        if let Err(e) = broadcast(node_id, NewNeighbour {}).await {
+            log::error!("Error broadcasting new neighbour: {e}");
         }
-        _ => {}
     }
 }
 
diff --git a/docs/development-plan.md b/docs/development-plan.md
index d6a951bb7f..c7430d6af6 100644
--- a/docs/development-plan.md
+++ b/docs/development-plan.md
@@ -73,7 +73,7 @@ https://phauer.com/2018/code-review-guidelines/
 
 ### Automatic Builds
 
-The project artifacts (i.e. installation packages and standalone/portable binaries) 
+The project artifacts (i.e. installation packages and standalone/portable binaries)
 should automatically build in Jenkins for every supported operating system (Linux, macOS, Windows).
 
 ### Bug Reporting
@@ -85,7 +85,7 @@ Bugs should be reported in GitHub Issues.
 ### Technology Stack
 
 The programming language used in this project will be Rust (https://www.rust-lang.org/).
-The newest stable version of Rust compiler (`rustc`) should compile all source code without errors.
+The 1.64.0 stable version of Rust compiler (`rustc`) should compile all source code without errors.
 
 For HTTP client/server code, Actix Web 1.0 (https://actix.rs) will be used.
 
@@ -126,7 +126,7 @@ The dependencies should not be spontaneously updated by developers.
 
 ### Usage Examples
 
-If a crate needs usage examples, they should be placed in the `examples` subdirectory of the crate. To run such example, 
+If a crate needs usage examples, they should be placed in the `examples` subdirectory of the crate. To run such example,
 please run `cargo run -p <package name> --example <example name>` command.
 
 ### Tests
diff --git a/golem_cli/src/command/provider.rs b/golem_cli/src/command/provider.rs
index 605a630b25..c52a51cac5 100644
--- a/golem_cli/src/command/provider.rs
+++ b/golem_cli/src/command/provider.rs
@@ -1,5 +1,6 @@
 use anyhow::Context;
 use serde::Deserialize;
+use std::ffi::OsStr;
 use std::{collections::BTreeMap, process::Stdio};
 use tokio::process::{Child, Command};
 
@@ -300,6 +301,65 @@ impl YaProviderCommand {
             .stdout(Stdio::inherit())
             .spawn()?)
     }
+
+    pub async fn add_certs<I, S>(self, certs: I) -> anyhow::Result<()>
+    where
+        I: IntoIterator<Item = S>,
+        S: AsRef<OsStr>,
+    {
+        let mut cmd = self.cmd;
+
+        let output = cmd
+            .args(&[
+                "keystore",
+                "add",
+                "-p",
+                "outbound-manifest",
+                "unverified-permissions-chain",
+                "-w",
+            ])
+            .args(certs)
+            .stderr(Stdio::piped())
+            .stdout(Stdio::null())
+            .stdin(Stdio::null())
+            .output()
+            .await
+            .context("failed adding certificates")?;
+
+        if output.status.success() {
+            Ok(())
+        } else {
+            let output = String::from_utf8_lossy(&output.stderr);
+            Err(anyhow::anyhow!("{}", output))
+        }
+    }
+
+    pub async fn extend_whitelist(
+        self,
+        whitelist_type: String,
+        entries: Vec<&str>,
+    ) -> anyhow::Result<()> {
+        let mut cmd = self.cmd;
+
+        let output = cmd
+            .args(&["whitelist", "add", "-t"])
+            .arg(whitelist_type)
+            .arg("-p")
+            .args(entries)
+            .stderr(Stdio::piped())
+            .stdout(Stdio::null())
+            .stdin(Stdio::null())
+            .output()
+            .await
+            .context("failed adding all entries to whitelist")?;
+
+        if output.status.success() {
+            Ok(())
+        } else {
+            let output = String::from_utf8_lossy(&output.stderr);
+            Err(anyhow::anyhow!("{}", output))
+        }
+    }
 }
 
 fn preset_command<'a, 'b>(
diff --git a/golem_cli/src/main.rs b/golem_cli/src/main.rs
index eb70578ce2..393aa85edc 100644
--- a/golem_cli/src/main.rs
+++ b/golem_cli/src/main.rs
@@ -8,6 +8,7 @@ use structopt::{clap, StructOpt};
 
 mod appkey;
 mod command;
+mod manifest;
 mod platform;
 mod service;
 mod settings;
@@ -31,6 +32,9 @@ enum Commands {
     #[structopt(setting = clap::AppSettings::Hidden)]
     Setup(setup::RunConfig),
 
+    #[structopt(setting = clap::AppSettings::Hidden)]
+    ManifestBundle(manifest::ManifestBundleCommand),
+
     /// Run the golem provider
     Run(setup::RunConfig),
 
@@ -105,8 +109,9 @@ async fn my_main() -> Result</*exit code*/ i32> {
             );
             Ok(0)
         }
+        Commands::ManifestBundle(command) => manifest::manifest_bundle(command).await,
         Commands::Other(args) => {
-            let cmd = crate::command::YaCommand::new()?;
+            let cmd = command::YaCommand::new()?;
             match cmd.yagna()?.forward(args).await? {
                 1 => {
                     let mut clap = Commands::clap();
diff --git a/golem_cli/src/manifest.rs b/golem_cli/src/manifest.rs
new file mode 100644
index 0000000000..bf4a234206
--- /dev/null
+++ b/golem_cli/src/manifest.rs
@@ -0,0 +1,95 @@
+use std::fs;
+use std::path::Path;
+use std::str::FromStr;
+
+use anyhow::Result;
+use structopt::StructOpt;
+use strum_macros::{Display, EnumString};
+
+use crate::command::YaCommand;
+
+#[derive(StructOpt)]
+pub enum ManifestBundleCommand {
+    /// Extend the configuration with the contents of the bundle
+    Add(ManifestBundle),
+}
+
+#[derive(StructOpt, Debug)]
+pub struct ManifestBundle {
+    /// Path to the decompressed bundle
+    // Golemfactory specific bundle is at https://github.com/golemfactory/ya-installer-resources/releases/latest
+    path: String,
+}
+
+#[derive(Display, EnumString)]
+#[strum(serialize_all = "snake_case")]
+enum WhitelistType {
+    Strict,
+    Regex,
+}
+
+pub async fn manifest_bundle(command: ManifestBundleCommand) -> Result<i32> {
+    match command {
+        ManifestBundleCommand::Add(ManifestBundle { path }) => add_manifest_bundle(path).await,
+    }
+}
+
+pub async fn add_manifest_bundle(path: String) -> Result<i32> {
+    add_certs(&path).await?;
+    add_whitelisted_domains(&path).await?;
+
+    Ok(0)
+}
+
+async fn add_certs(path: &String) -> Result<()> {
+    let cert_directory = format!("{path}/certs");
+    let directory = fs::read_dir(cert_directory)?;
+    let certs = directory
+        // canonicalize first to resolve symlinks
+        .map(|path| path.and_then(|p| p.path().canonicalize()))
+        // this will ignore paths that has errors (for example broken symlinks)
+        .filter(|path| path.as_ref().map(|p| p.is_file()).unwrap_or(false))
+        .map(|path| path.unwrap())
+        .collect::<Vec<_>>();
+
+    let cmd = YaCommand::new()?;
+    let provider = cmd.ya_provider()?;
+    provider.add_certs(certs).await
+}
+
+async fn add_whitelisted_domains(path: &String) -> Result<()> {
+    let whitelist_directory = format!("{path}/whitelist");
+    let directory = fs::read_dir(whitelist_directory)?;
+    let whitelists = directory
+        // canonicalize first to resolve symlinks
+        .map(|path| path.and_then(|p| p.path().canonicalize()))
+        // this will ignore paths that has errors (for example broken symlinks)
+        .filter(|path| path.as_ref().map(|p| p.is_file()).unwrap_or(false))
+        .map(|path| path.unwrap());
+
+    for whitelist in whitelists {
+        extend_whitelist(whitelist.as_path()).await?;
+    }
+
+    Ok(())
+}
+
+async fn extend_whitelist(path: &Path) -> Result<()> {
+    let file_stem = path
+        .file_stem()
+        .and_then(|osstr| osstr.to_str())
+        .ok_or_else(|| anyhow::anyhow!("Cannot determine filename from path: {:?}", path))?;
+
+    let whitelist_type = WhitelistType::from_str(file_stem)?;
+    let file_content = fs::read_to_string(path)?;
+    let entries = file_content
+        .lines()
+        .map(|line| line.trim())
+        .collect::<Vec<_>>();
+
+    let cmd = YaCommand::new()?;
+    let provider = cmd.ya_provider()?;
+    provider
+        .extend_whitelist(whitelist_type.to_string(), entries)
+        .await
+}
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
new file mode 100644
index 0000000000..326e550597
--- /dev/null
+++ b/rust-toolchain.toml
@@ -0,0 +1,4 @@
+[toolchain]
+channel = "1.64.0"
+components = [ "rustfmt", "clippy" ]
+targets = [ "x86_64-linux-musl" ]
diff --git a/utils/agreement-utils/src/agreement.rs b/utils/agreement-utils/src/agreement.rs
index ede5a4fb07..6f4f7d89f8 100644
--- a/utils/agreement-utils/src/agreement.rs
+++ b/utils/agreement-utils/src/agreement.rs
@@ -316,7 +316,7 @@ impl TypedArrayPointer for Option<&Value> {
 }
 
 pub fn try_from_path(path: &PathBuf) -> Result<Value, Error> {
-    let contents = std::fs::read_to_string(&path).map_err(Error::from)?;
+    let contents = std::fs::read_to_string(path).map_err(Error::from)?;
     let ext = match path.extension().and_then(|e| e.to_str()) {
         Some(ext) => ext,
         None => DEFAULT_FORMAT,
diff --git a/utils/fd-metrics/src/lib.rs b/utils/fd-metrics/src/lib.rs
index be5816b504..a7c4214bb4 100644
--- a/utils/fd-metrics/src/lib.rs
+++ b/utils/fd-metrics/src/lib.rs
@@ -69,6 +69,7 @@ pub fn fd_metrics() -> HashMap<FdType, usize> {
 /// Maps fd to FdType
 ///
 /// Uses fstat on unix, always returns None on Windows
+#[allow(unused_variables)]
 fn fd_type(fd: i32) -> Option<FdType> {
     #[cfg(target_family = "unix")]
     {


Test patch:
diff --git a/.github/workflows/market-test-suite.yml b/.github/workflows/market-test-suite.yml
index 5d108673e1..8d9285e525 100644
--- a/.github/workflows/market-test-suite.yml
+++ b/.github/workflows/market-test-suite.yml
@@ -10,6 +10,9 @@ on:
       - master
       - release/*
 
+env:
+  rust_stable: 1.64.0
+
 jobs:
   build:
     name: Market Test Suite
@@ -26,10 +29,10 @@ jobs:
       - name: Checkout
         uses: actions/checkout@v1
 
-      - name: Install last stable Rust
+      - name: Install Rust ${{ env.rust_stable }}
         uses: actions-rs/toolchain@v1
         with:
-          toolchain: stable
+          toolchain: ${{ env.rust_stable }}
           components: rustfmt, clippy
 
       - name: Check lockfile
diff --git a/.github/workflows/unit-test-sgx.yml b/.github/workflows/unit-test-sgx.yml
index 47b2bacccc..ae696030d1 100644
--- a/.github/workflows/unit-test-sgx.yml
+++ b/.github/workflows/unit-test-sgx.yml
@@ -11,6 +11,9 @@ on:
       - release/*
       - sgx/*
 
+env:
+  rust_stable: 1.64.0
+
 jobs:
   build:
     name: SGX Unit Tests
@@ -26,10 +29,10 @@ jobs:
       - name: Checkout
         uses: actions/checkout@v1
 
-      - name: Install last stable Rust
+      - name: Install Rust ${{ env.rust_stable }}
         uses: actions-rs/toolchain@v1
         with:
-          toolchain: stable
+          toolchain: ${{ env.rust_stable }}
 
       - name: Unit tests for SGX
         working-directory: exe-unit
diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml
index 330e1f2b7b..b7acbb0a24 100644
--- a/.github/workflows/unit-test.yml
+++ b/.github/workflows/unit-test.yml
@@ -10,12 +10,15 @@ on:
       - master
       - release/*
 
+env:
+  rust_stable: 1.64.0
+
 jobs:
   build:
     name: Unit Tests
     env:
       # `-D warnings` means any warnings emitted will cause build to fail
-      RUSTFLAGS: "-C opt-level=z -C target-cpu=x86-64 -C debuginfo=1"
+      RUSTFLAGS: "-D warnings -C opt-level=z -C target-cpu=x86-64 -C debuginfo=1"
       X86_64_PC_WINDOWS_MSVC_OPENSSL_DIR: c:/vcpkg/installed/x64-windows
     runs-on: ${{ matrix.os }}
     strategy:
@@ -26,10 +29,10 @@ jobs:
       - name: Checkout
         uses: actions/checkout@v1
 
-      - name: Install last stable Rust
+      - name: Install Rust ${{ env.rust_stable }}
         uses: actions-rs/toolchain@v1
         with:
-          toolchain: stable
+          toolchain: ${{ env.rust_stable }}
           components: rustfmt, clippy
 
       - name: Check lockfile
@@ -48,7 +51,7 @@ jobs:
         uses: actions-rs/cargo@v1
         with:
           command: clippy
-          args: --all-targets --all-features --workspace
+          args: --all-targets --all-features --workspace -- -D warnings
 
       - name: Install openssl ( Windows only )
         if: runner.os == 'Windows'
diff --git a/goth_tests/poetry.lock b/goth_tests/poetry.lock
index 833c4fb1cc..ac5b516c31 100644
--- a/goth_tests/poetry.lock
+++ b/goth_tests/poetry.lock
@@ -269,11 +269,11 @@ python-versions = "*"
 
 [[package]]
 name = "dpath"
-version = "2.0.6"
+version = "2.0.8"
 description = "Filesystem-like pathing and searching for dictionaries"
 category = "main"
 optional = false
-python-versions = ">=3"
+python-versions = ">=3.7"
 
 [[package]]
 name = "fastcore"
@@ -617,7 +617,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
 [[package]]
 name = "pathspec"
-version = "0.10.1"
+version = "0.10.2"
 description = "Utility library for gitignore style pattern matching of file paths."
 category = "dev"
 optional = false
@@ -789,17 +789,29 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xm
 
 [[package]]
 name = "pytest-asyncio"
-version = "0.14.0"
-description = "Pytest support for asyncio."
+version = "0.20.2"
+description = "Pytest support for asyncio"
 category = "main"
 optional = false
-python-versions = ">= 3.5"
+python-versions = ">=3.7"
 
 [package.dependencies]
-pytest = ">=5.4.0"
+pytest = ">=6.1.0"
 
 [package.extras]
-testing = ["async-generator (>=1.3)", "coverage", "hypothesis (>=5.7.1)"]
+testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"]
+
+[[package]]
+name = "pytest-rerunfailures"
+version = "10.3"
+description = "pytest plugin to re-run tests to eliminate flaky failures"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+packaging = ">=17.1"
+pytest = ">=5.3"
 
 [[package]]
 name = "python-dateutil"
@@ -890,7 +902,7 @@ python-versions = ">=3.5"
 
 [[package]]
 name = "setuptools"
-version = "65.5.1"
+version = "65.6.3"
 description = "Easily download, build, install, upgrade, and uninstall Python packages"
 category = "main"
 optional = false
@@ -919,8 +931,8 @@ python-versions = "*"
 
 [[package]]
 name = "texttable"
-version = "1.6.4"
-description = "module for creating simple ASCII tables"
+version = "1.6.7"
+description = "module to create simple ASCII tables"
 category = "main"
 optional = false
 python-versions = "*"
@@ -982,11 +994,11 @@ python-versions = "*"
 
 [[package]]
 name = "urllib3"
-version = "1.26.12"
+version = "1.26.13"
 description = "HTTP library with thread-safe connection pooling, file post, and more."
 category = "main"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
 
 [package.extras]
 brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
@@ -1071,7 +1083,7 @@ python-versions = "*"
 [metadata]
 lock-version = "1.1"
 python-versions = "^3.8.0"
-content-hash = "cc5966c072e9037f5a79dc21e18c3b5b50025d5a87befe63b021d75520f9c203"
+content-hash = "0ae3d50fbe13355544c6bf89ca3ff7a971e51fcaf530220b0d479c98b5b1f2cb"
 
 [metadata.files]
 aiohttp = [
@@ -1358,8 +1370,8 @@ docopt = [
     {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"},
 ]
 dpath = [
-    {file = "dpath-2.0.6-py3-none-any.whl", hash = "sha256:8c439bb1c3b3222427e9b8812701cd99a0ef3415ddbb7c03a2379f6989a03965"},
-    {file = "dpath-2.0.6.tar.gz", hash = "sha256:5a1ddae52233fbc8ef81b15fb85073a81126bb43698d3f3a1b6aaf561a46cdc0"},
+    {file = "dpath-2.0.8-py3-none-any.whl", hash = "sha256:f92f595214dd93a00558d75d4b858beee519f4cffca87f02616ad6cd013f3436"},
+    {file = "dpath-2.0.8.tar.gz", hash = "sha256:a3440157ebe80d0a3ad794f1b61c571bef125214800ffdb9afc9424e8250fe9b"},
 ]
 fastcore = [
     {file = "fastcore-1.5.27-py3-none-any.whl", hash = "sha256:79dffaa3de96066e4d7f2b8793f1a8a9468c82bc97d3d48ec002de34097b2a9f"},
@@ -1646,8 +1658,8 @@ pastel = [
     {file = "pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d"},
 ]
 pathspec = [
-    {file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"},
-    {file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"},
+    {file = "pathspec-0.10.2-py3-none-any.whl", hash = "sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5"},
+    {file = "pathspec-0.10.2.tar.gz", hash = "sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0"},
 ]
 pip = [
     {file = "pip-22.3.1-py3-none-any.whl", hash = "sha256:908c78e6bc29b676ede1c4d57981d490cb892eb45cd8c214ab6298125119e077"},
@@ -1753,8 +1765,12 @@ pytest = [
     {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"},
 ]
 pytest-asyncio = [
-    {file = "pytest-asyncio-0.14.0.tar.gz", hash = "sha256:9882c0c6b24429449f5f969a5158b528f39bde47dc32e85b9f0403965017e700"},
-    {file = "pytest_asyncio-0.14.0-py3-none-any.whl", hash = "sha256:2eae1e34f6c68fc0a9dc12d4bea190483843ff4708d24277c41568d6b6044f1d"},
+    {file = "pytest-asyncio-0.20.2.tar.gz", hash = "sha256:32a87a9836298a881c0ec637ebcc952cfe23a56436bdc0d09d1511941dd8a812"},
+    {file = "pytest_asyncio-0.20.2-py3-none-any.whl", hash = "sha256:07e0abf9e6e6b95894a39f688a4a875d63c2128f76c02d03d16ccbc35bcc0f8a"},
+]
+pytest-rerunfailures = [
+    {file = "pytest-rerunfailures-10.3.tar.gz", hash = "sha256:d8244d799f89a6edb5e57301ddaeb3b6f10d6691638d51e80b371311592e28c6"},
+    {file = "pytest_rerunfailures-10.3-py3-none-any.whl", hash = "sha256:6be6f96510bf94b54198bf15bc5568fe2cdff88e83875912e22d29810acf65ff"},
 ]
 python-dateutil = [
     {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
@@ -1943,8 +1959,8 @@ ruamel-yaml-clib = [
     {file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"},
 ]
 setuptools = [
-    {file = "setuptools-65.5.1-py3-none-any.whl", hash = "sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31"},
-    {file = "setuptools-65.5.1.tar.gz", hash = "sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"},
+    {file = "setuptools-65.6.3-py3-none-any.whl", hash = "sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54"},
+    {file = "setuptools-65.6.3.tar.gz", hash = "sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75"},
 ]
 six = [
     {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
@@ -1955,8 +1971,8 @@ sortedcontainers = [
     {file = "sortedcontainers-2.2.2.tar.gz", hash = "sha256:4e73a757831fc3ca4de2859c422564239a31d8213d09a2a666e375807034d2ba"},
 ]
 texttable = [
-    {file = "texttable-1.6.4-py2.py3-none-any.whl", hash = "sha256:dd2b0eaebb2a9e167d1cefedab4700e5dcbdb076114eed30b58b97ed6b37d6f2"},
-    {file = "texttable-1.6.4.tar.gz", hash = "sha256:42ee7b9e15f7b225747c3fa08f43c5d6c83bc899f80ff9bae9319334824076e9"},
+    {file = "texttable-1.6.7-py2.py3-none-any.whl", hash = "sha256:b7b68139aa8a6339d2c320ca8b1dc42d13a7831a346b446cb9eb385f0c76310c"},
+    {file = "texttable-1.6.7.tar.gz", hash = "sha256:290348fb67f7746931bcdfd55ac7584ecd4e5b0846ab164333f0794b121760f2"},
 ]
 toml = [
     {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
@@ -2021,8 +2037,8 @@ typing-extensions = [
     {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"},
 ]
 urllib3 = [
-    {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"},
-    {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"},
+    {file = "urllib3-1.26.13-py2.py3-none-any.whl", hash = "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc"},
+    {file = "urllib3-1.26.13.tar.gz", hash = "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8"},
 ]
 urwid = [
     {file = "urwid-2.1.2.tar.gz", hash = "sha256:588bee9c1cb208d0906a9f73c613d2bd32c3ed3702012f51efe318a3f2127eae"},
diff --git a/goth_tests/pyproject.toml b/goth_tests/pyproject.toml
index d4f1f54b49..a06c1f8826 100644
--- a/goth_tests/pyproject.toml
+++ b/goth_tests/pyproject.toml
@@ -19,7 +19,8 @@ readme = "README.md"
 [tool.poetry.dependencies]
 python = "^3.8.0"
 pytest = "^6.2"
-pytest-asyncio = "^0.14"
+pytest-asyncio = "^0.20.2"
+pytest-rerunfailures = "^10.3"
 #goth = "^0.11"
 # to use development goth version uncomment below
 goth =  { git = "https://github.com/golemfactory/goth.git", rev = "e81663ab5f220abf4dd497dec735c3ec73702351" }
@@ -32,6 +33,6 @@ poethepoet = "^0.10.0"
 [tool.poe.tasks]
 codestyle = "black --check --diff ."
 goth-assets = "python -m goth create-assets assets"
-goth-tests = "pytest -svx ."
+goth-tests = "pytest -svx . --reruns 3 --only-rerun AssertionError --only-rerun TimeoutError --only-rerun ApiException --only-rerun goth.runner.exceptions.TemporalAssertionError --only-rerun urllib.error.URLError --only-rerun goth.runner.exceptions.CommandError"
 provider-tests = "pytest -svx ./domain/ya-provider"
 typecheck = "mypy ."