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