Skip to content

Commit d8dd54f

Browse files
authored
install-chain: Add alias feature via avalanched (#412)
* install-chain: Add alias feature via avalanched Signed-off-by: Dan Sover <[email protected]> * alias: Send dummy command to SSM Signed-off-by: Dan Sover <[email protected]> --------- Signed-off-by: Dan Sover <[email protected]>
1 parent d44eec6 commit d8dd54f

File tree

5 files changed

+113
-5
lines changed

5 files changed

+113
-5
lines changed

avalanche-ops/src/aws/cfn-templates/ssm_install_subnet_chain.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ Resources:
3535
avalanchedArgs:
3636
type: String
3737
description: New blockchain id to move configuration to.
38+
aliasArgs:
39+
type: String
40+
description: Aliasing arguments for avalanched.
3841
mainSteps:
3942
- action: aws:runShellScript
4043
name: installSubnetChain
@@ -50,6 +53,9 @@ Resources:
5053
# to download vm binary, write/update subnet/chain config
5154
/usr/local/bin/avalanched-aws {{ avalanchedArgs }}
5255
56+
# to set the chain alias
57+
/usr/local/bin/avalanched-aws {{ aliasArgs }}
58+
5359
# to reload updated configs
5460
sudo systemctl restart --no-block avalanchego.service
5561
sleep 7

avalanched-aws/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ log = "0.4.18"
2727
prometheus-manager = "0.0.30"
2828
random-manager = "0.0.5"
2929
serde = { version = "1.0.163", features = ["derive"] }
30+
serde_json = "1.0.103"
3031
tempfile = "3.5.0"
3132
tokio = { version = "1.29.1", features = ["full"] } # https://github.com/tokio-rs/tokio/releases
3233

avalanched-aws/src/alias_chain/mod.rs

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use std::{collections::HashMap, fs::File, io, path::Path};
2+
3+
use clap::{Arg, Command};
4+
use serde::{Deserialize, Serialize};
5+
6+
pub const NAME: &str = "alias-chain";
7+
8+
/// Defines "alias-chain" option.
9+
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
10+
pub struct Flags {
11+
pub log_level: String,
12+
13+
pub chain_id: String,
14+
pub chain_name: String,
15+
}
16+
17+
pub fn command() -> Command {
18+
Command::new(NAME)
19+
.about("Sets chain alias (WARN: ALWAYS OVERWRITES)")
20+
.arg(
21+
Arg::new("LOG_LEVEL")
22+
.long("log-level")
23+
.short('l')
24+
.help("Sets the log level")
25+
.required(false)
26+
.num_args(1)
27+
.value_parser(["debug", "info"])
28+
.default_value("info"),
29+
)
30+
.arg(
31+
Arg::new("CHAIN_ID")
32+
.long("chain-id")
33+
.help("Chain ID")
34+
.required(false)
35+
.num_args(1),
36+
)
37+
.arg(
38+
Arg::new("CHAIN_NAME")
39+
.long("chain-name")
40+
.help("Chain name to use as an alias")
41+
.required(false)
42+
.num_args(1),
43+
)
44+
}
45+
46+
pub async fn execute(opts: Flags) -> io::Result<()> {
47+
// ref. <https://github.com/env-logger-rs/env_logger/issues/47>
48+
env_logger::init_from_env(
49+
env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, opts.log_level),
50+
);
51+
52+
// Create alias.json file
53+
// TODO: import type from avalanche-rust
54+
pub type Aliases = HashMap<String, Vec<String>>;
55+
let mut aliases = Aliases::new();
56+
aliases.insert(opts.chain_id, Vec::from([opts.chain_name]));
57+
58+
// Write it to default location
59+
// TODO: import location from avalanche-rust
60+
pub const DEFAULT_CHAIN_ALIASES_PATH: &str = "/data/avalanche-configs/chains/aliases.json";
61+
let path = Path::new(DEFAULT_CHAIN_ALIASES_PATH);
62+
63+
let file = File::create(path)?;
64+
::serde_json::to_writer(file, &aliases)?;
65+
66+
// At this point avalanchego should be restarted to notice the new alias.
67+
// This is done via the ssm_install_subnet_chain SSM document under src/aws/cfn-templates.
68+
Ok(())
69+
}

avalanched-aws/src/main.rs

+21
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod agent;
2+
mod alias_chain;
23
mod install_artifacts;
34
mod install_chain;
45
mod install_subnet;
@@ -17,6 +18,7 @@ async fn main() {
1718
install_artifacts::command(),
1819
install_chain::command(),
1920
install_subnet::command(),
21+
alias_chain::command(),
2022
])
2123
.get_matches();
2224

@@ -154,6 +156,25 @@ async fn main() {
154156
.unwrap();
155157
}
156158

