Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
483 changes: 335 additions & 148 deletions golden-file-tests/apidocs_golden.swagger.json

Large diffs are not rendered by default.

543 changes: 350 additions & 193 deletions golden-file-tests/apidocs_golden_preview_visibility.swagger.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Directory containing the protobuf files
mkdir -p proto
cp -a src/** proto/
cp -a deps/** proto/
proto_dir="proto"
go_out_dir="internal"
mod_prefix="github.com/coralogix"
mod_name="$mod_prefix/openapi-facade/go"
proto_files=($(find "$proto_dir" -name "*.proto" -print))
openapi_args=""

# Build arguments for import paths of all modules
for proto_file in "${proto_files[@]}"
do
out_module=$(dirname $proto_file)

if [[ $out_module == *"coralogix"* ]]; then
mod_path="${out_module##*/com/}"
# For all other protos, the package path is the same as the directory path
openapi_args+="--openapiv3_opt=M${proto_file##*$proto_dir/}=${mod_name}/${go_out_dir}/${mod_path} "
fi
done

protofile_list=""

for proto_file in "${proto_files[@]}"
do
protofile_list+="${proto_file} "
done

protoc --proto_path=$proto_dir --openapiv3_out=.. --openapiv3_opt=allow_merge=true,ignore_additional_bindings=true,openapi_naming_strategy=simple,visibility_restriction_selectors=PREVIEW $openapi_args $protofile_list
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,25 @@ message Thing {
optional google.protobuf.Timestamp created_at = 4 [(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"2021-01-01T00:00:00Z\""}];
NestedStruct nested_field = 5;
string preview_field = 6 [(google.api.field_visibility).restriction = "PREVIEW"];
ThingType thing_type = 7 [(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"THING_TYPE_STANDARD\""}];
oneof polymorphic_field {
PolymorphicVariantA variant_a = 8;
PolymorphicVariantB variant_b = 9;
}
}

message NestedStruct {
int32 numeric_field = 1;
string string_field = 2;
}

message PolymorphicVariantA {
string field_a = 1;
}

message PolymorphicVariantB {
int32 field_b = 1;
}

