diff --git a/crates/dagger-core/src/dagger.rs b/crates/dagger-core/src/dagger.rs deleted file mode 100644 index eb16a65..0000000 --- a/crates/dagger-core/src/dagger.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::sync::Arc; - -pub fn connect() -> eyre::Result { - Client::new() -} - -struct InnerClient {} - -#[allow(dead_code)] -pub struct Client { - inner: Arc, -} - -impl Client { - pub fn new() -> eyre::Result { - Ok(Self { - inner: Arc::new(InnerClient {}), - }) - } -} diff --git a/crates/dagger-core/src/lib.rs b/crates/dagger-core/src/lib.rs index b717286..d765ba1 100644 --- a/crates/dagger-core/src/lib.rs +++ b/crates/dagger-core/src/lib.rs @@ -1,7 +1,6 @@ pub mod cli_session; pub mod config; pub mod connect_params; -pub mod dagger; pub mod downloader; pub mod engine; pub mod introspection; diff --git a/crates/dagger-sdk/Cargo.toml b/crates/dagger-sdk/Cargo.toml index 690fda6..dc417f3 100644 --- a/crates/dagger-sdk/Cargo.toml +++ b/crates/dagger-sdk/Cargo.toml @@ -9,6 +9,7 @@ description = "A dagger sdk for rust, written in rust" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +base64 = "0.21.0" dagger-core = { path = "../dagger-core" } eyre = "0.6.8" futures = "0.3.26" @@ -18,3 +19,4 @@ gql_client = "1.0.7" pretty_assertions = "1.3.0" serde = { version = "1.0.152", features = ["derive"] } serde_json = "1.0.92" +tokio = { version = "1.25.0", features = ["full"] } diff --git a/crates/dagger-sdk/examples_tests/mod.rs b/crates/dagger-sdk/examples_tests/mod.rs deleted file mode 100644 index c7242c4..0000000 --- a/crates/dagger-sdk/examples_tests/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -#[cfg(example_test)] -mod examples { - #[test] - fn test_example_container() { - unimplemented!(); - } -} - - - diff --git a/crates/dagger-sdk/src/client.rs b/crates/dagger-sdk/src/client.rs new file mode 100644 index 0000000..346e13e --- /dev/null +++ b/crates/dagger-sdk/src/client.rs @@ -0,0 +1,51 @@ +use std::collections::HashMap; +use std::sync::Arc; + +use base64::engine::general_purpose; +use base64::Engine; +use dagger_core::config::Config; +use dagger_core::connect_params::ConnectParams; +use dagger_core::engine::Engine as DaggerEngine; +use gql_client::ClientConfig; + +use crate::gen::Query; +use crate::querybuilder::query; + +pub type DaggerConn = Arc; + +pub fn connect() -> eyre::Result { + let cfg = Config::default(); + let (conn, proc) = DaggerEngine::new().start(&cfg)?; + + Ok(Arc::new(Query { + conn, + proc: Arc::new(proc), + selection: query(), + })) +} + +pub fn graphql_client(conn: &ConnectParams) -> gql_client::Client { + let token = general_purpose::URL_SAFE.encode(format!("{}:", conn.session_token)); + + let mut headers = HashMap::new(); + headers.insert("Authorization".to_string(), format!("Basic {}", token)); + + gql_client::Client::new_with_config(ClientConfig { + endpoint: conn.url(), + timeout: None, + headers: Some(headers), + proxy: None, + }) +} + +// Conn will automatically close on drop of proc + +#[cfg(test)] +mod test { + use super::connect; + + #[test] + fn test_connect() { + let _ = connect().unwrap(); + } +} diff --git a/crates/dagger-sdk/src/gen.rs b/crates/dagger-sdk/src/gen.rs index 00ae7dd..14caa4b 100644 --- a/crates/dagger-sdk/src/gen.rs +++ b/crates/dagger-sdk/src/gen.rs @@ -1,5 +1,12 @@ +use std::process::Child; +use std::sync::Arc; + +use dagger_core::connect_params::ConnectParams; use dagger_core::{Boolean, Input, Int, Scalar}; +use crate::client::graphql_client; +use crate::querybuilder::Selection; + // code generated by dagger. DO NOT EDIT. /// A global cache volume identifier. @@ -46,7 +53,11 @@ impl CacheVolume { impl Input for CacheVolume {} /// An OCI-compatible container, also known as a docker container. -pub struct Container {} +pub struct Container { + pub conn: ConnectParams, + pub proc: Arc, + pub selection: Selection, +} impl Container { /// Initializes this container from a Dockerfile build, using the context, a dockerfile file path and some additional buildArgs. @@ -104,13 +115,20 @@ impl Container { /// The command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. pub fn exec( &self, - _args: Option>, + args: Option>, _stdin: Option, _redirect_stdout: Option, _redirect_stderr: Option, _experimental_privileged_nesting: Option, ) -> Container { - todo!() + let query = self.selection.select("exec"); + let query = query.arg("args", args).unwrap(); + + Container { + conn: self.conn.clone(), + proc: self.proc.clone(), + selection: query, + } } /// Exit code of the last executed command. Zero means success. @@ -141,8 +159,15 @@ impl Container { /// /// * `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: String) -> Container { - todo!() + pub fn from(&self, address: String) -> Container { + let query = self.selection.select("from"); + let query = query.arg("address", address).unwrap(); + + Container { + conn: self.conn.clone(), + proc: self.proc.clone(), + selection: query, + } } /// Retrieves this container's root filesystem. Mounts are not included. @@ -187,7 +212,11 @@ impl Container { /// Formatted as [host]/[user]/[repo]:[tag] (e.g. docker.io/dagger/dagger:main). /// * `platformVariants` - Identifiers for other platform specific containers. /// Used for multi-platform image. - pub fn publish(&self, _address: String, _platform_variants: Option>) -> String { + pub fn publish( + &self, + _address: String, + _platform_variants: Option>, + ) -> String { todo!() } @@ -205,7 +234,9 @@ impl Container { /// The output stream of the last executed command. /// Null if no command has been executed. pub fn stdout(&self) -> Option { - todo!() + let query = self.selection.select("stdout"); + + query.execute(&graphql_client(&self.conn)).unwrap() } /// Retrieves the user to be set for all commands. @@ -251,7 +282,7 @@ impl Container { /// The command being executed WILL BE GRANTED FULL ACCESS TO YOUR HOST FILESYSTEM. pub fn with_exec( &self, - _args: Vec, + args: Vec, _stdin: Option, _redirect_stdout: Option, _redirect_stderr: Option, @@ -266,7 +297,12 @@ impl Container { } /// Retrieves this container plus the contents of the given file copied to the given path. - pub fn with_file(&self, _path: String, _source: FileID, _permissions: Option) -> Container { + pub fn with_file( + &self, + _path: String, + _source: FileID, + _permissions: Option, + ) -> Container { todo!() } @@ -448,7 +484,12 @@ impl Directory { } /// Retrieves this directory plus the contents of the given file copied to the given path. - pub fn with_file(&self, _path: String, _source: FileID, _permissions: Option) -> Directory { + pub fn with_file( + &self, + _path: String, + _source: FileID, + _permissions: Option, + ) -> Directory { todo!() } @@ -617,7 +658,11 @@ impl Host { } /// Retrieves the current working directory on the host. - pub fn workdir(&self, _exclude: Option>, _include: Option>) -> Directory { + pub fn workdir( + &self, + _exclude: Option>, + _include: Option>, + ) -> Directory { todo!() } } @@ -696,7 +741,11 @@ impl Project { impl Input for Project {} /// -pub struct Query {} +pub struct Query { + pub conn: ConnectParams, + pub proc: Arc, + pub selection: Selection, +} impl Query { /// Constructs a cache volume for a given cache key. @@ -711,7 +760,13 @@ impl Query { /// Null ID returns an empty container (scratch). /// Optional platform argument initializes new containers to execute and publish as that platform. Platform defaults to that of the builder's host. pub fn container(&self, _id: Option, _platform: Option) -> Container { - todo!() + let query = self.selection.select("container"); + + return Container { + conn: self.conn.clone(), + proc: self.proc.clone(), + selection: query, + }; } /// The default platform of the builder. diff --git a/crates/dagger-sdk/src/lib.rs b/crates/dagger-sdk/src/lib.rs index 8b79c72..b675c7e 100644 --- a/crates/dagger-sdk/src/lib.rs +++ b/crates/dagger-sdk/src/lib.rs @@ -1,3 +1,4 @@ +pub mod client; pub mod gen; mod querybuilder; diff --git a/crates/dagger-sdk/src/querybuilder.rs b/crates/dagger-sdk/src/querybuilder.rs index 79d9930..890fd76 100644 --- a/crates/dagger-sdk/src/querybuilder.rs +++ b/crates/dagger-sdk/src/querybuilder.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, ops::Add, sync::Arc}; -use futures::executor::block_on; use serde::{Deserialize, Serialize}; +use tokio::task::block_in_place; pub fn query() -> Selection { Selection::default() @@ -99,7 +99,14 @@ impl Selection { { let query = self.build()?; - let resp: Option = match block_on(gql_client.query(&query)) { + let basic = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap(); + + dbg!(&query); + + let resp: Option = match basic.block_on(gql_client.query(&query)) { Ok(r) => r, Err(e) => eyre::bail!(e), }; diff --git a/crates/dagger-sdk/tests/mod.rs b/crates/dagger-sdk/tests/mod.rs new file mode 100644 index 0000000..581a8b7 --- /dev/null +++ b/crates/dagger-sdk/tests/mod.rs @@ -0,0 +1,20 @@ +use dagger_sdk::client::connect; + +#[test] +fn test_example_container() { + let client = connect().unwrap(); + + let alpine = client.container(None, None).from("alpine:3.16.2".into()); + + let out = alpine + .exec( + Some(vec!["cat".into(), "/etc/alpine-release".into()]), + None, + None, + None, + None, + ) + .stdout(); + + assert_eq!(out, Some("3.16.2".to_string())) +}