diff --git a/changelog/v0.21.5/fix-unstructured-map.yaml b/changelog/v0.21.5/fix-unstructured-map.yaml new file mode 100644 index 000000000..a2563e5a1 --- /dev/null +++ b/changelog/v0.21.5/fix-unstructured-map.yaml @@ -0,0 +1,4 @@ +changelog: + - type: FIX + description: Fix CRD rendering for unstructured map fields + issueLink: https://github.com/solo-io/skv2/issues/311 diff --git a/codegen/proto/options.go b/codegen/proto/options.go index 0aa11c863..6ecfb28f8 100644 --- a/codegen/proto/options.go +++ b/codegen/proto/options.go @@ -54,10 +54,19 @@ func (o Options) getUnstructuredFields(protoPkg string, rootMessage []string) ([ } var unstructuredFields [][]string for _, field := range root.Fields { - fieldPath := []string{strcase.ToLowerCamel(field.Field.GetName())} + rawFieldPath := []string{strcase.ToLowerCamel(field.Field.GetName())} if field.Field.GetLabel() == descriptor.FieldDescriptorProto_LABEL_REPEATED { // arrays become the path element '*' in the cue openapi builder - fieldPath = append(fieldPath, "*") + rawFieldPath = append(rawFieldPath, "*") + } + + // Cue does not include "value" in it's path so we have to remove it from + // the fieldPath when it's included in map messages + var fieldPath []string + for _, fieldStr := range rawFieldPath { + if fieldStr != "value" { + fieldPath = append(fieldPath, fieldStr) + } } if field.OpenAPIValidationDisabled { @@ -71,7 +80,6 @@ func (o Options) getUnstructuredFields(protoPkg string, rootMessage []string) ([ // the field is a primitive type continue case descriptor.FieldDescriptorProto_TYPE_MESSAGE: - // TODO: verify this works with map types } // check if this field has any unstructured fields in its children diff --git a/codegen/test/api/things.test.io/v1/test_api.pb.go b/codegen/test/api/things.test.io/v1/test_api.pb.go index a7bc4e73c..8f2d08b6f 100644 --- a/codegen/test/api/things.test.io/v1/test_api.pb.go +++ b/codegen/test/api/things.test.io/v1/test_api.pb.go @@ -373,8 +373,9 @@ type PaintStatus struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ObservedGeneration int64 `protobuf:"varint,1,opt,name=observedGeneration,proto3" json:"observedGeneration,omitempty"` - PercentRemaining int64 `protobuf:"varint,2,opt,name=percentRemaining,proto3" json:"percentRemaining,omitempty"` + ObservedGeneration int64 `protobuf:"varint,1,opt,name=observedGeneration,proto3" json:"observedGeneration,omitempty"` + PercentRemaining int64 `protobuf:"varint,2,opt,name=percentRemaining,proto3" json:"percentRemaining,omitempty"` + NearbyPaints map[string]*PaintStatus_Location `protobuf:"bytes,3,rep,name=nearbyPaints,proto3" json:"nearbyPaints,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *PaintStatus) Reset() { @@ -423,6 +424,13 @@ func (x *PaintStatus) GetPercentRemaining() int64 { return 0 } +func (x *PaintStatus) GetNearbyPaints() map[string]*PaintStatus_Location { + if x != nil { + return x.NearbyPaints + } + return nil +} + type ClusterResourceSpec struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -526,6 +534,61 @@ func (x *PaintSpec_RecursiveType) GetRepeatedRecursiveField() []*PaintSpec_Recur return nil } +type PaintStatus_Location struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + X string `protobuf:"bytes,1,opt,name=x,proto3" json:"x,omitempty"` + Y string `protobuf:"bytes,2,opt,name=y,proto3" json:"y,omitempty"` +} + +func (x *PaintStatus_Location) Reset() { + *x = PaintStatus_Location{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_solo_io_skv2_codegen_test_test_api_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PaintStatus_Location) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PaintStatus_Location) ProtoMessage() {} + +func (x *PaintStatus_Location) ProtoReflect() protoreflect.Message { + mi := &file_github_com_solo_io_skv2_codegen_test_test_api_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PaintStatus_Location.ProtoReflect.Descriptor instead. +func (*PaintStatus_Location) Descriptor() ([]byte, []int) { + return file_github_com_solo_io_skv2_codegen_test_test_api_proto_rawDescGZIP(), []int{4, 1} +} + +func (x *PaintStatus_Location) GetX() string { + if x != nil { + return x.X + } + return "" +} + +func (x *PaintStatus_Location) GetY() string { + if x != nil { + return x.Y + } + return "" +} + var File_github_com_solo_io_skv2_codegen_test_test_api_proto protoreflect.FileDescriptor var file_github_com_solo_io_skv2_codegen_test_test_api_proto_rawDesc = []byte{ @@ -589,23 +652,38 @@ var file_github_com_solo_io_skv2_codegen_test_test_api_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x70, 0x6f, 0x77, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x05, 0x66, 0x6c, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x66, 0x6c, 0x75, 0x69, 0x64, 0x42, 0x0d, 0x0a, 0x0b, 0x70, 0x69, 0x67, 0x6d, 0x65, 0x6e, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0x69, 0x0a, 0x0b, 0x50, 0x61, 0x69, 0x6e, 0x74, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x12, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x10, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, - 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, - 0x22, 0x4f, 0x0a, 0x13, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x38, 0x0a, 0x08, 0x69, 0x6d, 0x70, 0x6f, 0x72, - 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x42, 0x3c, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x73, 0x6f, 0x6c, 0x6f, 0x2d, 0x69, 0x6f, 0x2f, 0x73, 0x6b, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x64, - 0x65, 0x67, 0x65, 0x6e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x74, 0x68, - 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6f, 0x2f, 0x76, 0x31, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0xd9, 0x02, 0x0a, 0x0b, 0x50, 0x61, 0x69, 0x6e, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x64, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x12, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x10, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, + 0x52, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x10, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, + 0x67, 0x12, 0x51, 0x0a, 0x0c, 0x6e, 0x65, 0x61, 0x72, 0x62, 0x79, 0x50, 0x61, 0x69, 0x6e, 0x74, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, + 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6f, 0x2e, 0x50, 0x61, 0x69, 0x6e, 0x74, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4e, 0x65, 0x61, 0x72, 0x62, 0x79, 0x50, 0x61, 0x69, 0x6e, 0x74, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x6e, 0x65, 0x61, 0x72, 0x62, 0x79, 0x50, 0x61, + 0x69, 0x6e, 0x74, 0x73, 0x1a, 0x65, 0x0a, 0x11, 0x4e, 0x65, 0x61, 0x72, 0x62, 0x79, 0x50, 0x61, + 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3a, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x68, 0x69, + 0x6e, 0x67, 0x73, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6f, 0x2e, 0x50, 0x61, 0x69, 0x6e, + 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x34, 0x0a, 0x08, 0x4c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x0a, 0x01, 0x78, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x05, 0xea, 0x42, 0x02, 0x10, 0x01, 0x52, 0x01, 0x78, 0x12, 0x13, 0x0a, 0x01, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x05, 0xea, 0x42, 0x02, 0x10, 0x01, 0x52, 0x01, + 0x79, 0x22, 0x4f, 0x0a, 0x13, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x38, 0x0a, 0x08, 0x69, 0x6d, 0x70, 0x6f, + 0x72, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, + 0x65, 0x64, 0x42, 0x3c, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x73, 0x6f, 0x6c, 0x6f, 0x2d, 0x69, 0x6f, 0x2f, 0x73, 0x6b, 0x76, 0x32, 0x2f, 0x63, 0x6f, + 0x64, 0x65, 0x67, 0x65, 0x6e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x74, + 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6f, 0x2f, 0x76, 0x31, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -621,7 +699,7 @@ func file_github_com_solo_io_skv2_codegen_test_test_api_proto_rawDescGZIP() []by } var file_github_com_solo_io_skv2_codegen_test_test_api_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_github_com_solo_io_skv2_codegen_test_test_api_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_github_com_solo_io_skv2_codegen_test_test_api_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_github_com_solo_io_skv2_codegen_test_test_api_proto_goTypes = []interface{}{ (AcrylicType_Body)(0), // 0: things.test.io.AcrylicType.Body (*PaintSpec)(nil), // 1: things.test.io.PaintSpec @@ -631,24 +709,28 @@ var file_github_com_solo_io_skv2_codegen_test_test_api_proto_goTypes = []interfa (*PaintStatus)(nil), // 5: things.test.io.PaintStatus (*ClusterResourceSpec)(nil), // 6: things.test.io.ClusterResourceSpec (*PaintSpec_RecursiveType)(nil), // 7: things.test.io.PaintSpec.RecursiveType - (*any.Any)(nil), // 8: google.protobuf.Any - (*wrappers.StringValue)(nil), // 9: google.protobuf.StringValue + nil, // 8: things.test.io.PaintStatus.NearbyPaintsEntry + (*PaintStatus_Location)(nil), // 9: things.test.io.PaintStatus.Location + (*any.Any)(nil), // 10: google.protobuf.Any + (*wrappers.StringValue)(nil), // 11: google.protobuf.StringValue } var file_github_com_solo_io_skv2_codegen_test_test_api_proto_depIdxs = []int32{ - 2, // 0: things.test.io.PaintSpec.color:type_name -> things.test.io.PaintColor - 3, // 1: things.test.io.PaintSpec.acrylic:type_name -> things.test.io.AcrylicType - 4, // 2: things.test.io.PaintSpec.oil:type_name -> things.test.io.OilType - 8, // 3: things.test.io.PaintSpec.my_favorite:type_name -> google.protobuf.Any - 7, // 4: things.test.io.PaintSpec.recursive_type:type_name -> things.test.io.PaintSpec.RecursiveType - 0, // 5: things.test.io.AcrylicType.body:type_name -> things.test.io.AcrylicType.Body - 9, // 6: things.test.io.ClusterResourceSpec.imported:type_name -> google.protobuf.StringValue - 7, // 7: things.test.io.PaintSpec.RecursiveType.recursive_field:type_name -> things.test.io.PaintSpec.RecursiveType - 7, // 8: things.test.io.PaintSpec.RecursiveType.repeated_recursive_field:type_name -> things.test.io.PaintSpec.RecursiveType - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 2, // 0: things.test.io.PaintSpec.color:type_name -> things.test.io.PaintColor + 3, // 1: things.test.io.PaintSpec.acrylic:type_name -> things.test.io.AcrylicType + 4, // 2: things.test.io.PaintSpec.oil:type_name -> things.test.io.OilType + 10, // 3: things.test.io.PaintSpec.my_favorite:type_name -> google.protobuf.Any + 7, // 4: things.test.io.PaintSpec.recursive_type:type_name -> things.test.io.PaintSpec.RecursiveType + 0, // 5: things.test.io.AcrylicType.body:type_name -> things.test.io.AcrylicType.Body + 8, // 6: things.test.io.PaintStatus.nearbyPaints:type_name -> things.test.io.PaintStatus.NearbyPaintsEntry + 11, // 7: things.test.io.ClusterResourceSpec.imported:type_name -> google.protobuf.StringValue + 7, // 8: things.test.io.PaintSpec.RecursiveType.recursive_field:type_name -> things.test.io.PaintSpec.RecursiveType + 7, // 9: things.test.io.PaintSpec.RecursiveType.repeated_recursive_field:type_name -> things.test.io.PaintSpec.RecursiveType + 9, // 10: things.test.io.PaintStatus.NearbyPaintsEntry.value:type_name -> things.test.io.PaintStatus.Location + 11, // [11:11] is the sub-list for method output_type + 11, // [11:11] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_github_com_solo_io_skv2_codegen_test_test_api_proto_init() } @@ -741,6 +823,18 @@ func file_github_com_solo_io_skv2_codegen_test_test_api_proto_init() { return nil } } + file_github_com_solo_io_skv2_codegen_test_test_api_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PaintStatus_Location); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_github_com_solo_io_skv2_codegen_test_test_api_proto_msgTypes[0].OneofWrappers = []interface{}{ (*PaintSpec_Acrylic)(nil), @@ -756,7 +850,7 @@ func file_github_com_solo_io_skv2_codegen_test_test_api_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_github_com_solo_io_skv2_codegen_test_test_api_proto_rawDesc, NumEnums: 1, - NumMessages: 7, + NumMessages: 9, NumExtensions: 0, NumServices: 0, }, diff --git a/codegen/test/chart/crds/things.test.io_v1_crds.yaml b/codegen/test/chart/crds/things.test.io_v1_crds.yaml index f09e5ec99..c6ee76330 100644 --- a/codegen/test/chart/crds/things.test.io_v1_crds.yaml +++ b/codegen/test/chart/crds/things.test.io_v1_crds.yaml @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: aa25e4ed1772db41 + crd.solo.io/specHash: d651a92d5426c5e5 labels: app: "" app.kubernetes.io/name: "" @@ -105,6 +105,17 @@ spec: type: object status: properties: + nearbyPaints: + additionalProperties: + properties: + x: + type: object + x-kubernetes-preserve-unknown-fields: true + "y": + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + type: object observedGeneration: format: int64 type: integer diff --git a/codegen/test/test_api.proto b/codegen/test/test_api.proto index f27c6bb97..4a52a90d7 100644 --- a/codegen/test/test_api.proto +++ b/codegen/test/test_api.proto @@ -54,6 +54,12 @@ message OilType { message PaintStatus { int64 observedGeneration = 1; int64 percentRemaining = 2; + map nearbyPaints = 3; + + message Location { + string x = 1 [(cue.opt).disable_openapi_validation = true]; + string y = 2 [(cue.opt).disable_openapi_validation = true]; + } } message ClusterResourceSpec {