Skip to content

Commit

Permalink
feat: add tman check manifest-json & check property-json command (#447)
Browse files Browse the repository at this point in the history
  • Loading branch information
halajohn authored Dec 22, 2024
1 parent 6573e16 commit ea7de0e
Show file tree
Hide file tree
Showing 9 changed files with 382 additions and 43 deletions.
45 changes: 22 additions & 23 deletions core/src/ten_manager/src/cmd/cmd_check/cmd_check_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// Licensed under the Apache License, Version 2.0, with certain conditions.
// Refer to the "LICENSE" file in the root directory for more information.
//

use std::{collections::HashMap, fs, path, str::FromStr};

use anyhow::{Context, Result};
Expand All @@ -20,9 +19,9 @@ use crate::config::TmanConfig;

#[derive(Debug)]
pub struct CheckGraphCommand {
pub app: Vec<String>,
pub app_dir: Vec<String>,
pub predefined_graph_name: Option<String>,
pub graph: Option<String>,
pub graph_json_str: Option<String>,
}

pub fn create_sub_cmd(_args_cfg: &crate::cmd_line::ArgsCfg) -> Command {
Expand All @@ -31,14 +30,14 @@ pub fn create_sub_cmd(_args_cfg: &crate::cmd_line::ArgsCfg) -> Command {
"Check whether the graph content of the predefined graph or start_graph command is correct",
)
.arg(
Arg::new("APP")
.long("app")
Arg::new("APP_DIR")
.long("app-dir")
.help(
"The absolute path of the app declared in the graph. By \
default, the predefined graph will be read from the first \
one in the list.",
)
.required(true),
.required(true).num_args(1..),
)
.arg(
Arg::new("PREDEFINED_GRAPH_NAME")
Expand All @@ -48,11 +47,11 @@ pub fn create_sub_cmd(_args_cfg: &crate::cmd_line::ArgsCfg) -> Command {
otherwise, all predefined graphs will be checked.",
)
.required(false)
.conflicts_with("GRAPH"),
.conflicts_with("GRAPH_JSON_STR"),
)
.arg(
Arg::new("GRAPH")
.long("graph")
Arg::new("GRAPH_JSON_STR")
.long("graph-json-str")
.help(
"Specify the json string of a 'start_graph' cmd to be \
checked. If not specified, the predefined graph in the \
Expand All @@ -63,26 +62,26 @@ pub fn create_sub_cmd(_args_cfg: &crate::cmd_line::ArgsCfg) -> Command {
)
}

pub fn parse_sub_cmd(
_sub_cmd_args: &ArgMatches,
) -> crate::cmd::cmd_check::cmd_check_graph::CheckGraphCommand {
pub fn parse_sub_cmd(sub_cmd_args: &ArgMatches) -> CheckGraphCommand {
let cmd = CheckGraphCommand {
app: _sub_cmd_args
.get_many::<String>("APP")
app_dir: sub_cmd_args
.get_many::<String>("APP_DIR")
.unwrap_or_default()
.map(|s| s.to_string())
.collect(),
predefined_graph_name: _sub_cmd_args
predefined_graph_name: sub_cmd_args
.get_one::<String>("PREDEFINED_GRAPH_NAME")
.cloned(),
graph: _sub_cmd_args.get_one::<String>("GRAPH").cloned(),
graph_json_str: sub_cmd_args
.get_one::<String>("GRAPH_JSON_STR")
.cloned(),
};

cmd
}

fn validate_cmd_args(command: &CheckGraphCommand) -> Result<()> {
for app in &command.app {
for app in &command.app_dir {
let stat = fs::metadata(app).with_context(|| {
format!("Failed to get metadata of app path [{}].", app)
})?;
Expand All @@ -102,9 +101,9 @@ fn get_existed_pkgs_of_all_apps(
) -> Result<HashMap<String, Vec<PkgInfo>>> {
let mut pkgs_info: HashMap<String, Vec<PkgInfo>> = HashMap::new();

let single_app = command.app.len() == 1;
let single_app = command.app_dir.len() == 1;

for app in &command.app {
for app in &command.app_dir {
let app_path = path::Path::new(app);
let app_existed_pkgs = get_all_existed_pkgs_info_of_app(app_path)?;

Expand Down Expand Up @@ -137,13 +136,13 @@ fn get_existed_pkgs_of_all_apps(
fn get_graphs_to_be_checked(command: &CheckGraphCommand) -> Result<Vec<Graph>> {
let mut graphs_to_be_checked: Vec<Graph> = Vec::new();

if let Some(graph_str) = &command.graph {
if let Some(graph_str) = &command.graph_json_str {
let graph: Graph = Graph::from_str(graph_str).map_err(|e| {
anyhow::anyhow!("Failed to parse graph string, {}", e)
})?;
graphs_to_be_checked.push(graph);
} else {
let first_app_path = path::Path::new(&command.app[0]);
let first_app_path = path::Path::new(&command.app_dir[0]);
let first_app_property = parse_property_in_folder(first_app_path)?;
if first_app_property.is_none() {
return Err(anyhow::anyhow!("The property.json is not found in the first app, which is required to retrieve the predefined graphs."));
Expand Down Expand Up @@ -201,10 +200,10 @@ pub async fn execute_cmd(
print!("Checking graph[{}]... ", graph_idx);

match graph.check(&existed_pkgs_of_all_apps) {
Ok(_) => println!("{}", Emoji("", "Passed")),
Ok(_) => println!("{}", Emoji("👍", "Passed")),
Err(e) => {
err_count += 1;
println!("{}. Details:", Emoji("🔴", "Failed"));
println!("{} Details:", Emoji("🔴", "Failed"));
display_error(&e);
println!();
}
Expand Down
53 changes: 53 additions & 0 deletions core/src/ten_manager/src/cmd/cmd_check/cmd_check_manifest_json.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// Copyright © 2024 Agora
// This file is part of TEN Framework, an open source project.
// Licensed under the Apache License, Version 2.0, with certain conditions.
// Refer to the "LICENSE" file in the root directory for more information.
//
use anyhow::Result;
use clap::{Arg, ArgMatches, Command};
use console::Emoji;
use ten_rust::json_schema::ten_validate_manifest_json_string;

use crate::{config::TmanConfig, utils::read_file_to_string};

#[derive(Debug)]
pub struct CheckManifestJsonCommand {
pub path: String,
}

pub fn create_sub_cmd(_args_cfg: &crate::cmd_line::ArgsCfg) -> Command {
Command::new("manifest-json")
.about(
"Check if the manifest.json is valid according to the json schema",
)
.arg(
Arg::new("PATH")
.long("path")
.help("The file path of manifest.json to be checked")
.required(true)
.num_args(1),
)
}

pub fn parse_sub_cmd(sub_cmd_args: &ArgMatches) -> CheckManifestJsonCommand {
let cmd = CheckManifestJsonCommand {
path: sub_cmd_args.get_one::<String>("PATH").cloned().unwrap(),
};

cmd
}

pub async fn execute_cmd(
_tman_config: &TmanConfig,
command_data: CheckManifestJsonCommand,
) -> Result<()> {
let content = read_file_to_string(&command_data.path)?;
match ten_validate_manifest_json_string(&content) {
Ok(_) => {
println!("{} Conforms to JSON schema.", Emoji("👍", "Passed"));
Ok(())
}
Err(e) => Err(e),
}
}
53 changes: 53 additions & 0 deletions core/src/ten_manager/src/cmd/cmd_check/cmd_check_property_json.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// Copyright © 2024 Agora
// This file is part of TEN Framework, an open source project.
// Licensed under the Apache License, Version 2.0, with certain conditions.
// Refer to the "LICENSE" file in the root directory for more information.
//
use anyhow::Result;
use clap::{Arg, ArgMatches, Command};
use console::Emoji;
use ten_rust::json_schema::ten_validate_property_json_string;

use crate::utils::read_file_to_string;

#[derive(Debug)]
pub struct CheckPropertyJsonCommand {
pub path: String,
}

pub fn create_sub_cmd(_args_cfg: &crate::cmd_line::ArgsCfg) -> Command {
Command::new("property-json")
.about(
"Check if the property.json is valid according to the json schema",
)
.arg(
Arg::new("PATH")
.long("path")
.help("The file path of property.json to be checked")
.required(true)
.num_args(1),
)
}

pub fn parse_sub_cmd(sub_cmd_args: &ArgMatches) -> CheckPropertyJsonCommand {
let cmd = CheckPropertyJsonCommand {
path: sub_cmd_args.get_one::<String>("PATH").cloned().unwrap(),
};

cmd
}

pub async fn execute_cmd(
_tman_config: &crate::config::TmanConfig,
command_data: CheckPropertyJsonCommand,
) -> Result<()> {
let content = read_file_to_string(&command_data.path)?;
match ten_validate_property_json_string(&content) {
Ok(_) => {
println!("{} Conforms to JSON schema.", Emoji("👍", "Passed"));
Ok(())
}
Err(e) => Err(e),
}
}
44 changes: 43 additions & 1 deletion core/src/ten_manager/src/cmd/cmd_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// Refer to the "LICENSE" file in the root directory for more information.
//
pub mod cmd_check_graph;
pub mod cmd_check_manifest_json;
pub mod cmd_check_property_json;

use anyhow::Result;
use clap::{ArgMatches, Command};
Expand All @@ -13,7 +15,9 @@ use crate::config::TmanConfig;

#[derive(Debug)]
pub enum CheckCommandData {
CheckGraph(crate::cmd::cmd_check::cmd_check_graph::CheckGraphCommand),
CheckGraph(cmd_check_graph::CheckGraphCommand),
CheckManifestJson(cmd_check_manifest_json::CheckManifestJsonCommand),
CheckPropertyJson(cmd_check_property_json::CheckPropertyJsonCommand),
}

pub fn create_sub_cmd(args_cfg: &crate::cmd_line::ArgsCfg) -> Command {
Expand All @@ -24,6 +28,16 @@ pub fn create_sub_cmd(args_cfg: &crate::cmd_line::ArgsCfg) -> Command {
.subcommand(crate::cmd::cmd_check::cmd_check_graph::create_sub_cmd(
args_cfg,
))
.subcommand(
crate::cmd::cmd_check::cmd_check_manifest_json::create_sub_cmd(
args_cfg,
),
)
.subcommand(
crate::cmd::cmd_check::cmd_check_property_json::create_sub_cmd(
args_cfg,
),
)
}

pub fn parse_sub_cmd(sub_cmd_args: &ArgMatches) -> CheckCommandData {
Expand All @@ -33,6 +47,20 @@ pub fn parse_sub_cmd(sub_cmd_args: &ArgMatches) -> CheckCommandData {
graph_cmd_args,
),
),
Some(("manifest-json", manifest_json_cmd_args)) => {
CheckCommandData::CheckManifestJson(
crate::cmd::cmd_check::cmd_check_manifest_json::parse_sub_cmd(
manifest_json_cmd_args,
),
)
}
Some(("property-json", property_json_cmd_args)) => {
CheckCommandData::CheckPropertyJson(
crate::cmd::cmd_check::cmd_check_property_json::parse_sub_cmd(
property_json_cmd_args,
),
)
}

_ => unreachable!("Command not found"),
}
Expand All @@ -50,5 +78,19 @@ pub async fn execute_cmd(
)
.await
}
CheckCommandData::CheckManifestJson(cmd) => {
crate::cmd::cmd_check::cmd_check_manifest_json::execute_cmd(
tman_config,
cmd,
)
.await
}
CheckCommandData::CheckPropertyJson(cmd) => {
crate::cmd::cmd_check::cmd_check_property_json::execute_cmd(
tman_config,
cmd,
)
.await
}
}
}
Loading

0 comments on commit ea7de0e

Please sign in to comment.