Skip to content
This repository has been archived by the owner on Jul 25, 2022. It is now read-only.

Commit

Permalink
Add CLI for stratagem reports (#2323)
Browse files Browse the repository at this point in the history
Signed-off-by: Igor Pashev <pashev.igor@gmail.com>
  • Loading branch information
ip1981 authored Oct 13, 2020
1 parent e53c301 commit f417361
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 86 deletions.
13 changes: 1 addition & 12 deletions iml-api/src/graphql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use iml_rabbit::Pool;
use iml_wire_types::{
graphql_duration::GraphQLDuration,
snapshot::{ReserveUnit, Snapshot, SnapshotInterval, SnapshotRetention},
Command, EndpointName, Job,
Command, EndpointName, Job, StratagemReport,
};
use itertools::Itertools;
use juniper::{
Expand Down Expand Up @@ -141,17 +141,6 @@ impl Deref for SortDir {
}
}

#[derive(juniper::GraphQLObject)]
/// Information about a stratagem report
struct StratagemReport {
/// The filename of the stratagem report under /var/spool/iml/report
filename: String,
/// When the report was last modified
modify_time: DateTime<Utc>,
/// The size of the report in bytes
size: i32,
}

pub(crate) struct QueryRoot;

#[juniper::graphql_object(Context = Context)]
Expand Down
1 change: 1 addition & 0 deletions iml-graphql-queries/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// license that can be found in the LICENSE file.

pub mod snapshot;
pub mod stratagem;

use std::fmt;

Expand Down
64 changes: 64 additions & 0 deletions iml-graphql-queries/src/stratagem.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) 2020 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

pub mod list_reports {
use crate::Query;
use iml_wire_types::StratagemReport;

pub static QUERY: &str = r#"
query StratagemReports {
stratagemReports {
filename
size
modify_time: modifyTime
}
}
"#;

#[derive(Debug, serde::Serialize)]
pub struct Vars {}

pub fn build() -> Query<Vars> {
Query {
query: QUERY.to_string(),
variables: None,
}
}

#[derive(Debug, Clone, serde::Deserialize)]
pub struct Resp {
#[serde(rename(deserialize = "stratagemReports"))]
pub stratagem_reports: Vec<StratagemReport>,
}
}

pub mod delete_report {
use crate::Query;

pub static QUERY: &str = r#"
mutation DeleteStratagemReport($filename: String!) {
deleteStratagemReport(filename: $filename)
}
"#;

#[derive(Debug, serde::Serialize)]
pub struct Vars {
filename: String,
}

pub fn build(filename: impl ToString) -> Query<Vars> {
Query {
query: QUERY.to_string(),
variables: Some(Vars {
filename: filename.to_string(),
}),
}
}

#[derive(Debug, Clone, serde::Deserialize)]
pub struct Resp {
#[serde(rename(deserialize = "deleteStratagemReport"))]
pub delete_stratagem_report: bool,
}
}
12 changes: 11 additions & 1 deletion iml-manager-cli/src/display_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use console::style;
use futures::{Future, FutureExt};
use iml_wire_types::{
snapshot::{ReserveUnit, Snapshot, SnapshotInterval, SnapshotRetention},
Command, Filesystem, Host, OstPool, ServerProfile, StratagemConfiguration,
Command, Filesystem, Host, OstPool, ServerProfile, StratagemConfiguration, StratagemReport,
};
use indicatif::ProgressBar;
use number_formatter::{format_bytes, format_number};
Expand Down Expand Up @@ -186,6 +186,16 @@ impl IntoTable for Vec<SnapshotRetention> {
}
}

impl IntoTable for Vec<StratagemReport> {
fn into_table(self) -> Table {
generate_table(
&["Filename", "Size", "Modify Time"],
self.into_iter()
.map(|r| vec![r.filename, r.size.to_string(), r.modify_time.to_rfc2822()]),
)
}
}

