mirror of
https://github.com/kjuulh/dagger-rs.git
synced 2024-12-23 10:44:09 +01:00
can get schema
This commit is contained in:
parent
83ecbd238a
commit
06fd730a1c
@ -1,9 +1,11 @@
|
||||
use core::time;
|
||||
use std::{
|
||||
fs::canonicalize,
|
||||
io::{BufRead, BufReader},
|
||||
path::PathBuf,
|
||||
process::Stdio,
|
||||
sync::Arc,
|
||||
process::{Child, Stdio},
|
||||
sync::{mpsc::sync_channel, Arc},
|
||||
thread::sleep,
|
||||
};
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -29,9 +35,13 @@ impl CliSession {
|
||||
struct InnerCliSession {}
|
||||
|
||||
impl InnerCliSession {
|
||||
pub fn connect(&self, config: &Config, cli_path: &PathBuf) -> eyre::Result<ConnectParams> {
|
||||
let mut proc = self.start(config, cli_path)?;
|
||||
let params = self.get_conn(&mut proc)?;
|
||||
pub fn connect(
|
||||
&self,
|
||||
config: &Config,
|
||||
cli_path: &PathBuf,
|
||||
) -> eyre::Result<(ConnectParams, Child)> {
|
||||
let proc = self.start(config, cli_path)?;
|
||||
let params = self.get_conn(proc)?;
|
||||
Ok(params)
|
||||
}
|
||||
|
||||
@ -62,7 +72,10 @@ impl InnerCliSession {
|
||||
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
|
||||
.stdout
|
||||
.take()
|
||||
@ -73,31 +86,28 @@ impl InnerCliSession {
|
||||
.take()
|
||||
.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| {
|
||||
s.spawn(|| {
|
||||
let stdout_bufr = BufReader::new(stdout);
|
||||
let mut res_conn: Option<ConnectParams> = None;
|
||||
for line in stdout_bufr.lines() {
|
||||
let out = line.unwrap();
|
||||
let conn: ConnectParams = serde_json::from_str(&out).unwrap();
|
||||
res_conn = Some(conn);
|
||||
break;
|
||||
std::thread::spawn(move || {
|
||||
let stdout_bufr = BufReader::new(stdout);
|
||||
for line in stdout_bufr.lines() {
|
||||
let out = line.unwrap();
|
||||
if let Ok(conn) = serde_json::from_str::<ConnectParams>(&out) {
|
||||
sender.send(conn).unwrap();
|
||||
}
|
||||
|
||||
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::{
|
||||
cli_session::CliSession, config::Config, connect_params::ConnectParams, downloader::Downloader,
|
||||
};
|
||||
@ -9,7 +11,7 @@ impl Engine {
|
||||
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_session = CliSession::new();
|
||||
@ -17,7 +19,7 @@ impl Engine {
|
||||
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
|
||||
self.from_cli(cfg)
|
||||
}
|
||||
@ -36,7 +38,7 @@ mod tests {
|
||||
let params = engine.start(&Config::new(None, None, None, None)).unwrap();
|
||||
|
||||
assert_ne!(
|
||||
params,
|
||||
params.0,
|
||||
ConnectParams {
|
||||
port: 123,
|
||||
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 reqwest::blocking::Client;
|
||||
use reqwest::{
|
||||
blocking::{Client, RequestBuilder},
|
||||
header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE},
|
||||
};
|
||||
|
||||
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 {
|
||||
pub fn new() -> 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()
|
||||
.user_agent("graphql-rust/0.10.0")
|
||||
.default_headers(
|
||||
std::iter::once((
|
||||
reqwest::header::AUTHORIZATION,
|
||||
reqwest::header::HeaderValue::from_str(&format!(
|
||||
"Bearer {}",
|
||||
conn.session_token
|
||||
))
|
||||
.unwrap(),
|
||||
))
|
||||
.collect(),
|
||||
)
|
||||
.connection_verbose(true)
|
||||
//.danger_accept_invalid_certs(true)
|
||||
.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