vector_config/schema/visitors/
human_name.rs1use serde_json::Value;
2use vector_config_common::{
3 constants,
4 human_friendly::generate_human_friendly_string,
5 schema::{visit::Visitor, *},
6};
7
8#[derive(Debug, Default)]
28pub struct GenerateHumanFriendlyNameVisitor;
29
30impl GenerateHumanFriendlyNameVisitor {
31 pub fn from_settings(_: &SchemaSettings) -> Self {
32 Self
33 }
34}
35
36impl Visitor for GenerateHumanFriendlyNameVisitor {
37 fn visit_schema_object(
38 &mut self,
39 definitions: &mut Map<String, Schema>,
40 schema: &mut SchemaObject,
41 ) {
42 visit::visit_schema_object(self, definitions, schema);
44
45 if has_schema_metadata_attr_str(schema, constants::DOCS_META_HUMAN_NAME) {
47 return;
48 }
49
50 if let Some(logical_name) = get_schema_metadata_attr_str(schema, constants::LOGICAL_NAME) {
54 let human_name = generate_human_friendly_string(logical_name);
55 set_schema_metadata_attr_str(schema, constants::DOCS_META_HUMAN_NAME, human_name);
56 }
57
58 if let Some(properties) = schema.object.as_mut().map(|object| &mut object.properties) {
61 for (property_name, property_schema) in properties.iter_mut() {
62 if let Some(property_schema) = property_schema.as_object_mut()
63 && !has_schema_metadata_attr_str(
64 property_schema,
65 constants::DOCS_META_HUMAN_NAME,
66 )
67 {
68 let human_name = generate_human_friendly_string(property_name);
69 set_schema_metadata_attr_str(
70 property_schema,
71 constants::DOCS_META_HUMAN_NAME,
72 human_name,
73 );
74 }
75 }
76 }
77 }
78}
79
80fn has_schema_metadata_attr_str(schema: &SchemaObject, key: &str) -> bool {
81 get_schema_metadata_attr_str(schema, key).is_some()
82}
83
84fn get_schema_metadata_attr_str<'a>(schema: &'a SchemaObject, key: &str) -> Option<&'a str> {
85 schema
86 .extensions
87 .get(constants::METADATA)
88 .and_then(|metadata| metadata.get(key))
89 .and_then(|value| value.as_str())
90}
91
92fn set_schema_metadata_attr_str(schema: &mut SchemaObject, key: &str, value: String) {
93 let metadata = schema
94 .extensions
95 .entry(constants::METADATA.to_string())
96 .or_insert_with(|| Value::Object(serde_json::Map::new()));
97
98 let metadata_map = metadata
99 .as_object_mut()
100 .expect("schema metadata must always be an object");
101 metadata_map.insert(key.to_string(), Value::String(value));
102}
103
104#[cfg(test)]
105mod tests {
106 use serde_json::json;
107 use vector_config_common::schema::visit::Visitor;
108
109 use super::GenerateHumanFriendlyNameVisitor;
110 use crate::schema::visitors::test::{as_schema, assert_schemas_eq};
111
112 #[test]
113 fn logical_name() {
114 let mut actual_schema = as_schema(json!({
115 "type": "string",
116 "_metadata": {
117 "logical_name": "LogToMetric"
118 }
119 }));
120
121 let expected_schema = as_schema(json!({
122 "type": "string",
123 "_metadata": {
124 "docs::human_name": "Log To Metric",
125 "logical_name": "LogToMetric"
126 }
127 }));
128
129 let mut visitor = GenerateHumanFriendlyNameVisitor;
130 visitor.visit_root_schema(&mut actual_schema);
131
132 assert_schemas_eq(expected_schema, actual_schema);
133 }
134
135 #[test]
136 fn logical_name_with_replacement() {
137 let mut actual_schema = as_schema(json!({
138 "type": "string",
139 "_metadata": {
140 "logical_name": "AwsCloudwatchLogs"
141 }
142 }));
143
144 let expected_schema = as_schema(json!({
145 "type": "string",
146 "_metadata": {
147 "docs::human_name": "AWS CloudWatch Logs",
148 "logical_name": "AwsCloudwatchLogs"
149 }
150 }));
151
152 let mut visitor = GenerateHumanFriendlyNameVisitor;
153 visitor.visit_root_schema(&mut actual_schema);
154
155 assert_schemas_eq(expected_schema, actual_schema);
156 }
157
158 #[test]
159 fn property_name() {
160 let mut actual_schema = as_schema(json!({
161 "type": "object",
162 "properties": {
163 "store_key": { "type": "boolean" }
164 }
165 }));
166
167 let expected_schema = as_schema(json!({
168 "type": "object",
169 "properties": {
170 "store_key": {
171 "type": "boolean",
172 "_metadata": {
173 "docs::human_name": "Store Key"
174 }
175 }
176 }
177 }));
178
179 let mut visitor = GenerateHumanFriendlyNameVisitor;
180 visitor.visit_root_schema(&mut actual_schema);
181
182 assert_schemas_eq(expected_schema, actual_schema);
183 }
184
185 #[test]
186 fn property_name_with_replacement() {
187 let mut actual_schema = as_schema(json!({
188 "type": "object",
189 "properties": {
190 "store_api_key": { "type": "boolean" }
191 }
192 }));
193
194 let expected_schema = as_schema(json!({
195 "type": "object",
196 "properties": {
197 "store_api_key": {
198 "type": "boolean",
199 "_metadata": {
200 "docs::human_name": "Store API Key"
201 }
202 }
203 }
204 }));
205
206 let mut visitor = GenerateHumanFriendlyNameVisitor;
207 visitor.visit_root_schema(&mut actual_schema);
208
209 assert_schemas_eq(expected_schema, actual_schema);
210 }
211
212 #[test]
213 fn logical_name_override() {
214 let mut actual_schema = as_schema(json!({
215 "type": "string",
216 "_metadata": {
217 "docs::human_name": "AWS EC2 Metadata",
218 "logical_name": "Ec2Metadata"
219 }
220 }));
221
222 let expected_schema = actual_schema.clone();
223
224 let mut visitor = GenerateHumanFriendlyNameVisitor;
225 visitor.visit_root_schema(&mut actual_schema);
226
227 assert_schemas_eq(expected_schema, actual_schema);
228 }
229
230 #[test]
231 fn property_name_override() {
232 let mut actual_schema = as_schema(json!({
233 "type": "object",
234 "properties": {
235 "store_api_key": {
236 "type": "boolean",
237 "_metadata": {
238 "docs::human_name": "Store_api_key"
239 }
240 }
241 }
242 }));
243
244 let expected_schema = actual_schema.clone();
245
246 let mut visitor = GenerateHumanFriendlyNameVisitor;
247 visitor.visit_root_schema(&mut actual_schema);
248
249 assert_schemas_eq(expected_schema, actual_schema);
250 }
251
252 #[test]
253 fn mixed_with_replacement() {
254 let mut actual_schema = as_schema(json!({
255 "type": "object",
256 "properties": {
257 "store_api_key": { "type": "boolean" }
258 },
259 "_metadata": {
260 "logical_name": "AwsEc2Metadata"
261 }
262 }));
263
264 let expected_schema = as_schema(json!({
265 "type": "object",
266 "properties": {
267 "store_api_key": {
268 "type": "boolean",
269 "_metadata": {
270 "docs::human_name": "Store API Key"
271 }
272 }
273 },
274 "_metadata": {
275 "docs::human_name": "AWS EC2 Metadata",
276 "logical_name": "AwsEc2Metadata"
277 }
278 }));
279
280 let mut visitor = GenerateHumanFriendlyNameVisitor;
281 visitor.visit_root_schema(&mut actual_schema);
282
283 assert_schemas_eq(expected_schema, actual_schema);
284 }
285}