Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rate-limiting-canister): added option to check format #3274

Merged
merged 1 commit into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions rs/boundary_node/rate_limits/canister_client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,13 @@ use rate_limits_api::{
use serde::Deserialize;
use std::{fs, path::PathBuf, str};
use tracing::{debug, info};
use tracing_subscriber::EnvFilter;
use uuid::Uuid;

pub async fn submit_config(
config_file: PathBuf,
canister_id: Principal,
agent: Agent,
debug: bool,
) -> Result<(), Error> {
// initialize tracing subscriber with corresponding log level
let log_level = if debug { "debug" } else { "info" };
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::new(log_level))
.init();

// read the rules
let rules = read_yaml_file(&config_file)?;

Expand Down Expand Up @@ -83,6 +75,11 @@ pub async fn submit_config(
Ok(())
}

pub fn check_config(config_file: PathBuf) -> Result<(), Error> {
let _ = read_yaml_file(&config_file)?;
Ok(())
}

#[derive(Debug, Deserialize)]
struct YamlRule {
#[serde(flatten)]
Expand All @@ -95,8 +92,7 @@ fn read_yaml_file(file_path: &PathBuf) -> Result<Vec<InputRule>, Error> {
let yaml_str = fs::read_to_string(file_path).context("Unable to read file")?;

// Deserialize directly into `YamlRule` and transform `InputRule`
let yaml_rules: Vec<YamlRule> =
serde_yaml::from_str(&yaml_str).context("Failed to parse YAML")?;
let yaml_rules: Vec<YamlRule> = serde_yaml::from_str(&yaml_str)?;
let input_rules = yaml_rules
.into_iter()
.map(|entry| InputRule {
Expand Down
59 changes: 42 additions & 17 deletions rs/boundary_node/rate_limits/canister_client/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use anyhow::{bail, Context, Error};
use candid::Principal;
use clap::Parser;
use ic_agent::{identity::Secp256k1Identity, Agent};
use k256::elliptic_curve::SecretKey;
use rate_limiting_canister_client::submit_config;
use rate_limiting_canister_client::{check_config, submit_config};
use std::{path::PathBuf, str};
use tracing::info;
use tracing_subscriber::EnvFilter;

const SERVICE_NAME: &str = "rate-limiting-canister-client";

Expand All @@ -12,41 +15,63 @@ const SERVICE_NAME: &str = "rate-limiting-canister-client";
struct Cli {
/// ID of the rate-limiting canister
#[arg(long)]
canister_id: Principal,
canister_id: Option<Principal>,

/// Path to the file containing all the rules
#[arg(long)]
config_file: PathBuf,

/// Identity key
#[arg(long)]
identity_key: String,
identity_key: Option<String>,

/// IC domain URL
#[arg(long, default_value = "https://icp-api.io")]
ic_domain: String,

/// Only check the config file
#[arg(long)]
check: bool,

/// Enable debug logging
#[arg(long)]
debug: bool,
}

#[tokio::main]
async fn main() {
async fn main() -> Result<(), Error> {
// parse command-line arguments
let cli = Cli::parse();

// create the agent
let identity = Secp256k1Identity::from_private_key(
SecretKey::from_sec1_pem(&cli.identity_key).expect("failed to parse the identity key"),
);
let agent = Agent::builder()
.with_url(cli.ic_domain)
.with_identity(identity)
.build()
.expect("failed to build the agent");

submit_config(cli.config_file, cli.canister_id, agent, cli.debug)
.await
.expect("failed to submit the config to the canister");
// initialize tracing subscriber with corresponding log level
let log_level = if cli.debug { "debug" } else { "info" };
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::new(log_level))
.init();

if cli.check {
check_config(cli.config_file).context("Failed to parse the config")?;
info!("Config file is correctly formatted");
} else {
if cli.identity_key.is_none() || cli.canister_id.is_none() {
bail!("Canister ID and identity key are required to submit the configuration to the canister!");
}
let identity_key = cli.identity_key.unwrap();
let canister_id = cli.canister_id.unwrap();

// create the agent
let identity = Secp256k1Identity::from_private_key(
SecretKey::from_sec1_pem(&identity_key).context("failed to parse the identity key")?,
);
let agent = Agent::builder()
.with_url(cli.ic_domain)
.with_identity(identity)
.build()
.context("failed to build the agent")?;

submit_config(cli.config_file, canister_id, agent)
.await
.context("failed to submit the config to the canister")?;
}
Ok(())
}
Loading