community: trim premium backend surfaces
This commit is contained in:
Generated
-104
@@ -10,11 +10,8 @@ dependencies = [
|
|||||||
"axum",
|
"axum",
|
||||||
"axum-extra",
|
"axum-extra",
|
||||||
"base64",
|
"base64",
|
||||||
"crank-adapter-grpc",
|
|
||||||
"crank-adapter-soap",
|
|
||||||
"crank-core",
|
"crank-core",
|
||||||
"crank-mapping",
|
"crank-mapping",
|
||||||
"crank-proto",
|
|
||||||
"crank-registry",
|
"crank-registry",
|
||||||
"crank-runtime",
|
"crank-runtime",
|
||||||
"crank-schema",
|
"crank-schema",
|
||||||
@@ -383,20 +380,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crank-adapter-graphql"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"axum",
|
|
||||||
"crank-core",
|
|
||||||
"crank-mapping",
|
|
||||||
"reqwest",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"thiserror",
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crank-adapter-grpc"
|
name = "crank-adapter-grpc"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -432,35 +415,6 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crank-adapter-soap"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"axum",
|
|
||||||
"crank-core",
|
|
||||||
"crank-mapping",
|
|
||||||
"reqwest",
|
|
||||||
"roxmltree",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"thiserror",
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crank-adapter-websocket"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"crank-core",
|
|
||||||
"futures-util",
|
|
||||||
"reqwest",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"thiserror",
|
|
||||||
"tokio",
|
|
||||||
"tokio-tungstenite",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crank-core"
|
name = "crank-core"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -521,11 +475,7 @@ dependencies = [
|
|||||||
"async-trait",
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
"base64",
|
"base64",
|
||||||
"crank-adapter-graphql",
|
|
||||||
"crank-adapter-grpc",
|
|
||||||
"crank-adapter-rest",
|
"crank-adapter-rest",
|
||||||
"crank-adapter-soap",
|
|
||||||
"crank-adapter-websocket",
|
|
||||||
"crank-core",
|
"crank-core",
|
||||||
"crank-mapping",
|
"crank-mapping",
|
||||||
"crank-schema",
|
"crank-schema",
|
||||||
@@ -538,7 +488,6 @@ dependencies = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
"time",
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-tungstenite",
|
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
@@ -604,12 +553,6 @@ dependencies = [
|
|||||||
"cipher",
|
"cipher",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "data-encoding"
|
|
||||||
version = "2.10.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "der"
|
name = "der"
|
||||||
version = "0.7.10"
|
version = "0.7.10"
|
||||||
@@ -2160,12 +2103,6 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "roxmltree"
|
|
||||||
version = "0.20.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rsa"
|
name = "rsa"
|
||||||
version = "0.9.10"
|
version = "0.9.10"
|
||||||
@@ -2894,22 +2831,6 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-tungstenite"
|
|
||||||
version = "0.26.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084"
|
|
||||||
dependencies = [
|
|
||||||
"futures-util",
|
|
||||||
"log",
|
|
||||||
"rustls",
|
|
||||||
"rustls-pki-types",
|
|
||||||
"tokio",
|
|
||||||
"tokio-rustls",
|
|
||||||
"tungstenite",
|
|
||||||
"webpki-roots 0.26.11",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.7.18"
|
version = "0.7.18"
|
||||||
@@ -3108,25 +3029,6 @@ version = "0.2.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tungstenite"
|
|
||||||
version = "0.26.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"data-encoding",
|
|
||||||
"http",
|
|
||||||
"httparse",
|
|
||||||
"log",
|
|
||||||
"rand 0.9.2",
|
|
||||||
"rustls",
|
|
||||||
"rustls-pki-types",
|
|
||||||
"sha1",
|
|
||||||
"thiserror",
|
|
||||||
"utf-8",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.19.0"
|
version = "1.19.0"
|
||||||
@@ -3206,12 +3108,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "utf-8"
|
|
||||||
version = "0.7.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8_iter"
|
name = "utf8_iter"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ members = [
|
|||||||
"crates/crank-registry",
|
"crates/crank-registry",
|
||||||
"crates/crank-runtime",
|
"crates/crank-runtime",
|
||||||
"crates/crank-adapter-rest",
|
"crates/crank-adapter-rest",
|
||||||
"crates/crank-adapter-graphql",
|
|
||||||
"crates/crank-adapter-grpc",
|
|
||||||
"crates/crank-adapter-websocket",
|
|
||||||
"crates/crank-adapter-soap",
|
|
||||||
]
|
]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
|
|
||||||
|
|||||||
@@ -10,11 +10,8 @@ argon2.workspace = true
|
|||||||
axum.workspace = true
|
axum.workspace = true
|
||||||
axum-extra.workspace = true
|
axum-extra.workspace = true
|
||||||
base64.workspace = true
|
base64.workspace = true
|
||||||
crank-adapter-grpc = { path = "../../crates/crank-adapter-grpc", features = ["test-support"] }
|
|
||||||
crank-adapter-soap = { path = "../../crates/crank-adapter-soap" }
|
|
||||||
crank-core = { path = "../../crates/crank-core" }
|
crank-core = { path = "../../crates/crank-core" }
|
||||||
crank-mapping = { path = "../../crates/crank-mapping" }
|
crank-mapping = { path = "../../crates/crank-mapping" }
|
||||||
crank-proto = { path = "../../crates/crank-proto" }
|
|
||||||
crank-registry = { path = "../../crates/crank-registry" }
|
crank-registry = { path = "../../crates/crank-registry" }
|
||||||
crank-runtime = { path = "../../crates/crank-runtime" }
|
crank-runtime = { path = "../../crates/crank-runtime" }
|
||||||
crank-schema = { path = "../../crates/crank-schema" }
|
crank-schema = { path = "../../crates/crank-schema" }
|
||||||
|
|||||||
@@ -29,9 +29,8 @@ use crate::{
|
|||||||
operations::{
|
operations::{
|
||||||
archive_operation, create_operation, create_version, delete_operation,
|
archive_operation, create_operation, create_version, delete_operation,
|
||||||
export_operation, generate_draft, get_operation, get_operation_version,
|
export_operation, generate_draft, get_operation, get_operation_version,
|
||||||
list_grpc_services, list_operations, list_soap_services, publish_operation, run_test,
|
list_operations, publish_operation, run_test, update_operation, upload_input_json,
|
||||||
update_operation, upload_descriptor_set, upload_input_json, upload_output_json,
|
upload_output_json,
|
||||||
upload_proto_descriptor, upload_wsdl_descriptor, upload_xsd_descriptor,
|
|
||||||
},
|
},
|
||||||
secrets::{create_secret, delete_secret, get_secret, list_secrets, rotate_secret},
|
secrets::{create_secret, delete_secret, get_secret, list_secrets, rotate_secret},
|
||||||
streaming::{
|
streaming::{
|
||||||
@@ -75,30 +74,6 @@ pub fn build_app(state: AppState) -> Router {
|
|||||||
"/operations/{operation_id}/samples/output-json",
|
"/operations/{operation_id}/samples/output-json",
|
||||||
post(upload_output_json),
|
post(upload_output_json),
|
||||||
)
|
)
|
||||||
.route(
|
|
||||||
"/operations/{operation_id}/descriptors/proto",
|
|
||||||
post(upload_proto_descriptor),
|
|
||||||
)
|
|
||||||
.route(
|
|
||||||
"/operations/{operation_id}/descriptors/descriptor-set",
|
|
||||||
post(upload_descriptor_set),
|
|
||||||
)
|
|
||||||
.route(
|
|
||||||
"/operations/{operation_id}/descriptors/wsdl",
|
|
||||||
post(upload_wsdl_descriptor),
|
|
||||||
)
|
|
||||||
.route(
|
|
||||||
"/operations/{operation_id}/descriptors/xsd",
|
|
||||||
post(upload_xsd_descriptor),
|
|
||||||
)
|
|
||||||
.route(
|
|
||||||
"/operations/{operation_id}/grpc/services",
|
|
||||||
get(list_grpc_services),
|
|
||||||
)
|
|
||||||
.route(
|
|
||||||
"/operations/{operation_id}/soap/services",
|
|
||||||
get(list_soap_services),
|
|
||||||
)
|
|
||||||
.route(
|
.route(
|
||||||
"/operations/{operation_id}/drafts/generate",
|
"/operations/{operation_id}/drafts/generate",
|
||||||
post(generate_draft),
|
post(generate_draft),
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use axum::{
|
use axum::{
|
||||||
Json,
|
Json,
|
||||||
body::Bytes,
|
|
||||||
extract::{Extension, Path, Query, State},
|
extract::{Extension, Path, Query, State},
|
||||||
http::{HeaderMap, StatusCode, header},
|
http::{HeaderMap, StatusCode, header},
|
||||||
response::IntoResponse,
|
response::IntoResponse,
|
||||||
@@ -232,118 +231,6 @@ pub async fn upload_output_json(
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn upload_proto_descriptor(
|
|
||||||
Path(path): Path<WorkspaceOperationPath>,
|
|
||||||
State(state): State<AppState>,
|
|
||||||
headers: HeaderMap,
|
|
||||||
body: Bytes,
|
|
||||||
) -> Result<Json<Value>, ApiError> {
|
|
||||||
let source_name = header_file_name(&headers);
|
|
||||||
let descriptor = state
|
|
||||||
.service
|
|
||||||
.upload_proto_file(
|
|
||||||
&path.workspace_id.as_str().into(),
|
|
||||||
&path.operation_id.as_str().into(),
|
|
||||||
source_name.as_deref(),
|
|
||||||
body.as_ref(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(Json(json!(descriptor)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn upload_descriptor_set(
|
|
||||||
Path(path): Path<WorkspaceOperationPath>,
|
|
||||||
State(state): State<AppState>,
|
|
||||||
headers: HeaderMap,
|
|
||||||
body: Bytes,
|
|
||||||
) -> Result<Json<Value>, ApiError> {
|
|
||||||
let source_name = header_file_name(&headers);
|
|
||||||
let descriptor = state
|
|
||||||
.service
|
|
||||||
.upload_descriptor_set(
|
|
||||||
&path.workspace_id.as_str().into(),
|
|
||||||
&path.operation_id.as_str().into(),
|
|
||||||
source_name.as_deref(),
|
|
||||||
body.as_ref(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(Json(json!(descriptor)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn upload_wsdl_descriptor(
|
|
||||||
Path(path): Path<WorkspaceOperationPath>,
|
|
||||||
State(state): State<AppState>,
|
|
||||||
headers: HeaderMap,
|
|
||||||
body: Bytes,
|
|
||||||
) -> Result<Json<Value>, ApiError> {
|
|
||||||
let source_name = header_file_name(&headers);
|
|
||||||
let descriptor = state
|
|
||||||
.service
|
|
||||||
.upload_wsdl_file(
|
|
||||||
&path.workspace_id.as_str().into(),
|
|
||||||
&path.operation_id.as_str().into(),
|
|
||||||
source_name.as_deref(),
|
|
||||||
body.as_ref(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(Json(json!(descriptor)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn upload_xsd_descriptor(
|
|
||||||
Path(path): Path<WorkspaceOperationPath>,
|
|
||||||
State(state): State<AppState>,
|
|
||||||
headers: HeaderMap,
|
|
||||||
body: Bytes,
|
|
||||||
) -> Result<Json<Value>, ApiError> {
|
|
||||||
let source_name = header_file_name(&headers);
|
|
||||||
let descriptor = state
|
|
||||||
.service
|
|
||||||
.upload_xsd_file(
|
|
||||||
&path.workspace_id.as_str().into(),
|
|
||||||
&path.operation_id.as_str().into(),
|
|
||||||
source_name.as_deref(),
|
|
||||||
body.as_ref(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(Json(json!(descriptor)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn list_grpc_services(
|
|
||||||
Path(path): Path<WorkspaceOperationPath>,
|
|
||||||
Query(query): Query<ExportQuery>,
|
|
||||||
State(state): State<AppState>,
|
|
||||||
) -> Result<Json<Value>, ApiError> {
|
|
||||||
let services = state
|
|
||||||
.service
|
|
||||||
.list_grpc_services(
|
|
||||||
&path.workspace_id.as_str().into(),
|
|
||||||
&path.operation_id.as_str().into(),
|
|
||||||
query.version,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
Ok(Json(json!({ "services": services })))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn list_soap_services(
|
|
||||||
Path(path): Path<WorkspaceOperationPath>,
|
|
||||||
Query(query): Query<ExportQuery>,
|
|
||||||
State(state): State<AppState>,
|
|
||||||
) -> Result<Json<Value>, ApiError> {
|
|
||||||
let services = state
|
|
||||||
.service
|
|
||||||
.list_soap_services(
|
|
||||||
&path.workspace_id.as_str().into(),
|
|
||||||
&path.operation_id.as_str().into(),
|
|
||||||
query.version,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
Ok(Json(json!({ "services": services })))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn generate_draft(
|
pub async fn generate_draft(
|
||||||
Path(path): Path<WorkspaceOperationPath>,
|
Path(path): Path<WorkspaceOperationPath>,
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
@@ -394,10 +281,3 @@ pub async fn import_operation(
|
|||||||
.await?;
|
.await?;
|
||||||
Ok(Json(json!(imported)))
|
Ok(Json(json!(imported)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn header_file_name(headers: &HeaderMap) -> Option<String> {
|
|
||||||
headers
|
|
||||||
.get("x-file-name")
|
|
||||||
.and_then(|value| value.to_str().ok())
|
|
||||||
.map(ToOwned::to_owned)
|
|
||||||
}
|
|
||||||
|
|||||||
+16
-478
@@ -2,7 +2,6 @@ use std::collections::BTreeMap;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
|
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
|
||||||
use crank_adapter_soap::{SoapServiceSummary, inspect_wsdl};
|
|
||||||
use crank_core::{
|
use crank_core::{
|
||||||
Agent, AgentId, AgentOperationBinding, AgentStatus, AgentVersion, AggregationMode,
|
Agent, AgentId, AgentOperationBinding, AgentStatus, AgentVersion, AggregationMode,
|
||||||
AsyncJobHandle, AuthConfig, AuthKind, AuthProfile, AuthProfileId, ConfigExport,
|
AsyncJobHandle, AuthConfig, AuthKind, AuthProfile, AuthProfileId, ConfigExport,
|
||||||
@@ -17,7 +16,6 @@ use crank_core::{
|
|||||||
Workspace, WorkspaceId, WorkspaceStatus,
|
Workspace, WorkspaceId, WorkspaceStatus,
|
||||||
};
|
};
|
||||||
use crank_mapping::{JsonPathRoot, MappingSet, infer_mapping_from_samples};
|
use crank_mapping::{JsonPathRoot, MappingSet, infer_mapping_from_samples};
|
||||||
use crank_proto::{ProtoService, services_from_descriptor_set_bytes};
|
|
||||||
use crank_registry::{
|
use crank_registry::{
|
||||||
AgentSummary, AgentVersionRecord, AsyncJobFilter, CreateAgentRequest, CreateAsyncJobRequest,
|
AgentSummary, AgentVersionRecord, AsyncJobFilter, CreateAgentRequest, CreateAsyncJobRequest,
|
||||||
CreateInvitationRequest, CreateInvocationLogRequest, CreatePlatformApiKeyRequest,
|
CreateInvitationRequest, CreateInvocationLogRequest, CreatePlatformApiKeyRequest,
|
||||||
@@ -26,10 +24,10 @@ use crank_registry::{
|
|||||||
OperationAgentRef, OperationSampleMetadata, OperationSummary, OperationUsageSummary,
|
OperationAgentRef, OperationSampleMetadata, OperationSummary, OperationUsageSummary,
|
||||||
OperationVersionRecord, Page, PlatformApiKeyRecord, PostgresRegistry, PublishAgentRequest,
|
OperationVersionRecord, Page, PlatformApiKeyRecord, PostgresRegistry, PublishAgentRequest,
|
||||||
PublishRequest, RegistryError, RegistryOperation, RotateSecretRequest, SampleKind,
|
PublishRequest, RegistryError, RegistryOperation, RotateSecretRequest, SampleKind,
|
||||||
SaveAgentBindingsRequest, SaveAuthProfileRequest, SaveDescriptorMetadataRequest,
|
SaveAgentBindingsRequest, SaveAuthProfileRequest, SaveSampleMetadataRequest,
|
||||||
SaveSampleMetadataRequest, StreamSessionFilter, UpdateAsyncJobStatusRequest,
|
StreamSessionFilter, UpdateAsyncJobStatusRequest, UpdateWorkspaceRequest,
|
||||||
UpdateWorkspaceRequest, UsageAgentBreakdown, UsageBucket, UsageOperationBreakdown, UsageQuery,
|
UsageAgentBreakdown, UsageBucket, UsageOperationBreakdown, UsageQuery, UsageSummary,
|
||||||
UsageSummary, UsageTimelinePoint, WorkspaceMembershipRecord, WorkspaceRecord,
|
UsageTimelinePoint, WorkspaceMembershipRecord, WorkspaceRecord,
|
||||||
};
|
};
|
||||||
use crank_runtime::{
|
use crank_runtime::{
|
||||||
PreparedRequest, ResolvedAuth, RuntimeError, RuntimeExecutor, RuntimeOperation,
|
PreparedRequest, ResolvedAuth, RuntimeError, RuntimeExecutor, RuntimeOperation,
|
||||||
@@ -696,8 +694,6 @@ pub struct GrpcMethodSummary {
|
|||||||
pub output_schema: Schema,
|
pub output_schema: Schema,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type SoapServiceCatalog = Vec<SoapServiceSummary>;
|
|
||||||
|
|
||||||
fn default_operation_category() -> String {
|
fn default_operation_category() -> String {
|
||||||
"general".to_owned()
|
"general".to_owned()
|
||||||
}
|
}
|
||||||
@@ -3265,332 +3261,6 @@ impl AdminService {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self, payload), fields(operation_id = %operation_id.as_str(), source_name = source_name.unwrap_or("descriptor-set.bin")))]
|
|
||||||
pub async fn upload_descriptor_set(
|
|
||||||
&self,
|
|
||||||
workspace_id: &WorkspaceId,
|
|
||||||
operation_id: &OperationId,
|
|
||||||
source_name: Option<&str>,
|
|
||||||
payload: &[u8],
|
|
||||||
) -> Result<DescriptorUploadResponse, ApiError> {
|
|
||||||
let summary = self.get_operation(workspace_id, operation_id).await?;
|
|
||||||
if summary.protocol != Protocol::Grpc {
|
|
||||||
return Err(ApiError::validation(
|
|
||||||
"descriptor upload is only allowed for grpc operations",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let services = services_from_descriptor_set_bytes(payload)
|
|
||||||
.map_err(|error| ApiError::validation(error.to_string()))?;
|
|
||||||
let descriptor_id = crank_core::DescriptorId::new(new_prefixed_id("desc"));
|
|
||||||
let created_at = OffsetDateTime::now_utc();
|
|
||||||
let storage_ref = self
|
|
||||||
.storage
|
|
||||||
.write_descriptor(
|
|
||||||
operation_id,
|
|
||||||
summary.current_draft_version,
|
|
||||||
crank_registry::DescriptorKind::DescriptorSet,
|
|
||||||
&descriptor_id,
|
|
||||||
source_name,
|
|
||||||
payload,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
self.registry
|
|
||||||
.save_descriptor_metadata(SaveDescriptorMetadataRequest {
|
|
||||||
descriptor: &crank_registry::DescriptorMetadata {
|
|
||||||
id: descriptor_id.clone(),
|
|
||||||
operation_id: Some(operation_id.clone()),
|
|
||||||
version: Some(summary.current_draft_version),
|
|
||||||
descriptor_kind: crank_registry::DescriptorKind::DescriptorSet,
|
|
||||||
storage_ref,
|
|
||||||
source_name: source_name.map(ToOwned::to_owned),
|
|
||||||
package_index: Some(
|
|
||||||
serde_json::to_value(&services)
|
|
||||||
.map_err(|error| ApiError::internal(error.to_string()))?,
|
|
||||||
),
|
|
||||||
created_at,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
info!(
|
|
||||||
operation_id = %operation_id.as_str(),
|
|
||||||
descriptor_id = %descriptor_id.as_str(),
|
|
||||||
version = summary.current_draft_version,
|
|
||||||
"descriptor set uploaded"
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(DescriptorUploadResponse {
|
|
||||||
descriptor_id: descriptor_id.as_str().to_owned(),
|
|
||||||
version: summary.current_draft_version,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(skip(self, payload), fields(operation_id = %operation_id.as_str(), source_name = source_name.unwrap_or("schema.proto")))]
|
|
||||||
pub async fn upload_proto_file(
|
|
||||||
&self,
|
|
||||||
workspace_id: &WorkspaceId,
|
|
||||||
operation_id: &OperationId,
|
|
||||||
source_name: Option<&str>,
|
|
||||||
payload: &[u8],
|
|
||||||
) -> Result<DescriptorUploadResponse, ApiError> {
|
|
||||||
let summary = self.get_operation(workspace_id, operation_id).await?;
|
|
||||||
if summary.protocol != Protocol::Grpc {
|
|
||||||
return Err(ApiError::validation(
|
|
||||||
"proto upload is only allowed for grpc operations",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let descriptor_id = crank_core::DescriptorId::new(new_prefixed_id("desc"));
|
|
||||||
let created_at = OffsetDateTime::now_utc();
|
|
||||||
let storage_ref = self
|
|
||||||
.storage
|
|
||||||
.write_descriptor(
|
|
||||||
operation_id,
|
|
||||||
summary.current_draft_version,
|
|
||||||
crank_registry::DescriptorKind::ProtoUpload,
|
|
||||||
&descriptor_id,
|
|
||||||
source_name,
|
|
||||||
payload,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
self.registry
|
|
||||||
.save_descriptor_metadata(SaveDescriptorMetadataRequest {
|
|
||||||
descriptor: &crank_registry::DescriptorMetadata {
|
|
||||||
id: descriptor_id.clone(),
|
|
||||||
operation_id: Some(operation_id.clone()),
|
|
||||||
version: Some(summary.current_draft_version),
|
|
||||||
descriptor_kind: crank_registry::DescriptorKind::ProtoUpload,
|
|
||||||
storage_ref,
|
|
||||||
source_name: source_name.map(ToOwned::to_owned),
|
|
||||||
package_index: None,
|
|
||||||
created_at,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
info!(
|
|
||||||
operation_id = %operation_id.as_str(),
|
|
||||||
descriptor_id = %descriptor_id.as_str(),
|
|
||||||
version = summary.current_draft_version,
|
|
||||||
"proto file uploaded"
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(DescriptorUploadResponse {
|
|
||||||
descriptor_id: descriptor_id.as_str().to_owned(),
|
|
||||||
version: summary.current_draft_version,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(skip(self), fields(operation_id = %operation_id.as_str(), version))]
|
|
||||||
pub async fn list_grpc_services(
|
|
||||||
&self,
|
|
||||||
workspace_id: &WorkspaceId,
|
|
||||||
operation_id: &OperationId,
|
|
||||||
version: Option<u32>,
|
|
||||||
) -> Result<Vec<GrpcServiceSummary>, ApiError> {
|
|
||||||
let summary = self.get_operation(workspace_id, operation_id).await?;
|
|
||||||
if summary.protocol != Protocol::Grpc {
|
|
||||||
return Err(ApiError::validation(
|
|
||||||
"grpc services are only available for grpc operations",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let version = version.unwrap_or(summary.current_draft_version);
|
|
||||||
let descriptor = self
|
|
||||||
.registry
|
|
||||||
.list_descriptor_metadata(operation_id, version)
|
|
||||||
.await?
|
|
||||||
.into_iter()
|
|
||||||
.rev()
|
|
||||||
.find(|descriptor| {
|
|
||||||
descriptor.descriptor_kind == crank_registry::DescriptorKind::DescriptorSet
|
|
||||||
})
|
|
||||||
.ok_or_else(|| {
|
|
||||||
ApiError::not_found_with_context(
|
|
||||||
"descriptor set was not uploaded",
|
|
||||||
json!({
|
|
||||||
"operation_id": operation_id.as_str(),
|
|
||||||
"version": version,
|
|
||||||
"descriptor_kind": "descriptor_set",
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
let bytes = self.storage.read_bytes(&descriptor.storage_ref).await?;
|
|
||||||
let services = services_from_descriptor_set_bytes(&bytes)
|
|
||||||
.map_err(|error| ApiError::validation(error.to_string()))?;
|
|
||||||
|
|
||||||
services
|
|
||||||
.into_iter()
|
|
||||||
.map(proto_service_summary)
|
|
||||||
.collect::<Result<Vec<_>, _>>()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(skip(self, payload), fields(operation_id = %operation_id.as_str(), source_name = source_name.unwrap_or("service.wsdl")))]
|
|
||||||
pub async fn upload_wsdl_file(
|
|
||||||
&self,
|
|
||||||
workspace_id: &WorkspaceId,
|
|
||||||
operation_id: &OperationId,
|
|
||||||
source_name: Option<&str>,
|
|
||||||
payload: &[u8],
|
|
||||||
) -> Result<DescriptorUploadResponse, ApiError> {
|
|
||||||
let summary = self.get_operation(workspace_id, operation_id).await?;
|
|
||||||
if summary.protocol != Protocol::Soap {
|
|
||||||
return Err(ApiError::validation(
|
|
||||||
"wsdl upload is only allowed for soap operations",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let services =
|
|
||||||
inspect_wsdl(payload).map_err(|error| ApiError::validation(error.to_string()))?;
|
|
||||||
let descriptor_id = crank_core::DescriptorId::new(new_prefixed_id("desc"));
|
|
||||||
let created_at = OffsetDateTime::now_utc();
|
|
||||||
let storage_ref = self
|
|
||||||
.storage
|
|
||||||
.write_descriptor(
|
|
||||||
operation_id,
|
|
||||||
summary.current_draft_version,
|
|
||||||
crank_registry::DescriptorKind::WsdlUpload,
|
|
||||||
&descriptor_id,
|
|
||||||
source_name,
|
|
||||||
payload,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
self.registry
|
|
||||||
.save_descriptor_metadata(SaveDescriptorMetadataRequest {
|
|
||||||
descriptor: &crank_registry::DescriptorMetadata {
|
|
||||||
id: descriptor_id.clone(),
|
|
||||||
operation_id: Some(operation_id.clone()),
|
|
||||||
version: Some(summary.current_draft_version),
|
|
||||||
descriptor_kind: crank_registry::DescriptorKind::WsdlUpload,
|
|
||||||
storage_ref,
|
|
||||||
source_name: source_name.map(ToOwned::to_owned),
|
|
||||||
package_index: Some(
|
|
||||||
serde_json::to_value(&services)
|
|
||||||
.map_err(|error| ApiError::internal(error.to_string()))?,
|
|
||||||
),
|
|
||||||
created_at,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
info!(
|
|
||||||
operation_id = %operation_id.as_str(),
|
|
||||||
descriptor_id = %descriptor_id.as_str(),
|
|
||||||
version = summary.current_draft_version,
|
|
||||||
"wsdl uploaded"
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(DescriptorUploadResponse {
|
|
||||||
descriptor_id: descriptor_id.as_str().to_owned(),
|
|
||||||
version: summary.current_draft_version,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(skip(self, payload), fields(operation_id = %operation_id.as_str(), source_name = source_name.unwrap_or("schema.xsd")))]
|
|
||||||
pub async fn upload_xsd_file(
|
|
||||||
&self,
|
|
||||||
workspace_id: &WorkspaceId,
|
|
||||||
operation_id: &OperationId,
|
|
||||||
source_name: Option<&str>,
|
|
||||||
payload: &[u8],
|
|
||||||
) -> Result<DescriptorUploadResponse, ApiError> {
|
|
||||||
let summary = self.get_operation(workspace_id, operation_id).await?;
|
|
||||||
if summary.protocol != Protocol::Soap {
|
|
||||||
return Err(ApiError::validation(
|
|
||||||
"xsd upload is only allowed for soap operations",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let descriptor_id = crank_core::DescriptorId::new(new_prefixed_id("desc"));
|
|
||||||
let created_at = OffsetDateTime::now_utc();
|
|
||||||
let storage_ref = self
|
|
||||||
.storage
|
|
||||||
.write_descriptor(
|
|
||||||
operation_id,
|
|
||||||
summary.current_draft_version,
|
|
||||||
crank_registry::DescriptorKind::XsdUpload,
|
|
||||||
&descriptor_id,
|
|
||||||
source_name,
|
|
||||||
payload,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
self.registry
|
|
||||||
.save_descriptor_metadata(SaveDescriptorMetadataRequest {
|
|
||||||
descriptor: &crank_registry::DescriptorMetadata {
|
|
||||||
id: descriptor_id.clone(),
|
|
||||||
operation_id: Some(operation_id.clone()),
|
|
||||||
version: Some(summary.current_draft_version),
|
|
||||||
descriptor_kind: crank_registry::DescriptorKind::XsdUpload,
|
|
||||||
storage_ref,
|
|
||||||
source_name: source_name.map(ToOwned::to_owned),
|
|
||||||
package_index: None,
|
|
||||||
created_at,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
info!(
|
|
||||||
operation_id = %operation_id.as_str(),
|
|
||||||
descriptor_id = %descriptor_id.as_str(),
|
|
||||||
version = summary.current_draft_version,
|
|
||||||
"xsd uploaded"
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(DescriptorUploadResponse {
|
|
||||||
descriptor_id: descriptor_id.as_str().to_owned(),
|
|
||||||
version: summary.current_draft_version,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(skip(self), fields(operation_id = %operation_id.as_str(), version))]
|
|
||||||
pub async fn list_soap_services(
|
|
||||||
&self,
|
|
||||||
workspace_id: &WorkspaceId,
|
|
||||||
operation_id: &OperationId,
|
|
||||||
version: Option<u32>,
|
|
||||||
) -> Result<SoapServiceCatalog, ApiError> {
|
|
||||||
let summary = self.get_operation(workspace_id, operation_id).await?;
|
|
||||||
if summary.protocol != Protocol::Soap {
|
|
||||||
return Err(ApiError::validation(
|
|
||||||
"soap services are only available for soap operations",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let version = version.unwrap_or(summary.current_draft_version);
|
|
||||||
let descriptor = self
|
|
||||||
.registry
|
|
||||||
.list_descriptor_metadata(operation_id, version)
|
|
||||||
.await?
|
|
||||||
.into_iter()
|
|
||||||
.rev()
|
|
||||||
.find(|descriptor| {
|
|
||||||
descriptor.descriptor_kind == crank_registry::DescriptorKind::WsdlUpload
|
|
||||||
})
|
|
||||||
.ok_or_else(|| {
|
|
||||||
ApiError::not_found_with_context(
|
|
||||||
"wsdl was not uploaded",
|
|
||||||
json!({
|
|
||||||
"operation_id": operation_id.as_str(),
|
|
||||||
"version": version,
|
|
||||||
"descriptor_kind": "wsdl_upload",
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
let package_index = descriptor.package_index.ok_or_else(|| {
|
|
||||||
ApiError::not_found_with_context(
|
|
||||||
"wsdl inspection metadata is not available",
|
|
||||||
json!({
|
|
||||||
"operation_id": operation_id.as_str(),
|
|
||||||
"version": version,
|
|
||||||
"descriptor_kind": "wsdl_upload",
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
serde_json::from_value(package_index).map_err(|error| ApiError::internal(error.to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(skip(self))]
|
#[instrument(skip(self))]
|
||||||
pub async fn get_auth_profile(
|
pub async fn get_auth_profile(
|
||||||
&self,
|
&self,
|
||||||
@@ -4802,11 +4472,7 @@ fn protocol_capability_view(protocol: Protocol, edition: ProductEdition) -> Prot
|
|||||||
.filter(|behavior| protocol.supports_transport_behavior(*behavior))
|
.filter(|behavior| protocol.supports_transport_behavior(*behavior))
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
let supports_upload_artifacts = match protocol {
|
let supports_upload_artifacts = Vec::new();
|
||||||
Protocol::Rest | Protocol::Graphql | Protocol::Websocket => Vec::new(),
|
|
||||||
Protocol::Grpc => vec!["proto".to_owned(), "descriptor_set".to_owned()],
|
|
||||||
Protocol::Soap => vec!["wsdl".to_owned(), "xsd".to_owned()],
|
|
||||||
};
|
|
||||||
|
|
||||||
ProtocolCapabilityView {
|
ProtocolCapabilityView {
|
||||||
protocol,
|
protocol,
|
||||||
@@ -5072,13 +4738,9 @@ fn validate_response_cache_policy(
|
|||||||
|
|
||||||
match target {
|
match target {
|
||||||
Target::Rest(rest_target) if rest_target.method == crank_core::HttpMethod::Get => {}
|
Target::Rest(rest_target) if rest_target.method == crank_core::HttpMethod::Get => {}
|
||||||
Target::Graphql(graphql_target)
|
|
||||||
if graphql_target.operation_type == crank_core::GraphqlOperationType::Query => {}
|
|
||||||
Target::Grpc(grpc_target) if grpc_target.read_only => {}
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ApiError::validation_with_context(
|
return Err(ApiError::validation_with_context(
|
||||||
"response cache is supported only for REST GET, GraphQL query, and read-only unary gRPC operations"
|
"response cache is supported only for REST GET operations".to_owned(),
|
||||||
.to_owned(),
|
|
||||||
json!({
|
json!({
|
||||||
"field": "execution_config.response_cache",
|
"field": "execution_config.response_cache",
|
||||||
}),
|
}),
|
||||||
@@ -5103,8 +4765,7 @@ mod tests {
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use crank_core::{
|
use crank_core::{
|
||||||
ExecutionConfig, GraphqlOperationType, GraphqlTarget, GrpcTarget, HttpMethod,
|
ExecutionConfig, HttpMethod, ResponseCachePolicy, RestTarget, Target,
|
||||||
ResponseCachePolicy, RestTarget, StreamingConfig, Target, TransportBehavior,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::validate_response_cache_policy;
|
use super::validate_response_cache_policy;
|
||||||
@@ -5121,44 +4782,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn accepts_response_cache_for_graphql_query() {
|
|
||||||
let target = Target::Graphql(GraphqlTarget {
|
|
||||||
endpoint: "http://example.invalid/graphql".to_owned(),
|
|
||||||
operation_type: GraphqlOperationType::Query,
|
|
||||||
operation_name: "LookupLead".to_owned(),
|
|
||||||
query_template:
|
|
||||||
"query LookupLead($email: String!) { lookupLead(email: $email) { id } }".to_owned(),
|
|
||||||
response_path: "$.response.body.data.lookupLead".to_owned(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let result = validate_response_cache_policy(&target, &cacheable_execution_config());
|
|
||||||
|
|
||||||
assert!(result.is_ok());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn rejects_response_cache_for_graphql_mutation() {
|
|
||||||
let target = Target::Graphql(GraphqlTarget {
|
|
||||||
endpoint: "http://example.invalid/graphql".to_owned(),
|
|
||||||
operation_type: GraphqlOperationType::Mutation,
|
|
||||||
operation_name: "CreateLead".to_owned(),
|
|
||||||
query_template:
|
|
||||||
"mutation CreateLead($email: String!) { createLead(email: $email) { id } }"
|
|
||||||
.to_owned(),
|
|
||||||
response_path: "$.response.body.data.createLead".to_owned(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let error =
|
|
||||||
validate_response_cache_policy(&target, &cacheable_execution_config()).unwrap_err();
|
|
||||||
|
|
||||||
assert!(matches!(error, crate::error::ApiError::Validation { .. }));
|
|
||||||
assert_eq!(
|
|
||||||
error.to_string(),
|
|
||||||
"response cache is supported only for REST GET, GraphQL query, and read-only unary gRPC operations"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn accepts_response_cache_for_rest_get() {
|
fn accepts_response_cache_for_rest_get() {
|
||||||
let target = Target::Rest(RestTarget {
|
let target = Target::Rest(RestTarget {
|
||||||
@@ -5174,32 +4797,14 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn accepts_response_cache_for_read_only_unary_grpc() {
|
fn rejects_response_cache_for_non_rest_target() {
|
||||||
let target = Target::Grpc(GrpcTarget {
|
let target = Target::Graphql(crank_core::GraphqlTarget {
|
||||||
server_addr: "http://127.0.0.1:50051".to_owned(),
|
endpoint: "http://example.invalid/graphql".to_owned(),
|
||||||
package: "echo".to_owned(),
|
operation_type: crank_core::GraphqlOperationType::Query,
|
||||||
service: "EchoService".to_owned(),
|
operation_name: "LookupLead".to_owned(),
|
||||||
method: "UnaryEcho".to_owned(),
|
query_template:
|
||||||
read_only: true,
|
"query LookupLead($email: String!) { lookupLead(email: $email) { id } }".to_owned(),
|
||||||
descriptor_ref: "desc_echo".into(),
|
response_path: "$.response.body.data.lookupLead".to_owned(),
|
||||||
descriptor_set_b64: "ZmFrZQ==".to_owned(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let result = validate_response_cache_policy(&target, &cacheable_execution_config());
|
|
||||||
|
|
||||||
assert!(result.is_ok());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn rejects_response_cache_for_non_read_only_grpc() {
|
|
||||||
let target = Target::Grpc(GrpcTarget {
|
|
||||||
server_addr: "http://127.0.0.1:50051".to_owned(),
|
|
||||||
package: "echo".to_owned(),
|
|
||||||
service: "EchoService".to_owned(),
|
|
||||||
method: "UnaryEcho".to_owned(),
|
|
||||||
read_only: false,
|
|
||||||
descriptor_ref: "desc_echo".into(),
|
|
||||||
descriptor_set_b64: "ZmFrZQ==".to_owned(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let error =
|
let error =
|
||||||
@@ -5208,52 +4813,7 @@ mod tests {
|
|||||||
assert!(matches!(error, crate::error::ApiError::Validation { .. }));
|
assert!(matches!(error, crate::error::ApiError::Validation { .. }));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
error.to_string(),
|
error.to_string(),
|
||||||
"response cache is supported only for REST GET, GraphQL query, and read-only unary gRPC operations"
|
"response cache is supported only for REST GET operations"
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn rejects_response_cache_for_streaming_grpc() {
|
|
||||||
let target = Target::Grpc(GrpcTarget {
|
|
||||||
server_addr: "http://127.0.0.1:50051".to_owned(),
|
|
||||||
package: "echo".to_owned(),
|
|
||||||
service: "EchoService".to_owned(),
|
|
||||||
method: "ServerEcho".to_owned(),
|
|
||||||
read_only: true,
|
|
||||||
descriptor_ref: "desc_echo".into(),
|
|
||||||
descriptor_set_b64: "ZmFrZQ==".to_owned(),
|
|
||||||
});
|
|
||||||
let mut execution_config = cacheable_execution_config();
|
|
||||||
execution_config.streaming = Some(StreamingConfig {
|
|
||||||
mode: crank_core::ExecutionMode::Window,
|
|
||||||
transport_behavior: TransportBehavior::ServerStream,
|
|
||||||
window_duration_ms: Some(1_000),
|
|
||||||
poll_interval_ms: None,
|
|
||||||
upstream_timeout_ms: Some(1_000),
|
|
||||||
idle_timeout_ms: None,
|
|
||||||
max_session_lifetime_ms: None,
|
|
||||||
max_items: Some(1),
|
|
||||||
max_bytes: None,
|
|
||||||
aggregation_mode: crank_core::AggregationMode::RawItems,
|
|
||||||
summary_path: None,
|
|
||||||
items_path: None,
|
|
||||||
cursor_path: None,
|
|
||||||
status_path: None,
|
|
||||||
done_path: None,
|
|
||||||
redacted_paths: Vec::new(),
|
|
||||||
truncate_item_fields: false,
|
|
||||||
max_field_length: None,
|
|
||||||
drop_duplicates: false,
|
|
||||||
sampling_rate: None,
|
|
||||||
tool_family: crank_core::ToolFamilyConfig::default(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let error = validate_response_cache_policy(&target, &execution_config).unwrap_err();
|
|
||||||
|
|
||||||
assert!(matches!(error, crate::error::ApiError::Validation { .. }));
|
|
||||||
assert_eq!(
|
|
||||||
error.to_string(),
|
|
||||||
"response cache is supported only for unary operations"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5283,25 +4843,3 @@ fn enrich_operation_summary(
|
|||||||
agent_refs,
|
agent_refs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn proto_service_summary(service: ProtoService) -> Result<GrpcServiceSummary, ApiError> {
|
|
||||||
let methods = service
|
|
||||||
.unary_methods()
|
|
||||||
.map(|method| {
|
|
||||||
Ok(GrpcMethodSummary {
|
|
||||||
name: method.name.clone(),
|
|
||||||
kind: "unary".to_owned(),
|
|
||||||
input_schema: crank_proto::message_to_schema(&method.input)
|
|
||||||
.map_err(|error| ApiError::validation(error.to_string()))?,
|
|
||||||
output_schema: crank_proto::message_to_schema(&method.output)
|
|
||||||
.map_err(|error| ApiError::validation(error.to_string()))?,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>, ApiError>>()?;
|
|
||||||
|
|
||||||
Ok(GrpcServiceSummary {
|
|
||||||
package: service.package,
|
|
||||||
service: service.name,
|
|
||||||
methods,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use crank_core::{DescriptorId, OperationId, SampleId};
|
use crank_core::{OperationId, SampleId};
|
||||||
use crank_registry::{DescriptorKind, SampleKind};
|
use crank_registry::SampleKind;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
@@ -58,40 +58,6 @@ impl LocalArtifactStorage {
|
|||||||
Ok(serde_json::from_slice(&bytes)?)
|
Ok(serde_json::from_slice(&bytes)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn write_descriptor(
|
|
||||||
&self,
|
|
||||||
operation_id: &OperationId,
|
|
||||||
version: u32,
|
|
||||||
descriptor_kind: DescriptorKind,
|
|
||||||
descriptor_id: &DescriptorId,
|
|
||||||
source_name: Option<&str>,
|
|
||||||
payload: &[u8],
|
|
||||||
) -> Result<String, StorageError> {
|
|
||||||
let file_name = match descriptor_kind {
|
|
||||||
DescriptorKind::ProtoUpload => source_name.unwrap_or("schema.proto").to_owned(),
|
|
||||||
DescriptorKind::DescriptorSet => source_name.unwrap_or("descriptor-set.bin").to_owned(),
|
|
||||||
DescriptorKind::ReflectionSnapshot => {
|
|
||||||
source_name.unwrap_or("reflection.bin").to_owned()
|
|
||||||
}
|
|
||||||
DescriptorKind::WsdlUpload => source_name.unwrap_or("service.wsdl").to_owned(),
|
|
||||||
DescriptorKind::XsdUpload => source_name.unwrap_or("schema.xsd").to_owned(),
|
|
||||||
};
|
|
||||||
let path = self
|
|
||||||
.root
|
|
||||||
.join("descriptors")
|
|
||||||
.join(operation_id.as_str())
|
|
||||||
.join(format!("v{version}"))
|
|
||||||
.join(format!("{}_{}", descriptor_id.as_str(), file_name));
|
|
||||||
|
|
||||||
write_bytes(&path, payload).await?;
|
|
||||||
|
|
||||||
Ok(to_storage_ref(&path))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn read_bytes(&self, storage_ref: &str) -> Result<Vec<u8>, StorageError> {
|
|
||||||
let path = from_storage_ref(storage_ref)?;
|
|
||||||
Ok(fs::read(path).await?)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn write_json_file(path: &Path, payload: &Value) -> Result<(), StorageError> {
|
async fn write_json_file(path: &Path, payload: &Value) -> Result<(), StorageError> {
|
||||||
@@ -104,15 +70,6 @@ async fn write_json_file(path: &Path, payload: &Value) -> Result<(), StorageErro
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn write_bytes(path: &Path, payload: &[u8]) -> Result<(), StorageError> {
|
|
||||||
if let Some(parent) = path.parent() {
|
|
||||||
fs::create_dir_all(parent).await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs::write(path, payload).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_storage_ref(path: &Path) -> String {
|
fn to_storage_ref(path: &Path) -> String {
|
||||||
format!("file://{}", path.display())
|
format!("file://{}", path.display())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,26 +6,17 @@ rust-version.workspace = true
|
|||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [
|
default = []
|
||||||
"protocol-graphql",
|
protocol-graphql = []
|
||||||
"protocol-grpc",
|
protocol-grpc = []
|
||||||
"protocol-soap",
|
protocol-soap = []
|
||||||
"protocol-websocket",
|
protocol-websocket = []
|
||||||
]
|
|
||||||
protocol-graphql = ["dep:crank-adapter-graphql"]
|
|
||||||
protocol-grpc = ["dep:crank-adapter-grpc"]
|
|
||||||
protocol-soap = ["dep:crank-adapter-soap"]
|
|
||||||
protocol-websocket = ["dep:crank-adapter-websocket"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aes-gcm.workspace = true
|
aes-gcm.workspace = true
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
base64.workspace = true
|
base64.workspace = true
|
||||||
crank-adapter-graphql = { path = "../crank-adapter-graphql", optional = true }
|
|
||||||
crank-adapter-grpc = { path = "../crank-adapter-grpc", optional = true }
|
|
||||||
crank-adapter-rest = { path = "../crank-adapter-rest" }
|
crank-adapter-rest = { path = "../crank-adapter-rest" }
|
||||||
crank-adapter-soap = { path = "../crank-adapter-soap", optional = true }
|
|
||||||
crank-adapter-websocket = { path = "../crank-adapter-websocket", optional = true }
|
|
||||||
crank-core = { path = "../crank-core" }
|
crank-core = { path = "../crank-core" }
|
||||||
crank-mapping = { path = "../crank-mapping" }
|
crank-mapping = { path = "../crank-mapping" }
|
||||||
crank-schema = { path = "../crank-schema" }
|
crank-schema = { path = "../crank-schema" }
|
||||||
@@ -40,8 +31,6 @@ tracing.workspace = true
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
axum.workspace = true
|
axum.workspace = true
|
||||||
crank-adapter-grpc = { path = "../crank-adapter-grpc", features = ["test-support"] }
|
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
time.workspace = true
|
time.workspace = true
|
||||||
tokio-tungstenite.workspace = true
|
|
||||||
tracing-subscriber.workspace = true
|
tracing-subscriber.workspace = true
|
||||||
|
|||||||
@@ -824,12 +824,8 @@ fn response_cache_ttl(operation: &RuntimeOperation) -> Option<Duration> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_cacheable_protocol = match &operation.target {
|
let is_cacheable_protocol =
|
||||||
Target::Rest(target) => target.method == HttpMethod::Get,
|
matches!(&operation.target, Target::Rest(target) if target.method == HttpMethod::Get);
|
||||||
Target::Graphql(target) => target.operation_type == crank_core::GraphqlOperationType::Query,
|
|
||||||
Target::Grpc(target) => target.read_only,
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
if !is_cacheable_protocol {
|
if !is_cacheable_protocol {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user