ya_runtime_wasi/
deploy.rs1use crate::manifest::WasmImage;
2
3use std::{
4 borrow::Cow,
5 path::{Path, PathBuf},
6 {fs, io},
7};
8
9use anyhow::{Context, Result};
10use serde::{Deserialize, Serialize};
11use uuid::Uuid;
12
13#[derive(Serialize, Deserialize)]
36pub struct DeployFile {
37 image_path: PathBuf,
38 vols: Vec<ContainerVolume>,
39}
40
41impl DeployFile {
42 fn for_image(image: &WasmImage) -> Result<Self> {
43 let image_path = image.path().to_owned();
44 let vols = image
45 .manifest
46 .mount_points
47 .iter()
48 .map(|mount_point| ContainerVolume {
49 name: format!("vol-{}", Uuid::new_v4()),
50 path: absolute_path(mount_point.path()).into(),
51 })
52 .collect();
53 Ok(DeployFile { image_path, vols })
54 }
55
56 pub fn load(work_dir: impl AsRef<Path>) -> Result<Self> {
60 let deploy_file = deploy_path(work_dir.as_ref());
61 let reader = io::BufReader::new(fs::File::open(&deploy_file).with_context(|| {
62 format!(
63 "Can't read deploy file {}. Did you run deploy command?",
64 deploy_file.display()
65 )
66 })?);
67 let deploy = serde_json::from_reader(reader)?;
68
69 Ok(deploy)
70 }
71
72 pub(crate) fn save(&self, work_dir: impl AsRef<Path>) -> Result<()> {
73 let deploy_file = deploy_path(work_dir.as_ref());
74 fs::write(&deploy_file, serde_json::to_vec(&self)?)?;
75 Ok(())
76 }
77
78 pub(crate) fn create_dirs(&self, work_dir: impl AsRef<Path>) -> Result<()> {
79 let work_dir = work_dir.as_ref();
80 for vol in &self.vols {
81 fs::create_dir(work_dir.join(&vol.name))?;
82 }
83 Ok(())
84 }
85
86 pub fn image_path(&self) -> &Path {
88 &self.image_path
89 }
90
91 pub fn vols(&self) -> impl Iterator<Item = &ContainerVolume> {
93 self.vols.iter()
94 }
95}
96
97fn deploy_path(work_dir: &Path) -> PathBuf {
98 work_dir.join("deploy.json")
99}
100
101fn absolute_path(path: &str) -> Cow<'_, str> {
102 if path.starts_with('/') {
103 Cow::Borrowed(path)
104 } else {
105 Cow::Owned(format!("/{}", path))
106 }
107}
108
109#[derive(Serialize, Deserialize, Debug, Clone)]
111#[serde(rename_all = "camelCase")]
112pub struct ContainerVolume {
113 pub name: String,
115
116 pub path: String,
118}
119
120pub fn deploy(workdir: impl AsRef<Path>, path: impl AsRef<Path>) -> Result<()> {
133 let workdir = workdir.as_ref();
134 let path = path.as_ref();
135
136 let image = WasmImage::new(&path)
137 .with_context(|| format!("Can't read image file {}.", path.display()))?;
138 let deploy_file = DeployFile::for_image(&image)?;
139 deploy_file.save(workdir)?;
140 deploy_file.create_dirs(workdir)?;
141
142 log::info!("Deploy completed");
143 log::info!("Volumes = {:#?}", deploy_file.vols);
144
145 Ok(())
146}