docker_registry/v2/manifest/
manifest_schema1.rs

1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4
5/// Manifest version 2 schema 1, signed.
6///
7/// Specification is at <https://docs.docker.com/registry/spec/manifest-v2-1/>.
8#[derive(Debug, Default, Deserialize, Serialize)]
9pub struct ManifestSchema1Signed {
10  #[serde(rename = "schemaVersion")]
11  schema_version: u16,
12  pub name: String,
13  pub tag: String,
14  pub architecture: String,
15  #[serde(rename = "fsLayers")]
16  fs_layers: Vec<S1Layer>,
17  history: Vec<V1Compat>,
18  signatures: Vec<Signature>,
19}
20
21#[derive(Debug, Default, Deserialize, Serialize)]
22struct Signature {
23  // TODO(lucab): switch to jsonwebtokens crate
24  // https://github.com/Keats/rust-jwt/pull/23
25  header: serde_json::Value,
26  signature: String,
27  protected: String,
28}
29
30/// Compatibility entry for version 1 manifest interoperability.
31#[derive(Debug, Deserialize, Serialize)]
32struct V1Compat {
33  #[serde(rename = "v1Compatibility")]
34  v1_compat: String,
35}
36
37#[derive(Debug, Deserialize, Serialize)]
38struct S1Layer {
39  #[serde(rename = "blobSum")]
40  blob_sum: String,
41}
42
43impl ManifestSchema1Signed {
44  /// List digests of all layers referenced by this manifest.
45  ///
46  /// The returned layers list is ordered starting with the base image first.
47  pub fn get_layers(&self) -> Vec<String> {
48    self.fs_layers.iter().rev().map(|l| l.blob_sum.clone()).collect()
49  }
50
51  /// Get a collection of all image labels stored in the history array of this manifest.
52  ///
53  /// Note that for this manifest type any `layer` beyond 0 probably returns None.
54  pub fn get_labels(&self, layer: usize) -> Option<HashMap<String, String>> {
55    Some(
56      serde_json::from_str::<serde_json::Value>(&self.history.get(layer)?.v1_compat)
57        .ok()?
58        .get("config")?
59        .get("Labels")?
60        .as_object()?
61        .into_iter()
62        .filter_map(|(label, value)| Some((label.to_owned(), value.as_str()?.to_owned())))
63        .collect(),
64    )
65  }
66}