| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use { |
| crate::{ |
| commands::{types::*, utils}, |
| types::Error, |
| }, |
| argh::{ArgsInfo, FromArgs}, |
| async_trait::async_trait, |
| diagnostics_data::{Inspect, InspectData}, |
| diagnostics_hierarchy::DiagnosticsHierarchy, |
| serde::Serialize, |
| std::fmt, |
| }; |
| |
| /// Lists all available full selectors (component selector + tree selector). |
| /// If a selector is provided, it’ll only print selectors for that component. |
| /// If a full selector (component + tree) is provided, it lists all selectors under the given node. |
| #[derive(ArgsInfo, FromArgs, PartialEq, Debug)] |
| #[argh(subcommand, name = "selectors")] |
| pub struct SelectorsCommand { |
| #[argh(option)] |
| /// the name of the manifest file that we are interested in. If this is provided, the output |
| /// will only contain monikers for components whose url contains the provided name. |
| pub manifest: Option<String>, |
| |
| #[argh(positional)] |
| /// selectors for which the selectors should be queried. Minimum: 1 unless `--manifest` is set. |
| /// When `--manifest` is provided then the selectors should be tree selectors, otherwise |
| /// they can be component selectors or full selectors. |
| pub selectors: Vec<String>, |
| |
| #[argh(option)] |
| /// A selector specifying what `fuchsia.diagnostics.ArchiveAccessor` to connect to. |
| /// The selector will be in the form of: |
| /// <moniker>:<directory>:fuchsia.diagnostics.ArchiveAccessorName |
| /// |
| /// Typically this is the output of `iquery list-accessors`. |
| /// |
| /// For example: `bootstrap/archivist:expose:fuchsia.diagnostics.FeedbackArchiveAccessor` |
| /// means that the command will connect to the `FeedbackArchiveAccecssor` |
| /// exposed by `bootstrap/archivist`. |
| pub accessor: Option<String>, |
| } |
| |
| #[async_trait] |
| impl Command for SelectorsCommand { |
| type Result = SelectorsResult; |
| |
| async fn execute<P: DiagnosticsProvider>(&self, provider: &P) -> Result<Self::Result, Error> { |
| if self.selectors.is_empty() && self.manifest.is_none() { |
| return Err(Error::invalid_arguments("Expected 1 or more selectors. Got zero.")); |
| } |
| let selectors = utils::get_selectors_for_manifest( |
| &self.manifest, |
| &self.selectors, |
| &self.accessor, |
| provider, |
| ) |
| .await?; |
| let selectors = utils::expand_selectors(selectors)?; |
| |
| let mut results = provider.snapshot::<Inspect>(&self.accessor, &selectors).await?; |
| for result in results.iter_mut() { |
| if let Some(hierarchy) = &mut result.payload { |
| hierarchy.sort(); |
| } |
| } |
| Ok(SelectorsResult(inspect_to_selectors(results))) |
| } |
| } |
| |
| #[derive(Serialize)] |
| pub struct SelectorsResult(Vec<String>); |
| |
| impl fmt::Display for SelectorsResult { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| for item in self.0.iter() { |
| writeln!(f, "{}", item)?; |
| } |
| Ok(()) |
| } |
| } |
| |
| fn get_selectors(moniker: String, hierarchy: DiagnosticsHierarchy) -> Vec<String> { |
| let component_selector = selectors::sanitize_moniker_for_selectors(&moniker); |
| hierarchy |
| .property_iter() |
| .flat_map(|(node_path, maybe_property)| maybe_property.map(|prop| (node_path, prop))) |
| .map(|(node_path, property)| { |
| let node_selector = node_path |
| .iter() |
| .map(|s| selectors::sanitize_string_for_selectors(s)) |
| .collect::<Vec<_>>() |
| .join("/"); |
| let property_selector = selectors::sanitize_string_for_selectors(property.name()); |
| format!("{}:{}:{}", component_selector, node_selector, property_selector) |
| }) |
| .collect() |
| } |
| |
| fn inspect_to_selectors(inspect_data: Vec<InspectData>) -> Vec<String> { |
| let mut result = inspect_data |
| .into_iter() |
| .filter_map(|schema| { |
| let moniker = schema.moniker; |
| schema.payload.map(|hierarchy| get_selectors(moniker, hierarchy)) |
| }) |
| .flat_map(|results| results) |
| .collect::<Vec<_>>(); |
| result.sort(); |
| result |
| } |