159+
Some((alias_chain::NAME, sub_matches)) => {
160+
alias_chain::execute(alias_chain::Flags {
161+
log_level: sub_matches
162+
.get_one::<String>("LOG_LEVEL")
163+
.unwrap_or(&String::from("info"))
164+
.to_string(),
165+
chain_name: sub_matches
166+
.get_one::<String>("CHAIN_NAME")
167+
.unwrap()
168+
.to_string(),
169+
chain_id: sub_matches
170+
.get_one::<String>("CHAIN_ID")
171+
.unwrap()
172+
.to_string(),
173+
})
174+
.await
175+
.unwrap();
176+
}
177+
157178
_ => unreachable!("unknown subcommand"),
158179
}
159180
}

avalancheup-aws/src/install_subnet_chain/mod.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use avalanche_types::{
1212
jsonrpc::client::info as json_client_info,
1313
key, subnet, units, wallet,
1414
};
15-
use aws_manager::{self, s3, ssm, sts};
15+
use aws_manager::{self, s3, ssm};
1616
use aws_sdk_ssm::types::CommandInvocationStatus;
1717
use clap::{value_parser, Arg, Command};
1818
use crossterm::{
@@ -515,11 +515,12 @@ pub async fn execute(opts: Flags) -> io::Result<()> {
515515
Some(Duration::from_secs(opts.s3_upload_timeout)),
516516
)
517517
.await;
518-
let sts_manager = sts::Manager::new(&shared_config);
518+
// let sts_manager = sts::Manager::new(&shared_config);
519519
let s3_manager = s3::Manager::new(&shared_config);
520520

521-
let current_identity = sts_manager.get_identity().await.unwrap();
522-
log::info!("current AWS identity: {:?}", current_identity);
521+
// TODO: This is now causing an error. It's optional so we can leave it is as is for now.
522+
// let current_identity = sts_manager.get_identity().await.unwrap();
523+
// log::info!("current AWS identity: {:?}", current_identity);
523524

524525
if !opts.skip_prompt {
525526
println!();
@@ -814,6 +815,8 @@ pub async fn execute(opts: Flags) -> io::Result<()> {
814815
.document_name(ssm_doc.clone())
815816
.set_instance_ids(Some(instance_ids.clone()))
816817
.parameters("avalanchedArgs", vec![avalanched_args.clone()])
818+
// hack: send in dummy alias parameters in the no-op case
819+
.parameters("aliasArgs", vec!["--version".to_string()])
817820
.output_s3_region(opts.s3_region.clone())
818821
.output_s3_bucket_name(opts.s3_bucket.clone())
819822
.output_s3_key_prefix(format!(
@@ -955,6 +958,12 @@ pub async fn execute(opts: Flags) -> io::Result<()> {
955958
file_stem.to_str().unwrap()
956959
);
957960

961+
let avalanched_alias_args = format!(
962+
"alias-chain --log-level info --chain_id {chain_id} --chain_alias {alias}",
963+
chain_id = blockchain_id,
964+
alias = opts.chain_name.clone(),
965+
);
966+
958967
// If a Subnet's chain id is 2ebCneCbwthjQ1rYT41nhd7M76Hc6YmosMAQrTFhBq8qeqh6tt,
959968
// the config file for this chain is located at {chain-config-dir}/2ebCneCbwthjQ1rYT41nhd7M76Hc6YmosMAQrTFhBq8qeqh6tt/config.json.
960969
let avalanched_args = format!("install-chain --log-level info --s3-region {region} --s3-bucket {s3_bucket} --chain-config-s3-key {chain_config_s3_key} --chain-config-local-path {chain_config_local_path}",
@@ -992,6 +1001,7 @@ pub async fn execute(opts: Flags) -> io::Result<()> {
9921001
.document_name(ssm_doc.clone())
9931002
.set_instance_ids(Some(instance_ids.clone()))
9941003
.parameters("avalanchedArgs", vec![avalanched_args.clone()])
1004+
.parameters("aliasArgs", vec![avalanched_alias_args.clone()])
9951005
.output_s3_region(opts.s3_region.clone())
9961006
.output_s3_bucket_name(opts.s3_bucket.clone())
9971007
.output_s3_key_prefix(format!(
@@ -1034,7 +1044,8 @@ pub async fn execute(opts: Flags) -> io::Result<()> {
10341044
stdout(),
10351045
SetForegroundColor(Color::Blue),
10361046
Print(format!(
1037-
"\n\n\nSUCCESS!\nsubnet Id: {created_subnet_id}\nblockchain Id: {blockchain_id}\n\n"
1047+
"\n\n\nSUCCESS!\nsubnet Id: {created_subnet_id}\nblockchain Id: {blockchain_id}\nchain alias: {chain_name}\n\n",
1048+
chain_name = opts.chain_name.clone(),
10381049
)),
10391050
ResetColor
10401051
)?;

0 commit comments

Comments
 (0)