Skip to main content

flowey_lib_common/
download_azcopy.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Download a copy of `azcopy`
5
6use flowey::node::prelude::*;
7
8flowey_config! {
9    /// Config for the download_azcopy node.
10    pub struct Config {
11        /// Version of `azcopy` to install (e.g: "10.31.0")
12        pub version: Option<String>,
13    }
14}
15
16flowey_request! {
17    pub enum Request {
18        /// Get a path to `azcopy`
19        GetAzCopy(WriteVar<PathBuf>),
20    }
21}
22
23new_flow_node_with_config!(struct Node);
24
25impl FlowNodeWithConfig for Node {
26    type Request = Request;
27    type Config = Config;
28
29    fn imports(ctx: &mut ImportCtx<'_>) {
30        ctx.import::<crate::install_dist_pkg::Node>();
31        ctx.import::<crate::download_gh_release::Node>();
32    }
33
34    fn emit(
35        config: Config,
36        requests: Vec<Self::Request>,
37        ctx: &mut NodeCtx<'_>,
38    ) -> anyhow::Result<()> {
39        let mut get_azcopy = Vec::new();
40
41        for req in requests {
42            match req {
43                Request::GetAzCopy(v) => get_azcopy.push(v),
44            }
45        }
46
47        // -- end of req processing -- //
48
49        if get_azcopy.is_empty() {
50            return Ok(());
51        }
52
53        let version = config
54            .version
55            .ok_or(anyhow::anyhow!("missing config: version"))?;
56        let version = &version;
57        let azcopy_bin = ctx.platform().binary("azcopy");
58
59        // in case we need to unzip the thing we downloaded
60        let platform = ctx.platform();
61        let bsdtar_installed = ctx.reqv(|v| crate::install_dist_pkg::Request::Install {
62            package_names: match platform {
63                FlowPlatform::Linux(linux_distribution) => match linux_distribution {
64                    FlowPlatformLinuxDistro::Fedora => {
65                        vec!["bsdtar".into()]
66                    }
67                    FlowPlatformLinuxDistro::Ubuntu => vec!["libarchive-tools".into()],
68                    FlowPlatformLinuxDistro::AzureLinux | FlowPlatformLinuxDistro::Arch => {
69                        vec!["libarchive".into()]
70                    }
71                    FlowPlatformLinuxDistro::Nix => vec![],
72                    FlowPlatformLinuxDistro::Unknown => vec![],
73                },
74                _ => {
75                    vec![]
76                }
77            },
78            done: v,
79        });
80
81        // Determine file name at emit time based on platform/arch
82        let (file_name, is_tar) = {
83            let arch = match ctx.arch() {
84                FlowArch::X86_64 => "amd64",
85                FlowArch::Aarch64 => "arm64",
86                _ => unreachable!("unsupported arch"),
87            };
88            match ctx.platform() {
89                FlowPlatform::Windows => (format!("azcopy_windows_{arch}_{version}.zip"), false),
90                FlowPlatform::Linux(_) => (format!("azcopy_linux_{arch}_{version}.tar.gz"), true),
91                FlowPlatform::MacOs => (format!("azcopy_darwin_{arch}_{version}.zip"), false),
92                _ => unreachable!("unsupported platform"),
93            }
94        };
95
96        let azcopy_archive = ctx.reqv(|v| crate::download_gh_release::Request {
97            repo_owner: "Azure".to_string(),
98            repo_name: "azure-storage-azcopy".to_string(),
99            needs_auth: false,
100            tag: format!("v{version}"),
101            file_name,
102            path: v,
103        });
104
105        ctx.emit_rust_step("extract azcopy from archive", |ctx| {
106            bsdtar_installed.claim(ctx);
107            let get_azcopy = get_azcopy.claim(ctx);
108            let azcopy_archive = azcopy_archive.claim(ctx);
109            let azcopy_bin = azcopy_bin.clone();
110            move |rt| {
111                let azcopy_archive = rt.read(azcopy_archive);
112
113                rt.sh.change_dir(azcopy_archive.parent().unwrap());
114
115                if is_tar {
116                    flowey::shell_cmd!(rt, "tar -xf {azcopy_archive} --strip-components=1")
117                        .run()?;
118                } else {
119                    let bsdtar = crate::_util::bsdtar_name(rt);
120                    flowey::shell_cmd!(rt, "{bsdtar} -xf {azcopy_archive} --strip-components=1")
121                        .run()?;
122                }
123
124                let path_to_azcopy = azcopy_archive
125                    .parent()
126                    .unwrap()
127                    .join(&azcopy_bin)
128                    .absolute()?;
129
130                for var in get_azcopy {
131                    rt.write(var, &path_to_azcopy)
132                }
133
134                Ok(())
135            }
136        });
137
138        Ok(())
139    }
140}