This repository was archived by the owner on Dec 13, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 1
Adding ipfs trait #10
Merged
Merged
Changes from all commits
Commits
Show all changes
64 commits
Select commit
Hold shift + click to select a range
cc7a1dd
Moving stuff from other branch
BoisterousCoder 3e5e770
IPFS Trait Complete
BoisterousCoder 9bf1c5e
adding what I got so I can review brian's pr
BoisterousCoder af8d470
ready for testing for a lot of it
BoisterousCoder 9dc9831
first test done
BoisterousCoder caaa869
fibonacci http retry wait
BoisterousCoder 3243116
try fail http fixed
BoisterousCoder cc4f983
refactor and more
BoisterousCoder faede32
files upload to ipfs finnally
BoisterousCoder 7c4d779
removing auto disconnect for now
BoisterousCoder c4442de
oops
BoisterousCoder a8114fe
testing add file
BoisterousCoder 66c040e
finnishing add file
BoisterousCoder 03bf7a4
quick fix for file adding
BoisterousCoder 72911e0
remove warnings
BoisterousCoder 31c0dee
fixing config
BoisterousCoder 3750b4f
Moving stuff from other branch
BoisterousCoder 5c665be
IPFS Trait Complete
BoisterousCoder 617cf35
adding what I got so I can review brian's pr
BoisterousCoder a8024c2
ready for testing for a lot of it
BoisterousCoder 3c06f28
first test done
BoisterousCoder bf7db06
fibonacci http retry wait
BoisterousCoder 0999da9
try fail http fixed
BoisterousCoder 262c6e7
refactor and more
BoisterousCoder d27be60
files upload to ipfs finnally
BoisterousCoder 1660c8a
removing auto disconnect for now
BoisterousCoder 5928dde
oops
BoisterousCoder 6034492
testing add file
BoisterousCoder a00f9d9
finnishing add file
BoisterousCoder 40c76ee
quick fix for file adding
BoisterousCoder 69e43c6
remove warnings
BoisterousCoder d13c31b
fixing config
BoisterousCoder 9c38cf3
rebase fix
BoisterousCoder cd728a5
Merge branch 'adding-ipfs-trait' of github.com:fission-codes/fission-…
BoisterousCoder 0a06fc7
fix duplicate
BoisterousCoder 5356210
started on cofig
BoisterousCoder ddf6387
Add error and formatting
bgins 1cd9f55
re adding the disconnect from on drop
BoisterousCoder e3b0423
remove add bootstrap
BoisterousCoder 0deb42c
Config templating
BoisterousCoder b604f5c
ready for refactor
BoisterousCoder c95cf61
Update import formatting
bgins 1ec8e4f
Rename IPFS Daemon
bgins d16023b
Handle null values in config
BoisterousCoder 1c963b5
Separate out daemon tests into a module
bgins 719f91d
Move http module to utils
bgins c746cc0
Add whitespace
bgins 97f91df
Starting to move to ipfs-api llib
BoisterousCoder 098141d
config moved to lib
BoisterousCoder 1548f7c
Graceful Shutdown
BoisterousCoder d48cc24
add bootstap start
BoisterousCoder e3a8750
Adding Documentation
BoisterousCoder 5243302
connect to
BoisterousCoder 0758c6b
switch to main fork for ipfs-api
BoisterousCoder b1b8126
Update src/ipfs.rs
88eea6c
Update src/ipfs.rs
09fae95
Update src/ipfs.rs
3f919c1
Update src/ipfs.rs
d3d5344
Update src/utils/config.rs
5c0bc5b
Update src/ipfs.rs
831647f
Accidently made changes to the wrong branch
e345e60
mostly copy edits
BoisterousCoder a3c934a
ignored doc tests
BoisterousCoder 1a80100
Removing dead code
BoisterousCoder File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| use std::{collections::HashMap, path::Path}; | ||
|
|
||
| use anyhow::Result; | ||
| use async_trait::async_trait; | ||
| use serde_json::Value; | ||
|
|
||
| pub mod daemon; | ||
| #[async_trait] | ||
| pub trait Ipfs { | ||
| /// This method uploads a file or directory at a given path to the IPFS swarm you are | ||
| /// currently connected to. | ||
| async fn add(&self, path:&Path) -> Result<HashMap<String, String>>; | ||
| /// This method connects to the given address, adding the address to the current swarm | ||
| async fn connect_to(&self, peer_id:&str) -> Result<()>; | ||
| /// This method returns a list of all the addresses that are currently connected | ||
| async fn get_connected(&self) -> Result<Vec<String>>; | ||
| /// This method changes the value of a given property in the IPFS config | ||
| /// | ||
| /// ```no_run | ||
| /// use fission::ipfs::daemon::IpfsDaemon; | ||
| /// use fission::ipfs::Ipfs; | ||
| /// use futures::executor::block_on; | ||
| /// use serde_json::Value; | ||
| /// | ||
| /// let ipfs = IpfsDaemon::default(); | ||
| /// let config_value = Value::from("11GB"); | ||
| /// block_on(ipfs.set_config("Datastore.StorageMax", &config_value)).unwrap(); | ||
| /// ``` | ||
| async fn set_config(&self, property:&str, val:&Value) -> Result<()>; | ||
|
|
||
| /// This method returns the value a property in the IPFS config | ||
| /// | ||
| /// ```no_run | ||
| /// use fission::ipfs::daemon::IpfsDaemon; | ||
| /// use fission::ipfs::Ipfs; | ||
| /// use futures::executor::block_on; | ||
| /// | ||
| /// let ipfs = IpfsDaemon::default(); | ||
| /// let config_value = block_on(ipfs.get_config("Datastore.StorageMax")).unwrap(); | ||
| /// ``` | ||
| async fn get_config(&self, property: &str) -> Result<Value>; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,236 @@ | ||
| use std::collections::HashMap; | ||
| use std::path::Path; | ||
| use std::process::Command; | ||
| use std::thread; | ||
| use std::time::{Duration, SystemTime}; | ||
|
|
||
| use anyhow::{bail, Result}; | ||
| use async_trait::async_trait; | ||
| use colored::Colorize; | ||
| use futures::executor::block_on; | ||
| use graceful::SignalGuard; | ||
| use ipfs_api_backend_hyper::{IpfsApi, IpfsClient, Logger, LoggingLevel, TryFromUri}; | ||
| use serde_json::Value; | ||
| use tokio::runtime::Runtime; | ||
|
|
||
| use crate::ipfs::Ipfs; | ||
| use crate::utils::config::{ | ||
| IPFS_ADDR, IPFS_API_PORT, IPFS_BOOT_TIME_OUT, IPFS_EXE, IPFS_SLEEP_LENGTH, | ||
| }; | ||
|
|
||
| /// This struct is a wrapper for the information needed to point the IPFS daemon at a diffrent address | ||
| /// than the default. | ||
| #[derive(Clone, Debug)] | ||
| pub struct IpfsConnInfo { | ||
| pub address: String, | ||
| pub port: u16, | ||
| } | ||
|
|
||
| pub struct IpfsDaemon { | ||
| conn_info: IpfsConnInfo, | ||
| client: IpfsClient, | ||
| tokio: Runtime, | ||
| } | ||
|
|
||
| impl IpfsDaemon { | ||
| /// This method launches the IPFS daemon on the port/address given when the instance was | ||
| /// created. During this proccess, it also creates a thread that listens for a shutdown signal | ||
| /// and stops the IPFS daemon gracefully if the signal is given. | ||
| pub async fn launch(&self) -> Result<()> { | ||
| //launch the daemon | ||
| let api_addr = format!( | ||
| "/ip4/{}/tcp/{}", | ||
| self.conn_info.address, self.conn_info.port | ||
| ); | ||
| println!("Launching IPFS..."); | ||
| Command::new(IPFS_EXE) | ||
| .arg("--api") | ||
| .arg(&api_addr) | ||
| .arg("daemon") | ||
| .spawn() | ||
| .unwrap_or_else(|e| panic!("Failed to start IPFS daemon: {}\n This error may be because the Kubo binary is not on your PATH.", e)); | ||
|
|
||
| // Wait ipfs to be ready | ||
| println!("Waiting for IPFS to ready.."); | ||
| self.await_ready().await?; | ||
|
|
||
| // Reduce log level for IPFS | ||
| self.tokio.block_on(async { | ||
| self.client | ||
| .log_level(Logger::All, LoggingLevel::Error) | ||
| .await | ||
| })?; | ||
|
|
||
| // Setup graceful shutdown | ||
| println!("Creating graceful shutdown for IPFS..."); | ||
| let me = self.clone(); | ||
| thread::spawn(move || { | ||
| let signal_guard = SignalGuard::new(); | ||
|
|
||
| signal_guard.at_exit(move |sig| { | ||
|
BoisterousCoder marked this conversation as resolved.
|
||
| println!("Signal {} received. Attempting to stop IPFS...", sig); | ||
| match me.shutdown() { | ||
| Ok(_) => println!("{}", "IPFS has shutdown successfully.".green()), | ||
| Err(_) => println!("{}", "IPFS failed to shutdown succefully! You may need to stop the proccess yourself.".red()) | ||
| }; | ||
| }); | ||
| }); | ||
|
|
||
| println!("{}", "IPFS has launched successfully!!".green()); | ||
| Ok(()) | ||
| } | ||
|
|
||
| /// This method sends an http signal to the IPFS deamon to shutdown. | ||
| /// | ||
| /// Note 1: This method should work even if the daemon was not started by this proccess. | ||
| /// | ||
| /// Note 2: This method returns when it recieves an http response from the daemon, not | ||
| /// when the proccess has actually stopped. | ||
| pub fn shutdown(&self) -> Result<()> { | ||
| self.tokio | ||
| .block_on(async { block_on(self.client.shutdown()) })?; | ||
| Ok(()) | ||
| } | ||
|
|
||
| async fn is_ipfs_ready(&self) -> bool { | ||
| let res = self | ||
| .tokio | ||
| .block_on(async { self.client.config_show().await }); | ||
| return match res { | ||
| Ok(_) => true, | ||
| Err(_) => false, | ||
| }; | ||
| } | ||
|
|
||
| async fn await_ready(&self) -> Result<()> { | ||
| let start_time = SystemTime::now(); | ||
| loop { | ||
| println!("{}", "Checking if ipfs is ready...".green()); | ||
|
|
||
| if self.is_ipfs_ready().await { | ||
| println!("{}", "IPFS is ready!!".green()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🕺✨ |
||
| break; | ||
| } | ||
|
|
||
| thread::sleep(Duration::new(IPFS_SLEEP_LENGTH as u64, 0)); | ||
|
|
||
| let now = SystemTime::now(); | ||
| if now.duration_since(start_time)? > Duration::new(IPFS_BOOT_TIME_OUT as u64, 0) { | ||
| bail!( | ||
| "{}", | ||
| "Failed to start IPFS because the timeout reached!!".red() | ||
| ) | ||
| } | ||
| } | ||
| anyhow::Ok(()) | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<IpfsConnInfo> for IpfsDaemon { | ||
| type Error = anyhow::Error; | ||
| /// This is one of the two ways to make a new instance of the IPFS daemon struct. Use this | ||
| /// method when you want to make a new instance and you need to set the port and address of | ||
| /// the daemon you are attempting to reference | ||
| fn try_from(conn_info: IpfsConnInfo) -> Result<Self> { | ||
| let client = | ||
| IpfsClient::from_host_and_port("http".parse()?, &conn_info.address, conn_info.port)?; | ||
|
|
||
| let runtime = tokio::runtime::Runtime::new()?; | ||
| Ok(Self { | ||
| client, | ||
| tokio: runtime, | ||
| conn_info, | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| impl Default for IpfsDaemon { | ||
| /// This is one of the two ways to make a new instance of the IPFS daemon struct. Use this | ||
| /// method when you want to make a new instance and you okay with using the default port and address | ||
| /// set by the config. | ||
| /// | ||
| /// Note: This method has the possiblity of throwing an error if the configuration of the port and | ||
| /// address is not setup right. | ||
| fn default() -> Self { | ||
| Self::try_from(IpfsConnInfo { | ||
| address: IPFS_ADDR.to_string(), | ||
| port: IPFS_API_PORT, | ||
| }) | ||
| .unwrap() | ||
| } | ||
| } | ||
| impl Clone for IpfsDaemon { | ||
| fn clone(&self) -> Self { | ||
| return Self { | ||
| client: self.client.clone(), | ||
| tokio: Runtime::new().unwrap(), | ||
| conn_info: self.conn_info.clone(), | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| #[async_trait] | ||
| impl Ipfs for IpfsDaemon { | ||
| async fn add(&self, path: &Path) -> Result<HashMap<String, String>> { | ||
| let response_list = self | ||
| .tokio | ||
| .block_on(async { self.client.add_path(path).await })?; | ||
| return Ok(response_list | ||
| .into_iter() | ||
| .map(|res| (res.name, res.hash)) | ||
| .collect()); | ||
| } | ||
| async fn connect_to(&self, peer_id: &str) -> Result<()> { | ||
| let messages = self | ||
| .tokio | ||
| .block_on(async { self.client.swarm_connect(peer_id).await })? | ||
| .strings; | ||
| for msg in messages { | ||
| println!("{}", msg.blue()); | ||
| if !msg.contains("success") { | ||
| bail!(msg); | ||
| } | ||
| } | ||
| return Ok(()); | ||
| } | ||
| async fn get_connected(&self) -> Result<Vec<String>> { | ||
| let peers = self | ||
| .tokio | ||
| .block_on(async { self.client.swarm_peers().await })?; | ||
| Ok(peers.peers.into_iter().map(|peer| peer.addr).collect()) | ||
| } | ||
| async fn get_config(&self, prop: &str) -> Result<Value> { | ||
| let config = self | ||
| .tokio | ||
| .block_on(async { self.client.config_get_json(prop).await })?; | ||
| return Ok(config.value); | ||
| } | ||
| async fn set_config(&self, prop: &str, val: &Value) -> Result<()> { | ||
| if val.is_boolean() { | ||
| self.tokio.block_on(async { | ||
| self.client | ||
| .config_set_bool(prop, val.as_bool().unwrap()) | ||
| .await | ||
| })?; | ||
| return Ok(()); | ||
| } | ||
| if val.is_string() { | ||
| self.tokio.block_on(async { | ||
| self.client | ||
| .config_set_string(prop, val.as_str().unwrap()) | ||
| .await | ||
| })?; | ||
| return Ok(()); | ||
| } | ||
| if val.is_number() || val.is_null() { | ||
| bail!( | ||
| "{}", | ||
| "The IPFS config API does not suport null or number json types" | ||
| ) | ||
| } | ||
| self.tokio | ||
| .block_on(async { self.client.config_set_json(prop, &val.to_string()).await })?; | ||
|
|
||
| return Ok(()); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,7 @@ | ||
| pub mod cmd; | ||
| pub mod ipfs; | ||
| pub mod legacy; | ||
| pub mod utils; | ||
|
|
||
| #[cfg(test)] | ||
| pub mod test; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| pub mod daemon; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.