1use std::collections::HashMap;
8
9pub use oci_distribution;
10use oci_distribution::{
11 annotations,
12 client::{Config, ImageLayer},
13 manifest,
14 secrets::RegistryAuth,
15 Client, Reference,
16};
17
18pub mod auth;
19
20#[cfg(test)]
21pub(crate) mod tests;
22
23use anyhow::{anyhow, bail, Context, Result};
24pub async fn pull_wasm_image(
28 reference: &Reference,
29 auth: &RegistryAuth,
30 client: Option<&mut Client>,
31) -> Result<Vec<u8>> {
32 let mut local_client = Client::default();
33 let client = client.unwrap_or(&mut local_client);
34 let out = client
35 .pull(reference, auth, vec![manifest::WASM_LAYER_MEDIA_TYPE])
36 .await
37 .with_context(|| anyhow!("Failed to pull wasm image"))?
38 .layers
39 .into_iter()
40 .next()
41 .map(|v| v.data)
42 .with_context(|| anyhow!("Data not found from the image"))?;
43 Ok(out)
44}
45
46pub async fn push_wasm_image(
47 auth: &RegistryAuth,
48 reference: &Reference,
49 annotations: Option<HashMap<String, String>>,
50 module: &[u8],
51 client: Option<&mut Client>,
52) -> Result<()> {
53 let mut local_client = Client::default();
54 let client = client.unwrap_or(&mut local_client);
55 let layers = vec![ImageLayer::new(
56 module.to_vec(),
57 manifest::WASM_LAYER_MEDIA_TYPE.to_string(),
58 None,
59 )];
60 let config = Config {
61 annotations: None,
62 data: b"{}".to_vec(),
63 media_type: manifest::WASM_CONFIG_MEDIA_TYPE.to_string(),
64 };
65 let image_manifest = manifest::OciImageManifest::build(&layers, &config, annotations);
66 client
67 .push(reference, &layers, config, auth, Some(image_manifest))
68 .await
69 .with_context(|| anyhow!("Failed to push image"))?;
70
71 Ok(())
72}
73pub fn parse_annotations<T: AsRef<str>>(input: &[T]) -> anyhow::Result<HashMap<String, String>> {
75 let mut annotations_map = HashMap::default();
76 for ent in input.iter() {
77 if let Some((key, value)) = ent.as_ref().split_once('=') {
78 annotations_map.insert(key.into(), value.into());
79 } else {
80 bail!("Annotations should be like `key=value`");
81 }
82 }
83 Ok(annotations_map)
84}
85pub fn parse_annotations_and_insert_image_title<T: AsRef<str>>(
88 input: &[T],
89 title: String,
90) -> anyhow::Result<HashMap<String, String>> {
91 let mut ret = parse_annotations(input)?;
92 if !ret.contains_key(&annotations::ORG_OPENCONTAINERS_IMAGE_TITLE.to_owned()) {
93 ret.insert(
94 annotations::ORG_OPENCONTAINERS_IMAGE_TITLE.to_string(),
95 title,
96 );
97 }
98 Ok(ret)
99}