Skip to content

Commit

Permalink
cli: Allow custom cluster config (coral-xyz#2271)
Browse files Browse the repository at this point in the history
* cli: Allow custom cluster config

* Update changelog

* Downgrade the code

* Fix rust fmt

Co-authored-by: Henry-E <henry.elder@adaptcentre.ie>
  • Loading branch information
2 people authored and henrye committed Dec 6, 2022
1 parent 52516ae commit 26edceb
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ The minor version will be incremented upon a breaking change and the patch versi
- ts: Update the Solana web3 library used by anchor ts to version 1.64.0 ([#2220](https://github.com/coral-xyz/anchor/issues/2220)).
- lang: Updates `AccountsClose` to make it safe to call manually ([#2209](https://github.com/coral-xyz/anchor/pull/2209)).
- lang: Update rust used in the repo version 1.64 ([#2272](https://github.com/coral-xyz/anchor/pull/2272)).
- cli: Allow custom cluster config ([#2271](https://github.com/coral-xyz/anchor/pull/2271)).
- cli: Add `test.validator.geyser_plugin_config` support ([#2016](https://github.com/coral-xyz/anchor/pull/2016)).

### Fixes
Expand Down
73 changes: 68 additions & 5 deletions cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,22 @@ use anchor_syn::idl::Idl;
use anyhow::{anyhow, Context, Error, Result};
use clap::{Parser, ValueEnum};
use heck::ToSnakeCase;
use serde::{Deserialize, Serialize};
use reqwest::Url;
use serde::de::{self, MapAccess, Visitor};
use serde::{Deserialize, Deserializer, Serialize};
use solana_cli_config::{Config as SolanaConfig, CONFIG_FILE};
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, Signer};
use std::collections::{BTreeMap, HashMap};
use std::convert::TryFrom;
use std::fs::{self, File};
use std::io;
use std::io::prelude::*;
use std::marker::PhantomData;
use std::ops::Deref;
use std::path::Path;
use std::path::PathBuf;
use std::str::FromStr;
use std::{fmt, io};
use walkdir::WalkDir;

pub trait Merge: Sized {
Expand Down Expand Up @@ -420,10 +423,58 @@ struct _Config {

#[derive(Debug, Serialize, Deserialize)]
struct Provider {
cluster: String,
#[serde(deserialize_with = "des_cluster")]
cluster: Cluster,
wallet: String,
}

fn des_cluster<'de, D>(deserializer: D) -> Result<Cluster, D::Error>
where
D: Deserializer<'de>,
{
struct StringOrCustomCluster(PhantomData<fn() -> Cluster>);

impl<'de> Visitor<'de> for StringOrCustomCluster {
type Value = Cluster;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string or map")
}

fn visit_str<E>(self, value: &str) -> Result<Cluster, E>
where
E: de::Error,
{
value.parse().map_err(de::Error::custom)
}

fn visit_map<M>(self, mut map: M) -> Result<Cluster, M::Error>
where
M: MapAccess<'de>,
{
// Gets keys
if let (Some((http_key, http_value)), Some((ws_key, ws_value))) = (
map.next_entry::<String, String>()?,
map.next_entry::<String, String>()?,
) {
// Checks keys
if http_key != "http" || ws_key != "ws" {
return Err(de::Error::custom("Invalid key"));
}

// Checks urls
Url::parse(&http_value).map_err(de::Error::custom)?;
Url::parse(&ws_value).map_err(de::Error::custom)?;

Ok(Cluster::Custom(http_value, ws_value))
} else {
Err(de::Error::custom("Invalid entry"))
}
}
}
deserializer.deserialize_any(StringOrCustomCluster(PhantomData))
}

impl ToString for Config {
fn to_string(&self) -> String {
let programs = {
Expand All @@ -440,7 +491,7 @@ impl ToString for Config {
features: Some(self.features.clone()),
registry: Some(self.registry.clone()),
provider: Provider {
cluster: format!("{}", self.provider.cluster),
cluster: self.provider.cluster.clone(),
wallet: self.provider.wallet.to_string(),
},
test: self.test_validator.clone().map(Into::into),
Expand Down Expand Up @@ -469,7 +520,7 @@ impl FromStr for Config {
features: cfg.features.unwrap_or_default(),
registry: cfg.registry.unwrap_or_default(),
provider: ProviderConfig {
cluster: cfg.provider.cluster.parse()?,
cluster: cfg.provider.cluster,
wallet: shellexpand::tilde(&cfg.provider.wallet).parse()?,
},
scripts: cfg.scripts.unwrap_or_default(),
Expand Down Expand Up @@ -1149,6 +1200,18 @@ mod tests {
wallet = \"id.json\"
";

const CUSTOM_CONFIG: &str = "
[provider]
cluster = { http = \"http://my-url.com\", ws = \"ws://my-url.com\" }
wallet = \"id.json\"
";

#[test]
fn parse_custom_cluster() {
let config = Config::from_str(CUSTOM_CONFIG).unwrap();
assert!(!config.features.skip_lint);
}

#[test]
fn parse_skip_lint_no_section() {
let config = Config::from_str(BASE_CONFIG).unwrap();
Expand Down

0 comments on commit 26edceb

Please sign in to comment.