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 if !has_schema_metadata_attr_str(
64 property_schema,
65 constants::DOCS_META_HUMAN_NAME,
66 ) {
67 let human_name = generate_human_friendly_string(property_name);
68 set_schema_metadata_attr_str(
69 property_schema,
70 constants::DOCS_META_HUMAN_NAME,
71 human_name,
72 );
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 crate::schema::visitors::test::{as_schema, assert_schemas_eq};
110
111 use super::GenerateHumanFriendlyNameVisitor;
112
113 #[test]
114 fn logical_name() {
115 let mut actual_schema = as_schema(json!({
116 "type": "string",
117 "_metadata": {
118 "logical_name": "LogToMetric"
119 }
120 }));
121
122 let expected_schema = as_schema(json!({
123 "type": "string",
124 "_metadata": {
125 "docs::human_name": "Log To Metric",
126 "logical_name": "LogToMetric"
127 }
128 }));
129
130 let mut visitor = GenerateHumanFriendlyNameVisitor;
131 visitor.visit_root_schema(&mut actual_schema);
132
133 assert_schemas_eq(expected_schema, actual_schema);
134 }
135
136 #[test]
137 fn logical_name_with_replacement() {
138 let mut actual_schema = as_schema(json!({
139 "type": "string",
140 "_metadata": {
141 "logical_name": "AwsCloudwatchLogs"
142 }
143 }));
144
145 let expected_schema = as_schema(json!({
146 "type": "string",
147 "_metadata": {
148 "docs::human_name": "AWS CloudWatch Logs",
149 "logical_name": "AwsCloudwatchLogs"
150 }
151 }));
152
153 let mut visitor = GenerateHumanFriendlyNameVisitor;
154 visitor.visit_root_schema(&mut actual_schema);
155
156 assert_schemas_eq(expected_schema, actual_schema);
157 }
158
159 #[test]
160 fn property_name() {
161 let mut actual_schema = as_schema(json!({
162 "type": "object",
163 "properties": {
164 "store_key": { "type": "boolean" }
165 }
166 }));
167
168 let expected_schema = as_schema(json!({
169 "type": "object",
170 "properties": {
171 "store_key": {
172 "type": "boolean",
173 "_metadata": {
174 "docs::human_name": "Store Key"
175 }
176 }
177 }
178 }));
179
180 let mut visitor = GenerateHumanFriendlyNameVisitor;
181 visitor.visit_root_schema(&mut actual_schema);
182
183 assert_schemas_eq(expected_schema, actual_schema);
184 }
185
186 #[test]
187 fn property_name_with_replacement() {
188 let mut actual_schema = as_schema(json!({
189 "type": "object",
190 "properties": {
191 "store_api_key": { "type": "boolean" }
192 }
193 }));
194
195 let expected_schema = as_schema(json!({
196 "type": "object",
197 "properties": {
198 "store_api_key": {
199 "type": "boolean",
200 "_metadata": {
201 "docs::human_name": "Store API Key"
202 }
203 }
204 }
205 }));
206
207 let mut visitor = GenerateHumanFriendlyNameVisitor;
208 visitor.visit_root_schema(&mut actual_schema);
209
210 assert_schemas_eq(expected_schema, actual_schema);
211 }
212
213 #[test]
214 fn logical_name_override() {
215 let mut actual_schema = as_schema(json!({
216 "type": "string",
217 "_metadata": {
218 "docs::human_name": "AWS EC2 Metadata",
219 "logical_name": "Ec2Metadata"
220 }
221 }));
222
223 let expected_schema = actual_schema.clone();
224
225 let mut visitor = GenerateHumanFriendlyNameVisitor;
226 visitor.visit_root_schema(&mut actual_schema);
227
228 assert_schemas_eq(expected_schema, actual_schema);
229 }
230
231 #[test]
232 fn property_name_override() {
233 let mut actual_schema = as_schema(json!({
234 "type": "object",
235 "properties": {
236 "store_api_key": {
237 "type": "boolean",
238 "_metadata": {
239 "docs::human_name": "Store_api_key"
240 }
241 }
242 }
243 }));
244
245 let expected_schema = actual_schema.clone();
246
247 let mut visitor = GenerateHumanFriendlyNameVisitor;
248 visitor.visit_root_schema(&mut actual_schema);
249
250 assert_schemas_eq(expected_schema, actual_schema);
251 }
252
253 #[test]
254 fn mixed_with_replacement() {
255 let mut actual_schema = as_schema(json!({
256 "type": "object",
257 "properties": {
258 "store_api_key": { "type": "boolean" }
259 },
260 "_metadata": {
261 "logical_name": "AwsEc2Metadata"
262 }
263 }));
264
265 let expected_schema = as_schema(json!({
266 "type": "object",
267 "properties": {
268 "store_api_key": {
269 "type": "boolean",
270 "_metadata": {
271 "docs::human_name": "Store API Key"
272 }
273 }
274 },
275 "_metadata": {
276 "docs::human_name": "AWS EC2 Metadata",
277 "logical_name": "AwsEc2Metadata"
278 }
279 }));
280
281 let mut visitor = GenerateHumanFriendlyNameVisitor;
282 visitor.visit_root_schema(&mut actual_schema);
283
284 assert_schemas_eq(expected_schema, actual_schema);
285 }
286}