feat(import): resolve references and schema composition
This commit is contained in:
@@ -1,30 +1,18 @@
|
||||
use std::{
|
||||
io,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use admin_api::service::{OpenApiImportCreatePayload, OpenApiUpload, OpenApiUploadLocale};
|
||||
use crank_artifacts::MAX_ARTIFACT_BYTES;
|
||||
use crank_core::{Workspace, WorkspaceId, WorkspaceStatus};
|
||||
use crank_registry::{ArtifactSourceId, ArtifactSourceLifecycle, CreateWorkspaceRequest};
|
||||
use metrics_util::debugging::DebuggingRecorder;
|
||||
use opentelemetry::trace::TracerProvider as _;
|
||||
use opentelemetry_sdk::{
|
||||
error::OTelSdkResult,
|
||||
trace::{SdkTracerProvider, SpanData, SpanExporter},
|
||||
};
|
||||
use reqwest::multipart::{Form, Part};
|
||||
use serde_json::Value;
|
||||
use serial_test::serial;
|
||||
use time::{Duration, OffsetDateTime};
|
||||
use tracing_subscriber::{fmt::MakeWriter, layer::SubscriberExt};
|
||||
|
||||
use super::common::{
|
||||
authorized_client, build_test_app, spawn_admin_api, test_auth_settings, test_registry,
|
||||
test_secret_crypto, test_service, test_storage_root,
|
||||
};
|
||||
use admin_api::service::{OpenApiImportCreatePayload, OpenApiUpload, OpenApiUploadLocale};
|
||||
use crank_artifacts::MAX_ARTIFACT_BYTES;
|
||||
use crank_core::{Workspace, WorkspaceId, WorkspaceStatus};
|
||||
use crank_registry::{ArtifactSourceId, ArtifactSourceLifecycle, CreateWorkspaceRequest};
|
||||
use reqwest::multipart::{Form, Part};
|
||||
use serde_json::Value;
|
||||
use serial_test::serial;
|
||||
use time::{Duration, OffsetDateTime};
|
||||
|
||||
mod apply_failures;
|
||||
mod telemetry;
|
||||
|
||||
const OPENAPI: &str = r#"
|
||||
openapi: 3.0.3
|
||||
@@ -136,78 +124,6 @@ async fn multipart_requires_an_owner_membership_before_reading_the_file() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
#[serial]
|
||||
async fn parser_canary_never_reaches_diagnostics_logs_traces_or_metrics() {
|
||||
const CANARY: &str = "openapi-telemetry-secret-canary";
|
||||
|
||||
let recorder = DebuggingRecorder::new();
|
||||
let snapshotter = recorder.snapshotter();
|
||||
recorder
|
||||
.install()
|
||||
.expect("isolated integration test metrics recorder");
|
||||
|
||||
let writer = SharedLogWriter::default();
|
||||
let exported = Arc::new(Mutex::new(Vec::new()));
|
||||
let provider = SdkTracerProvider::builder()
|
||||
.with_simple_exporter(CapturingExporter(Arc::clone(&exported)))
|
||||
.build();
|
||||
let tracer = provider.tracer("admin-openapi-source-test");
|
||||
let subscriber = tracing_subscriber::registry()
|
||||
.with(tracing_subscriber::fmt::layer().with_writer(writer.clone()))
|
||||
.with(tracing_opentelemetry::layer().with_tracer(tracer));
|
||||
let dispatch = tracing::Dispatch::new(subscriber);
|
||||
tracing::dispatcher::set_global_default(dispatch)
|
||||
.expect("isolated integration test tracing subscriber");
|
||||
|
||||
let registry = test_registry().await;
|
||||
let app = build_test_app(registry, test_storage_root("openapi_telemetry_canary"));
|
||||
let server = spawn_admin_api(app).await;
|
||||
let client = authorized_client(&server).await;
|
||||
let document = format!(
|
||||
"openapi: 3.0.3\ninfo: {{ title: Canary }}\npaths:\n /broken:\n get:\n description: {CANARY}\n responses: ["
|
||||
);
|
||||
let response = client
|
||||
.post(format!("{server}/imports/openapi/preview"))
|
||||
.multipart(Form::new().part(
|
||||
"file",
|
||||
file_part(document.as_bytes(), "openapi.yaml", "application/yaml"),
|
||||
))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(response.status(), reqwest::StatusCode::BAD_REQUEST);
|
||||
let trace_id = response
|
||||
.headers()
|
||||
.get("x-trace-id")
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_owned();
|
||||
let body = response.text().await.unwrap();
|
||||
assert!(!body.contains(CANARY));
|
||||
let diagnostics: Value = serde_json::from_str(&body).unwrap();
|
||||
assert_eq!(diagnostics["error"]["trace_id"], trace_id);
|
||||
|
||||
provider.force_flush().unwrap();
|
||||
let logs = writer.output();
|
||||
assert!(!logs.contains(CANARY));
|
||||
assert!(logs.contains(&trace_id));
|
||||
let spans = exported.lock().unwrap();
|
||||
let rendered_spans = format!("{spans:?}");
|
||||
assert!(!rendered_spans.contains(CANARY));
|
||||
drop(spans);
|
||||
for (key, _, _, _) in snapshotter.snapshot().into_vec() {
|
||||
assert!(!key.key().name().contains(CANARY));
|
||||
assert!(
|
||||
!key.key()
|
||||
.labels()
|
||||
.any(|label| { label.key().contains(CANARY) || label.value().contains(CANARY) })
|
||||
);
|
||||
}
|
||||
provider.shutdown().unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
#[serial]
|
||||
async fn multipart_boundary_rejections_are_localized_and_leave_no_entities() {
|
||||
@@ -939,49 +855,3 @@ async fn wait_for_specific_source_lifecycle(
|
||||
}
|
||||
panic!("artifact source {source_id:?} did not reach {expected}");
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct SharedLogWriter {
|
||||
buffer: Arc<Mutex<Vec<u8>>>,
|
||||
}
|
||||
|
||||
impl SharedLogWriter {
|
||||
fn output(&self) -> String {
|
||||
String::from_utf8(self.buffer.lock().unwrap().clone()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MakeWriter<'a> for SharedLogWriter {
|
||||
type Writer = SharedLogGuard;
|
||||
|
||||
fn make_writer(&'a self) -> Self::Writer {
|
||||
SharedLogGuard {
|
||||
buffer: Arc::clone(&self.buffer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SharedLogGuard {
|
||||
buffer: Arc<Mutex<Vec<u8>>>,
|
||||
}
|
||||
|
||||
impl io::Write for SharedLogGuard {
|
||||
fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
|
||||
self.buffer.lock().unwrap().extend_from_slice(bytes);
|
||||
Ok(bytes.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct CapturingExporter(Arc<Mutex<Vec<SpanData>>>);
|
||||
|
||||
impl SpanExporter for CapturingExporter {
|
||||
async fn export(&self, batch: Vec<SpanData>) -> OTelSdkResult {
|
||||
self.0.lock().unwrap().extend(batch);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user