mirror of
https://github.com/kjuulh/dagger-rs.git
synced 2024-11-25 16:32:42 +01:00
can get schema
This commit is contained in:
parent
83ecbd238a
commit
06fd730a1c
@ -1,9 +1,11 @@
|
|||||||
|
use core::time;
|
||||||
use std::{
|
use std::{
|
||||||
fs::canonicalize,
|
fs::canonicalize,
|
||||||
io::{BufRead, BufReader},
|
io::{BufRead, BufReader},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
process::Stdio,
|
process::{Child, Stdio},
|
||||||
sync::Arc,
|
sync::{mpsc::sync_channel, Arc},
|
||||||
|
thread::sleep,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{config::Config, connect_params::ConnectParams};
|
use crate::{config::Config, connect_params::ConnectParams};
|
||||||
@ -20,7 +22,11 @@ impl CliSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(&self, config: &Config, cli_path: &PathBuf) -> eyre::Result<ConnectParams> {
|
pub fn connect(
|
||||||
|
&self,
|
||||||
|
config: &Config,
|
||||||
|
cli_path: &PathBuf,
|
||||||
|
) -> eyre::Result<(ConnectParams, Child)> {
|
||||||
self.inner.connect(config, cli_path)
|
self.inner.connect(config, cli_path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,9 +35,13 @@ impl CliSession {
|
|||||||
struct InnerCliSession {}
|
struct InnerCliSession {}
|
||||||
|
|
||||||
impl InnerCliSession {
|
impl InnerCliSession {
|
||||||
pub fn connect(&self, config: &Config, cli_path: &PathBuf) -> eyre::Result<ConnectParams> {
|
pub fn connect(
|
||||||
let mut proc = self.start(config, cli_path)?;
|
&self,
|
||||||
let params = self.get_conn(&mut proc)?;
|
config: &Config,
|
||||||
|
cli_path: &PathBuf,
|
||||||
|
) -> eyre::Result<(ConnectParams, Child)> {
|
||||||
|
let proc = self.start(config, cli_path)?;
|
||||||
|
let params = self.get_conn(proc)?;
|
||||||
Ok(params)
|
Ok(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +72,10 @@ impl InnerCliSession {
|
|||||||
return Ok(proc);
|
return Ok(proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_conn(&self, proc: &mut std::process::Child) -> eyre::Result<ConnectParams> {
|
fn get_conn(
|
||||||
|
&self,
|
||||||
|
mut proc: std::process::Child,
|
||||||
|
) -> eyre::Result<(ConnectParams, std::process::Child)> {
|
||||||
let stdout = proc
|
let stdout = proc
|
||||||
.stdout
|
.stdout
|
||||||
.take()
|
.take()
|
||||||
@ -73,31 +86,28 @@ impl InnerCliSession {
|
|||||||
.take()
|
.take()
|
||||||
.ok_or(eyre::anyhow!("could not acquire stderr from child process"))?;
|
.ok_or(eyre::anyhow!("could not acquire stderr from child process"))?;
|
||||||
|
|
||||||
let mut conn: Option<ConnectParams> = None;
|
let (sender, receiver) = sync_channel(1);
|
||||||
|
|
||||||
std::thread::scope(|s| {
|
std::thread::spawn(move || {
|
||||||
s.spawn(|| {
|
let stdout_bufr = BufReader::new(stdout);
|
||||||
let stdout_bufr = BufReader::new(stdout);
|
for line in stdout_bufr.lines() {
|
||||||
let mut res_conn: Option<ConnectParams> = None;
|
let out = line.unwrap();
|
||||||
for line in stdout_bufr.lines() {
|
if let Ok(conn) = serde_json::from_str::<ConnectParams>(&out) {
|
||||||
let out = line.unwrap();
|
sender.send(conn).unwrap();
|
||||||
let conn: ConnectParams = serde_json::from_str(&out).unwrap();
|
|
||||||
res_conn = Some(conn);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
conn = res_conn;
|
|
||||||
});
|
|
||||||
|
|
||||||
//s.spawn(|| {
|
|
||||||
// let stderr_bufr = BufReader::new(stderr);
|
|
||||||
// for line in stderr_bufr.lines() {
|
|
||||||
// let out = line.unwrap();
|
|
||||||
// panic!("could not start dagger session: {}", out)
|
|
||||||
// }
|
|
||||||
//});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(conn.ok_or(eyre::anyhow!("could not connect to dagger"))?)
|
std::thread::spawn(|| {
|
||||||
|
let stderr_bufr = BufReader::new(stderr);
|
||||||
|
for line in stderr_bufr.lines() {
|
||||||
|
let out = line.unwrap();
|
||||||
|
panic!("could not start dagger session: {}", out)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let conn = receiver.recv()?;
|
||||||
|
|
||||||
|
Ok((conn, proc))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use std::process::Child;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cli_session::CliSession, config::Config, connect_params::ConnectParams, downloader::Downloader,
|
cli_session::CliSession, config::Config, connect_params::ConnectParams, downloader::Downloader,
|
||||||
};
|
};
|
||||||
@ -9,7 +11,7 @@ impl Engine {
|
|||||||
Self {}
|
Self {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_cli(&self, cfg: &Config) -> eyre::Result<ConnectParams> {
|
fn from_cli(&self, cfg: &Config) -> eyre::Result<(ConnectParams, Child)> {
|
||||||
let cli = Downloader::new("0.3.10".into())?.get_cli()?;
|
let cli = Downloader::new("0.3.10".into())?.get_cli()?;
|
||||||
|
|
||||||
let cli_session = CliSession::new();
|
let cli_session = CliSession::new();
|
||||||
@ -17,7 +19,7 @@ impl Engine {
|
|||||||
Ok(cli_session.connect(cfg, &cli)?)
|
Ok(cli_session.connect(cfg, &cli)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(&self, cfg: &Config) -> eyre::Result<ConnectParams> {
|
pub fn start(&self, cfg: &Config) -> eyre::Result<(ConnectParams, Child)> {
|
||||||
// TODO: Add from existing session as well
|
// TODO: Add from existing session as well
|
||||||
self.from_cli(cfg)
|
self.from_cli(cfg)
|
||||||
}
|
}
|
||||||
@ -36,7 +38,7 @@ mod tests {
|
|||||||
let params = engine.start(&Config::new(None, None, None, None)).unwrap();
|
let params = engine.start(&Config::new(None, None, None, None)).unwrap();
|
||||||
|
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
params,
|
params.0,
|
||||||
ConnectParams {
|
ConnectParams {
|
||||||
port: 123,
|
port: 123,
|
||||||
session_token: "123".into()
|
session_token: "123".into()
|
||||||
|
99
src/graphql/introspection_query.graphql
Normal file
99
src/graphql/introspection_query.graphql
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
query IntrospectionQuery {
|
||||||
|
__schema {
|
||||||
|
queryType {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
mutationType {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
subscriptionType {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
types {
|
||||||
|
...FullType
|
||||||
|
}
|
||||||
|
directives {
|
||||||
|
name
|
||||||
|
description
|
||||||
|
locations
|
||||||
|
args {
|
||||||
|
...InputValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment FullType on __Type {
|
||||||
|
kind
|
||||||
|
name
|
||||||
|
description
|
||||||
|
fields(includeDeprecated: true) {
|
||||||
|
name
|
||||||
|
description
|
||||||
|
args {
|
||||||
|
...InputValue
|
||||||
|
}
|
||||||
|
type {
|
||||||
|
...TypeRef
|
||||||
|
}
|
||||||
|
isDeprecated
|
||||||
|
deprecationReason
|
||||||
|
}
|
||||||
|
inputFields {
|
||||||
|
...InputValue
|
||||||
|
}
|
||||||
|
interfaces {
|
||||||
|
...TypeRef
|
||||||
|
}
|
||||||
|
enumValues(includeDeprecated: true) {
|
||||||
|
name
|
||||||
|
description
|
||||||
|
isDeprecated
|
||||||
|
deprecationReason
|
||||||
|
}
|
||||||
|
possibleTypes {
|
||||||
|
...TypeRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment InputValue on __InputValue {
|
||||||
|
name
|
||||||
|
description
|
||||||
|
type {
|
||||||
|
...TypeRef
|
||||||
|
}
|
||||||
|
defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment TypeRef on __Type {
|
||||||
|
kind
|
||||||
|
name
|
||||||
|
ofType {
|
||||||
|
kind
|
||||||
|
name
|
||||||
|
ofType {
|
||||||
|
kind
|
||||||
|
name
|
||||||
|
ofType {
|
||||||
|
kind
|
||||||
|
name
|
||||||
|
ofType {
|
||||||
|
kind
|
||||||
|
name
|
||||||
|
ofType {
|
||||||
|
kind
|
||||||
|
name
|
||||||
|
ofType {
|
||||||
|
kind
|
||||||
|
name
|
||||||
|
ofType {
|
||||||
|
kind
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
101
src/graphql/introspection_schema.graphql
Normal file
101
src/graphql/introspection_schema.graphql
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
schema {
|
||||||
|
query: Query
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
__schema: __Schema
|
||||||
|
}
|
||||||
|
|
||||||
|
type __Schema {
|
||||||
|
types: [__Type!]!
|
||||||
|
queryType: __Type!
|
||||||
|
mutationType: __Type
|
||||||
|
subscriptionType: __Type
|
||||||
|
directives: [__Directive!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
type __Type {
|
||||||
|
kind: __TypeKind!
|
||||||
|
name: String
|
||||||
|
description: String
|
||||||
|
|
||||||
|
# OBJECT and INTERFACE only
|
||||||
|
fields(includeDeprecated: Boolean = false): [__Field!]
|
||||||
|
|
||||||
|
# OBJECT only
|
||||||
|
interfaces: [__Type!]
|
||||||
|
|
||||||
|
# INTERFACE and UNION only
|
||||||
|
possibleTypes: [__Type!]
|
||||||
|
|
||||||
|
# ENUM only
|
||||||
|
enumValues(includeDeprecated: Boolean = false): [__EnumValue!]
|
||||||
|
|
||||||
|
# INPUT_OBJECT only
|
||||||
|
inputFields: [__InputValue!]
|
||||||
|
|
||||||
|
# NON_NULL and LIST only
|
||||||
|
ofType: __Type
|
||||||
|
}
|
||||||
|
|
||||||
|
type __Field {
|
||||||
|
name: String!
|
||||||
|
description: String
|
||||||
|
args: [__InputValue!]!
|
||||||
|
type: __Type!
|
||||||
|
isDeprecated: Boolean!
|
||||||
|
deprecationReason: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type __InputValue {
|
||||||
|
name: String!
|
||||||
|
description: String
|
||||||
|
type: __Type!
|
||||||
|
defaultValue: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type __EnumValue {
|
||||||
|
name: String!
|
||||||
|
description: String
|
||||||
|
isDeprecated: Boolean!
|
||||||
|
deprecationReason: String
|
||||||
|
}
|
||||||
|
|
||||||
|
enum __TypeKind {
|
||||||
|
SCALAR
|
||||||
|
OBJECT
|
||||||
|
INTERFACE
|
||||||
|
UNION
|
||||||
|
ENUM
|
||||||
|
INPUT_OBJECT
|
||||||
|
LIST
|
||||||
|
NON_NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
type __Directive {
|
||||||
|
name: String!
|
||||||
|
description: String
|
||||||
|
locations: [__DirectiveLocation!]!
|
||||||
|
args: [__InputValue!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
enum __DirectiveLocation {
|
||||||
|
QUERY
|
||||||
|
MUTATION
|
||||||
|
SUBSCRIPTION
|
||||||
|
FIELD
|
||||||
|
FRAGMENT_DEFINITION
|
||||||
|
FRAGMENT_SPREAD
|
||||||
|
INLINE_FRAGMENT
|
||||||
|
SCHEMA
|
||||||
|
SCALAR
|
||||||
|
OBJECT
|
||||||
|
FIELD_DEFINITION
|
||||||
|
ARGUMENT_DEFINITION
|
||||||
|
INTERFACE
|
||||||
|
UNION
|
||||||
|
ENUM
|
||||||
|
ENUM_VALUE
|
||||||
|
INPUT_OBJECT
|
||||||
|
INPUT_FIELD_DEFINITION
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
use core::time;
|
||||||
|
use std::thread::sleep;
|
||||||
|
|
||||||
|
use graphql_introspection_query::introspection_response::IntrospectionResponse;
|
||||||
|
|
||||||
|
use crate::{config::Config, engine::Engine, session::Session};
|
||||||
|
|
||||||
|
pub fn get_schema() -> eyre::Result<IntrospectionResponse> {
|
||||||
|
//TODO: Implement cotext for proc
|
||||||
|
let cfg = Config::new(None, None, None, None);
|
||||||
|
let (conn, proc) = Engine::new().start(&cfg)?;
|
||||||
|
let session = Session::new();
|
||||||
|
let req_builder = session.start(cfg, &conn)?;
|
||||||
|
let schema = session.schema(req_builder)?;
|
||||||
|
|
||||||
|
Ok(schema)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::get_schema;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_get_schema() {
|
||||||
|
let _ = get_schema().unwrap();
|
||||||
|
}
|
||||||
|
}
|
@ -1,34 +1,79 @@
|
|||||||
use graphql_client::reqwest::post_graphql_blocking;
|
use graphql_client::GraphQLQuery;
|
||||||
use graphql_introspection_query::introspection_response::IntrospectionResponse;
|
use graphql_introspection_query::introspection_response::IntrospectionResponse;
|
||||||
use reqwest::blocking::Client;
|
use reqwest::{
|
||||||
|
blocking::{Client, RequestBuilder},
|
||||||
|
header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{config::Config, connect_params::ConnectParams};
|
use crate::{config::Config, connect_params::ConnectParams};
|
||||||
|
|
||||||
pub struct Session {}
|
#[derive(GraphQLQuery)]
|
||||||
|
#[graphql(
|
||||||
|
schema_path = "src/graphql/introspection_schema.graphql",
|
||||||
|
query_path = "src/graphql/introspection_query.graphql",
|
||||||
|
responsive_path = "Serialize",
|
||||||
|
variable_derive = "Deserialize"
|
||||||
|
)]
|
||||||
|
struct IntrospectionQuery;
|
||||||
|
|
||||||
|
pub struct Session;
|
||||||
|
|
||||||
impl Session {
|
impl Session {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {}
|
Self {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(&self, cfg: Config, conn: &ConnectParams) -> eyre::Result<Client> {
|
pub fn start(&self, cfg: Config, conn: &ConnectParams) -> eyre::Result<RequestBuilder> {
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.user_agent("graphql-rust/0.10.0")
|
.user_agent("graphql-rust/0.10.0")
|
||||||
.default_headers(
|
.connection_verbose(true)
|
||||||
std::iter::once((
|
//.danger_accept_invalid_certs(true)
|
||||||
reqwest::header::AUTHORIZATION,
|
|
||||||
reqwest::header::HeaderValue::from_str(&format!(
|
|
||||||
"Bearer {}",
|
|
||||||
conn.session_token
|
|
||||||
))
|
|
||||||
.unwrap(),
|
|
||||||
))
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
let schema = post_graphql_blocking::<IntrospectionResponse, _>(&client, conn.url(), vec![]);
|
let req_builder = client
|
||||||
|
.post(conn.url())
|
||||||
|
.headers(construct_headers())
|
||||||
|
.basic_auth::<String, String>(conn.session_token.to_string(), None);
|
||||||
|
|
||||||
Ok(client)
|
Ok(req_builder)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn schema(&self, req_builder: RequestBuilder) -> eyre::Result<IntrospectionResponse> {
|
||||||
|
let request_body: graphql_client::QueryBody<()> = graphql_client::QueryBody {
|
||||||
|
variables: (),
|
||||||
|
query: introspection_query::QUERY,
|
||||||
|
operation_name: introspection_query::OPERATION_NAME,
|
||||||
|
};
|
||||||
|
|
||||||
|
let res = req_builder.json(&request_body).send()?;
|
||||||
|
|
||||||
|
if res.status().is_success() {
|
||||||
|
// do nothing
|
||||||
|
} else if res.status().is_server_error() {
|
||||||
|
return Err(eyre::anyhow!("server error!"));
|
||||||
|
} else {
|
||||||
|
let status = res.status();
|
||||||
|
let error_message = match res.text() {
|
||||||
|
Ok(msg) => match serde_json::from_str::<serde_json::Value>(&msg) {
|
||||||
|
Ok(json) => {
|
||||||
|
format!("HTTP {}\n{}", status, serde_json::to_string_pretty(&json)?)
|
||||||
|
}
|
||||||
|
Err(_) => format!("HTTP {}: {}", status, msg),
|
||||||
|
},
|
||||||
|
Err(_) => format!("HTTP {}", status),
|
||||||
|
};
|
||||||
|
return Err(eyre::anyhow!(error_message));
|
||||||
|
}
|
||||||
|
|
||||||
|
let json: IntrospectionResponse = res.json()?;
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn construct_headers() -> HeaderMap {
|
||||||
|
let mut headers = HeaderMap::new();
|
||||||
|
headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
|
||||||
|
headers.insert(ACCEPT, HeaderValue::from_static("application/json"));
|
||||||
|
headers
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user