Skip to main content

component_debug/cli/
create.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::cli::format::format_create_error;
6use crate::lifecycle::create_instance_in_collection;
7use anyhow::{Result, format_err};
8use flex_fuchsia_component_decl as fdecl;
9use flex_fuchsia_sys2 as fsys;
10use fuchsia_url::fuchsia_pkg::AbsoluteComponentUrl;
11use moniker::Moniker;
12
13pub async fn create_cmd<W: std::io::Write>(
14    url: AbsoluteComponentUrl,
15    moniker: Moniker,
16    config_overrides: Vec<fdecl::ConfigOverride>,
17    lifecycle_controller: fsys::LifecycleControllerProxy,
18    mut writer: W,
19) -> Result<()> {
20    let parent = moniker
21        .parent()
22        .ok_or_else(|| format_err!("Error: {} does not reference a dynamic instance", moniker))?;
23    let leaf = moniker
24        .leaf()
25        .ok_or_else(|| format_err!("Error: {} does not reference a dynamic instance", moniker))?;
26    let child_name = leaf.name();
27    let collection = leaf
28        .collection()
29        .ok_or_else(|| format_err!("Error: {} does not reference a dynamic instance", moniker))?;
30
31    writeln!(writer, "URL: {}", url)?;
32    writeln!(writer, "Moniker: {}", moniker)?;
33    writeln!(writer, "Creating component instance...")?;
34
35    create_instance_in_collection(
36        &lifecycle_controller,
37        &parent,
38        collection,
39        child_name,
40        &url,
41        config_overrides,
42        None,
43    )
44    .await
45    .map_err(|e| format_create_error(&moniker, &parent, collection, e))?;
46
47    writeln!(writer, "Created component instance!")?;
48    Ok(())
49}
50
51#[cfg(test)]
52mod test {
53    use super::*;
54    use fidl::endpoints::create_proxy_and_stream;
55    use futures::TryStreamExt;
56
57    fn setup_fake_lifecycle_controller(
58        expected_moniker: &'static str,
59        expected_collection: &'static str,
60        expected_name: &'static str,
61        expected_url: &'static str,
62    ) -> fsys::LifecycleControllerProxy {
63        let (lifecycle_controller, mut stream) =
64            create_proxy_and_stream::<fsys::LifecycleControllerMarker>();
65        fuchsia_async::Task::local(async move {
66            let req = stream.try_next().await.unwrap().unwrap();
67            match req {
68                fsys::LifecycleControllerRequest::CreateInstance {
69                    parent_moniker,
70                    collection,
71                    decl,
72                    responder,
73                    ..
74                } => {
75                    assert_eq!(
76                        Moniker::parse_str(expected_moniker),
77                        Moniker::parse_str(&parent_moniker)
78                    );
79                    assert_eq!(expected_collection, collection.name);
80                    assert_eq!(expected_name, decl.name.unwrap());
81                    assert_eq!(expected_url, decl.url.unwrap());
82                    responder.send(Ok(())).unwrap();
83                }
84                _ => panic!("Unexpected Lifecycle Controller request"),
85            }
86        })
87        .detach();
88        lifecycle_controller
89    }
90
91    #[fuchsia::test]
92    async fn test_success() -> Result<()> {
93        let mut output = Vec::new();
94        let lifecycle_controller = setup_fake_lifecycle_controller(
95            "core",
96            "ffx-laboratory",
97            "test",
98            "fuchsia-pkg://fuchsia.com/test#meta/test.cm",
99        );
100        let response = create_cmd(
101            "fuchsia-pkg://fuchsia.com/test#meta/test.cm".try_into().unwrap(),
102            "core/ffx-laboratory:test".try_into().unwrap(),
103            vec![],
104            lifecycle_controller,
105            &mut output,
106        )
107        .await;
108        response.unwrap();
109        Ok(())
110    }
111}