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 => {
55                        vec!["bsdtar".into()]
56                    }
57                    FlowPlatformLinuxDistro::Ubuntu => vec!["libarchive-tools".into()],
58                    FlowPlatformLinuxDistro::AzureLinux | FlowPlatformLinuxDistro::Arch => {
59                        vec!["libarchive".into()]
60                    }
61                    FlowPlatformLinuxDistro::Nix => vec![],
62                    FlowPlatformLinuxDistro::Unknown => vec![],
63                },
64                _ => {
65                    vec![]
66                }
67            },
68            done: v,
69        });
70
71        // Determine file name at emit time based on platform/arch
72        let (file_name, is_tar) = {
73            let arch = match ctx.arch() {
74                FlowArch::X86_64 => "amd64",
75                FlowArch::Aarch64 => "arm64",
76                _ => unreachable!("unsupported arch"),
77            };
78            match ctx.platform() {
79                FlowPlatform::Windows => (format!("azcopy_windows_{arch}_{version}.zip"), false),
80                FlowPlatform::Linux(_) => (format!("azcopy_linux_{arch}_{version}.tar.gz"), true),
81                FlowPlatform::MacOs => (format!("azcopy_darwin_{arch}_{version}.zip"), false),
82                _ => unreachable!("unsupported platform"),
83            }
84        };
85
86        let azcopy_archive = ctx.reqv(|v| crate::download_gh_release::Request {
87            repo_owner: "Azure".to_string(),
88            repo_name: "azure-storage-azcopy".to_string(),
89            needs_auth: false,
90            tag: format!("v{version}"),
91            file_name,
92            path: v,
93        });
94
95        ctx.emit_rust_step("extract azcopy from archive", |ctx| {
96            bsdtar_installed.claim(ctx);
97            let get_azcopy = get_azcopy.claim(ctx);
98            let azcopy_archive = azcopy_archive.claim(ctx);
99            let azcopy_bin = azcopy_bin.clone();
100            move |rt| {
101                let azcopy_archive = rt.read(azcopy_archive);
102
103                rt.sh.change_dir(azcopy_archive.parent().unwrap());
104
105                if is_tar {
106                    flowey::shell_cmd!(rt, "tar -xf {azcopy_archive} --strip-components=1")
107                        .run()?;
108                } else {
109                    let bsdtar = crate::_util::bsdtar_name(rt);
110                    flowey::shell_cmd!(rt, "{bsdtar} -xf {azcopy_archive} --strip-components=1")
111                        .run()?;
112                }
113
114                let path_to_azcopy = azcopy_archive
115                    .parent()
116                    .unwrap()
117                    .join(&azcopy_bin)
118                    .absolute()?;
119
120                for var in get_azcopy {
121                    rt.write(var, &path_to_azcopy)
122                }
123
124                Ok(())
125            }
126        });
127
128        Ok(())
129    }
130}