solana/install/src/main.rs

232 lines
8.6 KiB
Rust
Raw Normal View History

2019-03-15 10:54:54 -07:00
#[macro_use]
extern crate lazy_static;
2019-03-13 15:31:05 -07:00
use clap::{crate_description, crate_name, crate_version, App, AppSettings, Arg, SubCommand};
2019-03-15 10:54:54 -07:00
use solana_sdk::pubkey::Pubkey;
2019-03-13 15:31:05 -07:00
2019-03-15 10:54:54 -07:00
mod build_env;
mod command;
mod config;
mod defaults;
mod update_manifest;
2019-03-13 15:31:05 -07:00
// Return an error if a url cannot be parsed.
fn is_url(string: String) -> Result<(), String> {
match url::Url::parse(&string) {
Ok(url) => {
if url.has_host() {
Ok(())
} else {
Err("no host provided".to_string())
}
}
2019-03-20 16:12:50 -07:00
Err(err) => Err(format!("{:?}", err)),
}
}
// Return an error if a pubkey cannot be parsed.
fn is_pubkey(string: String) -> Result<(), String> {
match string.parse::<Pubkey>() {
2019-03-20 16:12:50 -07:00
Ok(_) => Ok(()),
Err(err) => Err(format!("{:?}", err)),
}
}
2019-03-15 10:54:54 -07:00
fn main() -> Result<(), String> {
2019-03-13 15:31:05 -07:00
solana_logger::setup();
let matches = App::new(crate_name!())
.about(crate_description!())
.version(crate_version!())
2019-03-15 10:54:54 -07:00
.setting(AppSettings::SubcommandRequiredElseHelp)
.arg({
let arg = Arg::with_name("config_file")
.short("c")
.long("config")
.value_name("PATH")
.takes_value(true)
.help("Configuration file to use");
match *defaults::CONFIG_FILE {
Some(ref config_file) => arg.default_value(&config_file),
None => arg.required(true),
}
})
2019-03-13 15:31:05 -07:00
.subcommand(
SubCommand::with_name("init")
.about("initializes a new installation")
.setting(AppSettings::DisableVersion)
2019-03-15 10:54:54 -07:00
.arg({
let arg = Arg::with_name("data_dir")
.short("d")
2019-05-27 07:31:50 -07:00
.long("data-dir")
2019-03-15 10:54:54 -07:00
.value_name("PATH")
.takes_value(true)
2019-03-20 16:12:50 -07:00
.required(true)
2019-03-15 10:54:54 -07:00
.help("Directory to store install data");
match *defaults::DATA_DIR {
Some(ref data_dir) => arg.default_value(&data_dir),
2019-03-20 16:12:50 -07:00
None => arg,
2019-03-15 10:54:54 -07:00
}
})
2019-03-13 15:31:05 -07:00
.arg(
Arg::with_name("json_rpc_url")
.short("u")
.long("url")
.value_name("URL")
.takes_value(true)
2019-03-15 10:54:54 -07:00
.default_value(defaults::JSON_RPC_URL)
.validator(is_url)
2019-03-13 15:31:05 -07:00
.help("JSON RPC URL for the solana cluster"),
)
2019-03-21 12:00:45 -07:00
.arg(
Arg::with_name("no_modify_path")
.long("no-modify-path")
.help("Don't configure the PATH environment variable"),
)
2019-03-15 10:54:54 -07:00
.arg({
2019-03-20 16:12:50 -07:00
let arg = Arg::with_name("update_manifest_pubkey")
2019-03-13 15:31:05 -07:00
.short("p")
.long("pubkey")
.value_name("PUBKEY")
.takes_value(true)
2019-03-20 16:12:50 -07:00
.required(true)
.validator(is_pubkey)
2019-03-15 10:54:54 -07:00
.help("Public key of the update manifest");
2019-03-20 16:12:50 -07:00
match defaults::update_manifest_pubkey(build_env::TARGET) {
2019-03-15 10:54:54 -07:00
Some(default_value) => arg.default_value(default_value),
2019-03-20 16:12:50 -07:00
None => arg,
2019-03-15 10:54:54 -07:00
}
}),
2019-03-13 15:31:05 -07:00
)
.subcommand(
SubCommand::with_name("info")
.about("displays information about the current installation")
.setting(AppSettings::DisableVersion)
.arg(
Arg::with_name("local_info_only")
.short("l")
.long("local")
.help(
"only display local information, don't check the cluster for new updates",
),
),
)
.subcommand(
SubCommand::with_name("deploy")
.about("deploys a new update")
.setting(AppSettings::DisableVersion)
2019-03-20 16:12:50 -07:00
.arg({
let arg = Arg::with_name("from_keypair_file")
.short("k")
.long("keypair")
.value_name("PATH")
.takes_value(true)
.required(true)
.help("Keypair file of the account that funds the deployment");
match *defaults::USER_KEYPAIR {
Some(ref config_file) => arg.default_value(&config_file),
None => arg,
}
})
.arg(
Arg::with_name("json_rpc_url")
.short("u")
.long("url")
.value_name("URL")
.takes_value(true)
.default_value(defaults::JSON_RPC_URL)
.validator(is_url)
2019-03-20 16:12:50 -07:00
.help("JSON RPC URL for the solana cluster"),
)
2019-03-13 15:31:05 -07:00
.arg(
Arg::with_name("download_url")
.index(1)
.required(true)
.validator(is_url)
2019-03-13 15:31:05 -07:00
.help("URL to the solana release archive"),
)
.arg(
2019-03-20 16:12:50 -07:00
Arg::with_name("update_manifest_keypair_file")
2019-03-13 15:31:05 -07:00
.index(2)
.required(true)
.help("Keypair file for the update manifest (/path/to/keypair.json)"),
),
)
.subcommand(
SubCommand::with_name("update")
.about("checks for an update, and if available downloads and applies it")
.setting(AppSettings::DisableVersion),
)
.subcommand(
SubCommand::with_name("run")
.about("Runs a program while periodically checking and applying software updates")
.after_help("The program will be restarted upon a successful software update")
.setting(AppSettings::DisableVersion)
.arg(
Arg::with_name("program_name")
.index(1)
.required(true)
.help("program to run"),
)
.arg(
Arg::with_name("program_arguments")
.index(2)
.multiple(true)
.help("arguments to supply to the program"),
),
)
.get_matches();
2019-03-15 10:54:54 -07:00
let config_file = matches.value_of("config_file").unwrap();
match matches.subcommand() {
("init", Some(matches)) => {
let json_rpc_url = matches.value_of("json_rpc_url").unwrap();
2019-03-20 16:12:50 -07:00
let update_manifest_pubkey = matches
.value_of("update_manifest_pubkey")
2019-03-15 10:54:54 -07:00
.unwrap()
.parse::<Pubkey>()
.unwrap();
let data_dir = matches.value_of("data_dir").unwrap();
2019-03-21 12:00:45 -07:00
let no_modify_path = matches.is_present("no_modify_path");
command::init(
config_file,
data_dir,
json_rpc_url,
&update_manifest_pubkey,
no_modify_path,
)
2019-03-15 10:54:54 -07:00
}
("info", Some(matches)) => {
let local_info_only = matches.is_present("local_info_only");
2019-03-20 16:12:50 -07:00
command::info(config_file, local_info_only).map(|_| ())
2019-03-15 10:54:54 -07:00
}
("deploy", Some(matches)) => {
2019-03-20 16:12:50 -07:00
let from_keypair_file = matches.value_of("from_keypair_file").unwrap();
let json_rpc_url = matches.value_of("json_rpc_url").unwrap();
2019-03-15 10:54:54 -07:00
let download_url = matches.value_of("download_url").unwrap();
2019-03-20 16:12:50 -07:00
let update_manifest_keypair_file =
matches.value_of("update_manifest_keypair_file").unwrap();
command::deploy(
json_rpc_url,
from_keypair_file,
download_url,
update_manifest_keypair_file,
)
2019-03-15 10:54:54 -07:00
}
2019-03-20 16:12:50 -07:00
("update", Some(_matches)) => command::update(config_file).map(|_| ()),
2019-03-15 10:54:54 -07:00
("run", Some(matches)) => {
let program_name = matches.value_of("program_name").unwrap();
let program_arguments = matches
.values_of("program_arguments")
.map(Iterator::collect)
2019-03-15 10:54:54 -07:00
.unwrap_or_else(|| vec![]);
command::run(config_file, program_name, program_arguments)
}
_ => unreachable!(),
}
2019-03-13 15:31:05 -07:00
}