diff --git a/Cargo.toml b/Cargo.toml index e1a88d2503..2b0fc6cd34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ categories = ["api-bindings"] [features] default = ["distribution", "image", "runtime"] proptests = ["quickcheck"] -builder = ["derive_builder", "getset"] distribution = [] image = [] runtime = [] @@ -29,8 +28,8 @@ serde = { version = "1.0.129", features = ["derive"] } thiserror = "1.0.26" serde_json = "1.0.66" quickcheck = { version = "1.0.3", optional = true } -derive_builder = { version = "0.10.2", optional = true } -getset = { version = "0.1.1", optional = true } +derive_builder = "0.10.2" +getset = "0.1.1" [dev-dependencies] tempfile = "3.2.0" diff --git a/src/distribution/error.rs b/src/distribution/error.rs index 8e51d61ea6..5fa5fb4174 100644 --- a/src/distribution/error.rs +++ b/src/distribution/error.rs @@ -1,5 +1,8 @@ //! Error types of the distribution spec. +use crate::error::OciSpecError; +use derive_builder::Builder; +use getset::Getters; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display, Formatter}; use thiserror::Error; @@ -42,23 +45,18 @@ pub enum ErrorCode { TooManyRequests, } -make_pub!( - #[derive(Clone, Debug, Deserialize, Eq, Error, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder), - builder( - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// ErrorResponse is returned by a registry on an invalid request. - struct ErrorResponse { - /// Available errors within the response. - errors: Vec, - } -); +#[derive(Builder, Clone, Debug, Deserialize, Eq, Error, Getters, PartialEq, Serialize)] +#[builder( + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// ErrorResponse is returned by a registry on an invalid request. +pub struct ErrorResponse { + /// Available errors within the response. + errors: Vec, +} impl Display for ErrorResponse { fn fmt(&self, f: &mut Formatter) -> fmt::Result { @@ -73,40 +71,33 @@ impl ErrorResponse { } } -make_pub!( - #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// Describes a server error returned from a registry. - struct ErrorInfo { - /// The code field MUST be a unique identifier, containing only uppercase alphabetic - /// characters and underscores. - code: ErrorCode, +#[derive(Builder, Clone, Debug, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[builder( + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// Describes a server error returned from a registry. +pub struct ErrorInfo { + /// The code field MUST be a unique identifier, containing only uppercase alphabetic + /// characters and underscores. + code: ErrorCode, - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", builder(default = "None"))] - /// The message field is OPTIONAL, and if present, it SHOULD be a human readable string or - /// MAY be empty. - message: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[builder(default = "None")] + /// The message field is OPTIONAL, and if present, it SHOULD be a human readable string or + /// MAY be empty. + message: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", builder(default = "None"))] - /// The detail field is OPTIONAL and MAY contain arbitrary JSON data providing information - /// the client can use to resolve the issue. - detail: Option, - } -); + #[serde(default, skip_serializing_if = "Option::is_none")] + #[builder(default = "None")] + /// The detail field is OPTIONAL and MAY contain arbitrary JSON data providing information + /// the client can use to resolve the issue. + detail: Option, +} #[cfg(test)] -#[cfg(feature = "builder")] mod tests { use super::*; use crate::error::Result; diff --git a/src/distribution/repository.rs b/src/distribution/repository.rs index c786aec202..81662e5e62 100644 --- a/src/distribution/repository.rs +++ b/src/distribution/repository.rs @@ -1,28 +1,24 @@ //! Repository types of the distribution spec. +use crate::error::OciSpecError; +use derive_builder::Builder; +use getset::Getters; use serde::{Deserialize, Serialize}; -make_pub!( - #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// RepositoryList returns a catalog of repositories maintained on the registry. - struct RepositoryList { - /// The items of the RepositoryList. - repositories: Vec, - } -); +#[derive(Builder, Clone, Debug, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[builder( + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// RepositoryList returns a catalog of repositories maintained on the registry. +pub struct RepositoryList { + /// The items of the RepositoryList. + repositories: Vec, +} #[cfg(test)] -#[cfg(feature = "builder")] mod tests { use super::*; use crate::error::Result; diff --git a/src/distribution/tag.rs b/src/distribution/tag.rs index a1c351e693..5b48552806 100644 --- a/src/distribution/tag.rs +++ b/src/distribution/tag.rs @@ -1,31 +1,27 @@ //! Tag types of the distribution spec. +use crate::error::OciSpecError; +use derive_builder::Builder; +use getset::Getters; use serde::{Deserialize, Serialize}; -make_pub!( - #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// A list of tags for a given repository. - struct TagList { - /// The namespace of the repository. - name: String, +#[derive(Builder, Clone, Debug, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[builder( + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// A list of tags for a given repository. +pub struct TagList { + /// The namespace of the repository. + name: String, - /// Each tags on the repository. - tags: Vec, - } -); + /// Each tags on the repository. + tags: Vec, +} #[cfg(test)] -#[cfg(feature = "builder")] mod tests { use super::*; use crate::error::Result; diff --git a/src/error.rs b/src/error.rs index 40feb035f5..02495e9fb3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -29,7 +29,6 @@ pub enum OciSpecError { SerDe(#[from] serde_json::Error), /// Builder specific errors. - #[cfg(feature = "builder")] #[error("uninitialized field")] Builder(#[from] derive_builder::UninitializedFieldError), } diff --git a/src/image/config.rs b/src/image/config.rs index ef6811a916..35d8e8b778 100644 --- a/src/image/config.rs +++ b/src/image/config.rs @@ -1,3 +1,11 @@ +use super::{Arch, Os}; +use crate::{ + error::{OciSpecError, Result}, + from_file, from_reader, to_file, to_writer, +}; +use derive_builder::Builder; +use getset::Getters; +use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; #[cfg(test)] use std::collections::BTreeMap; use std::{ @@ -6,82 +14,70 @@ use std::{ path::Path, }; -use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; - -use crate::{error::Result, from_file, from_reader, to_file, to_writer}; - -use super::{Arch, Os}; - -make_pub!( - #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// The image configuration is associated with an image and describes some - /// basic information about the image such as date created, author, as - /// well as execution/runtime configuration like its entrypoint, default - /// arguments, networking, and volumes. - struct ImageConfiguration { - /// An combined date and time at which the image was created, - /// formatted as defined by [RFC 3339, section 5.6.](https://tools.ietf.org/html/rfc3339#section-5.6) - #[serde(skip_serializing_if = "Option::is_none")] - created: Option, - /// Gives the name and/or email address of the person or entity - /// which created and is responsible for maintaining the image. - #[serde(skip_serializing_if = "Option::is_none")] - author: Option, - /// The CPU architecture which the binaries in this - /// image are built to run on. Configurations SHOULD use, and - /// implementations SHOULD understand, values listed in the Go - /// Language document for [GOARCH](https://golang.org/doc/install/source#environment). - architecture: Arch, - /// The name of the operating system which the image is built to run on. - /// Configurations SHOULD use, and implementations SHOULD understand, - /// values listed in the Go Language document for [GOOS](https://golang.org/doc/install/source#environment). - os: Os, - /// This OPTIONAL property specifies the version of the operating - /// system targeted by the referenced blob. Implementations MAY refuse - /// to use manifests where os.version is not known to work with - /// the host OS version. Valid values are - /// implementation-defined. e.g. 10.0.14393.1066 on windows. - #[serde(rename = "os.version", skip_serializing_if = "Option::is_none")] - os_version: Option, - /// This OPTIONAL property specifies an array of strings, - /// each specifying a mandatory OS feature. When os is windows, image - /// indexes SHOULD use, and implementations SHOULD understand - /// the following values: - /// - win32k: image requires win32k.sys on the host (Note: win32k.sys is - /// missing on Nano Server) - #[serde(rename = "os.features", skip_serializing_if = "Option::is_none")] - os_features: Option>, - /// The variant of the specified CPU architecture. Configurations SHOULD - /// use, and implementations SHOULD understand, variant values - /// listed in the [Platform Variants](https://github.com/opencontainers/image-spec/blob/main/image-index.md#platform-variants) table. - #[serde(skip_serializing_if = "Option::is_none")] - variant: Option, - /// The execution parameters which SHOULD be used as a base when - /// running a container using the image. This field can be None, in - /// which case any execution parameters should be specified at - /// creation of the container. - #[serde(skip_serializing_if = "Option::is_none")] - config: Option, - /// The rootfs key references the layer content addresses used by the - /// image. This makes the image config hash depend on the - /// filesystem hash. - rootfs: RootFs, - /// Describes the history of each layer. The array is ordered from first - /// to last. - history: Vec, - } -); +#[derive(Builder, Clone, Debug, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// The image configuration is associated with an image and describes some +/// basic information about the image such as date created, author, as +/// well as execution/runtime configuration like its entrypoint, default +/// arguments, networking, and volumes. +pub struct ImageConfiguration { + /// An combined date and time at which the image was created, + /// formatted as defined by [RFC 3339, section 5.6.](https://tools.ietf.org/html/rfc3339#section-5.6) + #[serde(skip_serializing_if = "Option::is_none")] + created: Option, + /// Gives the name and/or email address of the person or entity + /// which created and is responsible for maintaining the image. + #[serde(skip_serializing_if = "Option::is_none")] + author: Option, + /// The CPU architecture which the binaries in this + /// image are built to run on. Configurations SHOULD use, and + /// implementations SHOULD understand, values listed in the Go + /// Language document for [GOARCH](https://golang.org/doc/install/source#environment). + architecture: Arch, + /// The name of the operating system which the image is built to run on. + /// Configurations SHOULD use, and implementations SHOULD understand, + /// values listed in the Go Language document for [GOOS](https://golang.org/doc/install/source#environment). + os: Os, + /// This OPTIONAL property specifies the version of the operating + /// system targeted by the referenced blob. Implementations MAY refuse + /// to use manifests where os.version is not known to work with + /// the host OS version. Valid values are + /// implementation-defined. e.g. 10.0.14393.1066 on windows. + #[serde(rename = "os.version", skip_serializing_if = "Option::is_none")] + os_version: Option, + /// This OPTIONAL property specifies an array of strings, + /// each specifying a mandatory OS feature. When os is windows, image + /// indexes SHOULD use, and implementations SHOULD understand + /// the following values: + /// - win32k: image requires win32k.sys on the host (Note: win32k.sys is + /// missing on Nano Server) + #[serde(rename = "os.features", skip_serializing_if = "Option::is_none")] + os_features: Option>, + /// The variant of the specified CPU architecture. Configurations SHOULD + /// use, and implementations SHOULD understand, variant values + /// listed in the [Platform Variants](https://github.com/opencontainers/image-spec/blob/main/image-index.md#platform-variants) table. + #[serde(skip_serializing_if = "Option::is_none")] + variant: Option, + /// The execution parameters which SHOULD be used as a base when + /// running a container using the image. This field can be None, in + /// which case any execution parameters should be specified at + /// creation of the container. + #[serde(skip_serializing_if = "Option::is_none")] + config: Option, + /// The rootfs key references the layer content addresses used by the + /// image. This makes the image config hash depend on the + /// filesystem hash. + rootfs: RootFs, + /// Describes the history of each layer. The array is ordered from first + /// to last. + history: Vec, +} impl ImageConfiguration { /// Attempts to load an image configuration from a file. @@ -198,91 +194,85 @@ impl Default for ImageConfiguration { } } -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "PascalCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") +#[derive(Builder, Clone, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[serde(rename_all = "PascalCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// The execution parameters which SHOULD be used as a base when +/// running a container using the image. +pub struct Config { + /// The username or UID which is a platform-specific + /// structure that allows specific control over which + /// user the process run as. This acts as a default + /// value to use when the value is not specified when + /// creating a container. For Linux based systems, all + /// of the following are valid: user, uid, user:group, + /// uid:gid, uid:group, user:gid. If group/gid is not + /// specified, the default group and supplementary + /// groups of the given user/uid in /etc/passwd from + /// the container are applied. + #[serde(skip_serializing_if = "Option::is_none")] + user: Option, + /// A set of ports to expose from a container running this + /// image. Its keys can be in the format of: port/tcp, port/udp, + /// port with the default protocol being tcp if not specified. + /// These values act as defaults and are merged with any + /// specified when creating a container. + #[serde( + default, + skip_serializing_if = "Option::is_none", + deserialize_with = "deserialize_as_vec", + serialize_with = "serialize_as_map" )] - /// The execution parameters which SHOULD be used as a base when - /// running a container using the image. - struct Config { - /// The username or UID which is a platform-specific - /// structure that allows specific control over which - /// user the process run as. This acts as a default - /// value to use when the value is not specified when - /// creating a container. For Linux based systems, all - /// of the following are valid: user, uid, user:group, - /// uid:gid, uid:group, user:gid. If group/gid is not - /// specified, the default group and supplementary - /// groups of the given user/uid in /etc/passwd from - /// the container are applied. - #[serde(skip_serializing_if = "Option::is_none")] - user: Option, - /// A set of ports to expose from a container running this - /// image. Its keys can be in the format of: port/tcp, port/udp, - /// port with the default protocol being tcp if not specified. - /// These values act as defaults and are merged with any - /// specified when creating a container. - #[serde( - default, - skip_serializing_if = "Option::is_none", - deserialize_with = "deserialize_as_vec", - serialize_with = "serialize_as_map" - )] - exposed_ports: Option>, - /// Entries are in the format of VARNAME=VARVALUE. These - /// values act as defaults and are merged with any - /// specified when creating a container. - #[serde(skip_serializing_if = "Option::is_none")] - env: Option>, - /// A list of arguments to use as the command to execute - /// when the container starts. These values act as defaults - /// and may be replaced by an entrypoint specified when - /// creating a container. - #[serde(skip_serializing_if = "Option::is_none")] - entrypoint: Option>, - /// Default arguments to the entrypoint of the container. - /// These values act as defaults and may be replaced by any - /// specified when creating a container. If an Entrypoint - /// value is not specified, then the first entry of the Cmd - /// array SHOULD be interpreted as the executable to run. - #[serde(skip_serializing_if = "Option::is_none")] - cmd: Option>, - /// A set of directories describing where the process is - /// likely to write data specific to a container instance. - #[serde( - default, - skip_serializing_if = "Option::is_none", - deserialize_with = "deserialize_as_vec", - serialize_with = "serialize_as_map" - )] - volumes: Option>, - /// Sets the current working directory of the entrypoint process - /// in the container. This value acts as a default and may be - /// replaced by a working directory specified when creating - /// a container. - #[serde(skip_serializing_if = "Option::is_none")] - working_dir: Option, - /// The field contains arbitrary metadata for the container. - /// This property MUST use the annotation rules. - #[serde(skip_serializing_if = "Option::is_none")] - labels: Option>, - /// The field contains the system call signal that will be - /// sent to the container to exit. The signal can be a signal - /// name in the format SIGNAME, for instance SIGKILL or SIGRTMIN+3. - #[serde(skip_serializing_if = "Option::is_none")] - stop_signal: Option, - } -); + exposed_ports: Option>, + /// Entries are in the format of VARNAME=VARVALUE. These + /// values act as defaults and are merged with any + /// specified when creating a container. + #[serde(skip_serializing_if = "Option::is_none")] + env: Option>, + /// A list of arguments to use as the command to execute + /// when the container starts. These values act as defaults + /// and may be replaced by an entrypoint specified when + /// creating a container. + #[serde(skip_serializing_if = "Option::is_none")] + entrypoint: Option>, + /// Default arguments to the entrypoint of the container. + /// These values act as defaults and may be replaced by any + /// specified when creating a container. If an Entrypoint + /// value is not specified, then the first entry of the Cmd + /// array SHOULD be interpreted as the executable to run. + #[serde(skip_serializing_if = "Option::is_none")] + cmd: Option>, + /// A set of directories describing where the process is + /// likely to write data specific to a container instance. + #[serde( + default, + skip_serializing_if = "Option::is_none", + deserialize_with = "deserialize_as_vec", + serialize_with = "serialize_as_map" + )] + volumes: Option>, + /// Sets the current working directory of the entrypoint process + /// in the container. This value acts as a default and may be + /// replaced by a working directory specified when creating + /// a container. + #[serde(skip_serializing_if = "Option::is_none")] + working_dir: Option, + /// The field contains arbitrary metadata for the container. + /// This property MUST use the annotation rules. + #[serde(skip_serializing_if = "Option::is_none")] + labels: Option>, + /// The field contains the system call signal that will be + /// sent to the container to exit. The signal can be a signal + /// name in the format SIGNAME, for instance SIGKILL or SIGRTMIN+3. + #[serde(skip_serializing_if = "Option::is_none")] + stop_signal: Option, +} // Some fields of the image configuration are a json serialization of a // Go map[string]struct{} leading to the following json: @@ -339,29 +329,23 @@ where } } -make_pub!( - #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// RootFs references the layer content addresses used by the image. - struct RootFs { - /// MUST be set to layers. - #[serde(rename = "type")] - typ: String, - /// An array of layer content hashes (DiffIDs), in order - /// from first to last. - diff_ids: Vec, - } -); +#[derive(Builder, Clone, Debug, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// RootFs references the layer content addresses used by the image. +pub struct RootFs { + /// MUST be set to layers. + #[serde(rename = "type")] + typ: String, + /// An array of layer content hashes (DiffIDs), in order + /// from first to last. + diff_ids: Vec, +} impl Default for RootFs { fn default() -> Self { @@ -372,45 +356,39 @@ impl Default for RootFs { } } -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// Describes the history of a layer. - struct History { - /// A combined date and time at which the layer was created, - /// formatted as defined by [RFC 3339, section 5.6.](https://tools.ietf.org/html/rfc3339#section-5.6). - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - created: Option, - /// The author of the build point. - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - author: Option, - /// The command which created the layer. - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - created_by: Option, - /// A custom message set when creating the layer. - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - comment: Option, - /// This field is used to mark if the history item created - /// a filesystem diff. It is set to true if this history item - /// doesn't correspond to an actual layer in the rootfs section - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - empty_layer: Option, - } -); +#[derive(Builder, Clone, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// Describes the history of a layer. +pub struct History { + /// A combined date and time at which the layer was created, + /// formatted as defined by [RFC 3339, section 5.6.](https://tools.ietf.org/html/rfc3339#section-5.6). + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + created: Option, + /// The author of the build point. + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + author: Option, + /// The command which created the layer. + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + created_by: Option, + /// A custom message set when creating the layer. + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + comment: Option, + /// This field is used to mark if the history item created + /// a filesystem diff. It is set to true if this history item + /// doesn't correspond to an actual layer in the rootfs section + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + empty_layer: Option, +} #[cfg(test)] mod tests { @@ -419,7 +397,6 @@ mod tests { use super::*; use crate::image::Os; - #[cfg(feature = "builder")] fn create_config() -> ImageConfiguration { let configuration = ImageConfigurationBuilder::default() .created("2015-10-31T22:22:56.015925234Z".to_owned()) @@ -474,74 +451,6 @@ mod tests { configuration } - #[cfg(not(feature = "builder"))] - fn create_config() -> ImageConfiguration { - let config = Config { - user: Some("alice".to_owned()), - exposed_ports: Some(vec!["8080/tcp".to_owned()]), - env: Some(vec![ - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin".to_owned(), - "FOO=oci_is_a".to_owned(), - "BAR=well_written_spec".to_owned(), - ]), - entrypoint: Some(vec!["/bin/my-app-binary".to_owned()]), - cmd: Some(vec![ - "--foreground".to_owned(), - "--config".to_owned(), - "/etc/my-app.d/default.cfg".to_owned(), - ]), - volumes: Some(vec![ - "/var/job-result-data".to_owned(), - "/var/log/my-app-logs".to_owned(), - ]), - working_dir: Some("/home/alice".to_owned()), - labels: None, - stop_signal: None, - }; - - let rootfs = RootFs { - diff_ids: vec![ - "sha256:c6f988f4874bb0add23a778f753c65efe992244e148a1d2ec2a8b664fb66bbd1" - .to_owned(), - "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef" - .to_owned(), - ], - ..Default::default() - }; - - let history = vec![ - History { - created: Some("2015-10-31T22:22:54.690851953Z".to_owned()), - author: None, - created_by: Some("/bin/sh -c #(nop) ADD file:a3bc1e842b69636f9df5256c49c5374fb4eef1e281fe3f282c65fb853ee171c5 in /".to_owned()), - comment: None, - empty_layer: None, - }, - History { - created: Some("2015-10-31T22:22:55.613815829Z".to_owned()), - author: None, - created_by: Some("/bin/sh -c #(nop) CMD [\"sh\"]".to_owned()), - comment: None, - empty_layer: Some(true), - } - ]; - - let configuration = ImageConfiguration { - created: Some("2015-10-31T22:22:56.015925234Z".to_owned()), - author: Some("Alyssa P. Hacker ".to_owned()), - architecture: Arch::Amd64, - os: Os::Linux, - os_version: None, - os_features: None, - variant: None, - config: Some(config), - rootfs, - history, - }; - - configuration - } - fn get_config_path() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test/data/config.json") } diff --git a/src/image/descriptor.rs b/src/image/descriptor.rs index 5b5f30cb7e..32a5119813 100644 --- a/src/image/descriptor.rs +++ b/src/image/descriptor.rs @@ -1,119 +1,111 @@ -use std::collections::HashMap; - -use serde::{Deserialize, Serialize}; - use super::{Arch, MediaType, Os}; +use crate::error::OciSpecError; +use derive_builder::Builder; +use getset::{CopyGetters, Getters}; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; -make_pub!( - #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// A Content Descriptor (or simply Descriptor) describes the disposition of - /// the targeted content. It includes the type of the content, a content - /// identifier (digest), and the byte-size of the raw content. - /// Descriptors SHOULD be embedded in other formats to securely reference - /// external content. - struct Descriptor { - /// This REQUIRED property contains the media type of the referenced - /// content. Values MUST comply with RFC 6838, including the naming - /// requirements in its section 4.2. - #[serde(rename = "mediaType")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - media_type: MediaType, - /// This REQUIRED property is the digest of the targeted content, - /// conforming to the requirements outlined in Digests. Retrieved - /// content SHOULD be verified against this digest when consumed via - /// untrusted sources. - #[cfg_attr(feature = "builder", getset(get = "pub"))] - digest: String, - /// This REQUIRED property specifies the size, in bytes, of the raw - /// content. This property exists so that a client will have an - /// expected size for the content before processing. If the - /// length of the retrieved content does not match the specified - /// length, the content SHOULD NOT be trusted. - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - size: i64, - /// This OPTIONAL property specifies a list of URIs from which this - /// object MAY be downloaded. Each entry MUST conform to [RFC 3986](https://tools.ietf.org/html/rfc3986). - /// Entries SHOULD use the http and https schemes, as defined - /// in [RFC 7230](https://tools.ietf.org/html/rfc7230#section-2.7). - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"), builder(default))] - urls: Option>, - /// This OPTIONAL property contains arbitrary metadata for this - /// descriptor. This OPTIONAL property MUST use the annotation - /// rules. - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"), builder(default))] - annotations: Option>, - /// This OPTIONAL property describes the minimum runtime requirements of - /// the image. This property SHOULD be present if its target is - /// platform-specific. - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"), builder(default))] - platform: Option, - } -); +#[derive(Builder, Clone, CopyGetters, Debug, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[builder( + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// A Content Descriptor (or simply Descriptor) describes the disposition of +/// the targeted content. It includes the type of the content, a content +/// identifier (digest), and the byte-size of the raw content. +/// Descriptors SHOULD be embedded in other formats to securely reference +/// external content. +pub struct Descriptor { + /// This REQUIRED property contains the media type of the referenced + /// content. Values MUST comply with RFC 6838, including the naming + /// requirements in its section 4.2. + #[serde(rename = "mediaType")] + #[getset(get = "pub")] + media_type: MediaType, + /// This REQUIRED property is the digest of the targeted content, + /// conforming to the requirements outlined in Digests. Retrieved + /// content SHOULD be verified against this digest when consumed via + /// untrusted sources. + #[getset(get = "pub")] + digest: String, + /// This REQUIRED property specifies the size, in bytes, of the raw + /// content. This property exists so that a client will have an + /// expected size for the content before processing. If the + /// length of the retrieved content does not match the specified + /// length, the content SHOULD NOT be trusted. + #[getset(get_copy = "pub")] + size: i64, + /// This OPTIONAL property specifies a list of URIs from which this + /// object MAY be downloaded. Each entry MUST conform to [RFC 3986](https://tools.ietf.org/html/rfc3986). + /// Entries SHOULD use the http and https schemes, as defined + /// in [RFC 7230](https://tools.ietf.org/html/rfc7230#section-2.7). + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + #[builder(default)] + urls: Option>, + /// This OPTIONAL property contains arbitrary metadata for this + /// descriptor. This OPTIONAL property MUST use the annotation + /// rules. + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + #[builder(default)] + annotations: Option>, + /// This OPTIONAL property describes the minimum runtime requirements of + /// the image. This property SHOULD be present if its target is + /// platform-specific. + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + #[builder(default)] + platform: Option, +} -make_pub!( - #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// Describes the minimum runtime requirements of the image. - struct Platform { - /// This REQUIRED property specifies the CPU architecture. - /// Image indexes SHOULD use, and implementations SHOULD understand, - /// values listed in the Go Language document for GOARCH. - architecture: Arch, - /// This REQUIRED property specifies the operating system. - /// Image indexes SHOULD use, and implementations SHOULD understand, - /// values listed in the Go Language document for GOOS. - os: Os, - /// This OPTIONAL property specifies the version of the operating system - /// targeted by the referenced blob. Implementations MAY refuse to use - /// manifests where os.version is not known to work with the host OS - /// version. Valid values are implementation-defined. e.g. - /// 10.0.14393.1066 on windows. - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", builder(default))] - os_version: Option, - /// This OPTIONAL property specifies an array of strings, each - /// specifying a mandatory OS feature. When os is windows, image - /// indexes SHOULD use, and implementations SHOULD understand - /// the following values: - /// - win32k: image requires win32k.sys on the host (Note: win32k.sys is - /// missing on Nano Server) - /// - /// When os is not windows, values are implementation-defined and SHOULD - /// be submitted to this specification for standardization. - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", builder(default))] - os_features: Option>, - /// This OPTIONAL property specifies the variant of the CPU. - /// Image indexes SHOULD use, and implementations SHOULD understand, - /// variant values listed in the [Platform Variants] - /// () - /// table. - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", builder(default))] - variant: Option, - } -); +#[derive(Builder, Clone, Debug, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[builder( + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// Describes the minimum runtime requirements of the image. +pub struct Platform { + /// This REQUIRED property specifies the CPU architecture. + /// Image indexes SHOULD use, and implementations SHOULD understand, + /// values listed in the Go Language document for GOARCH. + architecture: Arch, + /// This REQUIRED property specifies the operating system. + /// Image indexes SHOULD use, and implementations SHOULD understand, + /// values listed in the Go Language document for GOOS. + os: Os, + /// This OPTIONAL property specifies the version of the operating system + /// targeted by the referenced blob. Implementations MAY refuse to use + /// manifests where os.version is not known to work with the host OS + /// version. Valid values are implementation-defined. e.g. + /// 10.0.14393.1066 on windows. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default)] + os_version: Option, + /// This OPTIONAL property specifies an array of strings, each + /// specifying a mandatory OS feature. When os is windows, image + /// indexes SHOULD use, and implementations SHOULD understand + /// the following values: + /// - win32k: image requires win32k.sys on the host (Note: win32k.sys is + /// missing on Nano Server) + /// + /// When os is not windows, values are implementation-defined and SHOULD + /// be submitted to this specification for standardization. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default)] + os_features: Option>, + /// This OPTIONAL property specifies the variant of the CPU. + /// Image indexes SHOULD use, and implementations SHOULD understand, + /// variant values listed in the [Platform Variants] + /// () + /// table. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default)] + variant: Option, +} impl Default for Platform { fn default() -> Self { diff --git a/src/image/index.rs b/src/image/index.rs index b32cdcdeb9..1d5ba22eba 100644 --- a/src/image/index.rs +++ b/src/image/index.rs @@ -1,5 +1,10 @@ use super::{Descriptor, MediaType}; -use crate::{error::Result, from_file, from_reader, to_file, to_writer}; +use crate::{ + error::{OciSpecError, Result}, + from_file, from_reader, to_file, to_writer, +}; +use derive_builder::Builder; +use getset::{CopyGetters, Getters}; use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, @@ -10,48 +15,44 @@ use std::{ /// The expected schema version; equals 2 for compatibility with older versions of Docker. pub const SCHEMA_VERSION: u32 = 2; -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), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// The image index is a higher-level manifest which points to specific - /// image manifests, ideal for one or more platforms. While the use of - /// an image index is OPTIONAL for image providers, image consumers - /// SHOULD be prepared to process them. - struct ImageIndex { - /// 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"), builder(default))] - media_type: Option, - /// This REQUIRED property contains a list of manifests for specific - /// platforms. While this property MUST be present, the size of - /// the array MAY be zero. - #[cfg_attr(feature = "builder", getset(get = "pub"))] - manifests: Vec, - /// This OPTIONAL property contains arbitrary metadata for the image - /// index. This OPTIONAL property MUST use the annotation rules. - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"), builder(default))] - annotations: Option>, - } -); +#[derive(Builder, Clone, CopyGetters, Debug, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +#[builder( + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// The image index is a higher-level manifest which points to specific +/// image manifests, ideal for one or more platforms. While the use of +/// an image index is OPTIONAL for image providers, image consumers +/// SHOULD be prepared to process them. +pub struct ImageIndex { + /// 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. + #[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")] + #[getset(get = "pub")] + #[builder(default)] + media_type: Option, + /// This REQUIRED property contains a list of manifests for specific + /// platforms. While this property MUST be present, the size of + /// the array MAY be zero. + #[getset(get = "pub")] + manifests: Vec, + /// This OPTIONAL property contains arbitrary metadata for the image + /// index. This OPTIONAL property MUST use the annotation rules. + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + #[builder(default)] + annotations: Option>, +} impl ImageIndex { /// Attempts to load an image index from a file. @@ -168,12 +169,8 @@ mod tests { use super::*; use crate::image::{Arch, Os}; - #[cfg(not(feature = "builder"))] - use crate::image::{Descriptor, Platform}; - #[cfg(feature = "builder")] use crate::image::{DescriptorBuilder, PlatformBuilder}; - #[cfg(feature = "builder")] fn create_index() -> ImageIndex { let ppc_manifest = DescriptorBuilder::default() .media_type(MediaType::ImageManifest) @@ -212,50 +209,6 @@ mod tests { index } - #[cfg(not(feature = "builder"))] - fn create_index() -> ImageIndex { - let ppc_manifest = { - let mut r = Descriptor::new( - MediaType::ImageManifest, - 7143, - "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f", - ); - r.platform = Some(Platform { - architecture: Arch::PowerPC64le, - os: Os::Linux, - os_version: None, - os_features: None, - variant: None, - }); - r - }; - - let amd64_manifest = Descriptor { - media_type: MediaType::ImageManifest, - digest: "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" - .to_owned(), - size: 7682, - urls: None, - annotations: None, - platform: Some(Platform { - architecture: Arch::Amd64, - os: Os::Linux, - os_version: None, - os_features: None, - variant: None, - }), - }; - - let index = ImageIndex { - schema_version: SCHEMA_VERSION, - media_type: None, - manifests: vec![ppc_manifest, amd64_manifest], - annotations: None, - }; - - index - } - fn get_index_path() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test/data/index.json") } diff --git a/src/image/manifest.rs b/src/image/manifest.rs index 5e9c0485ea..1752fc9566 100644 --- a/src/image/manifest.rs +++ b/src/image/manifest.rs @@ -1,72 +1,70 @@ +use super::{Descriptor, MediaType}; +use crate::{ + error::{OciSpecError, Result}, + from_file, from_reader, to_file, to_writer, +}; +use derive_builder::Builder; +use getset::{CopyGetters, Getters}; +use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, io::{Read, Write}, path::Path, }; -use crate::{error::Result, from_file, from_reader, to_file, to_writer}; - -use super::{Descriptor, MediaType}; - -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), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// 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"), builder(default))] - media_type: Option, - /// 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, - /// 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"), builder(default))] - annotations: Option>, - } -); +#[derive(Builder, Clone, CopyGetters, Debug, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +#[builder( + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// 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. +pub 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. + #[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")] + #[getset(get = "pub")] + #[builder(default)] + media_type: Option, + /// 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. + #[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. + #[getset(get = "pub")] + layers: Vec, + /// 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")] + #[getset(get = "pub")] + #[builder(default)] + annotations: Option>, +} impl ImageManifest { /// Attempts to load an image manifest from a file. @@ -171,12 +169,8 @@ mod tests { use std::{fs, path::PathBuf}; use super::*; - #[cfg(not(feature = "builder"))] - use crate::image::Descriptor; - #[cfg(feature = "builder")] use crate::image::{Descriptor, DescriptorBuilder}; - #[cfg(feature = "builder")] fn create_manifest() -> ImageManifest { use crate::image::SCHEMA_VERSION; @@ -222,61 +216,6 @@ mod tests { manifest } - #[cfg(not(feature = "builder"))] - fn create_manifest() -> ImageManifest { - use crate::image::SCHEMA_VERSION; - - let config = Descriptor { - media_type: MediaType::ImageConfig, - size: 7023, - digest: "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7" - .to_owned(), - urls: None, - annotations: None, - platform: None, - }; - - let layers = vec![ - Descriptor { - media_type: MediaType::ImageLayerGzip, - size: 32654, - digest: "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0" - .to_owned(), - urls: None, - annotations: None, - platform: None, - }, - Descriptor { - media_type: MediaType::ImageLayerGzip, - size: 16724, - digest: "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b" - .to_owned(), - urls: None, - annotations: None, - platform: None, - }, - Descriptor { - media_type: MediaType::ImageLayerGzip, - size: 73109, - digest: "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736" - .to_owned(), - urls: None, - annotations: None, - platform: None, - }, - ]; - - let manifest = ImageManifest { - schema_version: SCHEMA_VERSION, - media_type: None, - config, - layers, - annotations: None, - }; - - manifest - } - fn get_manifest_path() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test/data/manifest.json") } diff --git a/src/lib.rs b/src/lib.rs index acbcbf6e15..0a4ea1fbed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,6 @@ #![deny(missing_docs, warnings)] #![doc = include_str!("../README.md")] -#[macro_use] -mod macros; - #[cfg(feature = "distribution")] pub mod distribution; mod error; diff --git a/src/macros.rs b/src/macros.rs deleted file mode 100644 index a48268fe22..0000000000 --- a/src/macros.rs +++ /dev/null @@ -1,41 +0,0 @@ -#[cfg(not(feature = "builder"))] -macro_rules! make_pub { - { - $(#[$outer:meta])* - struct $name:ident { - $( - $(#[$inner:ident $($args:tt)*])* - $field:ident: $t:ty, - )* - } - } => { - $(#[$outer])* - pub struct $name { - $( - $(#[$inner $($args)*])* - pub $field: $t, - )* - } - } -} - -#[cfg(feature = "builder")] -macro_rules! make_pub { - { - $(#[$outer:meta])* - struct $name:ident { - $( - $(#[$inner:ident $($args:tt)*])* - $field:ident: $t:ty, - )* - } - } => { - $(#[$outer])* - pub struct $name { - $( - $(#[$inner $($args)*])* - $field: $t, - )* - } - } -} diff --git a/src/runtime/hooks.rs b/src/runtime/hooks.rs index acad5e6790..f98c1f3f80 100644 --- a/src/runtime/hooks.rs +++ b/src/runtime/hooks.rs @@ -1,111 +1,104 @@ +use crate::error::OciSpecError; +use derive_builder::Builder; +use getset::{CopyGetters, Getters}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") +#[derive(Builder, Clone, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// Hooks specifies a command that is run in the container at a particular +/// event in the lifecycle (setup and teardown) of a container. +pub struct Hooks { + #[deprecated( + note = "Prestart hooks were deprecated in favor of `createRuntime`, `createContainer` and `startContainer` hooks" )] - /// Hooks specifies a command that is run in the container at a particular - /// event in the lifecycle (setup and teardown) of a container. - struct Hooks { - #[deprecated( - note = "Prestart hooks were deprecated in favor of `createRuntime`, `createContainer` and `startContainer` hooks" - )] - #[serde(default, skip_serializing_if = "Option::is_none")] - /// The `prestart` hooks MUST be called after the `start` operation is - /// called but before the user-specified program command is - /// executed. - /// - /// On Linux, for example, they are called after the container - /// namespaces are created, so they provide an opportunity to - /// customize the container (e.g. the network namespace could be - /// specified in this hook). - /// - /// The `prestart` hooks' path MUST resolve in the runtime namespace. - /// The `prestart` hooks MUST be executed in the runtime namespace. - prestart: Option>, + #[serde(default, skip_serializing_if = "Option::is_none")] + /// The `prestart` hooks MUST be called after the `start` operation is + /// called but before the user-specified program command is + /// executed. + /// + /// On Linux, for example, they are called after the container + /// namespaces are created, so they provide an opportunity to + /// customize the container (e.g. the network namespace could be + /// specified in this hook). + /// + /// The `prestart` hooks' path MUST resolve in the runtime namespace. + /// The `prestart` hooks MUST be executed in the runtime namespace. + prestart: Option>, - #[serde(default, skip_serializing_if = "Option::is_none")] - /// CreateRuntime is a list of hooks to be run after the container has - /// been created but before `pivot_root` or any equivalent - /// operation has been called. It is called in the Runtime - /// Namespace. - create_runtime: Option>, + #[serde(default, skip_serializing_if = "Option::is_none")] + /// CreateRuntime is a list of hooks to be run after the container has + /// been created but before `pivot_root` or any equivalent + /// operation has been called. It is called in the Runtime + /// Namespace. + create_runtime: Option>, - #[serde(default, skip_serializing_if = "Option::is_none")] - /// CreateContainer is a list of hooks to be run after the container has - /// been created but before `pivot_root` or any equivalent - /// operation has been called. It is called in the - /// Container Namespace. - create_container: Option>, + #[serde(default, skip_serializing_if = "Option::is_none")] + /// CreateContainer is a list of hooks to be run after the container has + /// been created but before `pivot_root` or any equivalent + /// operation has been called. It is called in the + /// Container Namespace. + create_container: Option>, - #[serde(default, skip_serializing_if = "Option::is_none")] - /// StartContainer is a list of hooks to be run after the start - /// operation is called but before the container process is - /// started. It is called in the Container Namespace. - start_container: Option>, + #[serde(default, skip_serializing_if = "Option::is_none")] + /// StartContainer is a list of hooks to be run after the start + /// operation is called but before the container process is + /// started. It is called in the Container Namespace. + start_container: Option>, - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Poststart is a list of hooks to be run after the container process - /// is started. It is called in the Runtime Namespace. - poststart: Option>, + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Poststart is a list of hooks to be run after the container process + /// is started. It is called in the Runtime Namespace. + poststart: Option>, - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Poststop is a list of hooks to be run after the container process - /// exits. It is called in the Runtime Namespace. - poststop: Option>, - } -); + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Poststop is a list of hooks to be run after the container process + /// exits. It is called in the Runtime Namespace. + poststop: Option>, +} -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// Hook specifies a command that is run at a particular event in the - /// lifecycle of a container. - struct Hook { - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Path to the binary to be executed. Following similar semantics to - /// [IEEE Std 1003.1-2008 `execv`'s path](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html). This - /// specification extends the IEEE standard in that path MUST be - /// absolute. - path: PathBuf, +#[derive( + Builder, Clone, CopyGetters, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize, +)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// Hook specifies a command that is run at a particular event in the +/// lifecycle of a container. +pub struct Hook { + #[getset(get = "pub")] + /// Path to the binary to be executed. Following similar semantics to + /// [IEEE Std 1003.1-2008 `execv`'s path](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html). This + /// specification extends the IEEE standard in that path MUST be + /// absolute. + path: PathBuf, - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Arguments used for the binary, including the binary name itself. - /// Following the same semantics as [IEEE Std 1003.1-2008 - /// `execv`'s argv](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html). - args: Option>, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Arguments used for the binary, including the binary name itself. + /// Following the same semantics as [IEEE Std 1003.1-2008 + /// `execv`'s argv](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html). + args: Option>, - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Additional `key=value` environment variables. Following the same - /// semantics as [IEEE Std 1003.1-2008's `environ`](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_01). - env: Option>, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Additional `key=value` environment variables. Following the same + /// semantics as [IEEE Std 1003.1-2008's `environ`](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_01). + env: Option>, - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Timeout is the number of seconds before aborting the hook. If set, - /// timeout MUST be greater than zero. - timeout: Option, - } -); + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// Timeout is the number of seconds before aborting the hook. If set, + /// timeout MUST be greater than zero. + timeout: Option, +} diff --git a/src/runtime/linux.rs b/src/runtime/linux.rs index e0959f04d5..37317536e3 100644 --- a/src/runtime/linux.rs +++ b/src/runtime/linux.rs @@ -1,94 +1,90 @@ use crate::error::{oci_error, OciSpecError}; +use derive_builder::Builder; +use getset::{CopyGetters, Getters}; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, convert::TryFrom, path::PathBuf}; -make_pub!( - #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// Linux contains platform-specific configuration for Linux based - /// containers. - struct Linux { - #[serde(default, skip_serializing_if = "Option::is_none")] - /// UIDMappings specifies user mappings for supporting user namespaces. - uid_mappings: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// GIDMappings specifies group mappings for supporting user namespaces. - gid_mappings: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Sysctl are a set of key value pairs that are set for the container - /// on start. - sysctl: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Resources contain cgroup information for handling resource - /// constraints for the container. - resources: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// CgroupsPath specifies the path to cgroups that are created and/or - /// joined by the container. The path is expected to be relative - /// to the cgroups mountpoint. If resources are specified, - /// the cgroups at CgroupsPath will be updated based on resources. - cgroups_path: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Namespaces contains the namespaces that are created and/or joined by - /// the container. - namespaces: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Devices are a list of device nodes that are created for the - /// container. - devices: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Seccomp specifies the seccomp security settings for the container. - seccomp: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// RootfsPropagation is the rootfs mount propagation mode for the - /// container. - rootfs_propagation: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// MaskedPaths masks over the provided paths inside the container. - masked_paths: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// ReadonlyPaths sets the provided paths as RO inside the container. - readonly_paths: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// MountLabel specifies the selinux context for the mounts in the - /// container. - mount_label: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// IntelRdt contains Intel Resource Director Technology (RDT) - /// information for handling resource constraints (e.g., L3 - /// cache, memory bandwidth) for the container. - intel_rdt: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Personality contains configuration for the Linux personality - /// syscall. - personality: Option, - } -); +#[derive(Builder, Clone, Debug, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// Linux contains platform-specific configuration for Linux based +/// containers. +pub struct Linux { + #[serde(default, skip_serializing_if = "Option::is_none")] + /// UIDMappings specifies user mappings for supporting user namespaces. + uid_mappings: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// GIDMappings specifies group mappings for supporting user namespaces. + gid_mappings: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Sysctl are a set of key value pairs that are set for the container + /// on start. + sysctl: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Resources contain cgroup information for handling resource + /// constraints for the container. + resources: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// CgroupsPath specifies the path to cgroups that are created and/or + /// joined by the container. The path is expected to be relative + /// to the cgroups mountpoint. If resources are specified, + /// the cgroups at CgroupsPath will be updated based on resources. + cgroups_path: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Namespaces contains the namespaces that are created and/or joined by + /// the container. + namespaces: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Devices are a list of device nodes that are created for the + /// container. + devices: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Seccomp specifies the seccomp security settings for the container. + seccomp: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// RootfsPropagation is the rootfs mount propagation mode for the + /// container. + rootfs_propagation: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// MaskedPaths masks over the provided paths inside the container. + masked_paths: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// ReadonlyPaths sets the provided paths as RO inside the container. + readonly_paths: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// MountLabel specifies the selinux context for the mounts in the + /// container. + mount_label: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// IntelRdt contains Intel Resource Director Technology (RDT) + /// information for handling resource constraints (e.g., L3 + /// cache, memory bandwidth) for the container. + intel_rdt: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Personality contains configuration for the Linux personality + /// syscall. + personality: Option, +} // Default impl for Linux (see funtions for more info) impl Default for Linux { @@ -136,36 +132,32 @@ impl Default for Linux { } } -make_pub!( - #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get_copy = "pub") - )] - /// LinuxIDMapping specifies UID/GID mappings. - struct LinuxIdMapping { - #[serde(default, rename = "hostID")] - /// HostID is the starting UID/GID on the host to be mapped to - /// `container_id`. - host_id: u32, - - #[serde(default, rename = "containerID")] - /// ContainerID is the starting UID/GID in the container. - container_id: u32, - - #[serde(default)] - /// Size is the number of IDs to be mapped. - size: u32, - } -); +#[derive( + Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize, +)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get_copy = "pub")] +/// LinuxIDMapping specifies UID/GID mappings. +pub struct LinuxIdMapping { + #[serde(default, rename = "hostID")] + /// HostID is the starting UID/GID on the host to be mapped to + /// `container_id`. + host_id: u32, + + #[serde(default, rename = "containerID")] + /// ContainerID is the starting UID/GID in the container. + container_id: u32, + + #[serde(default)] + /// Size is the number of IDs to be mapped. + size: u32, +} #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)] #[serde(rename_all = "lowercase")] @@ -202,45 +194,41 @@ impl LinuxDeviceType { } } -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// Represents a device rule for the devices specified to the device - /// controller - struct LinuxDeviceCgroup { - #[serde(default)] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Allow or deny - allow: bool, - - #[serde(default, rename = "type")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Device type, block, char, etc. - typ: Option, - - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Device's major number - major: Option, - - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Device's minor number - minor: Option, - - /// Cgroup access premissions format, rwm. - #[serde(default)] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - access: Option, - } -); +#[derive( + Builder, Clone, CopyGetters, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize, +)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// Represents a device rule for the devices specified to the device +/// controller +pub struct LinuxDeviceCgroup { + #[serde(default)] + #[getset(get_copy = "pub")] + /// Allow or deny + allow: bool, + + #[serde(default, rename = "type")] + #[getset(get_copy = "pub")] + /// Device type, block, char, etc. + typ: Option, + + #[getset(get_copy = "pub")] + /// Device's major number + major: Option, + + #[getset(get_copy = "pub")] + /// Device's minor number + minor: Option, + + /// Cgroup access premissions format, rwm. + #[serde(default)] + #[getset(get = "pub")] + access: Option, +} impl ToString for LinuxDeviceCgroup { fn to_string(&self) -> String { @@ -263,303 +251,269 @@ impl ToString for LinuxDeviceCgroup { } } -make_pub!( - #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get_copy = "pub") - )] - /// LinuxMemory for Linux cgroup 'memory' resource management. - struct LinuxMemory { - #[serde(skip_serializing_if = "Option::is_none")] - /// Memory limit (in bytes). - limit: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - /// Memory reservation or soft_limit (in bytes). - reservation: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - /// Total memory limit (memory + swap). - swap: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - /// Kernel memory limit (in bytes). - kernel: Option, - - #[serde(skip_serializing_if = "Option::is_none", rename = "kernelTCP")] - /// Kernel memory limit for tcp (in bytes). - kernel_tcp: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - /// How aggressive the kernel will swap memory pages. - swappiness: Option, - - #[serde(skip_serializing_if = "Option::is_none", rename = "disableOOMKiller")] - /// DisableOOMKiller disables the OOM killer for out of memory - /// conditions. - disable_oom_killer: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - /// Enables hierarchical memory accounting - use_hierarchy: Option, - } -); - -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// LinuxCPU for Linux cgroup 'cpu' resource management. - struct LinuxCpu { - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// CPU shares (relative weight (ratio) vs. other cgroups with cpu - /// shares). - shares: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// CPU hardcap limit (in usecs). Allowed cpu time in a given period. - quota: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// CPU period to be used for hardcapping (in usecs). - period: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// How much time realtime scheduling may use (in usecs). - realtime_runtime: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// CPU period to be used for realtime scheduling (in usecs). - realtime_period: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// CPUs to use within the cpuset. Default is to use any CPU available. - cpus: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// List of memory nodes in the cpuset. Default is to use any available - /// memory node. - mems: Option, - } -); - -make_pub!( - #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get_copy = "pub") - )] - /// LinuxPids for Linux cgroup 'pids' resource management (Linux 4.3). - struct LinuxPids { - #[serde(default)] - /// Maximum number of PIDs. Default is "no limit". - limit: i64, - } -); - -make_pub!( - #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get_copy = "pub") - )] - /// LinuxWeightDevice struct holds a `major:minor weight` pair for - /// weightDevice. - struct LinuxWeightDevice { - #[serde(default)] - /// Major is the device's major number. - major: i64, - - #[serde(default)] - /// Minor is the device's minor number. - minor: i64, - - #[serde(skip_serializing_if = "Option::is_none")] - /// Weight is the bandwidth rate for the device. - weight: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - /// LeafWeight is the bandwidth rate for the device while competing with - /// the cgroup's child cgroups, CFQ scheduler only. - leaf_weight: Option, - } -); - -make_pub!( - #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get_copy = "pub") - )] - /// LinuxThrottleDevice struct holds a `major:minor rate_per_second` pair. - struct LinuxThrottleDevice { - #[serde(default)] - /// Major is the device's major number. - major: i64, - - #[serde(default)] - /// Minor is the device's minor number. - minor: i64, - - #[serde(default)] - /// Rate is the IO rate limit per cgroup per device. - rate: u64, - } -); - -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// LinuxBlockIO for Linux cgroup 'blkio' resource management. - struct LinuxBlockIo { - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Specifies per cgroup weight. - weight: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Specifies tasks' weight in the given cgroup while competing with the - /// cgroup's child cgroups, CFQ scheduler only. - leaf_weight: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Weight per cgroup per device, can override BlkioWeight. - weight_device: Option>, - - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// IO read rate limit per cgroup per device, bytes per second. - throttle_read_bps_device: Option>, - - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// IO write rate limit per cgroup per device, bytes per second. - throttle_write_bps_device: Option>, - - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// IO read rate limit per cgroup per device, IO per second. - throttle_read_iops_device: Option>, - - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// IO write rate limit per cgroup per device, IO per second. - throttle_write_iops_device: Option>, - } -); - -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// LinuxHugepageLimit structure corresponds to limiting kernel hugepages. - struct LinuxHugepageLimit { - #[serde(default)] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Pagesize is the hugepage size. - /// Format: "B' (e.g. 64KB, 2MB, 1GB, etc.) - page_size: String, - - #[serde(default)] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Limit is the limit of "hugepagesize" hugetlb usage. - limit: i64, - } -); - -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// LinuxInterfacePriority for network interfaces. - struct LinuxInterfacePriority { - #[serde(default)] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Name is the name of the network interface. - name: String, - - #[serde(default)] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Priority for the interface. - priority: u32, - } -); +#[derive( + Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize, +)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get_copy = "pub")] +/// LinuxMemory for Linux cgroup 'memory' resource management. +pub struct LinuxMemory { + #[serde(skip_serializing_if = "Option::is_none")] + /// Memory limit (in bytes). + limit: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + /// Memory reservation or soft_limit (in bytes). + reservation: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + /// Total memory limit (memory + swap). + swap: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + /// Kernel memory limit (in bytes). + kernel: Option, + + #[serde(skip_serializing_if = "Option::is_none", rename = "kernelTCP")] + /// Kernel memory limit for tcp (in bytes). + kernel_tcp: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + /// How aggressive the kernel will swap memory pages. + swappiness: Option, + + #[serde(skip_serializing_if = "Option::is_none", rename = "disableOOMKiller")] + /// DisableOOMKiller disables the OOM killer for out of memory + /// conditions. + disable_oom_killer: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + /// Enables hierarchical memory accounting + use_hierarchy: Option, +} + +#[derive( + Builder, Clone, CopyGetters, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize, +)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// LinuxCPU for Linux cgroup 'cpu' resource management. +pub struct LinuxCpu { + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// CPU shares (relative weight (ratio) vs. other cgroups with cpu + /// shares). + shares: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// CPU hardcap limit (in usecs). Allowed cpu time in a given period. + quota: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// CPU period to be used for hardcapping (in usecs). + period: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// How much time realtime scheduling may use (in usecs). + realtime_runtime: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// CPU period to be used for realtime scheduling (in usecs). + realtime_period: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// CPUs to use within the cpuset. Default is to use any CPU available. + cpus: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// List of memory nodes in the cpuset. Default is to use any available + /// memory node. + mems: Option, +} + +#[derive(Builder, Clone, Copy, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get_copy = "pub")] +/// LinuxPids for Linux cgroup 'pids' resource management (Linux 4.3). +pub struct LinuxPids { + #[serde(default)] + /// Maximum number of PIDs. Default is "no limit". + limit: i64, +} + +#[derive( + Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize, +)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get_copy = "pub")] +/// LinuxWeightDevice struct holds a `major:minor weight` pair for +/// weightDevice. +pub struct LinuxWeightDevice { + #[serde(default)] + /// Major is the device's major number. + major: i64, + + #[serde(default)] + /// Minor is the device's minor number. + minor: i64, + + #[serde(skip_serializing_if = "Option::is_none")] + /// Weight is the bandwidth rate for the device. + weight: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + /// LeafWeight is the bandwidth rate for the device while competing with + /// the cgroup's child cgroups, CFQ scheduler only. + leaf_weight: Option, +} + +#[derive( + Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize, +)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get_copy = "pub")] +/// LinuxThrottleDevice struct holds a `major:minor rate_per_second` pair. +pub struct LinuxThrottleDevice { + #[serde(default)] + /// Major is the device's major number. + major: i64, + + #[serde(default)] + /// Minor is the device's minor number. + minor: i64, + + #[serde(default)] + /// Rate is the IO rate limit per cgroup per device. + rate: u64, +} + +#[derive( + Builder, Clone, CopyGetters, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize, +)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// LinuxBlockIO for Linux cgroup 'blkio' resource management. +pub struct LinuxBlockIo { + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// Specifies per cgroup weight. + weight: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// Specifies tasks' weight in the given cgroup while competing with the + /// cgroup's child cgroups, CFQ scheduler only. + leaf_weight: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Weight per cgroup per device, can override BlkioWeight. + weight_device: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// IO read rate limit per cgroup per device, bytes per second. + throttle_read_bps_device: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// IO write rate limit per cgroup per device, bytes per second. + throttle_write_bps_device: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// IO read rate limit per cgroup per device, IO per second. + throttle_read_iops_device: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// IO write rate limit per cgroup per device, IO per second. + throttle_write_iops_device: Option>, +} + +#[derive( + Builder, Clone, CopyGetters, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize, +)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// LinuxHugepageLimit structure corresponds to limiting kernel hugepages. +pub struct LinuxHugepageLimit { + #[serde(default)] + #[getset(get = "pub")] + /// Pagesize is the hugepage size. + /// Format: "B' (e.g. 64KB, 2MB, 1GB, etc.) + page_size: String, + + #[serde(default)] + #[getset(get_copy = "pub")] + /// Limit is the limit of "hugepagesize" hugetlb usage. + limit: i64, +} + +#[derive( + Builder, Clone, CopyGetters, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize, +)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// LinuxInterfacePriority for network interfaces. +pub struct LinuxInterfacePriority { + #[serde(default)] + #[getset(get = "pub")] + /// Name is the name of the network interface. + name: String, + + #[serde(default)] + #[getset(get_copy = "pub")] + /// Priority for the interface. + priority: u32, +} impl ToString for LinuxInterfacePriority { fn to_string(&self) -> String { @@ -567,123 +521,111 @@ impl ToString for LinuxInterfacePriority { } } -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// LinuxNetwork identification and priority configuration. - struct LinuxNetwork { - #[serde(skip_serializing_if = "Option::is_none", rename = "classID")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Set class identifier for container's network packets - class_id: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Set priority of network traffic for container. - priorities: Option>, - } -); - -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// Resource constraints for container - struct LinuxResources { - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Devices configures the device allowlist. - devices: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Memory restriction configuration. - memory: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// CPU resource restriction configuration. - cpu: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Task resource restrictions - pids: Option, - - #[serde(default, skip_serializing_if = "Option::is_none", rename = "blockIO")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// BlockIO restriction configuration. - block_io: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Hugetlb limit (in bytes). - hugepage_limits: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Network restriction configuration. - network: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Rdma resource restriction configuration. Limits are a set of key - /// value pairs that define RDMA resource limits, where the key - /// is device name and value is resource limits. - rdma: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Unified resources. - unified: Option>, - } -); - -make_pub!( - #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get_copy = "pub") - )] - /// LinuxRdma for Linux cgroup 'rdma' resource management (Linux 4.11). - struct LinuxRdma { - #[serde(skip_serializing_if = "Option::is_none")] - /// Maximum number of HCA handles that can be opened. Default is "no - /// limit". - hca_handles: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - /// Maximum number of HCA objects that can be created. Default is "no - /// limit". - hca_objects: Option, - } -); +#[derive( + Builder, Clone, CopyGetters, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize, +)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// LinuxNetwork identification and priority configuration. +pub struct LinuxNetwork { + #[serde(skip_serializing_if = "Option::is_none", rename = "classID")] + #[getset(get_copy = "pub")] + /// Set class identifier for container's network packets + class_id: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Set priority of network traffic for container. + priorities: Option>, +} + +#[derive( + Builder, Clone, CopyGetters, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize, +)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// Resource constraints for container +pub struct LinuxResources { + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Devices configures the device allowlist. + devices: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// Memory restriction configuration. + memory: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// CPU resource restriction configuration. + cpu: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// Task resource restrictions + pids: Option, + + #[serde(default, skip_serializing_if = "Option::is_none", rename = "blockIO")] + #[getset(get = "pub")] + /// BlockIO restriction configuration. + block_io: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Hugetlb limit (in bytes). + hugepage_limits: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Network restriction configuration. + network: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Rdma resource restriction configuration. Limits are a set of key + /// value pairs that define RDMA resource limits, where the key + /// is device name and value is resource limits. + rdma: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Unified resources. + unified: Option>, +} + +#[derive( + Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize, +)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get_copy = "pub")] +/// LinuxRdma for Linux cgroup 'rdma' resource management (Linux 4.11). +pub struct LinuxRdma { + #[serde(skip_serializing_if = "Option::is_none")] + /// Maximum number of HCA handles that can be opened. Default is "no + /// limit". + hca_handles: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + /// Maximum number of HCA objects that can be created. Default is "no + /// limit". + hca_objects: Option, +} #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, Hash)] #[serde(rename_all = "snake_case")] @@ -737,32 +679,28 @@ impl Default for LinuxNamespaceType { } } -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// LinuxNamespace is the configuration for a Linux namespace. - struct LinuxNamespace { - #[serde(rename = "type")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Type is the type of namespace. - typ: LinuxNamespaceType, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Path is a path to an existing namespace persisted on disk that can - /// be joined and is of the same type - path: Option, - } -); +#[derive( + Builder, Clone, CopyGetters, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize, +)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// LinuxNamespace is the configuration for a Linux namespace. +pub struct LinuxNamespace { + #[serde(rename = "type")] + #[getset(get_copy = "pub")] + /// Type is the type of namespace. + typ: LinuxNamespaceType, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Path is a path to an existing namespace persisted on disk that can + /// be joined and is of the same type + path: Option, +} /// Utility function to get default namespaces. pub fn get_default_namespaces() -> Vec { @@ -790,58 +728,54 @@ pub fn get_default_namespaces() -> Vec { ] } -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// LinuxDevice represents the mknod information for a Linux special device - /// file. - struct LinuxDevice { - #[serde(default)] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Path to the device. - path: PathBuf, - - #[serde(rename = "type")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Device type, block, char, etc.. - typ: LinuxDeviceType, - - #[serde(default)] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Major is the device's major number. - major: i64, - - #[serde(default)] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Minor is the device's minor number. - minor: i64, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// FileMode permission bits for the device. - file_mode: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// UID of the device. - uid: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Gid of the device. - gid: Option, - } -); +#[derive( + Builder, Clone, CopyGetters, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize, +)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// LinuxDevice represents the mknod information for a Linux special device +/// file. +pub struct LinuxDevice { + #[serde(default)] + #[getset(get = "pub")] + /// Path to the device. + path: PathBuf, + + #[serde(rename = "type")] + #[getset(get_copy = "pub")] + /// Device type, block, char, etc.. + typ: LinuxDeviceType, + + #[serde(default)] + #[getset(get_copy = "pub")] + /// Major is the device's major number. + major: i64, + + #[serde(default)] + #[getset(get_copy = "pub")] + /// Minor is the device's minor number. + minor: i64, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// FileMode permission bits for the device. + file_mode: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// UID of the device. + uid: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// Gid of the device. + gid: Option, +} impl From<&LinuxDevice> for LinuxDeviceCgroup { fn from(linux_device: &LinuxDevice) -> LinuxDeviceCgroup { @@ -855,41 +789,37 @@ impl From<&LinuxDevice> for LinuxDeviceCgroup { } } -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// LinuxSeccomp represents syscall restrictions. - struct LinuxSeccomp { - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// The default action to be done. - default_action: LinuxSeccompAction, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Available architectures for the restriction. - architectures: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Flags added to the seccomp restriction. - flags: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// The syscalls for the restriction. - syscalls: Option>, - } -); +#[derive( + Builder, Clone, CopyGetters, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize, +)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// LinuxSeccomp represents syscall restrictions. +pub struct LinuxSeccomp { + #[getset(get_copy = "pub")] + /// The default action to be done. + default_action: LinuxSeccompAction, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Available architectures for the restriction. + architectures: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Flags added to the seccomp restriction. + flags: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// The syscalls for the restriction. + syscalls: Option>, +} #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] @@ -1020,70 +950,62 @@ impl Default for LinuxSeccompOperator { } } -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// LinuxSyscall is used to match a syscall in seccomp. - struct LinuxSyscall { - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// The names of the syscalls. - names: Vec, - - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// The action to be done for the syscalls. - action: LinuxSeccompAction, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// The error return value. - errno_ret: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// The arguments for the syscalls. - args: Option>, - } -); - -make_pub!( - #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get_copy = "pub") - )] - /// LinuxSeccompArg used for matching specific syscall arguments in seccomp. - struct LinuxSeccompArg { - /// The index of the argument. - index: usize, - - /// The value of the argument. - value: u64, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// The second value of the argument. - value_two: Option, - - /// The operator for the argument. - op: LinuxSeccompOperator, - } -); +#[derive( + Builder, Clone, CopyGetters, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize, +)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// LinuxSyscall is used to match a syscall in seccomp. +pub struct LinuxSyscall { + #[getset(get = "pub")] + /// The names of the syscalls. + names: Vec, + + #[getset(get_copy = "pub")] + /// The action to be done for the syscalls. + action: LinuxSeccompAction, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// The error return value. + errno_ret: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// The arguments for the syscalls. + args: Option>, +} + +#[derive( + Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize, +)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get_copy = "pub")] +/// LinuxSeccompArg used for matching specific syscall arguments in seccomp. +pub struct LinuxSeccompArg { + /// The index of the argument. + index: usize, + + /// The value of the argument. + value: u64, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// The second value of the argument. + value_two: Option, + + /// The operator for the argument. + op: LinuxSeccompOperator, +} /// Default masks paths, cannot read these host files. pub fn get_default_maskedpaths() -> Vec { @@ -1115,66 +1037,56 @@ pub fn get_default_readonly_paths() -> Vec { ] } -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// LinuxIntelRdt has container runtime resource constraints for Intel RDT - /// CAT and MBA features which introduced in Linux 4.10 and 4.12 kernel. - struct LinuxIntelRdt { - #[serde(default, skip_serializing_if = "Option::is_none")] - /// The identity for RDT Class of Service. - clos_id: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// The schema for L3 cache id and capacity bitmask (CBM). - /// Format: "L3:=;=;..." - l3_cache_schema: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// The schema of memory bandwidth per L3 cache id. - /// Format: "MB:=bandwidth0;=bandwidth1;..." - /// The unit of memory bandwidth is specified in "percentages" by - /// default, and in "MBps" if MBA Software Controller is - /// enabled. - mem_bw_schema: Option, - } -); - -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// LinuxPersonality represents the Linux personality syscall input. - struct LinuxPersonality { - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Domain for the personality. - domain: LinuxPersonalityDomain, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Additional flags - flags: Option>, - } -); +#[derive(Builder, Clone, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// LinuxIntelRdt has container runtime resource constraints for Intel RDT +/// CAT and MBA features which introduced in Linux 4.10 and 4.12 kernel. +pub struct LinuxIntelRdt { + #[serde(default, skip_serializing_if = "Option::is_none")] + /// The identity for RDT Class of Service. + clos_id: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// The schema for L3 cache id and capacity bitmask (CBM). + /// Format: "L3:=;=;..." + l3_cache_schema: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// The schema of memory bandwidth per L3 cache id. + /// Format: "MB:=bandwidth0;=bandwidth1;..." + /// The unit of memory bandwidth is specified in "percentages" by + /// default, and in "MBps" if MBA Software Controller is + /// enabled. + mem_bw_schema: Option, +} + +#[derive( + Builder, Clone, CopyGetters, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize, +)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// LinuxPersonality represents the Linux personality syscall input. +pub struct LinuxPersonality { + #[getset(get_copy = "pub")] + /// Domain for the personality. + domain: LinuxPersonalityDomain, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Additional flags + flags: Option>, +} #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)] /// Define domain and flags for LinuxPersonality. diff --git a/src/runtime/miscellaneous.rs b/src/runtime/miscellaneous.rs index 577cf1a65e..64a74ffb9d 100644 --- a/src/runtime/miscellaneous.rs +++ b/src/runtime/miscellaneous.rs @@ -1,33 +1,30 @@ +use crate::error::OciSpecError; +use derive_builder::Builder; +use getset::{CopyGetters, Getters}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; -make_pub!( - #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// Root contains information about the container's root filesystem on the - /// host. - struct Root { - /// Path is the absolute path to the container's root filesystem. - #[serde(default)] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - path: PathBuf, +#[derive(Builder, Clone, CopyGetters, Debug, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// Root contains information about the container's root filesystem on the +/// host. +pub struct Root { + /// Path is the absolute path to the container's root filesystem. + #[serde(default)] + #[getset(get = "pub")] + path: PathBuf, - /// Readonly makes the root filesystem for the container readonly before - /// the process is executed. - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - readonly: Option, - } -); + /// Readonly makes the root filesystem for the container readonly before + /// the process is executed. + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + readonly: Option, +} /// Default path for container root is "./rootfs" from config.json, with /// readonly true @@ -40,38 +37,32 @@ impl Default for Root { } } -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// Mount specifies a mount for a container. - struct Mount { - /// Destination is the absolute path where the mount will be placed in - /// the container. - destination: PathBuf, +#[derive(Builder, Clone, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// Mount specifies a mount for a container. +pub struct Mount { + /// Destination is the absolute path where the mount will be placed in + /// the container. + destination: PathBuf, - #[serde(default, skip_serializing_if = "Option::is_none", rename = "type")] - /// Type specifies the mount kind. - typ: Option, + #[serde(default, skip_serializing_if = "Option::is_none", rename = "type")] + /// Type specifies the mount kind. + typ: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Source specifies the source path of the mount. - source: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Source specifies the source path of the mount. + source: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Options are fstab style mount options. - options: Option>, - } -); + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Options are fstab style mount options. + options: Option>, +} /// utility function to generate default config for mounts. pub fn get_default_mounts() -> Vec { diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs index 5651732069..1af904a647 100644 --- a/src/runtime/mod.rs +++ b/src/runtime/mod.rs @@ -1,5 +1,7 @@ //! [OCI runtime spec](https://github.com/opencontainers/runtime-spec) types and definitions. +use derive_builder::Builder; +use getset::Getters; use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, @@ -7,7 +9,7 @@ use std::{ path::{Path, PathBuf}, }; -use crate::error::{oci_error, Result}; +use crate::error::{oci_error, OciSpecError, Result}; mod capability; mod hooks; @@ -31,110 +33,104 @@ pub use version::*; pub use vm::*; pub use windows::*; -make_pub!( - /// Base configuration for the container. - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - struct Spec { - #[serde(default, rename = "ociVersion")] - /// MUST be in SemVer v2.0.0 format and specifies the version of the - /// Open Container Initiative Runtime Specification with which - /// the bundle complies. The Open Container Initiative - /// Runtime Specification follows semantic versioning and retains - /// forward and backward compatibility within major versions. - /// For example, if a configuration is compliant with - /// version 1.1 of this specification, it is compatible with all - /// runtimes that support any 1.1 or later release of this - /// specification, but is not compatible with a runtime that supports - /// 1.0 and not 1.1. - version: String, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Specifies the container's root filesystem. On Windows, for Windows - /// Server Containers, this field is REQUIRED. For Hyper-V - /// Containers, this field MUST NOT be set. - /// - /// On all other platforms, this field is REQUIRED. - root: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Specifies additional mounts beyond `root`. The runtime MUST mount - /// entries in the listed order. - /// - /// For Linux, the parameters are as documented in - /// [`mount(2)`](http://man7.org/linux/man-pages/man2/mount.2.html) system call man page. For - /// Solaris, the mount entry corresponds to the 'fs' resource in the - /// [`zonecfg(1M)`](http://docs.oracle.com/cd/E86824_01/html/E54764/zonecfg-1m.html) man page. - mounts: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Specifies the container process. This property is REQUIRED when - /// [`start`](https://github.com/opencontainers/runtime-spec/blob/master/runtime.md#start) is - /// called. - process: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Specifies the container's hostname as seen by processes running - /// inside the container. On Linux, for example, this will - /// change the hostname in the container [UTS namespace](http://man7.org/linux/man-pages/man7/namespaces.7.html). Depending on your - /// [namespace - /// configuration](https://github.com/opencontainers/runtime-spec/blob/master/config-linux.md#namespaces), - /// the container UTS namespace may be the runtime UTS namespace. - hostname: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Hooks allow users to specify programs to run before or after various - /// lifecycle events. Hooks MUST be called in the listed order. - /// The state of the container MUST be passed to hooks over - /// stdin so that they may do work appropriate to the current state of - /// the container. - hooks: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Annotations contains arbitrary metadata for the container. This - /// information MAY be structured or unstructured. Annotations - /// MUST be a key-value map. If there are no annotations then - /// this property MAY either be absent or an empty map. - /// - /// Keys MUST be strings. Keys MUST NOT be an empty string. Keys SHOULD - /// be named using a reverse domain notation - e.g. - /// com.example.myKey. Keys using the org.opencontainers - /// namespace are reserved and MUST NOT be used by subsequent - /// specifications. Runtimes MUST handle unknown annotation keys - /// like any other unknown property. - /// - /// Values MUST be strings. Values MAY be an empty string. - annotations: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Linux is platform-specific configuration for Linux based containers. - linux: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Solaris is platform-specific configuration for Solaris based - /// containers. - solaris: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Windows is platform-specific configuration for Windows based - /// containers. - windows: Option, +/// Base configuration for the container. +#[derive(Builder, Clone, Debug, Deserialize, Getters, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +pub struct Spec { + #[serde(default, rename = "ociVersion")] + /// MUST be in SemVer v2.0.0 format and specifies the version of the + /// Open Container Initiative Runtime Specification with which + /// the bundle complies. The Open Container Initiative + /// Runtime Specification follows semantic versioning and retains + /// forward and backward compatibility within major versions. + /// For example, if a configuration is compliant with + /// version 1.1 of this specification, it is compatible with all + /// runtimes that support any 1.1 or later release of this + /// specification, but is not compatible with a runtime that supports + /// 1.0 and not 1.1. + version: String, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Specifies the container's root filesystem. On Windows, for Windows + /// Server Containers, this field is REQUIRED. For Hyper-V + /// Containers, this field MUST NOT be set. + /// + /// On all other platforms, this field is REQUIRED. + root: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - /// VM specifies configuration for Virtual Machine based containers. - vm: Option, - } -); + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Specifies additional mounts beyond `root`. The runtime MUST mount + /// entries in the listed order. + /// + /// For Linux, the parameters are as documented in + /// [`mount(2)`](http://man7.org/linux/man-pages/man2/mount.2.html) system call man page. For + /// Solaris, the mount entry corresponds to the 'fs' resource in the + /// [`zonecfg(1M)`](http://docs.oracle.com/cd/E86824_01/html/E54764/zonecfg-1m.html) man page. + mounts: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Specifies the container process. This property is REQUIRED when + /// [`start`](https://github.com/opencontainers/runtime-spec/blob/master/runtime.md#start) is + /// called. + process: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Specifies the container's hostname as seen by processes running + /// inside the container. On Linux, for example, this will + /// change the hostname in the container [UTS namespace](http://man7.org/linux/man-pages/man7/namespaces.7.html). Depending on your + /// [namespace + /// configuration](https://github.com/opencontainers/runtime-spec/blob/master/config-linux.md#namespaces), + /// the container UTS namespace may be the runtime UTS namespace. + hostname: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Hooks allow users to specify programs to run before or after various + /// lifecycle events. Hooks MUST be called in the listed order. + /// The state of the container MUST be passed to hooks over + /// stdin so that they may do work appropriate to the current state of + /// the container. + hooks: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Annotations contains arbitrary metadata for the container. This + /// information MAY be structured or unstructured. Annotations + /// MUST be a key-value map. If there are no annotations then + /// this property MAY either be absent or an empty map. + /// + /// Keys MUST be strings. Keys MUST NOT be an empty string. Keys SHOULD + /// be named using a reverse domain notation - e.g. + /// com.example.myKey. Keys using the org.opencontainers + /// namespace are reserved and MUST NOT be used by subsequent + /// specifications. Runtimes MUST handle unknown annotation keys + /// like any other unknown property. + /// + /// Values MUST be strings. Values MAY be an empty string. + annotations: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Linux is platform-specific configuration for Linux based containers. + linux: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Solaris is platform-specific configuration for Solaris based + /// containers. + solaris: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Windows is platform-specific configuration for Windows based + /// containers. + windows: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// VM specifies configuration for Virtual Machine based containers. + vm: Option, +} // This gives a basic boilerplate for Spec that can be used calling // Default::default(). The values given are similar to the defaults seen in @@ -200,18 +196,6 @@ impl Spec { Ok(()) } - #[cfg(not(feature = "builder"))] - /// Canonicalize the `root.path` of the `Spec` for the provided `bundle`. - pub fn canonicalize_rootfs>(&mut self, bundle: P) -> Result<()> { - let root = self - .root - .as_mut() - .ok_or_else(|| oci_error("no root path provided for canonicalization"))?; - root.path = Self::canonicalize_path(bundle, &root.path)?; - Ok(()) - } - - #[cfg(feature = "builder")] /// Canonicalize the `root.path` of the `Spec` for the provided `bundle`. pub fn canonicalize_rootfs>(&mut self, bundle: P) -> Result<()> { let root = self @@ -222,7 +206,7 @@ impl Spec { self.root = Some( RootBuilder::default() .path(path) - .readonly(root.readonly()) + .readonly(root.readonly().unwrap_or(false)) .build() .map_err(|_| oci_error("failed to set canonicalized root"))?, ); @@ -248,7 +232,6 @@ mod tests { use super::*; #[test] - #[cfg(feature = "builder")] fn test_canonicalize_rootfs() { let rootfs_name = "rootfs"; let bundle = tempfile::tempdir().expect("failed to create tmp test bundle dir"); @@ -295,57 +278,6 @@ mod tests { } } - #[test] - #[cfg(not(feature = "builder"))] - fn test_canonicalize_rootfs() { - let rootfs_name = "rootfs"; - let bundle = tempfile::tempdir().expect("failed to create tmp test bundle dir"); - let rootfs_absolute_path = bundle.path().join(rootfs_name); - assert!( - rootfs_absolute_path.is_absolute(), - "rootfs path is not absolute path" - ); - fs::create_dir_all(&rootfs_absolute_path).expect("failed to create the testing rootfs"); - { - // Test the case with absolute path - let mut spec = Spec { - root: Root { - path: rootfs_absolute_path.clone(), - ..Default::default() - } - .into(), - ..Default::default() - }; - - spec.canonicalize_rootfs(bundle.path()) - .expect("failed to canonicalize rootfs"); - - assert_eq!( - rootfs_absolute_path, - spec.root.expect("no root in spec").path - ); - } - { - // Test the case with relative path - let mut spec = Spec { - root: Root { - path: PathBuf::from(rootfs_name), - ..Default::default() - } - .into(), - ..Default::default() - }; - - spec.canonicalize_rootfs(bundle.path()) - .expect("failed to canonicalize rootfs"); - - assert_eq!( - rootfs_absolute_path, - spec.root.expect("no root in spec").path - ); - } - } - #[test] fn test_load_save() { let spec = Spec { diff --git a/src/runtime/process.rs b/src/runtime/process.rs index 3f450ad1e7..57242ada4b 100644 --- a/src/runtime/process.rs +++ b/src/runtime/process.rs @@ -1,92 +1,91 @@ -use crate::runtime::{Capabilities, Capability}; +use crate::{ + error::OciSpecError, + runtime::{Capabilities, Capability}, +}; +use derive_builder::Builder; +use getset::{CopyGetters, Getters}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; -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( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// Process contains information to start a specific application inside the - /// container. - struct Process { - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Terminal creates an interactive terminal for the container. - terminal: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// ConsoleSize specifies the size of the console. - console_size: Option, - - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// User specifies user information for the process. - user: User, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Args specifies the binary and arguments for the application to - /// execute. - args: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// CommandLine specifies the full command line for the application to - /// execute on Windows. - command_line: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Env populates the process environment for the process. - env: Option>, - - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Cwd is the current working directory for the process and must be - /// relative to the container's root. - cwd: PathBuf, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Capabilities are Linux capabilities that are kept for the process. - capabilities: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Rlimits specifies rlimit options to apply to the process. - rlimits: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// NoNewPrivileges controls whether additional privileges could be - /// gained by processes in the container. - no_new_privileges: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// ApparmorProfile specifies the apparmor profile for the container. - apparmor_profile: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Specify an oom_score_adj for the container. - oom_score_adj: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// SelinuxLabel specifies the selinux context that the container - /// process is run as. - selinux_label: Option, - } -); +#[derive(Builder, Clone, CopyGetters, Debug, Deserialize, Getters, Eq, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// Process contains information to start a specific application inside the +/// container. +pub struct Process { + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// Terminal creates an interactive terminal for the container. + terminal: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// ConsoleSize specifies the size of the console. + console_size: Option, + + #[getset(get = "pub")] + /// User specifies user information for the process. + user: User, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Args specifies the binary and arguments for the application to + /// execute. + args: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// CommandLine specifies the full command line for the application to + /// execute on Windows. + command_line: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Env populates the process environment for the process. + env: Option>, + + #[getset(get = "pub")] + /// Cwd is the current working directory for the process and must be + /// relative to the container's root. + cwd: PathBuf, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Capabilities are Linux capabilities that are kept for the process. + capabilities: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Rlimits specifies rlimit options to apply to the process. + rlimits: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// NoNewPrivileges controls whether additional privileges could be + /// gained by processes in the container. + no_new_privileges: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// ApparmorProfile specifies the apparmor profile for the container. + apparmor_profile: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// Specify an oom_score_adj for the container. + oom_score_adj: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// SelinuxLabel specifies the selinux context that the container + /// process is run as. + selinux_label: Option, +} // Default impl for processes in the container impl Default for Process { @@ -130,31 +129,27 @@ impl Default for Process { } } -make_pub!( - #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get_copy = "pub") - )] - /// Box specifies dimensions of a rectangle. Used for specifying the size of - /// a console. - struct Box { - #[serde(default)] - /// Height is the vertical dimension of a box. - height: u64, - - #[serde(default)] - /// Width is the horizontal dimension of a box. - width: u64, - } -); +#[derive( + Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize, +)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get_copy = "pub")] +/// Box specifies dimensions of a rectangle. Used for specifying the size of +/// a console. +pub struct Box { + #[serde(default)] + /// Height is the vertical dimension of a box. + height: u64, + + #[serde(default)] + /// Width is the horizontal dimension of a box. + width: u64, +} #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] @@ -221,115 +216,101 @@ impl Default for LinuxRlimitType { } } -make_pub!( - #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get_copy = "pub") - )] - /// RLimit types and restrictions. - struct LinuxRlimit { - #[serde(rename = "type")] - /// Type of Rlimit to set - typ: LinuxRlimitType, - - #[serde(default)] - /// Hard limit for specified type - hard: u64, - - #[serde(default)] - /// Soft limit for specified type - soft: u64, - } -); - -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// User id (uid) and group id (gid) tracks file permssions. - struct User { - #[serde(default)] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// UID is the user id. - uid: u32, - - #[serde(default)] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// GID is the group id. - gid: u32, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Specifies the umask of the user. - umask: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// AdditionalGids are additional group ids set for the container's - /// process. - additional_gids: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Username is the user name. - username: Option, - } -); - -make_pub!( - #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// LinuxCapabilities specifies the list of allowed capabilities that are - /// kept for a process. - struct LinuxCapabilities { - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Bounding is the set of capabilities checked by the kernel. - bounding: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Effective is the set of capabilities checked by the kernel. - effective: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Inheritable is the capabilities preserved across execve. - inheritable: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Permitted is the limiting superset for effective capabilities. - permitted: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Ambient is the ambient set of capabilities that are kept. - ambient: Option, - } -); +#[derive( + Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize, +)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get_copy = "pub")] +/// RLimit types and restrictions. +pub struct LinuxRlimit { + #[serde(rename = "type")] + /// Type of Rlimit to set + typ: LinuxRlimitType, + + #[serde(default)] + /// Hard limit for specified type + hard: u64, + + #[serde(default)] + /// Soft limit for specified type + soft: u64, +} + +#[derive( + Builder, Clone, CopyGetters, Debug, Default, Deserialize, Getters, Eq, PartialEq, Serialize, +)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// User id (uid) and group id (gid) tracks file permssions. +pub struct User { + #[serde(default)] + #[getset(get_copy = "pub")] + /// UID is the user id. + uid: u32, + + #[serde(default)] + #[getset(get_copy = "pub")] + /// GID is the group id. + gid: u32, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// Specifies the umask of the user. + umask: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// AdditionalGids are additional group ids set for the container's + /// process. + additional_gids: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Username is the user name. + username: Option, +} + +#[derive(Builder, Clone, Debug, Deserialize, Getters, Eq, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// LinuxCapabilities specifies the list of allowed capabilities that are +/// kept for a process. +pub struct LinuxCapabilities { + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Bounding is the set of capabilities checked by the kernel. + bounding: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Effective is the set of capabilities checked by the kernel. + effective: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Inheritable is the capabilities preserved across execve. + inheritable: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Permitted is the limiting superset for effective capabilities. + permitted: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Ambient is the ambient set of capabilities that are kept. + ambient: Option, +} // Default container's linux capabilities: // CAP_AUDIT_WRITE gives container ability to write to linux audit logs, diff --git a/src/runtime/solaris.rs b/src/runtime/solaris.rs index e2e8d3ad12..2a99dc8c3c 100644 --- a/src/runtime/solaris.rs +++ b/src/runtime/solaris.rs @@ -1,143 +1,122 @@ +use crate::error::OciSpecError; +use derive_builder::Builder; +use getset::Getters; use serde::{Deserialize, Serialize}; -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// Solaris contains platform-specific configuration for Solaris application - /// containers. - struct Solaris { - #[serde(default, skip_serializing_if = "Option::is_none")] - /// SMF FMRI which should go "online" before we start the container - /// process. - milestone: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Maximum set of privileges any process in this container can obtain. - limitpriv: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// The maximum amount of shared memory allowed for this container. - max_shm_memory: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Specification for automatic creation of network resources for this - /// container. - anet: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none", rename = "cappedCPU")] - /// Set limit on the amount of CPU time that can be used by container. - capped_cpu: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// The physical and swap caps on the memory that can be used by this - /// container. - capped_memory: Option, - } -); - -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// SolarisAnet provides the specification for automatic creation of network - /// resources for this container. - struct SolarisAnet { - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Specify a name for the automatically created VNIC datalink. - linkname: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Specify the link over which the VNIC will be created. - lower_link: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// The set of IP addresses that the container can use. - allowed_address: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Specifies whether allowedAddress limitation is to be applied to the - /// VNIC. - configure_allowed_address: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// The value of the optional default router. - defrouter: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Enable one or more types of link protection. - link_protection: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Set the VNIC's macAddress. - mac_address: Option, - } -); - -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// SolarisCappedCPU allows users to set limit on the amount of CPU time - /// that can be used by container. - struct SolarisCappedCPU { - #[serde(default, skip_serializing_if = "Option::is_none")] - /// The amount of CPUs. - ncpus: Option, - } -); - -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// SolarisCappedMemory allows users to set the physical and swap caps on - /// the memory that can be used by this container. - struct SolarisCappedMemory { - #[serde(default, skip_serializing_if = "Option::is_none")] - /// The physical caps on the memory. - physical: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// The swap caps on the memory. - swap: Option, - } -); +#[derive(Builder, Clone, Debug, Default, Deserialize, Getters, Eq, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// Solaris contains platform-specific configuration for Solaris application +/// containers. +pub struct Solaris { + #[serde(default, skip_serializing_if = "Option::is_none")] + /// SMF FMRI which should go "online" before we start the container + /// process. + milestone: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Maximum set of privileges any process in this container can obtain. + limitpriv: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// The maximum amount of shared memory allowed for this container. + max_shm_memory: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Specification for automatic creation of network resources for this + /// container. + anet: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none", rename = "cappedCPU")] + /// Set limit on the amount of CPU time that can be used by container. + capped_cpu: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// The physical and swap caps on the memory that can be used by this + /// container. + capped_memory: Option, +} + +#[derive(Builder, Clone, Debug, Default, Deserialize, Getters, Eq, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// SolarisAnet provides the specification for automatic creation of network +/// resources for this container. +pub struct SolarisAnet { + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Specify a name for the automatically created VNIC datalink. + linkname: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Specify the link over which the VNIC will be created. + lower_link: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// The set of IP addresses that the container can use. + allowed_address: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Specifies whether allowedAddress limitation is to be applied to the + /// VNIC. + configure_allowed_address: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// The value of the optional default router. + defrouter: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Enable one or more types of link protection. + link_protection: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Set the VNIC's macAddress. + mac_address: Option, +} + +#[derive(Builder, Clone, Debug, Default, Deserialize, Getters, Eq, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// SolarisCappedCPU allows users to set limit on the amount of CPU time +/// that can be used by container. +pub struct SolarisCappedCPU { + #[serde(default, skip_serializing_if = "Option::is_none")] + /// The amount of CPUs. + ncpus: Option, +} + +#[derive(Builder, Clone, Debug, Default, Deserialize, Getters, Eq, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// SolarisCappedMemory allows users to set the physical and swap caps on +/// the memory that can be used by this container. +pub struct SolarisCappedMemory { + #[serde(default, skip_serializing_if = "Option::is_none")] + /// The physical caps on the memory. + physical: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// The swap caps on the memory. + swap: Option, +} diff --git a/src/runtime/test.rs b/src/runtime/test.rs index f1fec9df13..905ca17edf 100644 --- a/src/runtime/test.rs +++ b/src/runtime/test.rs @@ -10,7 +10,6 @@ fn serialize_and_deserialize_spec() { } #[test] -#[cfg(feature = "builder")] fn test_linux_device_cgroup_to_string() { let ldc = LinuxDeviceCgroupBuilder::default() .allow(true) @@ -30,25 +29,3 @@ fn test_linux_device_cgroup_to_string() { .expect("build device cgroup"); assert_eq!(ldc.to_string(), "b 1:9 rwm"); } - -#[test] -#[cfg(not(feature = "builder"))] -fn test_linux_device_cgroup_to_string() { - let ldc = LinuxDeviceCgroup { - allow: true, - typ: Some(LinuxDeviceType::B), - major: None, - minor: None, - access: Some("rwm".into()), - }; - assert_eq!(ldc.to_string(), "b *:* rwm"); - - let ldc = LinuxDeviceCgroup { - allow: true, - typ: Some(LinuxDeviceType::B), - major: Some(1), - minor: Some(9), - access: Some("rwm".into()), - }; - assert_eq!(ldc.to_string(), "b 1:9 rwm"); -} diff --git a/src/runtime/vm.rs b/src/runtime/vm.rs index e800f1f53f..416087f112 100644 --- a/src/runtime/vm.rs +++ b/src/runtime/vm.rs @@ -1,115 +1,94 @@ +use crate::error::OciSpecError; +use derive_builder::Builder; +use getset::Getters; use serde::{Deserialize, Serialize}; use std::path::PathBuf; -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// VM contains information for virtual-machine-based containers. - struct VM { - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Hypervisor specifies hypervisor-related configuration for - /// virtual-machine-based containers. - hypervisor: Option, +#[derive(Builder, Clone, Debug, Default, Deserialize, Getters, Eq, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// VM contains information for virtual-machine-based containers. +pub struct VM { + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Hypervisor specifies hypervisor-related configuration for + /// virtual-machine-based containers. + hypervisor: Option, - /// Kernel specifies kernel-related configuration for - /// virtual-machine-based containers. - kernel: VMKernel, + /// Kernel specifies kernel-related configuration for + /// virtual-machine-based containers. + kernel: VMKernel, - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Image specifies guest image related configuration for - /// virtual-machine-based containers. - image: Option, - } -); + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Image specifies guest image related configuration for + /// virtual-machine-based containers. + image: Option, +} -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// VMHypervisor contains information about the hypervisor to use for a - /// virtual machine. - struct VMHypervisor { - /// Path is the host path to the hypervisor used to manage the virtual - /// machine. - path: PathBuf, +#[derive(Builder, Clone, Debug, Default, Deserialize, Getters, Eq, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// VMHypervisor contains information about the hypervisor to use for a +/// virtual machine. +pub struct VMHypervisor { + /// Path is the host path to the hypervisor used to manage the virtual + /// machine. + path: PathBuf, - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Parameters specifies parameters to pass to the hypervisor. - parameters: Option>, - } -); + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Parameters specifies parameters to pass to the hypervisor. + parameters: Option>, +} -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// VMKernel contains information about the kernel to use for a virtual +#[derive(Builder, Clone, Debug, Default, Deserialize, Getters, Eq, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// VMKernel contains information about the kernel to use for a virtual +/// machine. +pub struct VMKernel { + /// Path is the host path to the kernel used to boot the virtual /// machine. - struct VMKernel { - /// Path is the host path to the kernel used to boot the virtual - /// machine. - path: PathBuf, + path: PathBuf, - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Parameters specifies parameters to pass to the kernel. - parameters: Option>, + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Parameters specifies parameters to pass to the kernel. + parameters: Option>, - #[serde(default, skip_serializing_if = "Option::is_none")] - /// InitRD is the host path to an initial ramdisk to be used by the - /// kernel. - initrd: Option, - } -); + #[serde(default, skip_serializing_if = "Option::is_none")] + /// InitRD is the host path to an initial ramdisk to be used by the + /// kernel. + initrd: Option, +} -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// VMImage contains information about the virtual machine root image. - struct VMImage { - /// Path is the host path to the root image that the VM kernel would - /// boot into. - path: PathBuf, +#[derive(Builder, Clone, Debug, Default, Deserialize, Getters, Eq, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// VMImage contains information about the virtual machine root image. +pub struct VMImage { + /// Path is the host path to the root image that the VM kernel would + /// boot into. + path: PathBuf, - /// Format is the root image format type (e.g. "qcow2", "raw", "vhd", - /// etc). - format: String, - } -); + /// Format is the root image format type (e.g. "qcow2", "raw", "vhd", + /// etc). + format: String, +} diff --git a/src/runtime/windows.rs b/src/runtime/windows.rs index fa29f16378..5da7e6c992 100644 --- a/src/runtime/windows.rs +++ b/src/runtime/windows.rs @@ -1,278 +1,233 @@ +use crate::error::OciSpecError; +use derive_builder::Builder; +use getset::Getters; use serde::{Deserialize, Serialize}; use std::collections::HashMap; -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) +#[derive(Builder, Clone, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// Windows defines the runtime configuration for Windows based containers, +/// including Hyper-V containers. +pub struct Windows { + #[getset(get = "pub")] + /// LayerFolders contains a list of absolute paths to directories + /// containing image layers. + layer_folders: Vec, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Devices are the list of devices to be mapped into the container. + devices: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// Resources contains information for handling resource constraints for + /// the container. + resources: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// CredentialSpec contains a JSON object describing a group Managed + /// Service Account (gMSA) specification. + credential_spec: Option>>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// Servicing indicates if the container is being started in a mode to + /// apply a Windows Update servicing operation. + servicing: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get_copy = "pub")] + /// IgnoreFlushesDuringBoot indicates if the container is being started + /// in a mode where disk writes are not flushed during its boot + /// process. + ignore_flushes_during_boot: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// HyperV contains information for running a container with Hyper-V + /// isolation. + hyperv: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Network restriction configuration. + network: Option, +} + +#[derive(Builder, Clone, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// WindowsDevice represents information about a host device to be mapped +/// into the container. +pub struct WindowsDevice { + /// Device identifier: interface class GUID, etc.. + id: String, + + /// Device identifier type: "class", etc.. + id_type: String, +} + +#[derive(Builder, Clone, Copy, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get_copy = "pub")] +/// Available windows resources. +pub struct WindowsResources { + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Memory restriction configuration. + memory: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// CPU resource restriction configuration. + cpu: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Storage restriction configuration. + storage: Option, +} + +#[derive(Builder, Clone, Copy, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get_copy = "pub")] +/// WindowsMemoryResources contains memory resource management settings. +pub struct WindowsMemoryResources { + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Memory limit in bytes. + limit: Option, +} + +#[derive(Builder, Clone, Copy, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get_copy = "pub")] +/// WindowsCPUResources contains CPU resource management settings. +pub struct WindowsCPUResources { + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Number of CPUs available to the container. + count: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// CPU shares (relative weight to other containers with cpu shares). + shares: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Specifies the portion of processor cycles that this container can + /// use as a percentage times 100. + maximum: Option, +} + +#[derive(Builder, Clone, Copy, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get_copy = "pub")] +/// WindowsStorageResources contains storage resource management settings. +pub struct WindowsStorageResources { + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Specifies maximum Iops for the system drive. + iops: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Specifies maximum bytes per second for the system drive. + bps: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + /// Sandbox size specifies the minimum size of the system drive in + /// bytes. + sandbox_size: Option, +} + +#[derive(Builder, Clone, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +#[getset(get = "pub")] +/// WindowsHyperV contains information for configuring a container to run +/// with Hyper-V isolation. +pub struct WindowsHyperV { + #[serde(default, skip_serializing_if = "Option::is_none")] + /// UtilityVMPath is an optional path to the image used for the Utility + /// VM. + utility_vm_path: Option, +} + +#[derive(Builder, Clone, Debug, Default, Deserialize, Eq, Getters, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +#[builder( + default, + pattern = "owned", + setter(into, strip_option), + build_fn(error = "OciSpecError") +)] +/// WindowsNetwork contains network settings for Windows containers. +pub struct WindowsNetwork { + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// List of HNS endpoints that the container should connect to. + endpoint_list: Option>, + + #[serde( + default, + skip_serializing_if = "Option::is_none", + rename = "allowUnqualifiedDNSQuery" )] - /// Windows defines the runtime configuration for Windows based containers, - /// including Hyper-V containers. - struct Windows { - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// LayerFolders contains a list of absolute paths to directories - /// containing image layers. - layer_folders: Vec, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Devices are the list of devices to be mapped into the container. - devices: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Resources contains information for handling resource constraints for - /// the container. - resources: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// CredentialSpec contains a JSON object describing a group Managed - /// Service Account (gMSA) specification. - credential_spec: Option>>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Servicing indicates if the container is being started in a mode to - /// apply a Windows Update servicing operation. - servicing: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// IgnoreFlushesDuringBoot indicates if the container is being started - /// in a mode where disk writes are not flushed during its boot - /// process. - ignore_flushes_during_boot: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// HyperV contains information for running a container with Hyper-V - /// isolation. - hyperv: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Network restriction configuration. - network: Option, - } -); - -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") + #[getset(get_copy = "pub")] + /// Specifies if unqualified DNS name resolution is allowed. + allow_unqualified_dns_query: Option, + + #[serde( + default, + skip_serializing_if = "Option::is_none", + rename = "DNSSearchList" )] - /// WindowsDevice represents information about a host device to be mapped - /// into the container. - struct WindowsDevice { - /// Device identifier: interface class GUID, etc.. - id: String, - - /// Device identifier type: "class", etc.. - id_type: String, - } -); - -make_pub!( - #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get_copy = "pub") - )] - /// Available windows resources. - struct WindowsResources { - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Memory restriction configuration. - memory: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// CPU resource restriction configuration. - cpu: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Storage restriction configuration. - storage: Option, - } -); - -make_pub!( - #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get_copy = "pub") - )] - /// WindowsMemoryResources contains memory resource management settings. - struct WindowsMemoryResources { - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Memory limit in bytes. - limit: Option, - } -); - -make_pub!( - #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get_copy = "pub") - )] - /// WindowsCPUResources contains CPU resource management settings. - struct WindowsCPUResources { - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Number of CPUs available to the container. - count: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// CPU shares (relative weight to other containers with cpu shares). - shares: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Specifies the portion of processor cycles that this container can - /// use as a percentage times 100. - maximum: Option, - } -); - -make_pub!( - #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get_copy = "pub") - )] - /// WindowsStorageResources contains storage resource management settings. - struct WindowsStorageResources { - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Specifies maximum Iops for the system drive. - iops: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Specifies maximum bytes per second for the system drive. - bps: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - /// Sandbox size specifies the minimum size of the system drive in - /// bytes. - sandbox_size: Option, - } -); - -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ), - getset(get = "pub") - )] - /// WindowsHyperV contains information for configuring a container to run - /// with Hyper-V isolation. - struct WindowsHyperV { - #[serde(default, skip_serializing_if = "Option::is_none")] - /// UtilityVMPath is an optional path to the image used for the Utility - /// VM. - utility_vm_path: Option, - } -); - -make_pub!( - #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - #[cfg_attr( - feature = "builder", - derive(derive_builder::Builder, getset::CopyGetters, getset::Getters), - builder( - default, - pattern = "owned", - setter(into, strip_option), - build_fn(error = "crate::error::OciSpecError") - ) - )] - /// WindowsNetwork contains network settings for Windows containers. - struct WindowsNetwork { - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// List of HNS endpoints that the container should connect to. - endpoint_list: Option>, - - #[serde( - default, - skip_serializing_if = "Option::is_none", - rename = "allowUnqualifiedDNSQuery" - )] - #[cfg_attr(feature = "builder", getset(get_copy = "pub"))] - /// Specifies if unqualified DNS name resolution is allowed. - allow_unqualified_dns_query: Option, - - #[serde( - default, - skip_serializing_if = "Option::is_none", - rename = "DNSSearchList" - )] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Comma separated list of DNS suffixes to use for name resolution. - dns_search_list: Option>, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// Name (ID) of the container that we will share with the network - /// stack. - network_shared_container_name: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - #[cfg_attr(feature = "builder", getset(get = "pub"))] - /// name (ID) of the network namespace that will be used for the - /// container. - network_namespace: Option, - } -); + #[getset(get = "pub")] + /// Comma separated list of DNS suffixes to use for name resolution. + dns_search_list: Option>, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// Name (ID) of the container that we will share with the network + /// stack. + network_shared_container_name: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + #[getset(get = "pub")] + /// name (ID) of the network namespace that will be used for the + /// container. + network_namespace: Option, +}