Skip to content

Commit 872d84b

Browse files
authored
fix oneOf rendering when the oneOf field value is a proto Struct/Value (#21)
oneOf schema for a proto oneof containing an opaque field (Struct/Value) were not being generated. This fixes it. Signed-off-by: Shashank Ram <[email protected]>
1 parent 510e2d5 commit 872d84b

File tree

6 files changed

+149
-6
lines changed

6 files changed

+149
-6
lines changed

changelog/v0.2.1/oneof-fix.yaml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
changelog:
2+
- type: FIX
3+
issueLink: https://github.com/solo-io/protoc-gen-openapi/issues/20
4+
resolvesIssue: true
5+
description: |
6+
Adds support for the following:
7+
- encodes proto oneof to OpenAPI oneOf schema
8+
- multi-line descriptions for properties when using yaml=true
9+
- fixes uint32 schema to use min-max and not int32 format
10+
- adds proto for custom field options support
11+
- updates go protobuf packages to use new lib as per https://protobuf.dev/reference/go/faq/#versions
12+
- build changes for proto code generation

integration_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ func TestOpenAPIGeneration(t *testing.T) {
3232
perPackage bool
3333
genOpts string
3434
inputFiles map[string][]string
35+
protocArgs []string
3536
wantFiles []string
3637
}{
3738
{

openapiGenerator.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,12 @@ func (g *openapiGenerator) generateMessageSchema(message *protomodel.MessageDesc
426426
fieldDesc := g.generateDescription(field)
427427
fieldRules := g.validationRules(field)
428428

429+
// If the field is a oneof, we need to add the oneof property to the schema
430+
if field.OneofIndex != nil {
431+
idx := *field.OneofIndex
432+
oneOfFields[idx] = append(oneOfFields[idx], fieldName)
433+
}
434+
429435
schemaType := g.markerRegistry.GetSchemaType(fieldRules)
430436
if schemaType != "" {
431437
tmp := getSoloSchemaForMarkerType(schemaType)
@@ -439,12 +445,6 @@ func (g *openapiGenerator) generateMessageSchema(message *protomodel.MessageDesc
439445
sr := g.fieldTypeRef(field)
440446
g.markerRegistry.MustApplyRulesToSchema(fieldRules, sr.Value, markers.TargetType)
441447
o.WithProperty(fieldName, sr.Value)
442-
443-
// If the field is a oneof, we need to add the oneof property to the schema
444-
if field.OneofIndex != nil {
445-
idx := *field.OneofIndex
446-
oneOfFields[idx] = append(oneOfFields[idx], fieldName)
447-
}
448448
}
449449

450450
if g.protoOneof {

testdata/golden/test5/openapiv3.yaml

+22
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@ components:
22
schemas:
33
test5.Msg:
44
description: This is a top-level message.
5+
oneOf:
6+
- not:
7+
anyOf:
8+
- required:
9+
- oa
10+
- required:
11+
- ob
12+
- required:
13+
- oc
14+
- required:
15+
- oa
16+
- required:
17+
- ob
18+
- required:
19+
- oc
520
properties:
621
list:
722
items:
@@ -25,6 +40,13 @@ components:
2540
rule: self.b != 'default'
2641
nonNested:
2742
type: string
43+
oa:
44+
type: string
45+
ob:
46+
x-kubernetes-preserve-unknown-fields: true
47+
oc:
48+
type: object
49+
x-kubernetes-preserve-unknown-fields: true
2850
recursiveObj:
2951
description: Recursive object.
3052
items:

testdata/struct.proto

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Protocol Buffers - Google's data interchange format
2+
// Copyright 2008 Google Inc. All rights reserved.
3+
// https://developers.google.com/protocol-buffers/
4+
//
5+
// Redistribution and use in source and binary forms, with or without
6+
// modification, are permitted provided that the following conditions are
7+
// met:
8+
//
9+
// * Redistributions of source code must retain the above copyright
10+
// notice, this list of conditions and the following disclaimer.
11+
// * Redistributions in binary form must reproduce the above
12+
// copyright notice, this list of conditions and the following disclaimer
13+
// in the documentation and/or other materials provided with the
14+
// distribution.
15+
// * Neither the name of Google Inc. nor the names of its
16+
// contributors may be used to endorse or promote products derived from
17+
// this software without specific prior written permission.
18+
//
19+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30+
31+
syntax = "proto3";
32+
33+
package google.protobuf;
34+
35+
option cc_enable_arenas = true;
36+
option go_package = "google.golang.org/protobuf/types/known/structpb";
37+
option java_package = "com.google.protobuf";
38+
option java_outer_classname = "StructProto";
39+
option java_multiple_files = true;
40+
option objc_class_prefix = "GPB";
41+
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
42+
43+
// `Struct` represents a structured data value, consisting of fields
44+
// which map to dynamically typed values. In some languages, `Struct`
45+
// might be supported by a native representation. For example, in
46+
// scripting languages like JS a struct is represented as an
47+
// object. The details of that representation are described together
48+
// with the proto support for the language.
49+
//
50+
// The JSON representation for `Struct` is JSON object.
51+
message Struct {
52+
// Unordered map of dynamically typed values.
53+
map<string, Value> fields = 1;
54+
}
55+
56+
// `Value` represents a dynamically typed value which can be either
57+
// null, a number, a string, a boolean, a recursive struct value, or a
58+
// list of values. A producer of value is expected to set one of these
59+
// variants. Absence of any variant indicates an error.
60+
//
61+
// The JSON representation for `Value` is JSON value.
62+
message Value {
63+
// The kind of value.
64+
oneof kind {
65+
// Represents a null value.
66+
NullValue null_value = 1;
67+
// Represents a double value.
68+
double number_value = 2;
69+
// Represents a string value.
70+
string string_value = 3;
71+
// Represents a boolean value.
72+
bool bool_value = 4;
73+
// Represents a structured value.
74+
Struct struct_value = 5;
75+
// Represents a repeated `Value`.
76+
ListValue list_value = 6;
77+
}
78+
}
79+
80+
// `NullValue` is a singleton enumeration to represent the null value for the
81+
// `Value` type union.
82+
//
83+
// The JSON representation for `NullValue` is JSON `null`.
84+
enum NullValue {
85+
// Null value.
86+
NULL_VALUE = 0;
87+
}
88+
89+
// `ListValue` is a wrapper around a repeated field of values.
90+
//
91+
// The JSON representation for `ListValue` is JSON array.
92+
message ListValue {
93+
// Repeated field of dynamically typed values.
94+
repeated Value values = 1;
95+
}

testdata/test5/rules.proto

+13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ syntax = "proto3";
22

33
package test5;
44

5+
import "struct.proto";
6+
57
// This is a top-level message.
68
//
79
// +kubebuilder:validation:XValidation:rule="self.msgNested.a > 0",message="must be a postive value"
@@ -29,6 +31,17 @@ message Msg {
2931
// +kubebuilder:validation:XValidation:rule="self.x = 1"
3032
repeated Recursive recursive_val = 5;
3133

34+
// OneOf message.
35+
oneof oneof_field {
36+
string oa = 6;
37+
38+
// +kubebuilder:validation:Type=value
39+
google.protobuf.Value ob = 7;
40+
41+
// +kubebuilder:validation:Type=object
42+
google.protobuf.Struct oc = 8;
43+
}
44+
3245
// This is a nested message.
3346
//
3447
// +kubebuilder:validation:XValidation:rule="self.a > 0",message="must be a postive value"

0 commit comments

Comments
 (0)