From bedd261b882778a5b34ca609a37273eed9a6d5e2 Mon Sep 17 00:00:00 2001 From: Jordan Oroshiba Date: Mon, 11 Dec 2023 13:17:37 -0800 Subject: [PATCH] feat(cli)!: update to use new chart structure, dusk-2 (#611) ## Summary Updates the CLI to work with dusk-2 and the many chart structural updates since then. ## Background Migrating to dusk-2 which uses new charts which are improved, but have some structural differences ## Changes - added a `debug` flag and default false on deploy. Now defaults to not printing all k8s - deduped the sequencer rpc constants - updated to support namespaces with the new globals - added naming on the celestia light node to avoid collisions in same namespace - made namespaces set via the rollup config file ## Testing Manually deployed a local chart ## Breaking Changelist - Different APIs hit, supports different charts. The yaml files from previous cli will not be compatible. --- Cargo.lock | 2 +- crates/astria-cli/Cargo.toml | 2 +- crates/astria-cli/src/cli/mod.rs | 2 + crates/astria-cli/src/cli/rollup.rs | 15 ++- crates/astria-cli/src/cli/sequencer.rs | 12 +- crates/astria-cli/src/commands/rollup.rs | 19 ++-- crates/astria-cli/src/types.rs | 133 ++++++++++++++++++----- 7 files changed, 135 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de77dae9c0..6fe13de959 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -522,7 +522,7 @@ dependencies = [ [[package]] name = "astria-cli" -version = "0.1.0" +version = "0.2.0" dependencies = [ "assert_cmd", "astria-proto", diff --git a/crates/astria-cli/Cargo.toml b/crates/astria-cli/Cargo.toml index 4beca68c80..ddb06b6c23 100644 --- a/crates/astria-cli/Cargo.toml +++ b/crates/astria-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "astria-cli" -version = "0.1.0" +version = "0.2.0" edition = "2021" [[bin]] diff --git a/crates/astria-cli/src/cli/mod.rs b/crates/astria-cli/src/cli/mod.rs index c27d69ab81..49eb6b21cd 100644 --- a/crates/astria-cli/src/cli/mod.rs +++ b/crates/astria-cli/src/cli/mod.rs @@ -12,6 +12,8 @@ use crate::cli::{ sequencer::Command as SequencerCommand, }; +const DEFAULT_SEQUENCER_RPC: &str = "https://rpc.sequencer.dusk-2.devnet.astria.org"; + /// A CLI for deploying and managing Astria services and related infrastructure. #[derive(Debug, Parser)] #[clap(name = "astria-cli", version)] diff --git a/crates/astria-cli/src/cli/rollup.rs b/crates/astria-cli/src/cli/rollup.rs index 084fca7a8d..436f69e360 100644 --- a/crates/astria-cli/src/cli/rollup.rs +++ b/crates/astria-cli/src/cli/rollup.rs @@ -8,9 +8,8 @@ use color_eyre::eyre; use serde::Serialize; const DEFAULT_ROLLUP_CHART_PATH: &str = - "https://astriaorg.github.io/dev-cluster/astria-evm-rollup-0.4.4.tgz"; -const DEFAULT_SEQUENCER_RPC: &str = "https://rpc.sequencer.dusk-1.devnet.astria.org"; -const DEFAULT_SEQUENCER_WS: &str = "wss://rpc.sequencer.dusk-1.devnet.astria.org/websocket"; + "https://astriaorg.github.io/dev-cluster/astria-evm-rollup-0.7.1.tgz"; +const DEFAULT_SEQUENCER_WS: &str = "wss://rpc.sequencer.dusk-2.devnet.astria.org/websocket"; const DEFAULT_LOG_LEVEL: &str = "debug"; const DEFAULT_NETWORK_ID: u64 = 1337; const DEFAULT_HOSTNAME: &str = "localdev.me"; @@ -68,10 +67,6 @@ pub struct ConfigCreateArgs { /// The Network ID for the EVM chain #[clap(long = "rollup.network-id", env = "ROLLUP_NETWORK_ID", default_value_t = DEFAULT_NETWORK_ID)] pub network_id: u64, - /// When enabled, rollup will skip blocks which contain zero transactions. - #[clap(long = "rollup.skip-empty-blocks", env = "ROLLUP_SKIP_EMPTY_BLOCKS")] - pub skip_empty_blocks: bool, - /// List of genesis accounts to fund, in the form of `address:balance` #[clap( long = "rollup.genesis-accounts", @@ -99,7 +94,7 @@ pub struct ConfigCreateArgs { #[clap( long = "sequencer.rpc", env = "ROLLUP_SEQUENCER_RPC", - default_value = DEFAULT_SEQUENCER_RPC + default_value = crate::cli::DEFAULT_SEQUENCER_RPC )] pub sequencer_rpc: String, /// Optional. Will default to 'localdev.me' for local deployments. Will need to separately @@ -219,6 +214,10 @@ pub struct DeploymentCreateArgs { // that overwrite the key on drop and don't reveal it when printing. #[clap(long, env = "ROLLUP_SEQUENCER_PRIVATE_KEY")] pub(crate) sequencer_private_key: String, + /// Set if you want to see all k8s resources created by the deployment + /// Set if you want to do a dry run of the deployment + #[clap(long, env = "ROLLUP_DEBUG_DEPLOY", default_value = "false")] + pub(crate) debug: bool, } #[derive(Args, Debug)] diff --git a/crates/astria-cli/src/cli/sequencer.rs b/crates/astria-cli/src/cli/sequencer.rs index 213029bffb..094f480760 100644 --- a/crates/astria-cli/src/cli/sequencer.rs +++ b/crates/astria-cli/src/cli/sequencer.rs @@ -10,8 +10,6 @@ use color_eyre::{ eyre::Context, }; -const DEFAULT_SEQUENCER_RPC: &str = "https://rpc.sequencer.dusk-1.devnet.astria.org"; - /// Interact with a Sequencer node #[derive(Debug, Subcommand)] pub enum Command { @@ -55,7 +53,7 @@ pub struct BasicAccountArgs { #[clap( long, env = "SEQUENCER_URL", - default_value = DEFAULT_SEQUENCER_RPC + default_value = crate::cli::DEFAULT_SEQUENCER_RPC )] pub(crate) sequencer_url: String, /// The address of the Sequencer account @@ -80,7 +78,7 @@ pub struct TransferArgs { #[clap( long, env = "SEQUENCER_URL", - default_value = DEFAULT_SEQUENCER_RPC + default_value = crate::cli::DEFAULT_SEQUENCER_RPC )] pub(crate) sequencer_url: String, } @@ -112,7 +110,11 @@ pub enum BlockHeightCommand { #[derive(Args, Debug)] pub struct BlockHeightGetArgs { /// The url of the Sequencer node - #[clap(long)] + #[clap( + long, + env = "SEQUENCER_URL", + default_value = crate::cli::DEFAULT_SEQUENCER_RPC + )] pub(crate) sequencer_url: String, } diff --git a/crates/astria-cli/src/commands/rollup.rs b/crates/astria-cli/src/commands/rollup.rs index 295cda6dba..571ed83765 100644 --- a/crates/astria-cli/src/commands/rollup.rs +++ b/crates/astria-cli/src/commands/rollup.rs @@ -194,7 +194,6 @@ pub(crate) fn create_deployment(args: &DeploymentCreateArgs) -> eyre::Result<()> let helm = helm_from_env(); let mut cmd = Command::new(helm.clone()); cmd.arg("install") - .arg("--debug") .arg("--values") .arg(rollup.deployment_config.get_filename()) // TODO: https://github.com/astriaorg/astria/issues/594 @@ -213,15 +212,17 @@ pub(crate) fn create_deployment(args: &DeploymentCreateArgs) -> eyre::Result<()> )) .arg(rollup.deployment_config.get_chart_release_name()) .arg(&args.chart_path) - .arg("--set") - .arg(format!("namespace={}", rollup.namespace)) - .arg(format!("--namespace={}", rollup.namespace)) + .arg(format!("--namespace={}", rollup.globals_config.namespace)) .arg("--create-namespace"); if args.dry_run { cmd.arg("--dry-run"); } + if args.debug { + cmd.arg("--debug"); + } + match cmd.output() { Err(e) => { panic!("failed deploying config: failed to invoke helm (path: {helm:?}): {e:?}"); @@ -263,7 +264,7 @@ pub(crate) fn delete_deployment(args: &DeploymentDeleteArgs) -> eyre::Result<()> let mut cmd = Command::new(helm.clone()); cmd.arg("uninstall") .arg(rollup.deployment_config.get_chart_release_name()) - .arg(format!("--namespace={}", rollup.namespace)); + .arg(format!("--namespace={}", rollup.globals_config.namespace)); match cmd.output() { Err(e) => { @@ -327,14 +328,13 @@ mod test { name: "test".to_string(), chain_id: None, network_id: 0, - skip_empty_blocks: false, genesis_accounts: vec![], sequencer_initial_block_height: Some(1), sequencer_websocket: String::new(), sequencer_rpc: String::new(), log_level: String::new(), hostname: String::new(), - namespace: String::new(), + namespace: "namespace_test".to_string(), } } @@ -346,6 +346,11 @@ mod test { let file_path = PathBuf::from("test-rollup-conf.yaml"); assert!(file_path.exists()); + + let file = File::open(&file_path).unwrap(); + let rollup: Rollup = serde_yaml::from_reader(file).unwrap(); + assert_eq!(rollup.globals_config.namespace, args.namespace); + assert_eq!(rollup.deployment_config.get_rollup_name(), args.name); }) .await; } diff --git a/crates/astria-cli/src/types.rs b/crates/astria-cli/src/types.rs index d0c8715328..86fa3c4ba5 100644 --- a/crates/astria-cli/src/types.rs +++ b/crates/astria-cli/src/types.rs @@ -13,23 +13,30 @@ use crate::cli::rollup::{ #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Rollup { - pub(crate) namespace: String, + #[serde(rename = "global")] + pub(crate) globals_config: GlobalsConfig, #[serde(rename = "config")] pub(crate) deployment_config: RollupDeploymentConfig, - pub(crate) ingress: IngressConfig, + #[serde(rename = "ingress")] + pub(crate) ingress_config: IngressConfig, + #[serde(rename = "celestia-node")] + pub(crate) celestia_node: CelestiaNode, } impl TryFrom<&ConfigCreateArgs> for Rollup { type Error = eyre::Report; fn try_from(args: &ConfigCreateArgs) -> eyre::Result { + let globals_config = GlobalsConfig::from(args); let deployment_config = RollupDeploymentConfig::try_from(args)?; - let ingress = IngressConfig::from(args); + let ingress_config = IngressConfig::from(args); + let celestia_node = CelestiaNode::from(args); Ok(Self { - namespace: args.namespace.clone(), + globals_config, deployment_config, - ingress, + ingress_config, + celestia_node, }) } } @@ -49,9 +56,6 @@ impl TryInto for Rollup { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RollupDeploymentConfig { - #[serde(rename = "useTTY")] - use_tty: bool, - log_level: String, rollup: RollupConfig, sequencer: SequencerConfig, } @@ -73,6 +77,16 @@ impl RollupDeploymentConfig { } } +/// Describes the ingress config for the rollup chart. +/// +/// Serializes to a yaml file for usage with Helm, thus the +/// `rename_all = "camelCase"` naming convention. +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct IngressConfig { + hostname: String, +} + impl From<&ConfigCreateArgs> for IngressConfig { fn from(args: &ConfigCreateArgs) -> Self { Self { @@ -81,6 +95,69 @@ impl From<&ConfigCreateArgs> for IngressConfig { } } +/// Describes the globals used for rollup chart. +/// +/// Serializes to a yaml file for usage with Helm, thus the +/// `rename_all = "camelCase"` naming convention. +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct GlobalsConfig { + pub(crate) namespace: String, + #[serde(rename = "useTTY")] + use_tty: bool, + log_level: String, +} + +impl From<&ConfigCreateArgs> for GlobalsConfig { + fn from(args: &ConfigCreateArgs) -> Self { + Self { + namespace: args.namespace.clone(), + use_tty: args.use_tty, + log_level: args.log_level.clone(), + } + } +} + +/// Describes the values for Celestia Node helm chart, which is a dependency +/// of the rollup chart. +/// +/// Serializes to a yaml file for usage with Helm, thus the +/// `rename_all = "camelCase"` naming convention. +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CelestiaNode { + #[serde(rename = "config")] + celestia_node_config: CelestiaNodeConfig, +} + +impl From<&ConfigCreateArgs> for CelestiaNode { + fn from(args: &ConfigCreateArgs) -> Self { + let celestia_node_config = CelestiaNodeConfig::from(args); + + Self { + celestia_node_config, + } + } +} + +/// Describes the configuration for a Celestia Node values. +/// +/// Serializes to a yaml file for usage with Helm, thus the +/// `rename_all = "camelCase"` naming convention. +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CelestiaNodeConfig { + label_prefix: String, +} + +impl From<&ConfigCreateArgs> for CelestiaNodeConfig { + fn from(args: &ConfigCreateArgs) -> Self { + Self { + label_prefix: args.name.to_string(), + } + } +} + impl TryFrom<&ConfigCreateArgs> for RollupDeploymentConfig { type Error = eyre::Report; @@ -101,13 +178,10 @@ impl TryFrom<&ConfigCreateArgs> for RollupDeploymentConfig { .collect(); Ok(Self { - use_tty: args.use_tty, - log_level: args.log_level.clone(), rollup: RollupConfig { name: args.name.clone(), chain_id, network_id: args.network_id.to_string(), - skip_empty_blocks: args.skip_empty_blocks, genesis_accounts, }, sequencer: SequencerConfig { @@ -126,7 +200,6 @@ pub struct RollupConfig { chain_id: String, // NOTE - String here because yaml will serialize large ints w/ scientific notation network_id: String, - skip_empty_blocks: bool, genesis_accounts: Vec, } @@ -156,12 +229,6 @@ struct SequencerConfig { rpc: String, } -#[derive(Debug, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct IngressConfig { - hostname: String, -} - #[cfg(test)] mod tests { use super::*; @@ -179,7 +246,6 @@ mod tests { name: "rollup1".to_string(), chain_id: Some("chain1".to_string()), network_id: 1, - skip_empty_blocks: true, genesis_accounts: vec![ GenesisAccountArg { address: "0xA5TR14".to_string(), @@ -198,15 +264,16 @@ mod tests { }; let expected_config = Rollup { - namespace: "test-cluster".to_string(), - deployment_config: RollupDeploymentConfig { + globals_config: GlobalsConfig { use_tty: true, + namespace: "test-cluster".to_string(), log_level: "debug".to_string(), + }, + deployment_config: RollupDeploymentConfig { rollup: RollupConfig { name: "rollup1".to_string(), chain_id: "chain1".to_string(), network_id: "1".to_string(), - skip_empty_blocks: true, genesis_accounts: vec![ GenesisAccount { address: "0xA5TR14".to_string(), @@ -224,9 +291,14 @@ mod tests { rpc: "http://localhost:8081".to_string(), }, }, - ingress: IngressConfig { + ingress_config: IngressConfig { hostname: "test.com".to_string(), }, + celestia_node: CelestiaNode { + celestia_node_config: CelestiaNodeConfig { + label_prefix: "rollup1".to_string(), + }, + }, }; let result = Rollup::try_from(&args)?; @@ -247,7 +319,6 @@ mod tests { name: "rollup2".to_string(), chain_id: None, network_id: 2_211_011_801, - skip_empty_blocks: false, genesis_accounts: vec![GenesisAccountArg { address: "0xA5TR14".to_string(), balance: 10000, @@ -260,15 +331,16 @@ mod tests { }; let expected_config = Rollup { - namespace: "astria-dev-cluster".to_string(), - deployment_config: RollupDeploymentConfig { + globals_config: GlobalsConfig { use_tty: false, + namespace: "astria-dev-cluster".to_string(), log_level: "info".to_string(), + }, + deployment_config: RollupDeploymentConfig { rollup: RollupConfig { name: "rollup2".to_string(), chain_id: "rollup2-chain".to_string(), // Derived from name network_id: "2211011801".to_string(), - skip_empty_blocks: false, genesis_accounts: vec![GenesisAccount { address: "0xA5TR14".to_string(), balance: "10000".to_string(), @@ -280,9 +352,14 @@ mod tests { rpc: "http://localhost:8083".to_string(), }, }, - ingress: IngressConfig { + ingress_config: IngressConfig { hostname: "localdev.me".to_string(), }, + celestia_node: CelestiaNode { + celestia_node_config: CelestiaNodeConfig { + label_prefix: "rollup2".to_string(), + }, + }, }; let result = Rollup::try_from(&args)?;