From b03e41404c8893f30b40c3828e09e9a58090da71 Mon Sep 17 00:00:00 2001 From: Chad Roberts Date: Fri, 24 Jan 2025 11:25:34 -0500 Subject: [PATCH] Make schema type definitions recursive. --- pkg/schema/definitions/visitor.go | 27 ++++++++---- pkg/schema/definitions/visitor_test.go | 58 ++++++++++++++++++++------ 2 files changed, 65 insertions(+), 20 deletions(-) diff --git a/pkg/schema/definitions/visitor.go b/pkg/schema/definitions/visitor.go index 518bfb07..e8bf8722 100644 --- a/pkg/schema/definitions/visitor.go +++ b/pkg/schema/definitions/visitor.go @@ -20,23 +20,34 @@ func (s *schemaFieldVisitor) VisitArray(array *proto.Array) { // it was kept this way to provide backwards compat with previous endpoints. array.SubType.Accept(s) subField := s.field - field.Type = "array" - field.SubType = subField.Type + field.Type = "array[" + subField.Type + "]" s.field = field } // VisitMap turns a map into a definitionField (stored on the receiver). For maps of complex types, will also visit the // subtype. +//func (s *schemaFieldVisitor) VisitMap(protoMap *proto.Map) { +// field := definitionField{ +// Description: protoMap.GetDescription(), +// } +// // this currently is not recursive and provides little information for nested types- while this isn't optimal, +// // it was kept this way to provide backwards compat with previous endpoints. +// protoMap.SubType.Accept(s) +// subField := s.field +// field.Type = "map[" + subField.Type + "]" +// s.field = field +//} + func (s *schemaFieldVisitor) VisitMap(protoMap *proto.Map) { field := definitionField{ Description: protoMap.GetDescription(), } - // this currently is not recursive and provides little information for nested types- while this isn't optimal, - // it was kept this way to provide backwards compat with previous endpoints. - protoMap.SubType.Accept(s) - subField := s.field - field.Type = "map" - field.SubType = subField.Type + // Recursively visit the value subtype + subVisitor := &schemaFieldVisitor{definitions: s.definitions} + protoMap.SubType.Accept(subVisitor) + subField := subVisitor.field + // Represent the map as "map[string]" + field.Type = "map[string]" + subField.Type s.field = field } diff --git a/pkg/schema/definitions/visitor_test.go b/pkg/schema/definitions/visitor_test.go index c9497d4f..0e1df30c 100644 --- a/pkg/schema/definitions/visitor_test.go +++ b/pkg/schema/definitions/visitor_test.go @@ -72,6 +72,12 @@ var ( Description: "testArbitrary", }, } + protoNestedMap = proto.Map{ + BaseSchema: proto.BaseSchema{ + Description: "nestedMap", + }, + SubType: &protoKind, + } ) func TestSchemaFieldVisitor(t *testing.T) { @@ -87,9 +93,8 @@ func TestSchemaFieldVisitor(t *testing.T) { inputSchema: &protoArray, wantDefinitions: map[string]definition{}, wantField: definitionField{ - Type: "array", + Type: "array[string]", Description: protoArray.Description, - SubType: protoPrimitive.Type, }, }, { @@ -97,9 +102,8 @@ func TestSchemaFieldVisitor(t *testing.T) { inputSchema: &protoMap, wantDefinitions: map[string]definition{}, wantField: definitionField{ - Type: "map", + Type: "map[string]string", Description: protoMap.Description, - SubType: protoPrimitive.Type, }, }, { @@ -136,15 +140,13 @@ func TestSchemaFieldVisitor(t *testing.T) { protoKind.Path.String(): { ResourceFields: map[string]definitionField{ "protoArray": { - Type: "array", + Type: "array[" + protoPrimitive.Type + "]", Description: protoArray.Description, - SubType: protoPrimitive.Type, Required: true, }, "protoMap": { - Type: "map", + Type: "map[" + protoPrimitive.Type + "]string", Description: protoMap.Description, - SubType: protoPrimitive.Type, }, "protoPrimitive": { Type: protoPrimitive.Type, @@ -181,15 +183,13 @@ func TestSchemaFieldVisitor(t *testing.T) { protoKind.Path.String(): { ResourceFields: map[string]definitionField{ "protoArray": { - Type: "array", + Type: "array[string]", Description: protoArray.Description, - SubType: protoPrimitive.Type, Required: true, }, "protoMap": { - Type: "map", + Type: "map[string]string", Description: protoMap.Description, - SubType: protoPrimitive.Type, }, "protoPrimitive": { Type: protoPrimitive.Type, @@ -219,6 +219,40 @@ func TestSchemaFieldVisitor(t *testing.T) { Description: protoArbitrary.Description, }, }, + { + name: "nested map with kind", + inputSchema: &protoNestedMap, + wantDefinitions: map[string]definition{ + protoKind.Path.String(): { + ResourceFields: map[string]definitionField{ + "protoArray": { + Type: "array[string]", + Description: protoArray.Description, + Required: true, + }, + "protoMap": { + Type: "map[string]string", + Description: protoMap.Description, + }, + "protoPrimitive": { + Type: protoPrimitive.Type, + Description: protoPrimitive.Description, + Required: true, + }, + "protoRef": { + Type: protoKind.Path.String(), + Description: protoRef.Description, + }, + }, + Type: protoKind.Path.String(), + Description: protoKind.Description, + }, + }, + wantField: definitionField{ + Type: "map[string]io.cattle.test", + Description: protoNestedMap.Description, + }, + }, } for _, test := range tests {