impl IntoTable for Vec<Host> {
fn into_table(self) -> Table {
generate_table(
Expand Down
187 changes: 114 additions & 73 deletions iml-manager-cli/src/stratagem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
// license that can be found in the LICENSE file.

use crate::{
api_utils::{delete, first, get, post, put, wait_for_cmd_display},
api_utils::{delete, first, get, graphql, post, wait_for_cmd_display},
display_utils::{wrap_fut, DisplayType, IntoDisplayType as _},
error::{
DurationParseError, ImlManagerCliError, RunStratagemCommandResult,
RunStratagemValidationError,
},
};
use console::Term;
use iml_graphql_queries::stratagem as stratagem_queries;
use iml_manager_client::ImlManagerClientError;
use iml_wire_types::{ApiList, CmdWrapper, EndpointName, Filesystem, StratagemConfiguration};
use structopt::{clap::arg_enum, StructOpt};
Expand All @@ -22,47 +23,62 @@ pub enum StratagemCommand {
Scan(StratagemScanData),
/// Configure Stratagem scanning interval
#[structopt(name = "interval")]
StratagemInterval(StratagemInterval),
Interval(IntervalCommand),
/// Kickoff a Stratagem Filesync
#[structopt(name = "filesync")]
Filesync(StratagemFilesyncData),
/// Kickoff a Stratagem Cloudsync
#[structopt(name = "cloudsync")]
Cloudsync(StratagemCloudsyncData),
/// Work with Stratagem reports
#[structopt(name = "report")]
Report {
#[structopt(subcommand)]
command: Option<ReportCommand>,
},
}

#[derive(Debug, StructOpt)]
pub enum StratagemInterval {
pub enum ReportCommand {
/// List all existing Stratagem reports (default)
#[structopt(name = "list")]
List {
/// Display type: json, yaml, tabular
#[structopt(short = "d", long = "display", default_value = "tabular")]
display_type: DisplayType,
},
/// Delete Stratagem reports
#[structopt(name = "remove")]
Delete {
/// Report name to delete
#[structopt(required = true, min_values = 1)]
name: Vec<String>,
},
}

#[derive(Debug, StructOpt)]
pub enum IntervalCommand {
/// List all existing Stratagem intervals
#[structopt(name = "list")]
List {
/// Set the display type
///
/// The display type can be one of the following:
/// tabular: display content in a table format
/// json: return data in json format
/// yaml: return data in yaml format
/// Display type: json, yaml, tabular
#[structopt(short = "d", long = "display", default_value = "tabular")]
display_type: DisplayType,
},
/// Add a new Stratagem interval
#[structopt(name = "add")]
Add(StratagemIntervalConfig),
/// Update an existing Stratagem interval
#[structopt(name = "update")]
Update(StratagemIntervalConfig),
/// Create Stratagem scan interval
#[structopt(name = "create")]
Create(IntervalCommandConfig),
/// Remove a Stratagem interval
#[structopt(name = "remove")]
Remove(StratagemRemoveData),
}

#[derive(Debug, StructOpt, serde::Serialize)]
pub struct StratagemIntervalConfig {
pub struct IntervalCommandConfig {
/// Filesystem to configure
#[structopt(short = "f", long = "filesystem")]
filesystem: String,
/// Interval to scan
#[structopt(short = "i", long = "interval", parse(try_from_str = parse_duration))]
#[structopt(parse(try_from_str = parse_duration))]
interval: u64,
/// The report duration
#[structopt(short = "r", long = "report", parse(try_from_str = parse_duration))]
Expand All @@ -75,14 +91,12 @@ pub struct StratagemIntervalConfig {
#[derive(Debug, StructOpt, serde::Serialize)]
pub struct StratagemRemoveData {
/// Filesystem to unconfigure
#[structopt(short = "f", long = "filesystem")]
name: String,
filesystem: String,
}

#[derive(serde::Serialize, StructOpt, Debug)]
pub struct StratagemScanData {
/// The name of the filesystem to scan
#[structopt(short = "f", long = "filesystem")]
filesystem: String,
/// The report duration
#[structopt(short = "r", long = "report", parse(try_from_str = parse_duration))]
Expand Down Expand Up @@ -230,6 +244,78 @@ fn list_stratagem_configurations(
term.write_line(&x).unwrap();
}

async fn report_cli(cmd: ReportCommand) -> Result<(), ImlManagerCliError> {
match cmd {
ReportCommand::List { display_type } => {
let query = stratagem_queries::list_reports::build();

let resp: iml_graphql_queries::Response<stratagem_queries::list_reports::Resp> =
graphql(query).await?;
let reports = Result::from(resp)?.data.stratagem_reports;

let x = reports.into_display_type(display_type);

let term = Term::stdout();
term.write_line(&x).unwrap();

Ok(())
}
ReportCommand::Delete { name } => {
for n in name {
let query = stratagem_queries::delete_report::build(n);

let _resp: iml_graphql_queries::Response<stratagem_queries::delete_report::Resp> =
graphql(query).await?;
}
Ok(())
}
}
}

async fn interval_cli(cmd: IntervalCommand) -> Result<(), ImlManagerCliError> {
match cmd {
IntervalCommand::List { display_type } => {
let r: ApiList<StratagemConfiguration> = wrap_fut(
"Finding existing intervals...",
get(
StratagemConfiguration::endpoint_name(),
serde_json::json!({ "limit": 0 }),
),
)
.await?;

if r.objects.is_empty() {
println!("No Stratagem intervals found");
} else {
list_stratagem_configurations(r.objects, display_type);
}
Ok(())
}
IntervalCommand::Create(c) => {
let r = post(StratagemConfiguration::endpoint_name(), c).await?;

let CmdWrapper { command } = handle_cmd_resp(r).await?;

wait_for_cmd_display(command).await?;
Ok(())
}
IntervalCommand::Remove(StratagemRemoveData { filesystem }) => {
let x = get_stratagem_config_by_fs_name(&filesystem).await?;

let r = delete(
&format!("{}/{}", StratagemConfiguration::endpoint_name(), x.id),
Vec::<(String, String)>::new(),
)
.await?;

let CmdWrapper { command } = handle_cmd_resp(r).await?;

wait_for_cmd_display(command).await?;
Ok(())
}
}
}

pub async fn stratagem_cli(command: StratagemCommand) -> Result<(), ImlManagerCliError> {
match command {
StratagemCommand::Scan(data) => {
Expand Down Expand Up @@ -258,58 +344,13 @@ pub async fn stratagem_cli(command: StratagemCommand) -> Result<(), ImlManagerCl

wait_for_cmd_display(command).await?;
}
StratagemCommand::StratagemInterval(x) => match x {
StratagemInterval::List { display_type } => {
let r: ApiList<StratagemConfiguration> = wrap_fut(
"Finding existing intervals...",
get(
StratagemConfiguration::endpoint_name(),
serde_json::json!({ "limit": 0 }),
),
)
.await?;

if r.objects.is_empty() {
println!("No Stratagem intervals found");
return Ok(());
}

list_stratagem_configurations(r.objects, display_type);
}
StratagemInterval::Add(c) => {
let r = post(StratagemConfiguration::endpoint_name(), c).await?;

let CmdWrapper { command } = handle_cmd_resp(r).await?;

wait_for_cmd_display(command).await?;
}
StratagemInterval::Update(c) => {
let x = get_stratagem_config_by_fs_name(&c.filesystem).await?;

let r = put(
&format!("{}/{}", StratagemConfiguration::endpoint_name(), x.id),
c,
)
.await?;

let CmdWrapper { command } = handle_cmd_resp(r).await?;

wait_for_cmd_display(command).await?;
}
StratagemInterval::Remove(StratagemRemoveData { name }) => {
let x = get_stratagem_config_by_fs_name(&name).await?;

let r = delete(
&format!("{}/{}", StratagemConfiguration::endpoint_name(), x.id),
Vec::<(String, String)>::new(),
)
.await?;

let CmdWrapper { command } = handle_cmd_resp(r).await?;

wait_for_cmd_display(command).await?;
}
},
StratagemCommand::Interval(cmd) => interval_cli(cmd).await?,
StratagemCommand::Report { command } => {
report_cli(command.unwrap_or(ReportCommand::List {
display_type: DisplayType::Tabular,
}))
.await?
}
};

Ok(())
Expand Down
Loading

0 comments on commit f417361

Please sign in to comment.