From c7a8411a27b0cdad6649754bb2fc46d216a4d55b Mon Sep 17 00:00:00 2001 From: mogery Date: Wed, 31 Jan 2024 16:32:23 +0000 Subject: [PATCH] feat(ConfigReader): take an Option> --- src/cli/tc.rs | 2 +- src/config/reader.rs | 23 ++++++++++++----------- src/grpc/data_loader_request.rs | 2 +- src/grpc/protobuf.rs | 2 +- src/grpc/request_template.rs | 2 +- src/http/showcase.rs | 17 +++-------------- tests/graphql_spec.rs | 4 ++-- tests/http/showcase.yml | 4 ++-- tests/http_spec.rs | 2 +- tests/server_spec.rs | 4 ++-- 10 files changed, 26 insertions(+), 36 deletions(-) diff --git a/src/cli/tc.rs b/src/cli/tc.rs index 5064921fb3..7590966c2d 100644 --- a/src/cli/tc.rs +++ b/src/cli/tc.rs @@ -27,7 +27,7 @@ pub async fn run() -> Result<()> { update_checker::check_for_update().await; let file_io: Arc = init_file(); let default_http_io = init_http(&Upstream::default(), None); - let config_reader = ConfigReader::init(file_io.clone(), default_http_io); + let config_reader = ConfigReader::init(Some(file_io.clone()), default_http_io); match cli.command { Command::Start { file_paths } => { let config_set = config_reader.read_all(&file_paths).await?; diff --git a/src/config/reader.rs b/src/config/reader.rs index eefd85a373..831fb8cc40 100644 --- a/src/config/reader.rs +++ b/src/config/reader.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, VecDeque}; use std::sync::Arc; -use anyhow::Context; +use anyhow::{anyhow, Context}; use futures_util::future::join_all; use futures_util::TryFutureExt; use prost_reflect::prost_types::{FileDescriptorProto, FileDescriptorSet}; @@ -16,7 +16,7 @@ const NULL_STR: &str = "\0\0\0\0\0\0\0"; /// Reads the configuration from a file or from an HTTP URL and resolves all linked extensions to create a ConfigSet. pub struct ConfigReader { - file_io: Arc, + file_io: Option>, http_io: Arc, } @@ -28,7 +28,7 @@ struct FileRead { impl ConfigReader { pub fn init( - file_io: Arc, + file_io: Option>, http_io: Arc, ) -> Self { Self { file_io, http_io } @@ -44,10 +44,11 @@ impl ConfigReader { .await?; String::from_utf8(response.body.to_vec())? + } else if let Some(file_io) = &self.file_io { + // Is a file path and file IO is enabled + file_io.read(&file.to_string()).await? } else { - // Is a file path - - self.file_io.read(&file.to_string()).await? + return Err(anyhow!("Cannot read file {:#?}", file.to_string())); }; Ok(FileRead { content, path: file.to_string() }) @@ -196,7 +197,7 @@ mod test_proto_config { #[tokio::test] async fn test_resolve() { // Skipping IO tests as they are covered in reader.rs - let reader = ConfigReader::init(init_file(), init_http(&Default::default(), None)); + let reader = ConfigReader::init(Some(init_file()), init_http(&Default::default(), None)); reader .read_proto("google/protobuf/empty.proto") .await @@ -222,7 +223,7 @@ mod test_proto_config { assert!(test_file.exists()); let test_file = test_file.to_str().unwrap().to_string(); - let reader = ConfigReader::init(init_file(), init_http(&Default::default(), None)); + let reader = ConfigReader::init(Some(init_file()), init_http(&Default::default(), None)); let helper_map = reader .resolve_descriptors(HashMap::new(), test_file) .await?; @@ -312,7 +313,7 @@ mod reader_tests { .iter() .map(|x| x.to_string()) .collect(); - let cr = ConfigReader::init(file_io, http_io); + let cr = ConfigReader::init(Some(file_io), http_io); let c = cr.read_all(&files).await.unwrap(); assert_eq!( ["Post", "Query", "Test", "User"] @@ -341,7 +342,7 @@ mod reader_tests { .iter() .map(|x| x.to_string()) .collect(); - let cr = ConfigReader::init(file_io, http_io); + let cr = ConfigReader::init(Some(file_io), http_io); let c = cr.read_all(&files).await.unwrap(); assert_eq!( ["Post", "Query", "User"] @@ -361,7 +362,7 @@ mod reader_tests { let http_io = init_http(&Upstream::default(), None); let cargo_manifest = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let reader = ConfigReader::init(file_io, http_io); + let reader = ConfigReader::init(Some(file_io), http_io); let config = reader .read(&format!( diff --git a/src/grpc/data_loader_request.rs b/src/grpc/data_loader_request.rs index 434d644cb3..85f8a24107 100644 --- a/src/grpc/data_loader_request.rs +++ b/src/grpc/data_loader_request.rs @@ -86,7 +86,7 @@ mod tests { "foo".to_string(), Type::default().fields(vec![("bar", Field::default().grpc(grpc))]), ); - let reader = ConfigReader::init(file_io, http_io); + let reader = ConfigReader::init(Some(file_io), http_io); let config_set = reader.resolve(config).await.unwrap(); let protobuf_set = diff --git a/src/grpc/protobuf.rs b/src/grpc/protobuf.rs index c350bfd1b7..c4536d0f64 100644 --- a/src/grpc/protobuf.rs +++ b/src/grpc/protobuf.rs @@ -226,7 +226,7 @@ mod tests { async fn get_proto_file(name: &str) -> Result { let file_io = init_file(); let http_io = init_http(&Upstream::default(), None); - let reader = ConfigReader::init(file_io, http_io); + let reader = ConfigReader::init(Some(file_io), http_io); let mut config = Config::default(); let grpc = Grpc { proto_path: get_test_file(name) diff --git a/src/grpc/request_template.rs b/src/grpc/request_template.rs index 2774b3af94..2148298b9f 100644 --- a/src/grpc/request_template.rs +++ b/src/grpc/request_template.rs @@ -122,7 +122,7 @@ mod tests { let file_io = init_file(); let http_io = init_http(&Upstream::default(), None); - let reader = ConfigReader::init(file_io, http_io); + let reader = ConfigReader::init(Some(file_io), http_io); let mut config = Config::default(); let grpc = Grpc { proto_path: test_file.to_str().unwrap().to_string(), diff --git a/src/http/showcase.rs b/src/http/showcase.rs index d530d50739..ae81065e4d 100644 --- a/src/http/showcase.rs +++ b/src/http/showcase.rs @@ -58,23 +58,12 @@ pub async fn showcase_get_app_ctx( return Ok(Err(GraphQLResponse::from(response).to_response()?)); }; - let config = if let Some(file) = resources.file { - let reader = ConfigReader::init(file, http.clone()); - reader.read(config_url).await - } else { - let reader = ConfigReader::init(Arc::new(DummyFileIO), http.clone()); - reader.read(config_url).await - }; - - let config = match config { + let reader = ConfigReader::init(resources.file, http.clone()); + let config = match reader.read(config_url).await { Ok(config) => config, Err(e) => { let mut response = async_graphql::Response::default(); - let server_error = if format!("{:?}", e.source()) == "Some(\"DummyFileIO\")" { - ServerError::new("Invalid Config URL specified", None) - } else { - ServerError::new(format!("{}", e), None) - }; + let server_error = ServerError::new(format!("Failed to read config: {}", e), None); response.errors = vec![server_error]; return Ok(Err(GraphQLResponse::from(response).to_response()?)); } diff --git a/tests/graphql_spec.rs b/tests/graphql_spec.rs index 9ddfa0aed1..fc770ad549 100644 --- a/tests/graphql_spec.rs +++ b/tests/graphql_spec.rs @@ -291,7 +291,7 @@ async fn test_server_to_client_sdl() -> std::io::Result<()> { let content = content.as_str(); let config = Config::from_sdl(content).to_result().unwrap(); let upstream = config.upstream.clone(); - let reader = ConfigReader::init(file_io.clone(), init_http(&upstream, None)); + let reader = ConfigReader::init(Some(file_io.clone()), init_http(&upstream, None)); let config_set = reader.resolve(config).await.unwrap(); let actual = print_schema::print_schema((Blueprint::try_from(&config_set).unwrap()).to_schema()); @@ -391,7 +391,7 @@ async fn test_failures_in_client_sdl() -> std::io::Result<()> { let actual = match config { Ok(config) => { let upstream = config.upstream.clone(); - let reader = ConfigReader::init(file_io.clone(), init_http(&upstream, None)); + let reader = ConfigReader::init(Some(file_io.clone()), init_http(&upstream, None)); match reader.resolve(config).await { Ok(config_set) => Valid::from(Blueprint::try_from(&config_set)) .to_result() diff --git a/tests/http/showcase.yml b/tests/http/showcase.yml index 137a63ac9e..92a122cc9c 100644 --- a/tests/http/showcase.yml +++ b/tests/http/showcase.yml @@ -59,7 +59,7 @@ assert: body: data: null errors: - - message: "Invalid Config URL specified" + - message: "Failed to read config: ./tests/http/config/simple.graphql" - request: method: POST url: http://localhost:8080/showcase/graphql?config=http%3A%2F%2Fexample.com%2Finvalid.graphql @@ -69,7 +69,7 @@ assert: body: data: null errors: - - message: "Validation Error\n• --> 1:1\n |\n1 | \"dsjfsjdfjdsfjkdskjfjkds\"\n | ^---\n |\n = expected type_system_definition\n" + - message: "Failed to read config: Validation Error\n• --> 1:1\n |\n1 | \"dsjfsjdfjdsfjkdskjfjkds\"\n | ^---\n |\n = expected type_system_definition\n" - request: method: POST url: http://localhost:8080/showcase/graphql?config=http%3A%2F%2Fexample.com%2Fsimple.graphql diff --git a/tests/http_spec.rs b/tests/http_spec.rs index e47baa5c99..6d6e8ad939 100644 --- a/tests/http_spec.rs +++ b/tests/http_spec.rs @@ -205,7 +205,7 @@ impl HttpSpec { let http_client = init_http(&Upstream::default(), None); let config = match self.config.clone() { ConfigSource::File(file) => { - let reader = ConfigReader::init(file_io, http_client); + let reader = ConfigReader::init(Some(file_io), http_client); reader.read_all(&[file]).await.unwrap() } ConfigSource::Inline(config) => ConfigSet::from(config), diff --git a/tests/server_spec.rs b/tests/server_spec.rs index 6f4fe775ab..b98d9abaf3 100644 --- a/tests/server_spec.rs +++ b/tests/server_spec.rs @@ -8,7 +8,7 @@ use tailcall::config::Upstream; async fn test_server(configs: &[&str], url: &str) { let file_io = init_file(); let http_client = init_http(&Upstream::default(), None); - let reader = ConfigReader::init(file_io, http_client); + let reader = ConfigReader::init(Some(file_io), http_client); let config = reader.read_all(configs).await.unwrap(); let mut server = Server::new(config); let server_up_receiver = server.server_up_receiver(); @@ -94,7 +94,7 @@ async fn server_start_http2_nokey() { let configs = &["tests/server/config/server-start-http2-nokey.graphql"]; let file_io = init_file(); let http_client = init_http(&Upstream::default(), None); - let reader = ConfigReader::init(file_io, http_client); + let reader = ConfigReader::init(Some(file_io), http_client); let config = reader.read_all(configs).await.unwrap(); let server = Server::new(config); assert!(server.start().await.is_err())