enum ThingType {
option (grpc.gateway.protoc_gen_openapiv3.options.openapiv3_enum) = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "com/coralogixapis/thing/v1/thing.proto";
import "google/api/annotations.proto";
import "google/api/http.proto";
import "google/api/visibility.proto";
import "google/protobuf/timestamp.proto";
import "protoc-gen-openapiv3/options/annotations.proto";

// ThingService is the service for managing things.
Expand All @@ -18,8 +19,8 @@ service ThingService {
// RPC for creating a thing.
rpc CreateThing(CreateThingRequest) returns (CreateThingResponse) {
option (google.api.http) = {
post: "/v1/things/{thing.nested_field.numeric_field}"
body: "thing.name"
post: "/v1/things"
body: "*"
};

option (grpc.gateway.protoc_gen_openapiv3.options.openapiv3_operation) = {
Expand All @@ -44,7 +45,7 @@ service ThingService {
rpc PreviewMethod(CreateThingRequest) returns (CreateThingResponse) {
option (google.api.http) = {
post: "/v1/things/preview"
body: "thing.name"
body: "*"
};
option (google.api.method_visibility).restriction = "PREVIEW";

Expand All @@ -71,8 +72,8 @@ service ThingService {
// RPC for replacing a thing.
rpc ReplaceThing(ReplaceThingRequest) returns (ReplaceThingResponse) {
option (google.api.http) = {
put: "/v1/things/{thing.id}"
body: "*"
put: "/v1/things/{thing_id}"
body: "thing"
};

option (grpc.gateway.protoc_gen_openapiv3.options.openapiv3_operation) = {
Expand Down Expand Up @@ -139,7 +140,7 @@ service ThingService {

// RPC for listing things with pagination.
rpc ListThings(ListThingsRequest) returns (ListThingsResponse) {
option (google.api.http) = {get: "/v1/things"};
option (google.api.http) = {get: "/v1/things/{page_size}"};

option (grpc.gateway.protoc_gen_openapiv3.options.openapiv3_operation) = {
responses: {
Expand All @@ -162,9 +163,21 @@ service ThingService {

// CreateThingRequest is the request for the CreateThing RPC.
message CreateThingRequest {
// The thing to create.
Thing thing = 1;
string a_query_parameter = 2;
// ID is the unique identifier of the thing.
string id = 1 [(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"123e4567-e89b-12d3-a456-426614174000\""}];

// Name of the thing.
string name = 2 [(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"A Thing's Name\""}];

// Creation timestamp of the thing.
optional google.protobuf.Timestamp created_at = 4 [(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"2021-01-01T00:00:00Z\""}];
NestedStruct nested_field = 5;
string preview_field = 6 [(google.api.field_visibility).restriction = "PREVIEW"];
ThingType thing_type = 7 [(grpc.gateway.protoc_gen_openapiv3.options.openapiv3_field) = {example: "\"THING_TYPE_STANDARD\""}];
oneof polymorphic_field {
PolymorphicVariantA variant_a = 8;
PolymorphicVariantB variant_b = 9;
}
}

// CreateThingResponse is the response for the CreateThing RPC.
Expand All @@ -176,16 +189,16 @@ message CreateThingResponse {
// ListThingsRequest is the request for the ListThings RPC.
message ListThingsRequest {
// The filter.
optional string filter = 1; // use whatever type is actually required
string filter = 1; // use whatever type is actually required

// The page size.
optional int32 page_size = 2;
int32 page_size = 2;

// The skip count.
optional int32 skip = 3;
int32 skip = 3;

// The page token.
optional string page_token = 4;
string page_token = 4;
}

// ListThingsResponse is the response for the ListThings RPC.
Expand All @@ -203,6 +216,7 @@ message ListThingsResponse {
// ReplaceThingRequest is the request for the ReplaceThing RPC.
message ReplaceThingRequest {
// The thing to replace.
string thing_id = 2;
Thing thing = 1;
}

Expand Down
20 changes: 17 additions & 3 deletions golden-file-tests/run_golden_file_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,24 @@
cd cx-api && bash build_facade_files.sh
cd ..

if diff <(jq --sort-keys . apidocs_golden.swagger.json) <(jq --sort-keys . apidocs.swagger.json) > /dev/null; then
echo "Plugin output matches golden file."
if diff <(jq --sort-keys . apidocs_golden.swagger.json | jq 'walk(if type == "object" and has("oneOf") and (.oneOf | type) == "array" then .oneOf |= sort_by(."$ref") else . end)') \
<(jq --sort-keys . apidocs.swagger.json | jq 'walk(if type == "object" and has("oneOf") and (.oneOf | type) == "array" then .oneOf |= sort_by(."$ref") else . end)') > /dev/null; then
echo "Plugin output matches golden file without preview visibility."
else
echo "Plugin output does not match golden file."
echo "Plugin output does not match golden file without preview visibility."
exit 1
fi

rm -r apidocs.swagger.json

cd cx-api && bash build_facade_files_with_preview_visibility.sh
cd ..

if diff <(jq --sort-keys . apidocs_golden_preview_visibility.swagger.json | jq 'walk(if type == "object" and has("oneOf") and (.oneOf | type) == "array" then .oneOf |= sort_by(."$ref") else . end)') \
<(jq --sort-keys . apidocs.swagger.json | jq 'walk(if type == "object" and has("oneOf") and (.oneOf | type) == "array" then .oneOf |= sort_by(."$ref") else . end)') > /dev/null; then
echo "Plugin output matches golden file with preview visibility."
else
echo "Plugin output does not match golden file with preview visibility."
exit 1
fi

Expand Down
30 changes: 30 additions & 0 deletions protoc-gen-openapiv3/internal/genopenapi/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@

package genopenapi

import (
"strings"
"unicode"
)

// this method will filter the same fields and return the unique one
func getUniqueFields(schemaFieldsRequired []string, fieldsRequired []string) []string {
var unique []string
Expand All @@ -23,3 +28,28 @@ func getUniqueFields(schemaFieldsRequired []string, fieldsRequired []string) []s
}
return unique
}

func toPascalCase(s string) string {
if s == "" {
return ""
}

var builder strings.Builder
capitalizeNext := true

for _, r := range s {
if r == '_' {
capitalizeNext = true
continue // Skip the underscore itself
}

if capitalizeNext {
builder.WriteRune(unicode.ToUpper(r))
capitalizeNext = false // Reset the flag
} else {
builder.WriteRune(r)
}
}

return builder.String()
}
Loading
Loading