use crate::client::graphql_client; use crate::querybuilder::Selection; use dagger_core::connect_params::ConnectParams; use derive_builder::Builder; use serde::{Deserialize, Serialize}; use std::sync::Arc; use tokio::process::Child; #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct CacheId(String); #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct ContainerId(String); #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct DirectoryId(String); #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct FileId(String); #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct Platform(String); #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct SecretId(String); #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct SocketId(String); #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] pub struct BuildArg { pub value: String, pub name: String, } #[derive(Debug, Clone)] pub struct CacheVolume { pub proc: Arc, pub selection: Selection, pub conn: ConnectParams, } impl CacheVolume { pub async fn id(&self) -> eyre::Result { let mut query = self.selection.select("id"); query.execute(&graphql_client(&self.conn)).await } } #[derive(Debug, Clone)] pub struct Container { pub proc: Arc, pub selection: Selection, pub conn: ConnectParams, } #[derive(Builder, Debug, PartialEq)] pub struct ContainerBuildOpts<'a> { /// Path to the Dockerfile to use. /// Defaults to './Dockerfile'. #[builder(setter(into, strip_option))] pub dockerfile: Option<&'a str>, /// Additional build arguments. #[builder(setter(into, strip_option))] pub build_args: Option>, /// Target build stage to build. #[builder(setter(into, strip_option))] pub target: Option<&'a str>, } #[derive(Builder, Debug, PartialEq)] pub struct ContainerExecOpts<'a> { /// Command to run instead of the container's default command. #[builder(setter(into, strip_option))] pub args: Option>, /// Content to write to the command's standard input before closing. #[builder(setter(into, strip_option))] pub stdin: Option<&'a str>, /// Redirect the command's standard output to a file in the container. #[builder(setter(into, strip_option))] pub redirect_stdout: Option<&'a str>, /// Redirect the command's standard error to a file in the container. #[builder(setter(into, strip_option))] pub redirect_stderr: Option<&'a str>, /// Provide dagger access to the executed command. /// Do not use this option unless you trust the command being executed. /// The command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. #[builder(setter(into, strip_option))] pub experimental_privileged_nesting: Option, } #[derive(Builder, Debug, PartialEq)] pub struct ContainerExportOpts { /// Identifiers for other platform specific containers. /// Used for multi-platform image. #[builder(setter(into, strip_option))] pub platform_variants: Option>, } #[derive(Builder, Debug, PartialEq)] pub struct ContainerPipelineOpts<'a> { #[builder(setter(into, strip_option))] pub description: Option<&'a str>, } #[derive(Builder, Debug, PartialEq)] pub struct ContainerPublishOpts { /// Identifiers for other platform specific containers. /// Used for multi-platform image. #[builder(setter(into, strip_option))] pub platform_variants: Option>, } #[derive(Builder, Debug, PartialEq)] pub struct ContainerWithDefaultArgsOpts<'a> { #[builder(setter(into, strip_option))] pub args: Option>, } #[derive(Builder, Debug, PartialEq)] pub struct ContainerWithDirectoryOpts<'a> { #[builder(setter(into, strip_option))] pub exclude: Option>, #[builder(setter(into, strip_option))] pub include: Option>, } #[derive(Builder, Debug, PartialEq)] pub struct ContainerWithExecOpts<'a> { /// Content to write to the command's standard input before closing. #[builder(setter(into, strip_option))] pub stdin: Option<&'a str>, /// Redirect the command's standard output to a file in the container. #[builder(setter(into, strip_option))] pub redirect_stdout: Option<&'a str>, /// Redirect the command's standard error to a file in the container. #[builder(setter(into, strip_option))] pub redirect_stderr: Option<&'a str>, /// Provide dagger access to the executed command. /// Do not use this option unless you trust the command being executed. /// The command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. #[builder(setter(into, strip_option))] pub experimental_privileged_nesting: Option, } #[derive(Builder, Debug, PartialEq)] pub struct ContainerWithFileOpts { #[builder(setter(into, strip_option))] pub permissions: Option, } #[derive(Builder, Debug, PartialEq)] pub struct ContainerWithMountedCacheOpts { /// Directory to use as the cache volume's root. #[builder(setter(into, strip_option))] pub source: Option, /// Sharing mode of the cache volume. #[builder(setter(into, strip_option))] pub sharing: Option, } #[derive(Builder, Debug, PartialEq)] pub struct ContainerWithNewFileOpts<'a> { #[builder(setter(into, strip_option))] pub contents: Option<&'a str>, #[builder(setter(into, strip_option))] pub permissions: Option, } impl Container { /// Initializes this container from a Dockerfile build, using the context, a dockerfile file path and some additional buildArgs. /// /// # Arguments /// /// * `context` - Directory context used by the Dockerfile. /// * `opt` - optional argument, see inner type for documentation, use _opts to use pub fn build(&self, context: DirectoryId) -> Container { let mut query = self.selection.select("build"); query = query.arg("context", context); return Container { proc: self.proc.clone(), selection: query, conn: self.conn.clone(), }; } /// Initializes this container from a Dockerfile build, using the context, a dockerfile file path and some additional buildArgs. /// /// # Arguments /// /// * `context` - Directory context used by the Dockerfile. /// * `opt` - optional argument, see inner type for documentation, use _opts to use pub fn build_opts<'a>(&self, context: DirectoryId, opts: ContainerBuildOpts<'a>) -> Container { let mut query = self.selection.select("build"); query = query.arg("context", context); if let Some(dockerfile) = opts.dockerfile { query = query.arg("dockerfile", dockerfile); } if let Some(build_args) = opts.build_args { query = query.arg("buildArgs", build_args); } if let Some(target) = opts.target { query = query.arg("target", target); } return Container { proc: self.proc.clone(), selection: query, conn: self.conn.clone(), }; } /// Retrieves default arguments for future commands. pub async fn default_args(&self) -> eyre::Result> { let mut query = self.selection.select("defaultArgs"); query.execute(&graphql_client(&self.conn)).await } /// Retrieves a directory at the given path. Mounts are included. pub fn directory(&self, path: impl Into) -> Directory { let mut query = self.selection.select("directory"); query = query.arg("path", path.into()); return Directory { proc: self.proc.clone(), selection: query, conn: self.conn.clone(), }; } /// Retrieves entrypoint to be prepended to the arguments of all commands. pub async fn entrypoint(&self) -> eyre::Result> { let mut query = self.selection.select("entrypoint"); query.execute(&graphql_client(&self.conn)).await } /// Retrieves the value of the specified environment variable. pub async fn env_variable(&self, name: impl Into) -> eyre::Result { let mut query = self.selection.select("envVariable"); query = query.arg("name", name.into()); query.execute(&graphql_client(&self.conn)).await } /// Retrieves the list of environment variables passed to commands. pub fn env_variables(&self) -> Vec { let mut query = self.selection.select("envVariables"); return vec![EnvVariable { proc: self.proc.clone(), selection: query, conn: self.conn.clone(), }]; } /// Retrieves this container after executing the specified command inside it. /// /// # Arguments /// /// * `opt` - optional argument, see inner type for documentation, use _opts to use pub fn exec(&self) -> Container { let mut query = self.selection.select("exec"); return Container { proc: self.proc.clone(), selection: query, conn: self.conn.clone(), }; } /// Retrieves this container after executing the specified command inside it. /// /// # Arguments /// /// * `opt` - optional argument, see inner type for documentation, use _opts to use pub fn exec_opts<'a>(&self, opts: ContainerExecOpts<'a>) -> Container { let mut query = self.selection.select("exec"); if let Some(args) = opts.args { query = query.arg("args", args); } if let Some(stdin) = opts.stdin { query = query.arg("stdin", stdin); } if let Some(redirect_stdout) = opts.redirect_stdout { query = query.arg("redirectStdout", redirect_stdout); } if let Some(redirect_stderr) = opts.redirect_stderr { query = query.arg("redirectStderr", redirect_stderr); } if let Some(experimental_privileged_nesting) = opts.experimental_privileged_nesting { query = query.arg( "experimentalPrivilegedNesting", experimental_privileged_nesting, ); } return Container { proc: self.proc.clone(), selection: query, conn: self.conn.clone(), }; } /// Exit code of the last executed command. Zero means success. /// Null if no command has been executed. pub async fn exit_code(&self) -> eyre::Result { let mut query = self.selection.select("exitCode"); query.execute(&graphql_client(&self.conn)).await } /// Writes the container as an OCI tarball to the destination file path on the host for the specified platformVariants. /// Return true on success. /// /// # Arguments /// /// * `path` - Host's destination path. /// Path can be relative to the engine's workdir or absolute. /// * `opt` - optional argument, see inner type for documentation, use _opts to use pub async fn export(&self, path: impl Into) -> eyre::Result { let mut query = self.selection.select("export"); query = query.arg("path", path.into()); query.execute(&graphql_client(&self.conn)).await } /// Writes the container as an OCI tarball to the destination file path on the host for the specified platformVariants. /// Return true on success. /// /// # Arguments /// /// * `path` - Host's destination path. /// Path can be relative to the engine's workdir or absolute. /// * `opt` - optional argument, see inner type for documentation, use _opts to use pub async fn export_opts( &self, path: impl Into, opts: ContainerExportOpts, ) -> eyre::Result { let mut query = self.selection.select("export"); query = query.arg("path", path.into()); if let Some(platform_variants) = opts.platform_variants { query = query.arg("platformVariants", platform_variants); } query.execute(&graphql_client(&self.conn)).await } /// Retrieves a file at the given path. Mounts are included. pub fn file(&self, path: impl Into) -> File { let mut query = self.selection.select("file"); query = query.arg("path", path.into()); return File { proc: self.proc.clone(), selection: query, conn: self.conn.clone(), }; } /// Initializes this container from the base image published at the given address. /// /// # Arguments /// /// * `address` - Image's address from its registry. /// Formatted as [host]/[user]/[repo]:[tag] (e.g. docker.io/dagger/dagger:main). pub fn from(&self, address: impl Into) -> Container { let mut query = self.selection.select("from"); query = query.arg("address", address.into()); return Container { proc: self.proc.clone(), selection: query, conn: self.conn.clone(), }; } /// Retrieves this container's root filesystem. Mounts are not included. pub fn fs(&self) -> Directory { let mut query = self.selection.select("fs"); return Directory { proc: self.proc.clone(), selection: query, conn: self.conn.clone(), }; } /// A unique identifier for this container. pub async fn id(&self) -> eyre::Result { let mut query = self.selection.select("id"); query.execute(&graphql_client(&self.conn)).await } /// Retrieves the value of the specified label. pub async fn label(&self, name: impl Into) -> eyre::Result { let mut query = self.selection.select("label"); query = query.arg("name", name.into()); query.execute(&graphql_client(&self.conn)).await } /// Retrieves the list of labels passed to container. pub fn labels(&self) -> Vec