use serde_json::Value;
use vector_config_common::{
constants,
human_friendly::generate_human_friendly_string,
schema::{visit::Visitor, *},
};
#[derive(Debug, Default)]
pub struct GenerateHumanFriendlyNameVisitor;
impl GenerateHumanFriendlyNameVisitor {
pub fn from_settings(_: &SchemaSettings) -> Self {
Self
}
}
impl Visitor for GenerateHumanFriendlyNameVisitor {
fn visit_schema_object(
&mut self,
definitions: &mut Map<String, Schema>,
schema: &mut SchemaObject,
) {
visit::visit_schema_object(self, definitions, schema);
if has_schema_metadata_attr_str(schema, constants::DOCS_META_HUMAN_NAME) {
return;
}
if let Some(logical_name) = get_schema_metadata_attr_str(schema, constants::LOGICAL_NAME) {
let human_name = generate_human_friendly_string(logical_name);
set_schema_metadata_attr_str(schema, constants::DOCS_META_HUMAN_NAME, human_name);
}
if let Some(properties) = schema.object.as_mut().map(|object| &mut object.properties) {
for (property_name, property_schema) in properties.iter_mut() {
if let Some(property_schema) = property_schema.as_object_mut() {
if !has_schema_metadata_attr_str(
property_schema,
constants::DOCS_META_HUMAN_NAME,
) {
let human_name = generate_human_friendly_string(property_name);
set_schema_metadata_attr_str(
property_schema,
constants::DOCS_META_HUMAN_NAME,
human_name,
);
}
}
}
}
}
}
fn has_schema_metadata_attr_str(schema: &SchemaObject, key: &str) -> bool {
get_schema_metadata_attr_str(schema, key).is_some()
}
fn get_schema_metadata_attr_str<'a>(schema: &'a SchemaObject, key: &str) -> Option<&'a str> {
schema
.extensions
.get(constants::METADATA)
.and_then(|metadata| metadata.get(key))
.and_then(|value| value.as_str())
}
fn set_schema_metadata_attr_str(schema: &mut SchemaObject, key: &str, value: String) {
let metadata = schema
.extensions
.entry(constants::METADATA.to_string())
.or_insert_with(|| Value::Object(serde_json::Map::new()));
let metadata_map = metadata
.as_object_mut()
.expect("schema metadata must always be an object");
metadata_map.insert(key.to_string(), Value::String(value));
}
#[cfg(test)]
mod tests {
use serde_json::json;
use vector_config_common::schema::visit::Visitor;
use crate::schema::visitors::test::{as_schema, assert_schemas_eq};
use super::GenerateHumanFriendlyNameVisitor;
#[test]
fn logical_name() {
let mut actual_schema = as_schema(json!({
"type": "string",
"_metadata": {
"logical_name": "LogToMetric"
}
}));
let expected_schema = as_schema(json!({
"type": "string",
"_metadata": {
"docs::human_name": "Log To Metric",
"logical_name": "LogToMetric"
}
}));
let mut visitor = GenerateHumanFriendlyNameVisitor;
visitor.visit_root_schema(&mut actual_schema);
assert_schemas_eq(expected_schema, actual_schema);
}
#[test]
fn logical_name_with_replacement() {
let mut actual_schema = as_schema(json!({
"type": "string",
"_metadata": {
"logical_name": "AwsCloudwatchLogs"
}
}));
let expected_schema = as_schema(json!({
"type": "string",
"_metadata": {
"docs::human_name": "AWS CloudWatch Logs",
"logical_name": "AwsCloudwatchLogs"
}
}));
let mut visitor = GenerateHumanFriendlyNameVisitor;
visitor.visit_root_schema(&mut actual_schema);
assert_schemas_eq(expected_schema, actual_schema);
}
#[test]
fn property_name() {
let mut actual_schema = as_schema(json!({
"type": "object",
"properties": {
"store_key": { "type": "boolean" }
}
}));
let expected_schema = as_schema(json!({
"type": "object",
"properties": {
"store_key": {
"type": "boolean",
"_metadata": {
"docs::human_name": "Store Key"
}
}
}
}));
let mut visitor = GenerateHumanFriendlyNameVisitor;
visitor.visit_root_schema(&mut actual_schema);
assert_schemas_eq(expected_schema, actual_schema);
}
#[test]
fn property_name_with_replacement() {
let mut actual_schema = as_schema(json!({
"type": "object",
"properties": {
"store_api_key": { "type": "boolean" }
}
}));
let expected_schema = as_schema(json!({
"type": "object",
"properties": {
"store_api_key": {
"type": "boolean",
"_metadata": {
"docs::human_name": "Store API Key"
}
}
}
}));
let mut visitor = GenerateHumanFriendlyNameVisitor;
visitor.visit_root_schema(&mut actual_schema);
assert_schemas_eq(expected_schema, actual_schema);
}
#[test]
fn logical_name_override() {
let mut actual_schema = as_schema(json!({
"type": "string",
"_metadata": {
"docs::human_name": "AWS EC2 Metadata",
"logical_name": "Ec2Metadata"
}
}));
let expected_schema = actual_schema.clone();
let mut visitor = GenerateHumanFriendlyNameVisitor;
visitor.visit_root_schema(&mut actual_schema);
assert_schemas_eq(expected_schema, actual_schema);
}
#[test]
fn property_name_override() {
let mut actual_schema = as_schema(json!({
"type": "object",
"properties": {
"store_api_key": {
"type": "boolean",
"_metadata": {
"docs::human_name": "Store_api_key"
}
}
}
}));
let expected_schema = actual_schema.clone();
let mut visitor = GenerateHumanFriendlyNameVisitor;
visitor.visit_root_schema(&mut actual_schema);
assert_schemas_eq(expected_schema, actual_schema);
}
#[test]
fn mixed_with_replacement() {
let mut actual_schema = as_schema(json!({
"type": "object",
"properties": {
"store_api_key": { "type": "boolean" }
},
"_metadata": {
"logical_name": "AwsEc2Metadata"
}
}));
let expected_schema = as_schema(json!({
"type": "object",
"properties": {
"store_api_key": {
"type": "boolean",
"_metadata": {
"docs::human_name": "Store API Key"
}
}
},
"_metadata": {
"docs::human_name": "AWS EC2 Metadata",
"logical_name": "AwsEc2Metadata"
}
}));
let mut visitor = GenerateHumanFriendlyNameVisitor;
visitor.visit_root_schema(&mut actual_schema);
assert_schemas_eq(expected_schema, actual_schema);
}
}