1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use std::{collections::HashMap, fs, path::Path};
use crate::error::Result;
use super::Descriptor;
use serde::{Deserialize, Serialize};
make_pub!(
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(
feature = "builder",
derive(derive_builder::Builder, getset::CopyGetters, getset::Getters),
builder(pattern = "owned", setter(into, strip_option))
)]
/// Unlike the image index, which contains information about a set of images
/// that can span a variety of architectures and operating systems, an image
/// manifest provides a configuration and set of layers for a single
/// container image for a specific architecture and operating system.
struct ImageManifest {
/// This REQUIRED property specifies the image manifest schema version.
/// For this version of the specification, this MUST be 2 to ensure
/// backward compatibility with older versions of Docker. The
/// value of this field will not change. This field MAY be
/// removed in a future version of the specification.
#[cfg_attr(feature = "builder", getset(get_copy = "pub"))]
schema_version: u32,
/// This property is reserved for use, to maintain compatibility. When
/// used, this field contains the media type of this document,
/// which differs from the descriptor use of mediaType.
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "builder", getset(get = "pub"))]
media_type: Option<String>,
/// This REQUIRED property references a configuration object for a
/// container, by digest. Beyond the descriptor requirements,
/// the value has the following additional restrictions:
/// The media type descriptor property has additional restrictions for
/// config. Implementations MUST support at least the following
/// media types:
/// - application/vnd.oci.image.config.v1+json
/// Manifests concerned with portability SHOULD use one of the above
/// media types.
#[cfg_attr(feature = "builder", getset(get = "pub"))]
config: Descriptor,
/// Each item in the array MUST be a descriptor. The array MUST have the
/// base layer at index 0. Subsequent layers MUST then follow in
/// stack order (i.e. from `layers[0]` to `layers[len(layers)-1]`).
/// The final filesystem layout MUST match the result of applying
/// the layers to an empty directory. The ownership, mode, and other
/// attributes of the initial empty directory are unspecified.
#[cfg_attr(feature = "builder", getset(get = "pub"))]
layers: Vec<Descriptor>,
/// This OPTIONAL property contains arbitrary metadata for the image
/// manifest. This OPTIONAL property MUST use the annotation
/// rules.
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "builder", getset(get = "pub"))]
annotations: Option<HashMap<String, String>>,
}
);
impl ImageManifest {
/// Attempts to load an image manifest.
/// # Errors
/// This function will return an [OciSpecError::Io](crate::OciSpecError::Io)
/// if the image manifest does not exist or an
/// [OciSpecError::SerDe](crate::OciSpecError::SerDe) if it is invalid.
/// # Example
/// ``` no_run
/// use oci_spec::image::ImageManifest;
///
/// let image_manifest = ImageManifest::load("my-manifest.json").unwrap();
/// ```
pub fn load<P: AsRef<Path>>(path: P) -> Result<ImageManifest> {
let path = path.as_ref();
let manifest_file = fs::File::open(path)?;
let manifest = serde_json::from_reader(&manifest_file)?;
Ok(manifest)
}
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use super::*;
#[test]
fn test_load_manifest() {
let manifest_path =
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test/data/manifest.json");
let result = ImageManifest::load(manifest_path);
assert!(result.is_ok());
}
}