From 8ce66a9b815cc153ae88d2ae75ce047d7d815888 Mon Sep 17 00:00:00 2001 From: Jarrod Overson Date: Wed, 30 Aug 2023 11:38:24 -0400 Subject: [PATCH 1/2] fix: fixed config rendering within trigger operations --- .../wick-http-client/src/component.rs | 6 +- crates/components/wick-sql/src/common.rs | 2 +- crates/components/wick-sql/src/component.rs | 38 ++++---- .../wick-sql/src/mssql_tiberius/component.rs | 10 +- .../components/wick-sql/src/sqlx/component.rs | 10 +- crates/wick/flow-component/src/lib.rs | 19 ++++ .../wick/wick-config/src/config/app_config.rs | 91 +++++++++++++++++-- .../src/config/app_config/triggers.rs | 64 ++++++++++++- .../src/config/app_config/triggers/cli.rs | 14 +++ .../src/config/app_config/triggers/http.rs | 49 +++++++++- .../app_config/triggers/http/middleware.rs | 26 +++++- .../app_config/triggers/http/proxy_router.rs | 18 +++- .../app_config/triggers/http/raw_router.rs | 19 +++- .../app_config/triggers/http/rest_router.rs | 45 ++++++++- .../app_config/triggers/http/static_router.rs | 18 +++- .../src/config/app_config/triggers/time.rs | 14 +++ .../wick-config/src/config/common/bindings.rs | 11 +++ .../src/config/common/component_definition.rs | 13 +++ .../src/config/common/import_definition.rs | 30 ++++++ .../src/config/common/liquid_json_config.rs | 31 +++++++ .../src/config/common/resources.rs | 71 +++++---------- .../src/config/common/template_config.rs | 32 +++++++ .../src/config/component_config.rs | 10 +- .../wick-config/src/config/components/sql.rs | 79 ++++++++++------ crates/wick/wick-config/src/error.rs | 4 + crates/wick/wick-config/src/lib.rs | 2 + crates/wick/wick-config/src/utils.rs | 29 ++++++ crates/wick/wick-config/src/v1/conversions.rs | 16 ++-- src/commands/new/component/sql.rs | 10 +- 29 files changed, 635 insertions(+), 146 deletions(-) diff --git a/crates/components/wick-http-client/src/component.rs b/crates/components/wick-http-client/src/component.rs index 47ba9f96..4a935985 100644 --- a/crates/components/wick-http-client/src/component.rs +++ b/crates/components/wick-http-client/src/component.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::sync::Arc; -use flow_component::{BoxFuture, Component, ComponentError, RuntimeCallback}; +use flow_component::{BoxFuture, Component, ComponentError, IntoComponentResult, RuntimeCallback}; use futures::{Stream, StreamExt, TryStreamExt}; use reqwest::header::CONTENT_TYPE; use reqwest::{ClientBuilder, Method, Request, RequestBuilder}; @@ -44,8 +44,8 @@ impl HttpClientComponent { validate(&config, resolver)?; let addr: UrlResource = resolver(config.resource()) .and_then(|r| r.try_resource()) - .map_err(ComponentError::new)? - .into(); + .and_then(|r| r.try_url()) + .into_component_error()?; let mut sig = ComponentSignature::new("wick/component/http"); sig.metadata.version = metadata.map(|v| v.version().to_owned()); diff --git a/crates/components/wick-sql/src/common.rs b/crates/components/wick-sql/src/common.rs index 5e10fbd8..66f2da17 100644 --- a/crates/components/wick-sql/src/common.rs +++ b/crates/components/wick-sql/src/common.rs @@ -38,7 +38,7 @@ pub(crate) fn gen_signature( pub(crate) fn convert_url_resource(resolver: &Resolver, id: &str) -> Result { let addr = resolver(id).and_then(|r| r.try_resource())?; - let resource: UrlResource = addr.into(); + let resource: UrlResource = addr.try_into()?; resource.url().value().cloned().ok_or(Error::InvalidResourceConfig) } diff --git a/crates/components/wick-sql/src/component.rs b/crates/components/wick-sql/src/component.rs index 3f8c471f..1dae8cdf 100644 --- a/crates/components/wick-sql/src/component.rs +++ b/crates/components/wick-sql/src/component.rs @@ -9,7 +9,7 @@ use once_cell::sync::Lazy; use regex::{Captures, Regex}; use tracing::Span; use url::Url; -use wick_config::config::components::{ComponentConfig, OperationConfig, SqlComponentConfig, SqlOperationKind}; +use wick_config::config::components::{ComponentConfig, OperationConfig, SqlComponentConfig, SqlOperationDefinition}; use wick_config::config::{ErrorBehavior, Metadata}; use wick_config::Resolver; use wick_interface_types::{ComponentSignature, Field, OperationSignatures, Type}; @@ -228,7 +228,7 @@ fn validate(config: &SqlComponentConfig, _resolver: &Resolver) -> Result<(), Err async fn handle_call<'a, 'b, 'c>( connection: &'a mut Connection<'c>, - opdef: SqlOperationKind, + opdef: SqlOperationDefinition, input_streams: Vec, tx: PacketSender, stmt: &'b str, @@ -255,7 +255,7 @@ where async fn handle_stream<'a, 'b, 'c>( connection: &'a mut Connection<'c>, - opdef: SqlOperationKind, + opdef: SqlOperationDefinition, mut input_streams: Vec, tx: PacketSender, stmt: &'b str, @@ -304,10 +304,12 @@ where let start = SystemTime::now(); let result = match &opdef { - SqlOperationKind::Query(_) => { + SqlOperationDefinition::Query(_) => { query(connection, tx.clone(), opdef.clone(), type_wrappers, stmt, span.clone()).await } - SqlOperationKind::Exec(_) => exec(connection, tx.clone(), opdef.clone(), type_wrappers, stmt, span.clone()).await, + SqlOperationDefinition::Exec(_) => { + exec(connection, tx.clone(), opdef.clone(), type_wrappers, stmt, span.clone()).await + } }; let duration = SystemTime::now().duration_since(start).unwrap(); @@ -331,7 +333,7 @@ where async fn query<'a, 'b, 'c>( client: &'a mut Connection<'c>, tx: PacketSender, - def: SqlOperationKind, + def: SqlOperationDefinition, args: Vec<(Type, Packet)>, stmt: &'b str, _span: Span, @@ -360,7 +362,7 @@ where async fn exec<'a, 'b, 'c>( connection: &'a mut Connection<'c>, tx: PacketSender, - def: SqlOperationKind, + def: SqlOperationDefinition, args: Vec<(Type, Packet)>, stmt: &'b str, _span: Span, @@ -386,10 +388,10 @@ where static POSITIONAL_ARGS: Lazy = Lazy::new(|| Regex::new(r"\$(?\d+)\b").unwrap()); static WICK_ID_ARGS: Lazy = Lazy::new(|| Regex::new(r"\$\{(?\w+)\}").unwrap()); -fn normalize_operations(ops: &mut Vec, db: DbKind) { +fn normalize_operations(ops: &mut Vec, db: DbKind) { for operations in ops { match operations { - wick_config::config::components::SqlOperationKind::Query(ref mut op) => { + wick_config::config::components::SqlOperationDefinition::Query(ref mut op) => { let (mut query, args) = normalize_inline_ids(op.query(), op.arguments().to_vec()); if db == DbKind::Mssql { query = normalize_mssql_query(query); @@ -398,7 +400,7 @@ fn normalize_operations(ops: &mut Vec, db: DbKind) { op.set_query(query); op.set_arguments(args); } - wick_config::config::components::SqlOperationKind::Exec(ref mut op) => { + wick_config::config::components::SqlOperationDefinition::Exec(ref mut op) => { let (mut query, args) = normalize_inline_ids(op.exec(), op.arguments().to_vec()); if db == DbKind::Mssql { query = normalize_mssql_query(query); @@ -500,8 +502,8 @@ mod integration_test { use wick_config::config::components::{ ComponentConfig, SqlComponentConfigBuilder, - SqlOperationDefinitionBuilder, - SqlOperationKind, + SqlOperationDefinition, + SqlQueryOperationDefinitionBuilder, }; use wick_config::config::ResourceDefinition; use wick_interface_types::{Field, Type}; @@ -522,7 +524,7 @@ mod integration_test { .tls(false) .build() .unwrap(); - let op = SqlOperationDefinitionBuilder::default() + let op = SqlQueryOperationDefinitionBuilder::default() .name("test") .query("select id,name from users where id=$1;") .inputs([Field::new("input", Type::I32)]) @@ -531,7 +533,7 @@ mod integration_test { .build() .unwrap(); - config.operations_mut().push(SqlOperationKind::Query(op)); + config.operations_mut().push(SqlOperationDefinition::Query(op)); let mut app_config = wick_config::config::AppConfiguration::default(); app_config.add_resource( "db", @@ -578,7 +580,7 @@ mod integration_test { .tls(false) .build() .unwrap(); - let op = SqlOperationDefinitionBuilder::default() + let op = SqlQueryOperationDefinitionBuilder::default() .name("test") .query("select id,name from users where id=$1;") .inputs([Field::new("input", Type::I32)]) @@ -587,7 +589,7 @@ mod integration_test { .build() .unwrap(); - config.operations_mut().push(SqlOperationKind::Query(op)); + config.operations_mut().push(SqlOperationDefinition::Query(op)); let mut app_config = wick_config::config::AppConfiguration::default(); app_config.add_resource( "db", @@ -629,7 +631,7 @@ mod integration_test { .tls(false) .build() .unwrap(); - let op = SqlOperationDefinitionBuilder::default() + let op = SqlQueryOperationDefinitionBuilder::default() .name("test") .query("select id,name from users where id=$1;") .inputs([Field::new("input", Type::I32)]) @@ -638,7 +640,7 @@ mod integration_test { .build() .unwrap(); - config.operations_mut().push(SqlOperationKind::Query(op)); + config.operations_mut().push(SqlOperationDefinition::Query(op)); let mut app_config = wick_config::config::AppConfiguration::default(); app_config.add_resource( "db", diff --git a/crates/components/wick-sql/src/mssql_tiberius/component.rs b/crates/components/wick-sql/src/mssql_tiberius/component.rs index 042dda46..80ff4d7f 100644 --- a/crates/components/wick-sql/src/mssql_tiberius/component.rs +++ b/crates/components/wick-sql/src/mssql_tiberius/component.rs @@ -215,7 +215,11 @@ fn row_to_json(row: &Row) -> Value { #[cfg(test)] mod test { use anyhow::Result; - use wick_config::config::components::{SqlComponentConfigBuilder, SqlOperationDefinitionBuilder, SqlOperationKind}; + use wick_config::config::components::{ + SqlComponentConfigBuilder, + SqlOperationDefinition, + SqlQueryOperationDefinitionBuilder, + }; use wick_config::config::{ResourceDefinition, TcpPort}; use wick_interface_types::{Field, Type}; @@ -234,7 +238,7 @@ mod test { .tls(false) .build() .unwrap(); - let op = SqlOperationDefinitionBuilder::default() + let op = SqlQueryOperationDefinitionBuilder::default() .name("test") .query("select * from users where user_id = $1;") .inputs([Field::new("input", Type::I32)]) @@ -243,7 +247,7 @@ mod test { .build() .unwrap(); - config.operations_mut().push(SqlOperationKind::Query(op)); + config.operations_mut().push(SqlOperationDefinition::Query(op)); let mut app_config = wick_config::config::AppConfiguration::default(); app_config.add_resource("db", ResourceDefinition::TcpPort(TcpPort::new("0.0.0.0", 11111))); diff --git a/crates/components/wick-sql/src/sqlx/component.rs b/crates/components/wick-sql/src/sqlx/component.rs index 4c93af6e..04503538 100644 --- a/crates/components/wick-sql/src/sqlx/component.rs +++ b/crates/components/wick-sql/src/sqlx/component.rs @@ -221,7 +221,11 @@ async fn init_context(config: &SqlComponentConfig, addr: &Url) -> Result, } + impl std::error::Error for ComponentError {} impl std::fmt::Display for ComponentError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -142,6 +143,24 @@ impl From for ComponentError { } } +/// Trait that allows for conversion of a result into a component error. +pub trait IntoComponentResult +where + E: std::error::Error + Send + Sync + 'static, +{ + /// Convert a Result into a Result. + fn into_component_error(self) -> Result; +} + +impl IntoComponentResult for Result +where + E: std::error::Error + Send + Sync + 'static, +{ + fn into_component_error(self) -> Result { + self.map_err(ComponentError::new) + } +} + #[derive(Debug)] struct GenericError(String); impl std::error::Error for GenericError {} diff --git a/crates/wick/wick-config/src/config/app_config.rs b/crates/wick/wick-config/src/config/app_config.rs index c0a997f5..60228d22 100644 --- a/crates/wick/wick-config/src/config/app_config.rs +++ b/crates/wick/wick-config/src/config/app_config.rs @@ -214,14 +214,14 @@ impl AppConfiguration { pub(super) fn initialize(&mut self) -> Result<&Self> { // This pre-renders the application config's resources with access to the environment // so they're resulting value is intuitively based on where it was initially defined. - let root_config = self.root_config.clone(); + let root_config = self.root_config.as_ref(); trace!( num_resources = self.resources.len(), num_imports = self.import.len(), ?root_config, "initializing app resources" ); - let env = self.env.clone(); + let env = self.env.as_ref(); let mut bindings = Vec::new(); for (i, trigger) in self.triggers.iter_mut().enumerate() { @@ -229,12 +229,10 @@ impl AppConfiguration { } self.import.extend(bindings); - for resource in self.resources.iter_mut() { - resource.kind.render_config(root_config.as_ref(), env.as_ref())?; - } - for import in self.import.iter_mut() { - import.kind.render_config(root_config.as_ref(), env.as_ref())?; - } + self.resources.render_config(root_config, env)?; + self.import.render_config(root_config, env)?; + self.triggers.render_config(root_config, env)?; + Ok(self) } @@ -334,9 +332,82 @@ impl OwnedConfigurationItem { impl AppConfigurationBuilder { /// Build the configuration. - pub fn build(self) -> Result { - let config = self.build_internal()?; + pub fn build(&self) -> Result { + let config = self.clone(); + let config = config.build_internal()?; config.validate()?; Ok(config) } } + +#[cfg(test)] +mod test { + use anyhow::Result; + use serde_json::json; + + use super::*; + use crate::config::components::ManifestComponentBuilder; + use crate::config::{Codec, ComponentOperationExpressionBuilder, LiquidJsonConfig, MiddlewareBuilder}; + + #[test] + fn test_trigger_render() -> Result<()> { + let op = ComponentOperationExpressionBuilder::default() + .component(ComponentDefinition::Manifest( + ManifestComponentBuilder::default() + .reference("this/that:0.0.1") + .build()?, + )) + .config(LiquidJsonConfig::try_from( + json!({"op_config_field": "{{ctx.env.CARGO_MANIFEST_DIR}}"}), + )?) + .name("test") + .build()?; + let trigger = HttpTriggerConfigBuilder::default() + .resource("URL") + .routers(vec![HttpRouterConfig::RawRouter(RawRouterConfig { + path: "/".to_owned(), + middleware: Some( + MiddlewareBuilder::default() + .request(vec![op.clone()]) + .response(vec![op.clone()]) + .build()?, + ), + codec: Some(Codec::Json), + operation: op, + })]) + .build()?; + let mut config = AppConfigurationBuilder::default() + .name("test") + .resources(vec![ResourceBinding::new("PORT", TcpPort::new("0.0.0.0", 90))]) + .triggers(vec![TriggerDefinition::Http(trigger)]) + .build()?; + + config.env = Some(std::env::vars().collect()); + config.root_config = Some(json!({"config_val": "from_config"}).try_into()?); + + config.initialize()?; + + let TriggerDefinition::Http(mut trigger) = config.triggers.pop().unwrap() else { + unreachable!(); + }; + + let HttpRouterConfig::RawRouter(mut router) = trigger.routers.pop().unwrap() else { + unreachable!(); + }; + + let cargo_manifest_dir = json!(env!("CARGO_MANIFEST_DIR")); + + let config = router.operation.config.take().unwrap().value.unwrap(); + assert_eq!(config.get("op_config_field"), Some(&cargo_manifest_dir)); + + let mut mw = router.middleware.take().unwrap(); + + let mw_req_config = mw.request[0].config.take().unwrap().value.unwrap(); + assert_eq!(mw_req_config.get("op_config_field"), Some(&cargo_manifest_dir)); + + let mw_res_config = mw.response[0].config.take().unwrap().value.unwrap(); + assert_eq!(mw_res_config.get("op_config_field"), Some(&cargo_manifest_dir)); + + Ok(()) + } +} diff --git a/crates/wick/wick-config/src/config/app_config/triggers.rs b/crates/wick/wick-config/src/config/app_config/triggers.rs index f9a62243..07222e00 100644 --- a/crates/wick/wick-config/src/config/app_config/triggers.rs +++ b/crates/wick/wick-config/src/config/app_config/triggers.rs @@ -1,15 +1,57 @@ +use std::collections::HashMap; + use serde_json::Value; +use wick_asset_reference::AssetReference; +use wick_packet::RuntimeConfig; -use crate::config::*; use crate::error::ManifestError; use crate::ExpandImports; mod cli; mod http; mod time; -pub use cli::*; -pub use http::*; -pub use time::*; +pub use cli::{CliConfig, CliConfigBuilder, CliConfigBuilderError}; +pub use http::{ + Contact, + Documentation, + HttpRouterConfig, + HttpRouterKind, + HttpTriggerConfig, + HttpTriggerConfigBuilder, + HttpTriggerConfigBuilderError, + Info, + License, + Middleware, + MiddlewareBuilder, + MiddlewareBuilderError, + ProxyRouterConfig, + ProxyRouterConfigBuilder, + ProxyRouterConfigBuilderError, + RawRouterConfig, + RawRouterConfigBuilder, + RawRouterConfigBuilderError, + RestRoute, + RestRouterConfig, + RestRouterConfigBuilder, + RestRouterConfigBuilderError, + StaticRouterConfig, + StaticRouterConfigBuilder, + StaticRouterConfigBuilderError, + Tools, + WickRouter, +}; +pub use time::{ + ScheduleConfig, + ScheduleConfigBuilder, + ScheduleConfigBuilderError, + TimeTriggerConfig, + TimeTriggerConfigBuilder, + TimeTriggerConfigBuilderError, +}; + +use self::common::template_config::Renderable; +use self::common::ImportBinding; +use crate::config::common; #[derive(Debug, Clone, derive_asset_container::AssetManager, serde::Serialize)] #[asset(asset(AssetReference))] @@ -36,6 +78,20 @@ impl TriggerDefinition { } } +impl Renderable for TriggerDefinition { + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + match self { + TriggerDefinition::Cli(v) => v.render_config(root_config, env), + TriggerDefinition::Http(v) => v.render_config(root_config, env), + TriggerDefinition::Time(v) => v.render_config(root_config, env), + } + } +} + impl ExpandImports for TriggerDefinition { type Error = ManifestError; fn expand_imports(&mut self, bindings: &mut Vec, index: usize) -> Result<(), Self::Error> { diff --git a/crates/wick/wick-config/src/config/app_config/triggers/cli.rs b/crates/wick/wick-config/src/config/app_config/triggers/cli.rs index 2f8a4c8d..f236af6a 100644 --- a/crates/wick/wick-config/src/config/app_config/triggers/cli.rs +++ b/crates/wick/wick-config/src/config/app_config/triggers/cli.rs @@ -1,5 +1,9 @@ +use std::collections::HashMap; + use wick_asset_reference::AssetReference; +use wick_packet::RuntimeConfig; +use crate::config::template_config::Renderable; use crate::config::{ComponentOperationExpression, ImportBinding}; use crate::error::ManifestError; use crate::ExpandImports; @@ -30,3 +34,13 @@ impl ExpandImports for CliConfig { Ok(()) } } + +impl Renderable for CliConfig { + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + self.operation.render_config(root_config, env) + } +} diff --git a/crates/wick/wick-config/src/config/app_config/triggers/http.rs b/crates/wick/wick-config/src/config/app_config/triggers/http.rs index 380abc43..aa8b17a9 100644 --- a/crates/wick/wick-config/src/config/app_config/triggers/http.rs +++ b/crates/wick/wick-config/src/config/app_config/triggers/http.rs @@ -1,10 +1,24 @@ -pub use middleware::Middleware; +use std::collections::HashMap; + +pub use middleware::{Middleware, MiddlewareBuilder, MiddlewareBuilderError}; use wick_asset_reference::AssetReference; +use wick_packet::RuntimeConfig; -pub use self::proxy_router::ProxyRouterConfig; -pub use self::raw_router::RawRouterConfig; -pub use self::rest_router::{Contact, Documentation, Info, License, RestRoute, RestRouterConfig, Tools}; -pub use self::static_router::StaticRouterConfig; +pub use self::proxy_router::{ProxyRouterConfig, ProxyRouterConfigBuilder, ProxyRouterConfigBuilderError}; +pub use self::raw_router::{RawRouterConfig, RawRouterConfigBuilder, RawRouterConfigBuilderError}; +pub use self::rest_router::{ + Contact, + Documentation, + Info, + License, + RestRoute, + RestRouterConfig, + RestRouterConfigBuilder, + RestRouterConfigBuilderError, + Tools, +}; +pub use self::static_router::{StaticRouterConfig, StaticRouterConfigBuilder, StaticRouterConfigBuilderError}; +use crate::config::common::template_config::Renderable; use crate::config::ImportBinding; use crate::error::ManifestError; use crate::ExpandImports; @@ -44,6 +58,31 @@ pub enum HttpRouterConfig { ProxyRouter(ProxyRouterConfig), } +impl Renderable for HttpRouterConfig { + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + match self { + HttpRouterConfig::RawRouter(v) => v.render_config(root_config, env), + HttpRouterConfig::RestRouter(v) => v.render_config(root_config, env), + HttpRouterConfig::StaticRouter(v) => v.render_config(root_config, env), + HttpRouterConfig::ProxyRouter(v) => v.render_config(root_config, env), + } + } +} + +impl Renderable for HttpTriggerConfig { + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + self.routers.render_config(root_config, env) + } +} + impl ExpandImports for HttpTriggerConfig { type Error = ManifestError; fn expand_imports(&mut self, bindings: &mut Vec, trigger_index: usize) -> Result<(), Self::Error> { diff --git a/crates/wick/wick-config/src/config/app_config/triggers/http/middleware.rs b/crates/wick/wick-config/src/config/app_config/triggers/http/middleware.rs index 1c3cd3fd..c0e306a4 100644 --- a/crates/wick/wick-config/src/config/app_config/triggers/http/middleware.rs +++ b/crates/wick/wick-config/src/config/app_config/triggers/http/middleware.rs @@ -1,8 +1,21 @@ +use std::collections::HashMap; + +use wick_packet::RuntimeConfig; + use super::WickRouter; +use crate::config::template_config::Renderable; use crate::config::{self, ComponentOperationExpression, ImportBinding}; use crate::error::ManifestError; -#[derive(Debug, Clone, PartialEq, derive_asset_container::AssetManager, property::Property, serde::Serialize)] +#[derive( + Debug, + Clone, + derive_builder::Builder, + PartialEq, + derive_asset_container::AssetManager, + property::Property, + serde::Serialize, +)] #[property(get(public), set(private), mut(public, suffix = "_mut"))] #[asset(asset(config::AssetReference))] /// Request and response operations that run before and after the main operation. @@ -15,6 +28,17 @@ pub struct Middleware { pub(crate) response: Vec, } +impl Renderable for Middleware { + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + self.request.render_config(root_config, env)?; + self.response.render_config(root_config, env) + } +} + pub(super) fn expand_for_middleware_components( trigger_index: usize, router_index: usize, diff --git a/crates/wick/wick-config/src/config/app_config/triggers/http/proxy_router.rs b/crates/wick/wick-config/src/config/app_config/triggers/http/proxy_router.rs index 434d4adc..337a488c 100644 --- a/crates/wick/wick-config/src/config/app_config/triggers/http/proxy_router.rs +++ b/crates/wick/wick-config/src/config/app_config/triggers/http/proxy_router.rs @@ -1,11 +1,17 @@ +use std::collections::HashMap; + use wick_asset_reference::AssetReference; +use wick_packet::RuntimeConfig; use super::index_to_router_id; use super::middleware::expand_for_middleware_components; +use crate::config::template_config::Renderable; use crate::config::{self, ImportBinding}; use crate::error::ManifestError; -#[derive(Debug, Clone, derive_asset_container::AssetManager, property::Property, serde::Serialize)] +#[derive( + Debug, Clone, derive_builder::Builder, derive_asset_container::AssetManager, property::Property, serde::Serialize, +)] #[asset(asset(AssetReference))] #[property(get(public), set(private), mut(disable))] @@ -26,6 +32,16 @@ pub struct ProxyRouterConfig { pub(crate) strip_path: bool, } +impl Renderable for ProxyRouterConfig { + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + self.middleware.render_config(root_config, env) + } +} + impl super::WickRouter for ProxyRouterConfig { fn middleware(&self) -> Option<&super::Middleware> { self.middleware.as_ref() diff --git a/crates/wick/wick-config/src/config/app_config/triggers/http/raw_router.rs b/crates/wick/wick-config/src/config/app_config/triggers/http/raw_router.rs index f5a0f97b..dda854cf 100644 --- a/crates/wick/wick-config/src/config/app_config/triggers/http/raw_router.rs +++ b/crates/wick/wick-config/src/config/app_config/triggers/http/raw_router.rs @@ -1,11 +1,17 @@ +use std::collections::HashMap; + use wick_asset_reference::AssetReference; +use wick_packet::RuntimeConfig; use super::index_to_router_id; use super::middleware::expand_for_middleware_components; +use crate::config::template_config::Renderable; use crate::config::{self, ComponentOperationExpression, ImportBinding}; use crate::error::ManifestError; -#[derive(Debug, Clone, derive_asset_container::AssetManager, property::Property, serde::Serialize)] +#[derive( + Debug, Clone, derive_builder::Builder, derive_asset_container::AssetManager, property::Property, serde::Serialize, +)] #[asset(asset(AssetReference))] #[property(get(public), set(private), mut(public, suffix = "_mut"))] #[must_use] @@ -37,6 +43,17 @@ impl super::WickRouter for RawRouterConfig { } } +impl Renderable for RawRouterConfig { + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + self.operation.render_config(root_config, env)?; + self.middleware.render_config(root_config, env) + } +} + pub(crate) fn process_runtime_config( trigger_index: usize, index: usize, diff --git a/crates/wick/wick-config/src/config/app_config/triggers/http/rest_router.rs b/crates/wick/wick-config/src/config/app_config/triggers/http/rest_router.rs index aa785fed..80afc3bd 100644 --- a/crates/wick/wick-config/src/config/app_config/triggers/http/rest_router.rs +++ b/crates/wick/wick-config/src/config/app_config/triggers/http/rest_router.rs @@ -1,12 +1,24 @@ +use std::collections::HashMap; + use wick_asset_reference::AssetReference; +use wick_packet::RuntimeConfig; use super::index_to_router_id; use super::middleware::expand_for_middleware_components; use crate::config::common::HttpMethod; +use crate::config::template_config::Renderable; use crate::config::{self, ComponentOperationExpression, ImportBinding}; use crate::error::ManifestError; -#[derive(Debug, Clone, PartialEq, derive_asset_container::AssetManager, property::Property, serde::Serialize)] +#[derive( + Debug, + Clone, + PartialEq, + derive_builder::Builder, + derive_asset_container::AssetManager, + property::Property, + serde::Serialize, +)] #[asset(asset(AssetReference))] #[property(get(public), set(private), mut(public, suffix = "_mut"))] pub struct RestRouterConfig { @@ -31,6 +43,27 @@ pub struct RestRouterConfig { pub(crate) info: Option, } +impl Renderable for RestRouterConfig { + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + self.middleware.render_config(root_config, env)?; + self.routes.render_config(root_config, env) + } +} + +impl Renderable for RestRoute { + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + self.operation.render_config(root_config, env) + } +} + impl super::WickRouter for RestRouterConfig { fn middleware(&self) -> Option<&super::Middleware> { self.middleware.as_ref() @@ -116,7 +149,15 @@ pub struct Contact { pub(crate) email: Option, } -#[derive(Debug, Clone, PartialEq, derive_asset_container::AssetManager, property::Property, serde::Serialize)] +#[derive( + Debug, + Clone, + PartialEq, + derive_builder::Builder, + derive_asset_container::AssetManager, + property::Property, + serde::Serialize, +)] #[asset(asset(AssetReference))] #[property(get(public), set(private), mut(public, suffix = "_mut"))] /// A route to serve and the operation that handles it. diff --git a/crates/wick/wick-config/src/config/app_config/triggers/http/static_router.rs b/crates/wick/wick-config/src/config/app_config/triggers/http/static_router.rs index a644075c..b0f04f61 100644 --- a/crates/wick/wick-config/src/config/app_config/triggers/http/static_router.rs +++ b/crates/wick/wick-config/src/config/app_config/triggers/http/static_router.rs @@ -1,11 +1,17 @@ +use std::collections::HashMap; + use wick_asset_reference::AssetReference; +use wick_packet::RuntimeConfig; use super::index_to_router_id; use super::middleware::expand_for_middleware_components; +use crate::config::template_config::Renderable; use crate::config::{self, ImportBinding}; use crate::error::ManifestError; -#[derive(Debug, Clone, derive_asset_container::AssetManager, property::Property, serde::Serialize)] +#[derive( + Debug, Clone, derive_builder::Builder, derive_asset_container::AssetManager, property::Property, serde::Serialize, +)] #[asset(asset(AssetReference))] #[property(get(public), set(private), mut(disable))] #[must_use] @@ -38,6 +44,16 @@ impl super::WickRouter for StaticRouterConfig { } } +impl Renderable for StaticRouterConfig { + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + self.middleware.render_config(root_config, env) + } +} + pub(crate) fn process_runtime_config( trigger_index: usize, index: usize, diff --git a/crates/wick/wick-config/src/config/app_config/triggers/time.rs b/crates/wick/wick-config/src/config/app_config/triggers/time.rs index e00a341d..78d26c05 100644 --- a/crates/wick/wick-config/src/config/app_config/triggers/time.rs +++ b/crates/wick/wick-config/src/config/app_config/triggers/time.rs @@ -1,6 +1,10 @@ +use std::collections::HashMap; + use wick_asset_reference::AssetReference; +use wick_packet::RuntimeConfig; use super::OperationInputConfig; +use crate::config::template_config::Renderable; use crate::config::{ComponentOperationExpression, ImportBinding}; use crate::error::ManifestError; use crate::ExpandImports; @@ -27,6 +31,16 @@ pub struct TimeTriggerConfig { pub(crate) payload: Vec, } +impl Renderable for TimeTriggerConfig { + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + self.operation.render_config(root_config, env) + } +} + #[derive( Debug, Clone, diff --git a/crates/wick/wick-config/src/config/common/bindings.rs b/crates/wick/wick-config/src/config/common/bindings.rs index 4bff12fd..f3fc06b3 100644 --- a/crates/wick/wick-config/src/config/common/bindings.rs +++ b/crates/wick/wick-config/src/config/common/bindings.rs @@ -4,6 +4,7 @@ use std::collections::HashMap; use wick_packet::RuntimeConfig; +use super::template_config::Renderable; use super::{ComponentDefinition, HighLevelComponent, ImportDefinition, InterfaceDefinition}; use crate::config::components::WasmComponent; use crate::config::{self}; @@ -21,6 +22,16 @@ pub struct ImportBinding { pub(crate) kind: ImportDefinition, } +impl Renderable for ImportBinding { + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), crate::error::ManifestError> { + self.kind.render_config(root_config, env) + } +} + impl ImportBinding { /// Create a new [ImportBinding] with specified name and [ImportDefinition]. pub fn new(name: impl AsRef, kind: ImportDefinition) -> Self { diff --git a/crates/wick/wick-config/src/config/common/component_definition.rs b/crates/wick/wick-config/src/config/common/component_definition.rs index e15cbe1c..ca83b584 100644 --- a/crates/wick/wick-config/src/config/common/component_definition.rs +++ b/crates/wick/wick-config/src/config/common/component_definition.rs @@ -98,6 +98,19 @@ impl ComponentOperationExpression { } } +impl Renderable for ComponentOperationExpression { + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + if let Some(config) = self.config.as_mut() { + config.set_value(Some(config.render(root_config, None, env, None)?)); + } + Ok(()) + } +} + impl std::str::FromStr for ComponentOperationExpression { type Err = crate::Error; diff --git a/crates/wick/wick-config/src/config/common/import_definition.rs b/crates/wick/wick-config/src/config/common/import_definition.rs index 1b4911df..07832668 100644 --- a/crates/wick/wick-config/src/config/common/import_definition.rs +++ b/crates/wick/wick-config/src/config/common/import_definition.rs @@ -18,6 +18,9 @@ pub enum ImportDefinition { Types(config::components::TypesComponent), } +crate::impl_from_for!(ImportDefinition, Component, config::ComponentDefinition); +crate::impl_from_for!(ImportDefinition, Types, config::components::TypesComponent); + impl ImportDefinition { /// Returns true if the definition is a reference to another component. #[must_use] @@ -36,6 +39,33 @@ impl ImportDefinition { ImportDefinition::Types(_) => None, } } + + /// Get the configuration kind for this import. + #[must_use] + pub fn kind(&self) -> ImportKind { + match self { + ImportDefinition::Component(_) => ImportKind::Component, + ImportDefinition::Types(_) => ImportKind::Types, + } + } +} + +/// The kind of import an [ImportDefinition] is. +#[derive(Debug, Clone, Copy)] +pub enum ImportKind { + /// A component import. + Component, + /// A types import. + Types, +} + +impl std::fmt::Display for ImportKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ImportKind::Component => write!(f, "component"), + ImportKind::Types => write!(f, "types"), + } + } } impl Renderable for ImportDefinition { diff --git a/crates/wick/wick-config/src/config/common/liquid_json_config.rs b/crates/wick/wick-config/src/config/common/liquid_json_config.rs index f9d7bb25..b32b489a 100644 --- a/crates/wick/wick-config/src/config/common/liquid_json_config.rs +++ b/crates/wick/wick-config/src/config/common/liquid_json_config.rs @@ -103,6 +103,15 @@ impl LiquidJsonConfig { } } + #[must_use] + pub fn new_template(template: HashMap) -> Self { + Self { + value: None, + template, + root_config: None, + } + } + #[must_use] /// Retrieve the runtime configuration pub fn value(&self) -> Option<&RuntimeConfig> { @@ -140,3 +149,25 @@ impl From for HashMap { value.template } } + +impl TryFrom for LiquidJsonConfig { + type Error = Error; + + fn try_from(value: Value) -> Result { + let value = match value { + Value::Object(map) => map, + _ => return Err(Error::ConfigurationTemplate("expected object".to_owned())), + }; + + let mut template = HashMap::new(); + for (k, v) in value { + template.insert(k, v.into()); + } + + Ok(Self { + value: None, + template, + root_config: None, + }) + } +} diff --git a/crates/wick/wick-config/src/config/common/resources.rs b/crates/wick/wick-config/src/config/common/resources.rs index 49e3f734..f30d77fa 100644 --- a/crates/wick/wick-config/src/config/common/resources.rs +++ b/crates/wick/wick-config/src/config/common/resources.rs @@ -8,22 +8,12 @@ use wick_packet::RuntimeConfig; use super::template_config::Renderable; use crate::config::TemplateConfig; -use crate::error::{ManifestError, ReferenceError}; - -macro_rules! try_kind { - ($self:ident, $kind:ident) => { - match $self { - ResourceDefinition::$kind(v) => Ok(v), - _ => Err( - ReferenceError::ResourceType { - expected: ResourceKind::$kind, - actual: $self.kind(), - } - .into(), - ), - } - }; -} +use crate::error::ManifestError; + +crate::impl_from_for!(ResourceDefinition, TcpPort); +crate::impl_from_for!(ResourceDefinition, UdpPort); +crate::impl_from_for!(ResourceDefinition, Volume); +crate::impl_from_for!(ResourceDefinition, Url, UrlResource); #[derive( Debug, Clone, derive_builder::Builder, derive_asset_container::AssetManager, property::Property, serde::Serialize, @@ -41,12 +31,22 @@ pub struct ResourceBinding { pub(crate) kind: ResourceDefinition, } +impl Renderable for ResourceBinding { + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + self.kind.render_config(root_config, env) + } +} + impl ResourceBinding { /// Create a new [ResourceBinding] with specified name and [ResourceDefinition]. - pub fn new(name: impl AsRef, kind: ResourceDefinition) -> Self { + pub fn new(name: impl AsRef, kind: impl Into) -> Self { Self { id: name.as_ref().to_owned(), - kind, + kind: kind.into(), } } } @@ -116,46 +116,19 @@ impl ResourceDefinition { } pub fn try_tcpport(self) -> Result { - try_kind!(self, TcpPort) + self.try_into() } pub fn try_udpport(self) -> Result { - try_kind!(self, UdpPort) + self.try_into() } pub fn try_url(self) -> Result { - try_kind!(self, Url) + self.try_into() } pub fn try_volume(self) -> Result { - try_kind!(self, Volume) - } -} - -impl From for TcpPort { - fn from(value: ResourceDefinition) -> Self { - match value { - ResourceDefinition::TcpPort(v) => v, - _ => panic!("Cannot convert non-tcp port to tcp port"), - } - } -} - -impl From for UdpPort { - fn from(value: ResourceDefinition) -> Self { - match value { - ResourceDefinition::UdpPort(v) => v, - _ => panic!("Cannot convert non-udp port to udp port"), - } - } -} - -impl From for UrlResource { - fn from(value: ResourceDefinition) -> Self { - match value { - ResourceDefinition::Url(v) => v, - _ => panic!("Cannot convert non-URL resource to URL"), - } + self.try_into() } } diff --git a/crates/wick/wick-config/src/config/common/template_config.rs b/crates/wick/wick-config/src/config/common/template_config.rs index a2d5505e..bef546d1 100644 --- a/crates/wick/wick-config/src/config/common/template_config.rs +++ b/crates/wick/wick-config/src/config/common/template_config.rs @@ -166,3 +166,35 @@ pub(crate) trait Renderable { env: Option<&HashMap>, ) -> Result<(), ManifestError>; } + +impl Renderable for Option +where + T: Renderable, +{ + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + if let Some(v) = self { + v.render_config(root_config, env)?; + } + Ok(()) + } +} + +impl Renderable for Vec +where + T: Renderable, +{ + fn render_config( + &mut self, + root_config: Option<&RuntimeConfig>, + env: Option<&HashMap>, + ) -> Result<(), ManifestError> { + for el in self.iter_mut() { + el.render_config(root_config, env)?; + } + Ok(()) + } +} diff --git a/crates/wick/wick-config/src/config/component_config.rs b/crates/wick/wick-config/src/config/component_config.rs index 918a6191..4337f913 100644 --- a/crates/wick/wick-config/src/config/component_config.rs +++ b/crates/wick/wick-config/src/config/component_config.rs @@ -283,7 +283,7 @@ impl ComponentConfiguration { /// Initialize the configuration. pub(super) fn initialize(&mut self) -> Result<&Self> { // This pre-renders the component config's resources without access to the environment. - let root_config = self.root_config.clone(); + let root_config = self.root_config.as_ref(); trace!( num_resources = self.resources.len(), num_imports = self.import.len(), @@ -291,12 +291,8 @@ impl ComponentConfiguration { "initializing component" ); - for resource in self.resources.iter_mut() { - resource.kind.render_config(root_config.as_ref(), None)?; - } - for import in self.import.iter_mut() { - import.kind.render_config(root_config.as_ref(), None)?; - } + self.resources.render_config(root_config, None)?; + self.import.render_config(root_config, None)?; Ok(self) } diff --git a/crates/wick/wick-config/src/config/components/sql.rs b/crates/wick/wick-config/src/config/components/sql.rs index 3691c260..f465222c 100644 --- a/crates/wick/wick-config/src/config/components/sql.rs +++ b/crates/wick/wick-config/src/config/components/sql.rs @@ -6,6 +6,7 @@ use wick_interface_types::{Field, OperationSignatures}; use super::{ComponentConfig, OperationConfig}; use crate::config::{self, ErrorBehavior}; +use crate::utils::impl_from_for; #[derive( Debug, @@ -41,7 +42,7 @@ pub struct SqlComponentConfig { #[builder(default)] #[property(skip)] #[serde(skip_serializing_if = "Vec::is_empty")] - pub(crate) operations: Vec, + pub(crate) operations: Vec, } impl SqlComponentConfig {} @@ -52,17 +53,20 @@ impl OperationSignatures for SqlComponentConfig { } } -impl From for wick_interface_types::OperationSignature { - fn from(value: SqlOperationKind) -> Self { +impl_from_for!(SqlOperationDefinition, Query, SqlQueryOperationDefinition); +impl_from_for!(SqlOperationDefinition, Exec, SqlExecOperationDefinition); + +impl From for wick_interface_types::OperationSignature { + fn from(value: SqlOperationDefinition) -> Self { match value { - SqlOperationKind::Query(v) => v.into(), - SqlOperationKind::Exec(v) => v.into(), + SqlOperationDefinition::Query(v) => v.into(), + SqlOperationDefinition::Exec(v) => v.into(), } } } impl ComponentConfig for SqlComponentConfig { - type Operation = SqlOperationKind; + type Operation = SqlOperationDefinition; fn operations(&self) -> &[Self::Operation] { &self.operations @@ -75,61 +79,84 @@ impl ComponentConfig for SqlComponentConfig { #[derive(Debug, Clone, PartialEq, serde::Serialize)] #[serde(rename_all = "kebab-case")] -pub enum SqlOperationKind { - Query(SqlOperationDefinition), +pub enum SqlOperationDefinition { + Query(SqlQueryOperationDefinition), Exec(SqlExecOperationDefinition), } -impl SqlOperationKind { +#[derive(Debug, Clone, Copy)] +pub enum SqlOperationKind { + Query, + Exec, +} + +impl std::fmt::Display for SqlOperationKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + SqlOperationKind::Query => write!(f, "sql query operation"), + SqlOperationKind::Exec => write!(f, "sql exec operation"), + } + } +} + +impl SqlOperationDefinition { #[must_use] pub fn on_error(&self) -> ErrorBehavior { match self { - SqlOperationKind::Query(v) => v.on_error, - SqlOperationKind::Exec(v) => v.on_error, + SqlOperationDefinition::Query(v) => v.on_error, + SqlOperationDefinition::Exec(v) => v.on_error, } } #[must_use] pub fn arguments(&self) -> &[String] { match self { - SqlOperationKind::Query(v) => &v.arguments, - SqlOperationKind::Exec(v) => &v.arguments, + SqlOperationDefinition::Query(v) => &v.arguments, + SqlOperationDefinition::Exec(v) => &v.arguments, } } #[must_use] pub fn query(&self) -> &str { match self { - SqlOperationKind::Query(v) => &v.query, - SqlOperationKind::Exec(v) => &v.exec, + SqlOperationDefinition::Query(v) => &v.query, + SqlOperationDefinition::Exec(v) => &v.exec, + } + } + + #[must_use] + pub fn kind(&self) -> SqlOperationKind { + match self { + SqlOperationDefinition::Query(_) => SqlOperationKind::Query, + SqlOperationDefinition::Exec(_) => SqlOperationKind::Exec, } } } -impl OperationConfig for SqlOperationKind { +impl OperationConfig for SqlOperationDefinition { fn name(&self) -> &str { match self { - SqlOperationKind::Query(v) => &v.name, - SqlOperationKind::Exec(v) => &v.name, + SqlOperationDefinition::Query(v) => &v.name, + SqlOperationDefinition::Exec(v) => &v.name, } } fn inputs(&self) -> Cow> { match self { - SqlOperationKind::Query(v) => v.inputs(), - SqlOperationKind::Exec(v) => v.inputs(), + SqlOperationDefinition::Query(v) => v.inputs(), + SqlOperationDefinition::Exec(v) => v.inputs(), } } fn outputs(&self) -> Cow> { match self { - SqlOperationKind::Query(v) => v.outputs(), - SqlOperationKind::Exec(v) => v.outputs(), + SqlOperationDefinition::Query(v) => v.outputs(), + SqlOperationDefinition::Exec(v) => v.outputs(), } } } -impl OperationConfig for SqlOperationDefinition { +impl OperationConfig for SqlQueryOperationDefinition { fn name(&self) -> &str { &self.name } @@ -157,8 +184,8 @@ impl OperationConfig for SqlExecOperationDefinition { } } -impl From for wick_interface_types::OperationSignature { - fn from(operation: SqlOperationDefinition) -> Self { +impl From for wick_interface_types::OperationSignature { + fn from(operation: SqlQueryOperationDefinition) -> Self { // TODO: Properly use configured outputs here. // Forcing SQL components to have a single object output called "output" is a temporary // limitation @@ -198,7 +225,7 @@ impl From for wick_interface_types::OperationSignatu #[asset(asset(config::AssetReference))] #[builder(setter(into))] /// An operation whose implementation is a SQL query to execute on a database. -pub struct SqlOperationDefinition { +pub struct SqlQueryOperationDefinition { /// The name of the operation. #[asset(skip)] #[property(skip)] diff --git a/crates/wick/wick-config/src/error.rs b/crates/wick/wick-config/src/error.rs index ec166149..2017ab3a 100644 --- a/crates/wick/wick-config/src/error.rs +++ b/crates/wick/wick-config/src/error.rs @@ -85,6 +85,10 @@ pub enum ManifestError { #[error(transparent)] TypeParser(#[from] wick_interface_types::ParserError), + /// Error converting an enum to a specific variant. + #[error("could not convert a {0} into a {1}")] + VariantError(String, String), + /// Error parsing YAML as a string. #[error("Error parsing YAML as a string")] Utf8, diff --git a/crates/wick/wick-config/src/lib.rs b/crates/wick/wick-config/src/lib.rs index 71776e66..2305a796 100644 --- a/crates/wick/wick-config/src/lib.rs +++ b/crates/wick/wick-config/src/lib.rs @@ -105,6 +105,8 @@ pub mod config; pub mod error; mod utils; +pub(crate) use utils::impl_from_for; + /// Wick Manifest v0 implementation. #[cfg(feature = "v0")] pub mod v0; diff --git a/crates/wick/wick-config/src/utils.rs b/crates/wick/wick-config/src/utils.rs index 58f5fa44..991d01c3 100644 --- a/crates/wick/wick-config/src/utils.rs +++ b/crates/wick/wick-config/src/utils.rs @@ -17,6 +17,35 @@ pub(crate) fn opt_str_to_ipv4addr(v: &Option) -> Result }) } +/// Utility macro for implementing `From` for a type. +macro_rules! impl_from_for { + ($root:ident, $variant: ident, $type:ty) => { + impl From<$type> for $root { + fn from(value: $type) -> Self { + Self::$variant(value) + } + } + #[allow(unused_qualifications)] + impl TryFrom<$root> for $type { + type Error = crate::error::ManifestError; + fn try_from(value: $root) -> std::result::Result { + match value { + $root::$variant(value) => Ok(value), + _ => Err(Self::Error::VariantError( + value.kind().to_string(), + stringify!($type).to_owned(), + )), + } + } + } + }; + ($root:ident, $variant: ident) => { + crate::impl_from_for!($root, $variant, $variant); + }; +} +// has to be specified after the macro; +pub(crate) use impl_from_for; + pub(crate) trait VecTryMapInto { fn try_map_into(self) -> Result> where diff --git a/crates/wick/wick-config/src/v1/conversions.rs b/crates/wick/wick-config/src/v1/conversions.rs index b8383934..bfcea2b7 100644 --- a/crates/wick/wick-config/src/v1/conversions.rs +++ b/crates/wick/wick-config/src/v1/conversions.rs @@ -1200,7 +1200,7 @@ impl TryFrom for components::SqlComponentConfig { } } -impl TryFrom for components::SqlOperationKind { +impl TryFrom for components::SqlOperationDefinition { type Error = crate::Error; fn try_from(value: v1::SqlQueryKind) -> Result { Ok(match value { @@ -1210,7 +1210,7 @@ impl TryFrom for components::SqlOperationKind { } } -impl TryFrom for components::SqlOperationDefinition { +impl TryFrom for components::SqlQueryOperationDefinition { type Error = crate::Error; fn try_from(value: v1::SqlQueryOperationDefinition) -> Result { Ok(Self { @@ -1302,20 +1302,20 @@ impl TryFrom for v1::SqlComponent { } } -impl TryFrom for v1::SqlQueryKind { +impl TryFrom for v1::SqlQueryKind { type Error = crate::Error; - fn try_from(value: components::SqlOperationKind) -> std::result::Result { + fn try_from(value: components::SqlOperationDefinition) -> std::result::Result { Ok(match value { - components::SqlOperationKind::Query(v) => Self::SqlQueryOperationDefinition(v.try_into()?), - components::SqlOperationKind::Exec(v) => Self::SqlExecOperationDefinition(v.try_into()?), + components::SqlOperationDefinition::Query(v) => Self::SqlQueryOperationDefinition(v.try_into()?), + components::SqlOperationDefinition::Exec(v) => Self::SqlExecOperationDefinition(v.try_into()?), }) } } -impl TryFrom for v1::SqlQueryOperationDefinition { +impl TryFrom for v1::SqlQueryOperationDefinition { type Error = crate::Error; - fn try_from(value: components::SqlOperationDefinition) -> Result { + fn try_from(value: components::SqlQueryOperationDefinition) -> Result { Ok(Self { name: value.name, inputs: value.inputs.try_map_into()?, diff --git a/src/commands/new/component/sql.rs b/src/commands/new/component/sql.rs index e3bb6177..9d6174ae 100644 --- a/src/commands/new/component/sql.rs +++ b/src/commands/new/component/sql.rs @@ -1,7 +1,11 @@ use anyhow::Result; use clap::Args; use structured_output::StructuredOutput; -use wick_config::config::components::{SqlComponentConfigBuilder, SqlOperationDefinitionBuilder, SqlOperationKind}; +use wick_config::config::components::{ + SqlComponentConfigBuilder, + SqlOperationDefinition, + SqlQueryOperationDefinitionBuilder, +}; use wick_config::config::{self, ComponentConfiguration}; use wick_interface_types::{Field, Type}; @@ -43,8 +47,8 @@ pub(crate) async fn handle( let component = SqlComponentConfigBuilder::default() .resource(resource_name) - .operations([SqlOperationKind::Query( - SqlOperationDefinitionBuilder::default() + .operations([SqlOperationDefinition::Query( + SqlQueryOperationDefinitionBuilder::default() .name("example_query".to_owned()) .inputs([Field::new("id", Type::String)]) .query("SELECT * FROM users WHERE id = $1".to_owned()) From fd1e75eb7ce257ba479c3c9a3aa0c5df6cc7b2fc Mon Sep 17 00:00:00 2001 From: Jarrod Overson Date: Wed, 30 Aug 2023 11:38:40 -0400 Subject: [PATCH 2/2] chore: updated gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 21ace433..75657b32 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ crates/wick-rpc/src/generated/wick.rs crates/**/src/generated/mod.rs /crates/integration/*/build docs/static/rustdoc/ +/dump # Test & scratch files .wick-test.sqlite3.db