From 1e55ddce82fd1d948dee3bed656d48c1623a63da Mon Sep 17 00:00:00 2001 From: Filip Gschwandtner Date: Thu, 4 Feb 2021 18:49:32 +0100 Subject: [PATCH 01/10] feat: added external proto to jsonschema converter into ligato code Signed-off-by: Filip Gschwandtner --- go.mod | 4 + go.sum | 15 + plugins/restapi/jsonschema/README.md | 6 + .../restapi/jsonschema/converter/converter.go | 266 +++++++++ .../jsonschema/converter/converter_test.go | 317 +++++++++++ .../jsonschema/converter/proto_package.go | 167 ++++++ .../jsonschema/converter/sourcecodeinfo.go | 116 ++++ .../converter/sourcecodeinfo_test.go | 53 ++ .../jsonschema/converter/testdata/README.md | 6 + .../converter/testdata/array_of_enums.go | 27 + .../converter/testdata/array_of_messages.go | 61 ++ .../converter/testdata/array_of_objects.go | 127 +++++ .../converter/testdata/array_of_primitives.go | 201 +++++++ .../converter/testdata/cyclical_reference.go | 185 ++++++ .../converter/testdata/enum_ception.go | 120 ++++ .../converter/testdata/enum_imported.go | 29 + .../testdata/enum_nested_reference.go | 33 ++ .../converter/testdata/enum_with_message.go | 27 + .../converter/testdata/first_enum.go | 23 + .../converter/testdata/first_message.go | 24 + .../converter/testdata/google_value.go | 13 + .../converter/testdata/imported_enum.go | 23 + .../converter/testdata/json_fields.go | 28 + .../jsonschema/converter/testdata/maps.go | 69 +++ .../converter/testdata/message_kind_10.go | 25 + .../converter/testdata/message_kind_11.go | 113 ++++ .../converter/testdata/message_kind_12.go | 194 +++++++ .../testdata/message_with_comments.go | 14 + .../converter/testdata/nested_message.go | 57 ++ .../converter/testdata/nested_object.go | 57 ++ .../converter/testdata/payload_message.go | 48 ++ .../converter/testdata/payload_message_2.go | 56 ++ .../testdata/proto/ArrayOfEnums.proto | 13 + .../testdata/proto/ArrayOfMessages.proto | 9 + .../testdata/proto/ArrayOfObjects.proto | 26 + .../testdata/proto/ArrayOfPrimitives.proto | 10 + .../testdata/proto/CyclicalReference.proto | 21 + .../testdata/proto/EnumNestedReference.proto | 8 + .../testdata/proto/EnumWithMessage.proto | 12 + .../testdata/proto/Enumception.proto | 22 + .../testdata/proto/GoogleValue.proto | 8 + .../converter/testdata/proto/ImportEnum.proto | 8 + .../testdata/proto/ImportedEnum.proto | 9 + .../converter/testdata/proto/JSONFields.proto | 11 + .../converter/testdata/proto/Maps.proto | 10 + .../testdata/proto/MessageWithComments.proto | 9 + .../testdata/proto/NestedMessage.proto | 9 + .../testdata/proto/NestedObject.proto | 25 + .../converter/testdata/proto/NoPackage.proto | 9 + .../testdata/proto/PayloadMessage.proto | 20 + .../testdata/proto/PayloadMessage2.proto | 20 + .../testdata/proto/Proto2NestedMessage.proto | 25 + .../testdata/proto/Proto2NestedObject.proto | 25 + .../testdata/proto/Proto2Required.proto | 8 + .../testdata/proto/SelfReference.proto | 7 + .../testdata/proto/SeveralEnums.proto | 16 + .../testdata/proto/SeveralMessages.proto | 18 + .../converter/testdata/proto/Timestamp.proto | 8 + .../testdata/proto/TwelveMessages.proto | 109 ++++ .../converter/testdata/proto/WellKnown.proto | 11 + .../testdata/proto2_nested_message.go | 64 +++ .../testdata/proto2_nested_object.go | 69 +++ .../testdata/proto2_payload_message.go | 52 ++ .../converter/testdata/proto2_required.go | 21 + .../converter/testdata/second_enum.go | 23 + .../converter/testdata/second_message.go | 24 + .../converter/testdata/self_reference.go | 26 + .../converter/testdata/timestamp.go | 13 + .../converter/testdata/wellknown.go | 32 ++ plugins/restapi/jsonschema/converter/types.go | 531 ++++++++++++++++++ .../jsonschemas/ArrayOfEnums.jsonschema | 25 + .../jsonschemas/ArrayOfMessages.jsonschema | 125 +++++ .../jsonschemas/ArrayOfObjects.jsonschema | 125 +++++ .../jsonschemas/ArrayOfPrimitives.jsonschema | 100 ++++ .../jsonschemas/Enumception.jsonschema | 109 ++++ .../jsonschemas/FirstEnum.jsonschema | 21 + .../jsonschemas/FirstMessage.jsonschema | 22 + .../jsonschemas/GoogleValue.jsonschema | 17 + .../jsonschemas/ImportedEnum.jsonschema | 21 + .../jsonschemas/JSONFields.jsonschema | 32 ++ .../jsonschema/jsonschemas/Maps.jsonschema | 67 +++ .../jsonschemas/MessageKind10.jsonschema | 22 + .../jsonschemas/MessageKind11.jsonschema | 110 ++++ .../jsonschemas/MessageKind12.jsonschema | 198 +++++++ .../MessageWithComments.jsonschema | 12 + .../jsonschemas/NestedMessage.jsonschema | 55 ++ .../jsonschemas/NestedObject.jsonschema | 55 ++ .../jsonschemas/PayloadMessage.jsonschema | 46 ++ .../jsonschemas/PayloadMessage2.jsonschema | 54 ++ .../Proto2NestedMessage.jsonschema | 62 ++ .../jsonschemas/Proto2NestedObject.jsonschema | 67 +++ .../Proto2PayloadMessage.jsonschema | 50 ++ .../jsonschemas/Proto2Required.jsonschema | 19 + .../jsonschemas/SecondEnum.jsonschema | 21 + .../jsonschemas/SecondMessage.jsonschema | 22 + .../jsonschemas/Timestamp.jsonschema | 11 + .../jsonschemas/WellKnown.jsonschema | 49 ++ 97 files changed, 5362 insertions(+) create mode 100644 plugins/restapi/jsonschema/README.md create mode 100644 plugins/restapi/jsonschema/converter/converter.go create mode 100644 plugins/restapi/jsonschema/converter/converter_test.go create mode 100644 plugins/restapi/jsonschema/converter/proto_package.go create mode 100644 plugins/restapi/jsonschema/converter/sourcecodeinfo.go create mode 100644 plugins/restapi/jsonschema/converter/sourcecodeinfo_test.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/README.md create mode 100644 plugins/restapi/jsonschema/converter/testdata/array_of_enums.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/array_of_messages.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/array_of_objects.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/array_of_primitives.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/cyclical_reference.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/enum_ception.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/enum_imported.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/enum_nested_reference.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/enum_with_message.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/first_enum.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/first_message.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/google_value.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/imported_enum.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/json_fields.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/maps.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/message_kind_10.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/message_kind_11.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/message_kind_12.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/message_with_comments.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/nested_message.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/nested_object.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/payload_message.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/payload_message_2.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfEnums.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfMessages.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfObjects.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfPrimitives.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/CyclicalReference.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/EnumNestedReference.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/EnumWithMessage.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/Enumception.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/GoogleValue.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/ImportEnum.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/ImportedEnum.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/JSONFields.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/Maps.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/MessageWithComments.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/NestedMessage.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/NestedObject.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/NoPackage.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage2.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedMessage.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedObject.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/Proto2Required.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/SelfReference.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/SeveralEnums.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/SeveralMessages.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/Timestamp.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/TwelveMessages.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/WellKnown.proto create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto2_nested_message.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto2_nested_object.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto2_payload_message.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/proto2_required.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/second_enum.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/second_message.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/self_reference.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/timestamp.go create mode 100644 plugins/restapi/jsonschema/converter/testdata/wellknown.go create mode 100644 plugins/restapi/jsonschema/converter/types.go create mode 100644 plugins/restapi/jsonschema/jsonschemas/ArrayOfEnums.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/ArrayOfMessages.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/ArrayOfObjects.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/ArrayOfPrimitives.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/Enumception.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/FirstEnum.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/FirstMessage.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/GoogleValue.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/ImportedEnum.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/JSONFields.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/Maps.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/MessageKind10.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/MessageKind11.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/MessageKind12.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/MessageWithComments.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/NestedMessage.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/NestedObject.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/PayloadMessage.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/PayloadMessage2.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/Proto2NestedMessage.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/Proto2NestedObject.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/Proto2PayloadMessage.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/Proto2Required.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/SecondEnum.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/SecondMessage.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/Timestamp.jsonschema create mode 100644 plugins/restapi/jsonschema/jsonschemas/WellKnown.jsonschema diff --git a/go.mod b/go.mod index d6edac6030..3d76d64bad 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,9 @@ go 1.13 require ( git.fd.io/govpp.git v0.3.6-0.20200907135408-e517439567ad github.com/Shopify/sarama v1.20.1 // indirect + github.com/alecthomas/jsonschema v0.0.0-20200217214135-7152f22193c9 github.com/alicebob/miniredis v2.5.0+incompatible // indirect + github.com/chrusty/protoc-gen-jsonschema v0.0.0-20201201182816-de75f1b59c4e github.com/common-nighthawk/go-figure v0.0.0-20200609044655-c4b36f998cf2 github.com/coreos/bbolt v1.3.3 // indirect github.com/coreos/etcd v3.3.13+incompatible @@ -26,6 +28,7 @@ require ( github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-gateway v1.11.3 // indirect github.com/hashicorp/go-uuid v1.0.1 // indirect + github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 github.com/jhump/protoreflect v1.7.0 github.com/lunixbochs/struc v0.0.0-20200521075829-a4cb8d33dbbe github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936 @@ -44,6 +47,7 @@ require ( github.com/unrolled/render v0.0.0-20180914162206-b9786414de4d github.com/vishvananda/netlink v0.0.0-20180910184128-56b1bd27a9a3 github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc + github.com/xeipuuv/gojsonschema v1.1.0 github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036 // indirect go.ligato.io/cn-infra/v2 v2.5.0-alpha.0.20200313154441-b0d4c1b11c73 go.uber.org/multierr v1.2.0 // indirect diff --git a/go.sum b/go.sum index 14edc7eed7..1f6eb84092 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,8 @@ github.com/Shopify/sarama v1.20.1/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/Songmu/prompter v0.0.0-20150725163906-b5721e8d5566/go.mod h1:fNhSFBGC+sg+dZ7AqDHgq+xYiom23TeTESzUbO7PIrE= +github.com/alecthomas/jsonschema v0.0.0-20200217214135-7152f22193c9 h1:h+KAZEUnNceFhqyH46BgwH4lk8m6pdR/3x3h7IPn7VA= +github.com/alecthomas/jsonschema v0.0.0-20200217214135-7152f22193c9/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -51,6 +53,8 @@ github.com/bsm/sarama-cluster v2.1.15+incompatible/go.mod h1:r7ao+4tTNXvWm+VRpRJ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/chrusty/protoc-gen-jsonschema v0.0.0-20201201182816-de75f1b59c4e h1:VEDA+FrTIUnlSpMlo2i1e0L1hP45vek2ED+blYdOrxg= +github.com/chrusty/protoc-gen-jsonschema v0.0.0-20201201182816-de75f1b59c4e/go.mod h1:qYuJI3Nz/kjHcigPikCSSeh+pRGcCiT1U6qzWGEmaJ4= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -266,6 +270,8 @@ github.com/howeyc/crc16 v0.0.0-20171223171357-2b2a61e366a6 h1:IIVxLyDUYErC950b8k github.com/howeyc/crc16 v0.0.0-20171223171357-2b2a61e366a6/go.mod h1:JslaLRrzGsOKJgFEPBP65Whn+rdwDQSk0I0MCRFe2Zw= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk= +github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -281,6 +287,7 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -447,6 +454,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/tinylib/msgp v1.0.2 h1:DfdQrzQa7Yh2es9SuLkixqxuXS2SxsdYn0KbdrOGWD8= @@ -464,6 +472,12 @@ github.com/vishvananda/netlink v0.0.0-20180910184128-56b1bd27a9a3/go.mod h1:+SR5 github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/willfaught/gockle v0.0.0-20160623235217-4f254e1e0f0a/go.mod h1:NLcF+3nDpXVIZatjn5Z97gKzFFVU7TzgbAcs8G7/Jrs= +github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA= +github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.1.0 h1:ngVtJC9TY/lg0AA/1k48FYhBrhRoFlEmWzsehpNAaZg= +github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -560,6 +574,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/plugins/restapi/jsonschema/README.md b/plugins/restapi/jsonschema/README.md new file mode 100644 index 0000000000..61b363597c --- /dev/null +++ b/plugins/restapi/jsonschema/README.md @@ -0,0 +1,6 @@ +Initial commit changes: +extracted convertor out of internal package to be able to use it +removed convertor tests +relaxed some info level logging to debug level logging (proto_package.go, lines 78 and 121) + +other changes can be tracked by git changes in this package and its subpackages \ No newline at end of file diff --git a/plugins/restapi/jsonschema/converter/converter.go b/plugins/restapi/jsonschema/converter/converter.go new file mode 100644 index 0000000000..e2a1451f7b --- /dev/null +++ b/plugins/restapi/jsonschema/converter/converter.go @@ -0,0 +1,266 @@ +package converter + +import ( + "encoding/json" + "fmt" + "io" + "io/ioutil" + "path" + "regexp" + "strings" + + "github.com/alecthomas/jsonschema" + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/protoc-gen-go/descriptor" + plugin "github.com/golang/protobuf/protoc-gen-go/plugin" + "github.com/sirupsen/logrus" +) + +const ( + messageDelimiter = "+" +) + +// Converter is everything you need to convert protos to JSONSchemas: +type Converter struct { + AllFieldsRequired bool + AllowNullValues bool + DisallowAdditionalProperties bool + DisallowBigIntsAsStrings bool + PrefixSchemaFilesWithPackage bool + UseJSONFieldnamesOnly bool + UseProtoAndJSONFieldnames bool + logger *logrus.Logger + sourceInfo *sourceCodeInfo + messageTargets []string +} + +// New returns a configured *Converter: +func New(logger *logrus.Logger) *Converter { + return &Converter{ + logger: logger, + } +} + +// ConvertFrom tells the convert to work on the given input: +func (c *Converter) ConvertFrom(rd io.Reader) (*plugin.CodeGeneratorResponse, error) { + c.logger.Debug("Reading code generation request") + input, err := ioutil.ReadAll(rd) + if err != nil { + c.logger.WithError(err).Error("Failed to read request") + return nil, err + } + + req := &plugin.CodeGeneratorRequest{} + err = proto.Unmarshal(input, req) + if err != nil { + c.logger.WithError(err).Error("Can't unmarshal input") + return nil, err + } + + c.logger.Debug("Converting input") + return c.convert(req) +} + +func (c *Converter) parseGeneratorParameters(parameters string) { + for _, parameter := range strings.Split(parameters, ",") { + switch parameter { + case "all_fields_required": + c.AllFieldsRequired = true + case "allow_null_values": + c.AllowNullValues = true + case "debug": + c.logger.SetLevel(logrus.DebugLevel) + case "disallow_additional_properties": + c.DisallowAdditionalProperties = true + case "disallow_bigints_as_strings": + c.DisallowBigIntsAsStrings = true + case "json_fieldnames": + c.UseJSONFieldnamesOnly = true + case "prefix_schema_files_with_package": + c.PrefixSchemaFilesWithPackage = true + case "proto_and_json_fieldnames": + c.UseProtoAndJSONFieldnames = true + } + + // look for specific message targets + // message types are separated by messageDelimiter "+" + // examples: + // messages=[foo+bar] + // messages=[foo] + rx := regexp.MustCompile(`messages=\[([^\]]+)\]`) + if matches := rx.FindStringSubmatch(parameter); len(matches) == 2 { + c.messageTargets = strings.Split(matches[1], messageDelimiter) + } + } +} + +// Converts a proto "ENUM" into a JSON-Schema: +func (c *Converter) convertEnumType(enum *descriptor.EnumDescriptorProto) (jsonschema.Type, error) { + + // Prepare a new jsonschema.Type for our eventual return value: + jsonSchemaType := jsonschema.Type{ + Version: jsonschema.Version, + } + + // Generate a description from src comments (if available) + if src := c.sourceInfo.GetEnum(enum); src != nil { + jsonSchemaType.Description = formatDescription(src) + } + + // Allow both strings and integers: + jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: "string"}) + jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: "integer"}) + + // Add the allowed values: + for _, enumValue := range enum.Value { + jsonSchemaType.Enum = append(jsonSchemaType.Enum, enumValue.Name) + jsonSchemaType.Enum = append(jsonSchemaType.Enum, enumValue.Number) + } + + return jsonSchemaType, nil +} + +// Converts a proto file into a JSON-Schema: +func (c *Converter) convertFile(file *descriptor.FileDescriptorProto) ([]*plugin.CodeGeneratorResponse_File, error) { + // Input filename: + protoFileName := path.Base(file.GetName()) + + // Prepare a list of responses: + var response []*plugin.CodeGeneratorResponse_File + + // user wants specific messages + genSpecificMessages := len(c.messageTargets) > 0 + + // Warn about multiple messages / enums in files: + if !genSpecificMessages && len(file.GetMessageType()) > 1 { + c.logger.WithField("schemas", len(file.GetMessageType())).WithField("proto_filename", protoFileName).Warn("protoc-gen-jsonschema will create multiple MESSAGE schemas from one proto file") + } + + if len(file.GetEnumType()) > 1 { + c.logger.WithField("schemas", len(file.GetMessageType())).WithField("proto_filename", protoFileName).Warn("protoc-gen-jsonschema will create multiple ENUM schemas from one proto file") + } + + // Generate standalone ENUMs: + if len(file.GetMessageType()) == 0 { + for _, enum := range file.GetEnumType() { + jsonSchemaFileName := c.generateSchemaFilename(file, enum.GetName()) + c.logger.WithField("proto_filename", protoFileName).WithField("enum_name", enum.GetName()).WithField("jsonschema_filename", jsonSchemaFileName).Info("Generating JSON-schema for stand-alone ENUM") + + // Convert the ENUM: + enumJSONSchema, err := c.convertEnumType(enum) + if err != nil { + c.logger.WithError(err).WithField("proto_filename", protoFileName).Error("Failed to convert") + return nil, err + } + + // Marshal the JSON-Schema into JSON: + jsonSchemaJSON, err := json.MarshalIndent(enumJSONSchema, "", " ") + if err != nil { + c.logger.WithError(err).Error("Failed to encode jsonSchema") + return nil, err + } + + // Add a response: + resFile := &plugin.CodeGeneratorResponse_File{ + Name: proto.String(jsonSchemaFileName), + Content: proto.String(string(jsonSchemaJSON)), + } + response = append(response, resFile) + } + } else { + // Otherwise process MESSAGES (packages): + pkg, ok := c.relativelyLookupPackage(globalPkg, file.GetPackage()) + if !ok { + return nil, fmt.Errorf("no such package found: %s", file.GetPackage()) + } + + for _, msg := range file.GetMessageType() { + // skip if we are only generating schema for specific messages + if genSpecificMessages && !contains(c.messageTargets, msg.GetName()) { + continue + } + + jsonSchemaFileName := c.generateSchemaFilename(file, msg.GetName()) + c.logger.WithField("proto_filename", protoFileName).WithField("msg_name", msg.GetName()).WithField("jsonschema_filename", jsonSchemaFileName).Info("Generating JSON-schema for MESSAGE") + + // Convert the message: + messageJSONSchema, err := c.convertMessageType(pkg, msg) + if err != nil { + c.logger.WithError(err).WithField("proto_filename", protoFileName).Error("Failed to convert") + return nil, err + } + + // Marshal the JSON-Schema into JSON: + jsonSchemaJSON, err := json.MarshalIndent(messageJSONSchema, "", " ") + if err != nil { + c.logger.WithError(err).Error("Failed to encode jsonSchema") + return nil, err + } + + // Add a response: + resFile := &plugin.CodeGeneratorResponse_File{ + Name: proto.String(jsonSchemaFileName), + Content: proto.String(string(jsonSchemaJSON)), + } + response = append(response, resFile) + } + } + + return response, nil +} + +func (c *Converter) convert(req *plugin.CodeGeneratorRequest) (*plugin.CodeGeneratorResponse, error) { + c.parseGeneratorParameters(req.GetParameter()) + + generateTargets := make(map[string]bool) + for _, file := range req.GetFileToGenerate() { + generateTargets[file] = true + } + + c.sourceInfo = newSourceCodeInfo(req.GetProtoFile()) + res := &plugin.CodeGeneratorResponse{} + for _, file := range req.GetProtoFile() { + if file.GetPackage() == "" { + c.logger.WithField("filename", file.GetName()).Warn("Proto file doesn't specify a package") + continue + } + + for _, msg := range file.GetMessageType() { + c.logger.WithField("msg_name", msg.GetName()).WithField("package_name", file.GetPackage()).Debug("Loading a message") + c.registerType(file.Package, msg) + } + + for _, en := range file.GetEnumType() { + c.logger.WithField("enum_name", en.GetName()).WithField("package_name", file.GetPackage()).Debug("Loading an enum") + c.registerEnum(file.Package, en) + } + + if _, ok := generateTargets[file.GetName()]; ok { + c.logger.WithField("filename", file.GetName()).Debug("Converting file") + converted, err := c.convertFile(file) + if err != nil { + res.Error = proto.String(fmt.Sprintf("Failed to convert %s: %v", file.GetName(), err)) + return res, err + } + res.File = append(res.File, converted...) + } + } + return res, nil +} + +func (c *Converter) generateSchemaFilename(file *descriptor.FileDescriptorProto, protoName string) string { + if c.PrefixSchemaFilesWithPackage { + return fmt.Sprintf("%s/%s.jsonschema", file.GetPackage(), protoName) + } + return fmt.Sprintf("%s.jsonschema", protoName) +} + +func contains(haystack []string, needle string) bool { + for i := 0; i < len(haystack); i++ { + if haystack[i] == needle { + return true + } + } + + return false +} diff --git a/plugins/restapi/jsonschema/converter/converter_test.go b/plugins/restapi/jsonschema/converter/converter_test.go new file mode 100644 index 0000000000..8ed4e632ab --- /dev/null +++ b/plugins/restapi/jsonschema/converter/converter_test.go @@ -0,0 +1,317 @@ +package converter + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "strings" + "testing" + + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/protoc-gen-go/descriptor" + plugin "github.com/golang/protobuf/protoc-gen-go/plugin" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + + "go.ligato.io/vpp-agent/v3/examples/customize/custom_api_model/json_schema/converter/testdata" +) + +const ( + sampleProtoDirectory = "testdata/proto" +) + +type sampleProto struct { + AllFieldsRequired bool + AllowNullValues bool + ExpectedJSONSchema []string + FilesToGenerate []string + PrefixSchemaFilesWithPackage bool + ProtoFileName string + UseJSONFieldnamesOnly bool + UseProtoAndJSONFieldNames bool + TargetedMessages []string +} + +func TestGenerateJsonSchema(t *testing.T) { + + // Configure the list of sample protos to test, and their expected JSON-Schemas: + sampleProtos := configureSampleProtos() + + // Convert the protos, compare the results against the expected JSON-Schemas: + for name, sampleProto := range sampleProtos { + t.Run(name, func(t *testing.T) { + testConvertSampleProto(t, sampleProto) + }) + } +} + +func testConvertSampleProto(t *testing.T, sampleProto sampleProto) { + t.Helper() + + // Make a Logrus logger: + logger := logrus.New() + logger.SetLevel(logrus.ErrorLevel) + logger.SetOutput(os.Stderr) + + // Use the logger to make a Converter: + protoConverter := New(logger) + protoConverter.AllFieldsRequired = sampleProto.AllFieldsRequired + protoConverter.AllowNullValues = sampleProto.AllowNullValues + protoConverter.UseJSONFieldnamesOnly = sampleProto.UseJSONFieldnamesOnly + protoConverter.UseProtoAndJSONFieldnames = sampleProto.UseProtoAndJSONFieldNames + protoConverter.PrefixSchemaFilesWithPackage = sampleProto.PrefixSchemaFilesWithPackage + + // Open the sample proto file: + sampleProtoFileName := fmt.Sprintf("%v/%v", sampleProtoDirectory, sampleProto.ProtoFileName) + fileDescriptorSet := mustReadProtoFiles(t, sampleProtoDirectory, sampleProto.ProtoFileName) + + // Prepare a request: + codeGeneratorRequest := plugin.CodeGeneratorRequest{ + FileToGenerate: sampleProto.FilesToGenerate, + ProtoFile: fileDescriptorSet.GetFile(), + } + + if len(sampleProto.TargetedMessages) > 0 { + arg := fmt.Sprintf("messages=[%s]", strings.Join(sampleProto.TargetedMessages, messageDelimiter)) + codeGeneratorRequest.Parameter = &arg + } + + // Perform the conversion: + response, err := protoConverter.convert(&codeGeneratorRequest) + assert.NoError(t, err, "Unable to convert sample proto file (%v)", sampleProtoFileName) + assert.Equal(t, len(sampleProto.ExpectedJSONSchema), len(response.File), "Incorrect number of JSON-Schema files returned for sample proto file (%v)", sampleProtoFileName) + if len(sampleProto.ExpectedJSONSchema) != len(response.File) { + t.Fail() + } else { + for responseFileIndex, responseFile := range response.File { + assert.Equal(t, strings.TrimSpace(sampleProto.ExpectedJSONSchema[responseFileIndex]), *responseFile.Content, "Incorrect JSON-Schema returned for sample proto file (%v)", sampleProtoFileName) + } + } + + // Return now if we have no files: + if len(response.File) == 0 { + return + } + + // Check for the correct prefix: + if protoConverter.PrefixSchemaFilesWithPackage { + assert.Contains(t, response.File[0].GetName(), "samples") + } else { + assert.NotContains(t, response.File[0].GetName(), "samples") + } +} + +func configureSampleProtos() map[string]sampleProto { + return map[string]sampleProto{ + "ArrayOfMessages": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.PayloadMessage, testdata.ArrayOfMessages}, + FilesToGenerate: []string{"ArrayOfMessages.proto", "PayloadMessage.proto"}, + ProtoFileName: "ArrayOfMessages.proto", + }, + "ArrayOfObjects": { + AllowNullValues: true, + ExpectedJSONSchema: []string{testdata.ArrayOfObjects}, + FilesToGenerate: []string{"ArrayOfObjects.proto"}, + ProtoFileName: "ArrayOfObjects.proto", + }, + "ArrayOfPrimitives": { + AllowNullValues: true, + ExpectedJSONSchema: []string{testdata.ArrayOfPrimitives}, + FilesToGenerate: []string{"ArrayOfPrimitives.proto"}, + ProtoFileName: "ArrayOfPrimitives.proto", + }, + "ArrayOfPrimitivesDouble": { + AllowNullValues: true, + ExpectedJSONSchema: []string{testdata.ArrayOfPrimitivesDouble}, + FilesToGenerate: []string{"ArrayOfPrimitives.proto"}, + ProtoFileName: "ArrayOfPrimitives.proto", + UseProtoAndJSONFieldNames: true, + }, + "EnumNestedReference": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.EnumNestedReference}, + FilesToGenerate: []string{"EnumNestedReference.proto"}, + ProtoFileName: "EnumNestedReference.proto", + }, + "EnumWithMessage": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.EnumWithMessage}, + FilesToGenerate: []string{"EnumWithMessage.proto"}, + ProtoFileName: "EnumWithMessage.proto", + }, + "EnumImport": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.EnumImport}, + FilesToGenerate: []string{"ImportEnum.proto"}, + ProtoFileName: "ImportEnum.proto", + }, + "EnumCeption": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.PayloadMessage, testdata.ImportedEnum, testdata.EnumCeption}, + FilesToGenerate: []string{"Enumception.proto", "PayloadMessage.proto", "ImportedEnum.proto"}, + ProtoFileName: "Enumception.proto", + }, + "ImportedEnum": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.ImportedEnum}, + FilesToGenerate: []string{"ImportedEnum.proto"}, + ProtoFileName: "ImportedEnum.proto", + }, + "NestedMessage": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.PayloadMessage, testdata.NestedMessage}, + FilesToGenerate: []string{"NestedMessage.proto", "PayloadMessage.proto"}, + ProtoFileName: "NestedMessage.proto", + }, + "NestedObject": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.NestedObject}, + FilesToGenerate: []string{"NestedObject.proto"}, + ProtoFileName: "NestedObject.proto", + }, + "PayloadMessage": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.PayloadMessage}, + FilesToGenerate: []string{"PayloadMessage.proto"}, + ProtoFileName: "PayloadMessage.proto", + }, + "SeveralEnums": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.FirstEnum, testdata.SecondEnum}, + FilesToGenerate: []string{"SeveralEnums.proto"}, + ProtoFileName: "SeveralEnums.proto", + }, + "SeveralMessages": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.FirstMessage, testdata.SecondMessage}, + FilesToGenerate: []string{"SeveralMessages.proto"}, + ProtoFileName: "SeveralMessages.proto", + }, + "ArrayOfEnums": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.ArrayOfEnums}, + FilesToGenerate: []string{"ArrayOfEnums.proto"}, + ProtoFileName: "ArrayOfEnums.proto", + }, + "Maps": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.Maps}, + FilesToGenerate: []string{"Maps.proto"}, + ProtoFileName: "Maps.proto", + }, + "Comments": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.MessageWithComments}, + FilesToGenerate: []string{"MessageWithComments.proto"}, + ProtoFileName: "MessageWithComments.proto", + }, + "SelfReference": { + ExpectedJSONSchema: []string{testdata.SelfReference}, + FilesToGenerate: []string{"SelfReference.proto"}, + ProtoFileName: "SelfReference.proto", + }, + "CyclicalReference": { + ExpectedJSONSchema: []string{testdata.CyclicalReferenceMessageM, testdata.CyclicalReferenceMessageFoo, testdata.CyclicalReferenceMessageBar, testdata.CyclicalReferenceMessageBaz}, + FilesToGenerate: []string{"CyclicalReference.proto"}, + ProtoFileName: "CyclicalReference.proto", + }, + "WellKnown": { + ExpectedJSONSchema: []string{testdata.WellKnown}, + FilesToGenerate: []string{"WellKnown.proto"}, + ProtoFileName: "WellKnown.proto", + }, + "Timestamp": { + ExpectedJSONSchema: []string{testdata.Timestamp}, + FilesToGenerate: []string{"Timestamp.proto"}, + ProtoFileName: "Timestamp.proto", + }, + "NoPackage": { + ExpectedJSONSchema: []string{}, + FilesToGenerate: []string{}, + ProtoFileName: "NoPackage.proto", + }, + "PackagePrefix": { + ExpectedJSONSchema: []string{testdata.Timestamp}, + FilesToGenerate: []string{"Timestamp.proto"}, + ProtoFileName: "Timestamp.proto", + PrefixSchemaFilesWithPackage: true, + }, + "Proto2Required": { + ExpectedJSONSchema: []string{testdata.Proto2Required}, + FilesToGenerate: []string{"Proto2Required.proto"}, + ProtoFileName: "Proto2Required.proto", + }, + "AllRequired": { + AllFieldsRequired: true, + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.PayloadMessage2}, + FilesToGenerate: []string{"PayloadMessage2.proto"}, + ProtoFileName: "PayloadMessage2.proto", + }, + "Proto2NestedMessage": { + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.Proto2PayloadMessage, testdata.Proto2NestedMessage}, + FilesToGenerate: []string{"Proto2PayloadMessage.proto", "Proto2NestedMessage.proto"}, + ProtoFileName: "Proto2NestedMessage.proto", + }, + "Proto2NestedObject": { + AllFieldsRequired: true, + AllowNullValues: false, + ExpectedJSONSchema: []string{testdata.Proto2NestedObject}, + FilesToGenerate: []string{"Proto2NestedObject.proto"}, + ProtoFileName: "Proto2NestedObject.proto", + }, + "TargetedMessages": { + TargetedMessages: []string{"MessageKind10", "MessageKind11", "MessageKind12"}, + ExpectedJSONSchema: []string{testdata.MessageKind10, testdata.MessageKind11, testdata.MessageKind12}, + FilesToGenerate: []string{"TwelveMessages.proto"}, + ProtoFileName: "TwelveMessages.proto", + }, + "GoogleValue": { + ExpectedJSONSchema: []string{testdata.GoogleValue}, + FilesToGenerate: []string{"GoogleValue.proto"}, + ProtoFileName: "GoogleValue.proto", + }, + "JSONFields": { + ExpectedJSONSchema: []string{testdata.JSONFields}, + FilesToGenerate: []string{"JSONFields.proto"}, + ProtoFileName: "JSONFields.proto", + UseJSONFieldnamesOnly: true, + }, + } +} + +// Load the specified .proto files into a FileDescriptorSet. Any errors in loading/parsing will +// immediately fail the test. +func mustReadProtoFiles(t *testing.T, includePath string, filenames ...string) *descriptor.FileDescriptorSet { + protocBinary, err := exec.LookPath("protoc") + if err != nil { + t.Fatalf("Can't find 'protoc' binary in $PATH: %s", err.Error()) + } + + // Use protoc to output descriptor info for the specified .proto files. + var args []string + args = append(args, "--descriptor_set_out=/dev/stdout") + args = append(args, "--include_source_info") + args = append(args, "--include_imports") + args = append(args, "--proto_path="+includePath) + args = append(args, filenames...) + cmd := exec.Command(protocBinary, args...) + stdoutBuf := bytes.Buffer{} + stderrBuf := bytes.Buffer{} + cmd.Stdout = &stdoutBuf + cmd.Stderr = &stderrBuf + err = cmd.Run() + if err != nil { + t.Fatalf("failed to load descriptor set (%s): %s: %s", + strings.Join(cmd.Args, " "), err.Error(), stderrBuf.String()) + } + fds := &descriptor.FileDescriptorSet{} + err = proto.Unmarshal(stdoutBuf.Bytes(), fds) + if err != nil { + t.Fatalf("failed to parse protoc output as FileDescriptorSet: %s", err.Error()) + } + return fds +} diff --git a/plugins/restapi/jsonschema/converter/proto_package.go b/plugins/restapi/jsonschema/converter/proto_package.go new file mode 100644 index 0000000000..21ccab955d --- /dev/null +++ b/plugins/restapi/jsonschema/converter/proto_package.go @@ -0,0 +1,167 @@ +package converter + +import ( + "strings" + + "github.com/golang/protobuf/protoc-gen-go/descriptor" +) + +// ProtoPackage describes a package of Protobuf, which is an container of message types. +type ProtoPackage struct { + name string + parent *ProtoPackage + children map[string]*ProtoPackage + types map[string]*descriptor.DescriptorProto + enums map[string]*descriptor.EnumDescriptorProto +} + +func newProtoPackage(parent *ProtoPackage, name string) *ProtoPackage { + pkgName := name + if parent != nil { + pkgName = parent.name + "." + name + } + + return &ProtoPackage{ + name: pkgName, + parent: parent, + children: make(map[string]*ProtoPackage), + types: make(map[string]*descriptor.DescriptorProto), + enums: make(map[string]*descriptor.EnumDescriptorProto), + } +} + +func (c *Converter) lookupType(pkg *ProtoPackage, name string) (*descriptor.DescriptorProto, string, bool) { + if strings.HasPrefix(name, ".") { + return c.relativelyLookupType(globalPkg, name[1:]) + } + + for ; pkg != nil; pkg = pkg.parent { + if desc, pkgName, ok := c.relativelyLookupType(pkg, name); ok { + return desc, pkgName, ok + } + } + return nil, "", false +} + +func (c *Converter) lookupEnum(pkg *ProtoPackage, name string) (*descriptor.EnumDescriptorProto, string, bool) { + if strings.HasPrefix(name, ".") { + return c.relativelyLookupEnum(globalPkg, name[1:]) + } + + for ; pkg != nil; pkg = pkg.parent { + if desc, pkgName, ok := c.relativelyLookupEnum(pkg, name); ok { + return desc, pkgName, ok + } + } + return nil, "", false +} + +func (c *Converter) relativelyLookupType(pkg *ProtoPackage, name string) (*descriptor.DescriptorProto, string, bool) { + components := strings.SplitN(name, ".", 2) + switch len(components) { + case 0: + c.logger.Debug("empty message name") + return nil, "", false + case 1: + found, ok := pkg.types[components[0]] + return found, pkg.name, ok + case 2: + c.logger.Tracef("Looking for %s in %s at %s (%v)", components[1], components[0], pkg.name, pkg) + if child, ok := pkg.children[components[0]]; ok { + found, pkgName, ok := c.relativelyLookupType(child, components[1]) + return found, pkgName, ok + } + if msg, ok := pkg.types[components[0]]; ok { + found, ok := c.relativelyLookupNestedType(msg, components[1]) + return found, pkg.name, ok + } + c.logger.WithField("component", components[0]).WithField("package_name", pkg.name).Debug("No such package nor message in package") + return nil, "", false + default: + c.logger.Error("Failed to lookup type") + return nil, "", false + } +} + +func (c *Converter) relativelyLookupNestedType(desc *descriptor.DescriptorProto, name string) (*descriptor.DescriptorProto, bool) { + components := strings.Split(name, ".") +componentLoop: + for _, component := range components { + for _, nested := range desc.GetNestedType() { + if nested.GetName() == component { + desc = nested + continue componentLoop + } + } + c.logger.WithField("component", component).WithField("description", desc.GetName()).Info("no such nested message") + return nil, false + } + return desc, true +} + +func (c *Converter) relativelyLookupEnum(pkg *ProtoPackage, name string) (*descriptor.EnumDescriptorProto, string, bool) { + components := strings.SplitN(name, ".", 2) + switch len(components) { + case 0: + c.logger.Debug("empty enum name") + return nil, "", false + case 1: + found, ok := pkg.enums[components[0]] + return found, pkg.name, ok + case 2: + c.logger.Tracef("Looking for %s in %s at %s (%v)", components[1], components[0], pkg.name, pkg) + if child, ok := pkg.children[components[0]]; ok { + found, pkgName, ok := c.relativelyLookupEnum(child, components[1]) + return found, pkgName, ok + } + if msg, ok := pkg.types[components[0]]; ok { + found, ok := c.relativelyLookupNestedEnum(msg, components[1]) + return found, pkg.name, ok + } + c.logger.WithField("component", components[0]).WithField("package_name", pkg.name).Debug("No such package nor message in package") + return nil, "", false + default: + c.logger.Error("Failed to lookup type") + return nil, "", false + } +} + +func (c *Converter) relativelyLookupNestedEnum(desc *descriptor.DescriptorProto, name string) (*descriptor.EnumDescriptorProto, bool) { + components := strings.Split(name, ".") + + parent := desc + + if len(components) > 1 { + // The enum is nested inside a potentially nested message definition. + msgComponents := strings.Join(components[0:len(components)-1], ".") + var found bool + parent, found = c.relativelyLookupNestedType(parent, msgComponents) + if !found { + return nil, false + } + } + + // The enum is nested inside of a nested message. We need to dive down the + // tree to find the message the enum is nested in. Then we need to obtain the + // enum. + enumName := components[len(components)-1] + for _, enum := range parent.GetEnumType() { + if enum.GetName() == enumName { + return enum, true + } + } + + return nil, false +} + +func (c *Converter) relativelyLookupPackage(pkg *ProtoPackage, name string) (*ProtoPackage, bool) { + components := strings.Split(name, ".") + for _, c := range components { + var ok bool + pkg, ok = pkg.children[c] + if !ok { + return nil, false + } + } + return pkg, true +} diff --git a/plugins/restapi/jsonschema/converter/sourcecodeinfo.go b/plugins/restapi/jsonschema/converter/sourcecodeinfo.go new file mode 100644 index 0000000000..566a25b164 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/sourcecodeinfo.go @@ -0,0 +1,116 @@ +package converter + +import ( + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/protoc-gen-go/descriptor" +) + +// Protobuf tag values for relevant message fields. Full list here: +// https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/descriptor.proto +const ( + tag_FileDescriptor_messageType int32 = 4 + tag_FileDescriptor_enumType int32 = 5 + tag_Descriptor_field int32 = 2 + tag_Descriptor_nestedType int32 = 3 + tag_Descriptor_enumType int32 = 4 + tag_Descriptor_oneofDecl int32 = 8 + tag_EnumDescriptor_value int32 = 2 +) + +type sourceCodeInfo struct { + lookup map[proto.Message]*descriptor.SourceCodeInfo_Location +} + +func (s sourceCodeInfo) GetMessage(m *descriptor.DescriptorProto) *descriptor.SourceCodeInfo_Location { + return s.lookup[m] +} + +func (s sourceCodeInfo) GetField(f *descriptor.FieldDescriptorProto) *descriptor.SourceCodeInfo_Location { + return s.lookup[f] +} + +func (s sourceCodeInfo) GetEnum(e *descriptor.EnumDescriptorProto) *descriptor.SourceCodeInfo_Location { + return s.lookup[e] +} + +func (s sourceCodeInfo) GetEnumValue(e *descriptor.EnumValueDescriptorProto) *descriptor.SourceCodeInfo_Location { + return s.lookup[e] +} + +func newSourceCodeInfo(fs []*descriptor.FileDescriptorProto) *sourceCodeInfo { + // For each source location in the provided files + // - resolve the (annoyingly) encoded path to its message/field/service/enum/etc definition + // - store the source info by its resolved definition + lookup := map[proto.Message]*descriptor.SourceCodeInfo_Location{} + for _, f := range fs { + for _, loc := range f.GetSourceCodeInfo().GetLocation() { + declaration := getDefinitionAtPath(f, loc.Path) + if declaration != nil { + lookup[declaration] = loc + } + } + } + return &sourceCodeInfo{lookup} +} + +// Resolve a protobuf "file-source path" to its associated definition (eg message/field/enum/etc). +// Note that some paths don't point to definitions (some reference subcomponents like name, type, +// field #, etc) and will therefore return nil. +func getDefinitionAtPath(file *descriptor.FileDescriptorProto, path []int32) proto.Message { + // The way protobuf encodes "file-source path" is a little opaque/tricky; + // this doc describes how it works: + // https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/descriptor.proto#L730 + + // Starting at the root of the file descriptor, traverse its object graph by following the + // specified path (and updating our position/state at each step) until either: + // - we reach the definition referenced by the path (and return it) + // - we hit a dead end because the path references a grammar element more granular than a + // definition (so we return nil) + var pos proto.Message = file + for step := 0; step < len(path); step++ { + switch p := pos.(type) { + case *descriptor.FileDescriptorProto: + switch path[step] { + case tag_FileDescriptor_messageType: + step++ + pos = p.MessageType[path[step]] + case tag_FileDescriptor_enumType: + step++ + pos = p.EnumType[path[step]] + default: + return nil // ignore all other types + } + + case *descriptor.DescriptorProto: + switch path[step] { + case tag_Descriptor_field: + step++ + pos = p.Field[path[step]] + case tag_Descriptor_nestedType: + step++ + pos = p.NestedType[path[step]] + case tag_Descriptor_enumType: + step++ + pos = p.EnumType[path[step]] + case tag_Descriptor_oneofDecl: + step++ + pos = p.OneofDecl[path[step]] + default: + return nil // ignore all other types + } + + case *descriptor.EnumDescriptorProto: + switch path[step] { + case tag_EnumDescriptor_value: + step++ + pos = p.Value[path[step]] + default: + return nil // ignore all other types + } + + default: + return nil // ignore all other types + } + } + return pos +} diff --git a/plugins/restapi/jsonschema/converter/sourcecodeinfo_test.go b/plugins/restapi/jsonschema/converter/sourcecodeinfo_test.go new file mode 100644 index 0000000000..657453189e --- /dev/null +++ b/plugins/restapi/jsonschema/converter/sourcecodeinfo_test.go @@ -0,0 +1,53 @@ +package converter + +import ( + "testing" + + "github.com/golang/protobuf/protoc-gen-go/descriptor" +) + +func TestSourceInfoLookup(t *testing.T) { + // Read in the test file & get references to the things we've declared. + // Note that the hardcoded indexes must reflect the declaration order in + // the .proto file. + fds := mustReadProtoFiles(t, sampleProtoDirectory, "MessageWithComments.proto") + protoFile := fds.File[0] + msgWithComments := protoFile.MessageType[0] + msgWithComments_name1 := msgWithComments.Field[0] + + // Create an instance of our thing and test that it returns the expected + // source data for each of our above declarations. + src := newSourceCodeInfo(fds.File) + assertCommentsMatch(t, src.GetMessage(msgWithComments), &descriptor.SourceCodeInfo_Location{ + LeadingComments: strPtr(" This is a message level comment and talks about what this message is and why you should care about it!\n"), + }) + assertCommentsMatch(t, src.GetField(msgWithComments_name1), &descriptor.SourceCodeInfo_Location{ + LeadingComments: strPtr(" This field is supposed to represent blahblahblah\n"), + }) +} + +func assertCommentsMatch(t *testing.T, actual, expected *descriptor.SourceCodeInfo_Location) { + if len(actual.LeadingDetachedComments) != len(expected.LeadingDetachedComments) { + t.Fatalf("Wrong value for LeadingDetachedComments.\n got: %v\n want: %v", + actual.LeadingDetachedComments, expected.LeadingDetachedComments) + } + for i := 0; i < len(actual.LeadingDetachedComments); i++ { + if actual.LeadingDetachedComments[i] != expected.LeadingDetachedComments[i] { + t.Fatalf("Wrong value for LeadingDetachedComments.\n got: %v\n want: %v", + actual.LeadingDetachedComments, expected.LeadingDetachedComments) + } + } + if actual.GetTrailingComments() != expected.GetTrailingComments() { + t.Fatalf("Wrong value for TrailingComments.\n got: %q\n want: %q", + actual.GetTrailingComments(), expected.GetTrailingComments()) + } + if actual.GetLeadingComments() != expected.GetLeadingComments() { + t.Fatalf("Wrong value for LeadingComments.\n got: %q\n want: %q", + actual.GetLeadingComments(), expected.GetLeadingComments()) + } +} + +// Go doesn't have syntax for addressing a string literal, so this is the next best thing. +func strPtr(s string) *string { + return &s +} diff --git a/plugins/restapi/jsonschema/converter/testdata/README.md b/plugins/restapi/jsonschema/converter/testdata/README.md new file mode 100644 index 0000000000..f617cdbd65 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/README.md @@ -0,0 +1,6 @@ +Test Data +========= + +This package contains constants two sets of test data: +1) Proto definitions for various test cases. These define different types of messages and proto payloads which the test suite will attempt to compile. +2) The GoLang files contain consts which define the exact JSONSchemas which are expected to be generated by the tests. diff --git a/plugins/restapi/jsonschema/converter/testdata/array_of_enums.go b/plugins/restapi/jsonschema/converter/testdata/array_of_enums.go new file mode 100644 index 0000000000..d7ab881ca3 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/array_of_enums.go @@ -0,0 +1,27 @@ +package testdata + +const ArrayOfEnums = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "description": { + "type": "string" + }, + "stuff": { + "items": { + "enum": [ + "FOO", + 0, + "BAR", + 1, + "FIZZ", + 2, + "BUZZ", + 3 + ] + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/array_of_messages.go b/plugins/restapi/jsonschema/converter/testdata/array_of_messages.go new file mode 100644 index 0000000000..86d002dd58 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/array_of_messages.go @@ -0,0 +1,61 @@ +package testdata + +const ArrayOfMessages = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "description": { + "type": "string" + }, + "payload": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/array_of_objects.go b/plugins/restapi/jsonschema/converter/testdata/array_of_objects.go new file mode 100644 index 0000000000..4f1560ea60 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/array_of_objects.go @@ -0,0 +1,127 @@ +package testdata + +const ArrayOfObjects = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "payload": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "timestamp": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "id": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] + }, + "rating": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "number" + } + ] + }, + "complete": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "boolean" + } + ] + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": true, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + } + }, + "additionalProperties": true, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ] +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/array_of_primitives.go b/plugins/restapi/jsonschema/converter/testdata/array_of_primitives.go new file mode 100644 index 0000000000..cb0eb4f0ef --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/array_of_primitives.go @@ -0,0 +1,201 @@ +package testdata + +const ArrayOfPrimitives = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "luckyNumbers": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + }, + "luckyBigNumbers": { + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + }, + "keyWords": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + }, + "big_number": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": true, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ] +}` + +const ArrayOfPrimitivesDouble = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "luckyNumbers": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + }, + "luckyBigNumbers": { + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + }, + "keyWords": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + }, + "big_number": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "bigNumber": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": true, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ] +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/cyclical_reference.go b/plugins/restapi/jsonschema/converter/testdata/cyclical_reference.go new file mode 100644 index 0000000000..0f39c168ff --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/cyclical_reference.go @@ -0,0 +1,185 @@ +package testdata + +const ( + CyclicalReferenceMessageM = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "foo": { + "$ref": "samples.Foo", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object", + "definitions": { + "samples.Foo": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "bar": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "id": { + "type": "integer" + }, + "baz": { + "properties": { + "enabled": { + "type": "boolean" + }, + "foo": { + "$ref": "samples.Foo", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object", + "id": "samples.Foo" + } + } +}` + + CyclicalReferenceMessageFoo = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "Foo", + "definitions": { + "Foo": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "bar": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "id": { + "type": "integer" + }, + "baz": { + "properties": { + "enabled": { + "type": "boolean" + }, + "foo": { + "$ref": "Foo", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object", + "id": "Foo" + } + } +}` + + CyclicalReferenceMessageBar = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "Bar", + "definitions": { + "Bar": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "id": { + "type": "integer" + }, + "baz": { + "properties": { + "enabled": { + "type": "boolean" + }, + "foo": { + "properties": { + "name": { + "type": "string" + }, + "bar": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "Bar" + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object", + "id": "Bar" + } + } +}` + + CyclicalReferenceMessageBaz = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "Baz", + "definitions": { + "Baz": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "enabled": { + "type": "boolean" + }, + "foo": { + "properties": { + "name": { + "type": "string" + }, + "bar": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "id": { + "type": "integer" + }, + "baz": { + "$ref": "Baz", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object", + "id": "Baz" + } + } +}` +) diff --git a/plugins/restapi/jsonschema/converter/testdata/enum_ception.go b/plugins/restapi/jsonschema/converter/testdata/enum_ception.go new file mode 100644 index 0000000000..4db6ff0165 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/enum_ception.go @@ -0,0 +1,120 @@ +package testdata + +const EnumCeption = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "failureMode": { + "enum": [ + "RECURSION_ERROR", + 0, + "SYNTAX_ERROR", + 1 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "payload": { + "$ref": "samples.PayloadMessage", + "additionalProperties": true + }, + "payloads": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "samples.PayloadMessage" + }, + "type": "array" + }, + "importedEnum": { + "enum": [ + "VALUE_0", + 0, + "VALUE_1", + 1, + "VALUE_2", + 2, + "VALUE_3", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object", + "definitions": { + "samples.PayloadMessage": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object", + "id": "samples.PayloadMessage" + } + } +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/enum_imported.go b/plugins/restapi/jsonschema/converter/testdata/enum_imported.go new file mode 100644 index 0000000000..c15e08699b --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/enum_imported.go @@ -0,0 +1,29 @@ +package testdata + +const EnumImport = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "importedEnum": { + "enum": [ + "VALUE_0", + 0, + "VALUE_1", + 1, + "VALUE_2", + 2, + "VALUE_3", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/enum_nested_reference.go b/plugins/restapi/jsonschema/converter/testdata/enum_nested_reference.go new file mode 100644 index 0000000000..1f456e3beb --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/enum_nested_reference.go @@ -0,0 +1,33 @@ +package testdata + +const EnumNestedReference = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "nestedEnumField": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/enum_with_message.go b/plugins/restapi/jsonschema/converter/testdata/enum_with_message.go new file mode 100644 index 0000000000..68f7548acb --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/enum_with_message.go @@ -0,0 +1,27 @@ +package testdata + +const EnumWithMessage = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "enumField": { + "enum": [ + "Foo", + 0, + "Bar", + 1, + "Baz", + 2 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/first_enum.go b/plugins/restapi/jsonschema/converter/testdata/first_enum.go new file mode 100644 index 0000000000..3c046a836c --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/first_enum.go @@ -0,0 +1,23 @@ +package testdata + +const FirstEnum = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "enum": [ + "VALUE_0", + 0, + "VALUE_1", + 1, + "VALUE_2", + 2, + "VALUE_3", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/first_message.go b/plugins/restapi/jsonschema/converter/testdata/first_message.go new file mode 100644 index 0000000000..fac59444e6 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/first_message.go @@ -0,0 +1,24 @@ +package testdata + +const FirstMessage = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name1": { + "type": "string" + }, + "timestamp1": { + "type": "string" + }, + "id1": { + "type": "integer" + }, + "rating1": { + "type": "number" + }, + "complete1": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/google_value.go b/plugins/restapi/jsonschema/converter/testdata/google_value.go new file mode 100644 index 0000000000..511464e1df --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/google_value.go @@ -0,0 +1,13 @@ +package testdata + +const GoogleValue = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "arg": { + "additionalProperties": true, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/imported_enum.go b/plugins/restapi/jsonschema/converter/testdata/imported_enum.go new file mode 100644 index 0000000000..fbc17be22c --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/imported_enum.go @@ -0,0 +1,23 @@ +package testdata + +const ImportedEnum = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "enum": [ + "VALUE_0", + 0, + "VALUE_1", + 1, + "VALUE_2", + 2, + "VALUE_3", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/json_fields.go b/plugins/restapi/jsonschema/converter/testdata/json_fields.go new file mode 100644 index 0000000000..13a537f82b --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/json_fields.go @@ -0,0 +1,28 @@ +package testdata + +const JSONFields = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "identifier": { + "type": "integer" + }, + "someThing": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "snakeNumb": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" +} +` diff --git a/plugins/restapi/jsonschema/converter/testdata/maps.go b/plugins/restapi/jsonschema/converter/testdata/maps.go new file mode 100644 index 0000000000..d2d10ea7f8 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/maps.go @@ -0,0 +1,69 @@ +package testdata + +const Maps = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "map_of_strings": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "map_of_ints": { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + }, + "map_of_messages": { + "additionalProperties": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" + }, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/message_kind_10.go b/plugins/restapi/jsonschema/converter/testdata/message_kind_10.go new file mode 100644 index 0000000000..40adf17045 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/message_kind_10.go @@ -0,0 +1,25 @@ +package testdata + +const MessageKind10 = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" +} +` diff --git a/plugins/restapi/jsonschema/converter/testdata/message_kind_11.go b/plugins/restapi/jsonschema/converter/testdata/message_kind_11.go new file mode 100644 index 0000000000..6529e54f58 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/message_kind_11.go @@ -0,0 +1,113 @@ +package testdata + +const MessageKind11 = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "ones": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + "kind2": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "isa": { + "type": "boolean" + }, + "hasa": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" + }, + "kind3": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "someProp": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "kind4": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "special": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" +} +` diff --git a/plugins/restapi/jsonschema/converter/testdata/message_kind_12.go b/plugins/restapi/jsonschema/converter/testdata/message_kind_12.go new file mode 100644 index 0000000000..0743a51dc8 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/message_kind_12.go @@ -0,0 +1,194 @@ +package testdata + +const MessageKind12 = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "f": { + "properties": { + "name": { + "type": "string" + }, + "ones": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + "kind2": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "isa": { + "type": "boolean" + }, + "hasa": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" + }, + "kind3": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "someProp": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "kind4": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "special": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" + }, + "kind5": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "foo": { + "type": "number" + } + }, + "additionalProperties": true, + "type": "object" + }, + "kind6": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "bar": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "kind7": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "baz": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" +} +` diff --git a/plugins/restapi/jsonschema/converter/testdata/message_with_comments.go b/plugins/restapi/jsonschema/converter/testdata/message_with_comments.go new file mode 100644 index 0000000000..b14b869b89 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/message_with_comments.go @@ -0,0 +1,14 @@ +package testdata + +const MessageWithComments = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name1": { + "type": "string", + "description": "This field is supposed to represent blahblahblah" + } + }, + "additionalProperties": true, + "type": "object", + "description": "This is a message level comment and talks about what this message is and why you should care about it!" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/nested_message.go b/plugins/restapi/jsonschema/converter/testdata/nested_message.go new file mode 100644 index 0000000000..15dba579cb --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/nested_message.go @@ -0,0 +1,57 @@ +package testdata + +const NestedMessage = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "payload": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/nested_object.go b/plugins/restapi/jsonschema/converter/testdata/nested_object.go new file mode 100644 index 0000000000..3becb18d8b --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/nested_object.go @@ -0,0 +1,57 @@ +package testdata + +const NestedObject = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "payload": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/payload_message.go b/plugins/restapi/jsonschema/converter/testdata/payload_message.go new file mode 100644 index 0000000000..8cf27a4eba --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/payload_message.go @@ -0,0 +1,48 @@ +package testdata + +const PayloadMessage = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/payload_message_2.go b/plugins/restapi/jsonschema/converter/testdata/payload_message_2.go new file mode 100644 index 0000000000..69e7730cc5 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/payload_message_2.go @@ -0,0 +1,56 @@ +package testdata + +const PayloadMessage2 = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "required": [ + "name", + "timestamp", + "id", + "rating", + "complete", + "topology" + ], + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfEnums.proto b/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfEnums.proto new file mode 100644 index 0000000000..d72aab75fa --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfEnums.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; +package samples; + +message ArrayOfEnums { + string description = 1; + enum inline { + FOO = 0; + BAR = 1; + FIZZ = 2; + BUZZ = 3; + } + repeated inline stuff = 2; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfMessages.proto b/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfMessages.proto new file mode 100644 index 0000000000..16e286f87b --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfMessages.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; +package samples; + +import "PayloadMessage.proto"; + +message ArrayOfMessages { + string description = 1; + repeated PayloadMessage payload = 2; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfObjects.proto b/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfObjects.proto new file mode 100644 index 0000000000..5121474671 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfObjects.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; +package samples; + +message ArrayOfObjects { + + message RepeatedPayload { + enum Topology { + FLAT = 0; + NESTED_OBJECT = 1; + NESTED_MESSAGE = 2; + ARRAY_OF_TYPE = 3; + ARRAY_OF_OBJECT = 4; + ARRAY_OF_MESSAGE = 5; + } + + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; + Topology topology = 6; + } + + string description = 1; + repeated RepeatedPayload payload = 2; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfPrimitives.proto b/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfPrimitives.proto new file mode 100644 index 0000000000..08da80288c --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfPrimitives.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; +package samples; + +message ArrayOfPrimitives { + string description = 1; + repeated int32 luckyNumbers = 2; + repeated int64 luckyBigNumbers = 3; + repeated string keyWords = 4; + int64 big_number = 5; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/CyclicalReference.proto b/plugins/restapi/jsonschema/converter/testdata/proto/CyclicalReference.proto new file mode 100644 index 0000000000..77e9647d85 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/CyclicalReference.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; +package samples; + +message M { + Foo foo = 1; +} + +message Foo { + string name = 1; + repeated Bar bar = 2; +} + +message Bar { + uint32 id = 1; + Baz baz = 2; +} + +message Baz { + bool enabled = 1; + Foo foo = 2; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/EnumNestedReference.proto b/plugins/restapi/jsonschema/converter/testdata/proto/EnumNestedReference.proto new file mode 100644 index 0000000000..cfea653ba9 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/EnumNestedReference.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; +package samples; + +import "PayloadMessage.proto"; + +message Msg { + PayloadMessage.Topology nestedEnumField = 1; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/EnumWithMessage.proto b/plugins/restapi/jsonschema/converter/testdata/proto/EnumWithMessage.proto new file mode 100644 index 0000000000..f0e0ef8be8 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/EnumWithMessage.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; +package samples; + +enum FooBarBaz { + Foo = 0; + Bar = 1; + Baz = 2; +} + +message WithFooBarBaz { + FooBarBaz enumField = 1; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/Enumception.proto b/plugins/restapi/jsonschema/converter/testdata/proto/Enumception.proto new file mode 100644 index 0000000000..f2bdb180f5 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/Enumception.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; +package samples; + +import "PayloadMessage.proto"; +import "ImportedEnum.proto"; + +message Enumception { + enum FailureModes { + RECURSION_ERROR = 0; + SYNTAX_ERROR = 1; + } + + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; + FailureModes failureMode = 6; + PayloadMessage payload = 7; + repeated PayloadMessage payloads = 8; + ImportedEnum importedEnum = 9; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/GoogleValue.proto b/plugins/restapi/jsonschema/converter/testdata/proto/GoogleValue.proto new file mode 100644 index 0000000000..4fe3988637 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/GoogleValue.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; +package samples; + +import "google/protobuf/struct.proto"; + +message GoogleValue { + google.protobuf.Value arg = 1; +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/ImportEnum.proto b/plugins/restapi/jsonschema/converter/testdata/proto/ImportEnum.proto new file mode 100644 index 0000000000..09424642f4 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/ImportEnum.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; +package samples; + +import "ImportedEnum.proto"; + +message UseImportedEnum { + ImportedEnum importedEnum = 1; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/ImportedEnum.proto b/plugins/restapi/jsonschema/converter/testdata/proto/ImportedEnum.proto new file mode 100644 index 0000000000..0e8212a53f --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/ImportedEnum.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; +package samples; + +enum ImportedEnum { + VALUE_0 = 0; + VALUE_1 = 1; + VALUE_2 = 2; + VALUE_3 = 3; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/JSONFields.proto b/plugins/restapi/jsonschema/converter/testdata/proto/JSONFields.proto new file mode 100644 index 0000000000..8556d5a0bc --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/JSONFields.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; +package samples; + +message JSONFields { + string name = 1; + string timestamp = 2; + int32 id = 3 [json_name="identifier"]; + float some_thing = 4 [json_name="someThing"]; + bool complete = 5; + int64 snake_numb = 6; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/Maps.proto b/plugins/restapi/jsonschema/converter/testdata/proto/Maps.proto new file mode 100644 index 0000000000..18565f9a36 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/Maps.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; +package samples; + +import "PayloadMessage.proto"; + +message Maps { + map map_of_strings = 1; + map map_of_ints = 2; + map map_of_messages = 3; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/MessageWithComments.proto b/plugins/restapi/jsonschema/converter/testdata/proto/MessageWithComments.proto new file mode 100644 index 0000000000..43958911ac --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/MessageWithComments.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; +package samples; + +// This is a message level comment and talks about what this message is and why you should care about it! +message MessageWithComments { + + // This field is supposed to represent blahblahblah + string name1 = 1; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/NestedMessage.proto b/plugins/restapi/jsonschema/converter/testdata/proto/NestedMessage.proto new file mode 100644 index 0000000000..0245f0875f --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/NestedMessage.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; +package samples; + +import "PayloadMessage.proto"; + +message NestedMessage { + PayloadMessage payload = 1; + string description = 2; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/NestedObject.proto b/plugins/restapi/jsonschema/converter/testdata/proto/NestedObject.proto new file mode 100644 index 0000000000..9ffd03205f --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/NestedObject.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; +package samples; + +message NestedObject { + message NestedPayload { + enum Topology { + FLAT = 0; + NESTED_OBJECT = 1; + NESTED_MESSAGE = 2; + ARRAY_OF_TYPE = 3; + ARRAY_OF_OBJECT = 4; + ARRAY_OF_MESSAGE = 5; + } + + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; + Topology topology = 6; + } + + NestedPayload payload = 1; + string description = 2; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/NoPackage.proto b/plugins/restapi/jsonschema/converter/testdata/proto/NoPackage.proto new file mode 100644 index 0000000000..88fa892261 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/NoPackage.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +message NoPackage { + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage.proto b/plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage.proto new file mode 100644 index 0000000000..c5922eb68c --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; +package samples; + +message PayloadMessage { + enum Topology { + FLAT = 0; + NESTED_OBJECT = 1; + NESTED_MESSAGE = 2; + ARRAY_OF_TYPE = 3; + ARRAY_OF_OBJECT = 4; + ARRAY_OF_MESSAGE = 5; + } + + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; + Topology topology = 6; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage2.proto b/plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage2.proto new file mode 100644 index 0000000000..77579692cc --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage2.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; +package samples; + +message PayloadMessage2 { + enum Topology { + FLAT = 0; + NESTED_OBJECT = 1; + NESTED_MESSAGE = 2; + ARRAY_OF_TYPE = 3; + ARRAY_OF_OBJECT = 4; + ARRAY_OF_MESSAGE = 5; + } + + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; + Topology topology = 6; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedMessage.proto b/plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedMessage.proto new file mode 100644 index 0000000000..096cca95b7 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedMessage.proto @@ -0,0 +1,25 @@ +syntax = "proto2"; +package samples; + +message Proto2PayloadMessage { + enum Topology { + FLAT = 0; + NESTED_OBJECT = 1; + NESTED_MESSAGE = 2; + ARRAY_OF_TYPE = 3; + ARRAY_OF_OBJECT = 4; + ARRAY_OF_MESSAGE = 5; + } + + required string name = 1; + optional string timestamp = 2; + required int32 id = 3; + optional float rating = 4; + optional bool complete = 5; + optional Topology topology = 6; +} + +message Proto2NestedMessage { + required Proto2PayloadMessage payload = 1; + optional string description = 2; +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedObject.proto b/plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedObject.proto new file mode 100644 index 0000000000..09f9aea9a2 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedObject.proto @@ -0,0 +1,25 @@ +syntax = "proto2"; +package samples; + +message Proto2NestedObject { + message NestedPayload { + enum Topology { + FLAT = 0; + NESTED_OBJECT = 1; + NESTED_MESSAGE = 2; + ARRAY_OF_TYPE = 3; + ARRAY_OF_OBJECT = 4; + ARRAY_OF_MESSAGE = 5; + } + + required string name = 1; + optional string timestamp = 2; + required int32 id = 3; + optional float rating = 4; + optional bool complete = 5; + optional Topology topology = 6; + } + + required NestedPayload payload = 1; + optional string description = 2; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/Proto2Required.proto b/plugins/restapi/jsonschema/converter/testdata/proto/Proto2Required.proto new file mode 100644 index 0000000000..8d2aec389b --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/Proto2Required.proto @@ -0,0 +1,8 @@ +syntax = "proto2"; +package samples; + +message Proto2Required { + required string query = 1; + optional int32 page_number = 2; + optional int32 result_per_page = 3; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/SelfReference.proto b/plugins/restapi/jsonschema/converter/testdata/proto/SelfReference.proto new file mode 100644 index 0000000000..bfd6bb824b --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/SelfReference.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; +package samples; + +message Foo { + string name = 1; + repeated Foo bar = 2; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/SeveralEnums.proto b/plugins/restapi/jsonschema/converter/testdata/proto/SeveralEnums.proto new file mode 100644 index 0000000000..a487c473b2 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/SeveralEnums.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; +package samples; + +enum FirstEnum { + VALUE_0 = 0; + VALUE_1 = 1; + VALUE_2 = 2; + VALUE_3 = 3; +} + +enum SecondEnum { + VALUE_4 = 0; + VALUE_5 = 1; + VALUE_6 = 2; + VALUE_7 = 3; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/SeveralMessages.proto b/plugins/restapi/jsonschema/converter/testdata/proto/SeveralMessages.proto new file mode 100644 index 0000000000..351f0283ab --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/SeveralMessages.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; +package samples; + +message FirstMessage { + string name1 = 1; + string timestamp1 = 2; + int32 id1 = 3; + float rating1 = 4; + bool complete1 = 5; +} + +message SecondMessage { + string name2 = 1; + string timestamp2 = 2; + int32 id2 = 3; + float rating2 = 4; + bool complete2 = 5; +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/Timestamp.proto b/plugins/restapi/jsonschema/converter/testdata/proto/Timestamp.proto new file mode 100644 index 0000000000..1606edb6a9 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/Timestamp.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; +package samples; + +import "google/protobuf/timestamp.proto"; + +message Timestamp { + google.protobuf.Timestamp timestamp = 1; +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/TwelveMessages.proto b/plugins/restapi/jsonschema/converter/testdata/proto/TwelveMessages.proto new file mode 100644 index 0000000000..2c525312f2 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/TwelveMessages.proto @@ -0,0 +1,109 @@ +syntax = "proto3"; +package samples; + +message MessageKind1 { + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; +} + +message MessageKind2 { + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; + bool isa = 6; + bool hasa = 7; +} + +message MessageKind3 { + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; + string someProp = 6; +} + +message MessageKind4 { + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; + string special = 6; +} + +message MessageKind5 { + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; + double foo = 6; +} + +message MessageKind6 { + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; + string bar = 6; +} + +message MessageKind7 { + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; + int64 baz = 6; +} + +message MessageKind8 { + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; +} + +message MessageKind9 { + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; +} + +message MessageKind10 { + string name = 1; + string timestamp = 2; + int32 id = 3; + float rating = 4; + bool complete = 5; +} + +message MessageKind11 { + string name = 1; + repeated MessageKind1 ones = 2; + oneof iface { + MessageKind2 kind2 = 3; + MessageKind3 kind3 = 4; + MessageKind4 kind4 = 5; + } +} + +message MessageKind12 { + string name = 1; + MessageKind11 f = 2; + oneof iface { + MessageKind5 kind5 = 3; + MessageKind6 kind6 = 4; + MessageKind7 kind7 = 5; + } +} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/WellKnown.proto b/plugins/restapi/jsonschema/converter/testdata/proto/WellKnown.proto new file mode 100644 index 0000000000..f2ff5aff70 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto/WellKnown.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; +package samples; +import "google/protobuf/wrappers.proto"; + +message WellKnown { + google.protobuf.StringValue string_value = 1; + map map_of_integers = 2; + map map_of_scalar_integers = 3; + repeated google.protobuf.Int32Value list_of_integers = 4; +} + diff --git a/plugins/restapi/jsonschema/converter/testdata/proto2_nested_message.go b/plugins/restapi/jsonschema/converter/testdata/proto2_nested_message.go new file mode 100644 index 0000000000..018ca62f3c --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto2_nested_message.go @@ -0,0 +1,64 @@ +package testdata + +const Proto2NestedMessage = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "required": [ + "payload" + ], + "properties": { + "payload": { + "required": [ + "name", + "id" + ], + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": false, + "type": "object" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/proto2_nested_object.go b/plugins/restapi/jsonschema/converter/testdata/proto2_nested_object.go new file mode 100644 index 0000000000..2da65bca41 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto2_nested_object.go @@ -0,0 +1,69 @@ +package testdata + +const Proto2NestedObject = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "required": [ + "payload", + "description" + ], + "properties": { + "payload": { + "required": [ + "name", + "id", + "timestamp", + "rating", + "complete", + "topology" + ], + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": false, + "type": "object" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/proto2_payload_message.go b/plugins/restapi/jsonschema/converter/testdata/proto2_payload_message.go new file mode 100644 index 0000000000..ba780c161f --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto2_payload_message.go @@ -0,0 +1,52 @@ +package testdata + +const Proto2PayloadMessage = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "required": [ + "name", + "id" + ], + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/proto2_required.go b/plugins/restapi/jsonschema/converter/testdata/proto2_required.go new file mode 100644 index 0000000000..24c4d80e62 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/proto2_required.go @@ -0,0 +1,21 @@ +package testdata + +const Proto2Required = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "required": [ + "query" + ], + "properties": { + "query": { + "type": "string" + }, + "page_number": { + "type": "integer" + }, + "result_per_page": { + "type": "integer" + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/second_enum.go b/plugins/restapi/jsonschema/converter/testdata/second_enum.go new file mode 100644 index 0000000000..e3142f775e --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/second_enum.go @@ -0,0 +1,23 @@ +package testdata + +const SecondEnum = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "enum": [ + "VALUE_4", + 0, + "VALUE_5", + 1, + "VALUE_6", + 2, + "VALUE_7", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/second_message.go b/plugins/restapi/jsonschema/converter/testdata/second_message.go new file mode 100644 index 0000000000..a66933ef10 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/second_message.go @@ -0,0 +1,24 @@ +package testdata + +const SecondMessage = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name2": { + "type": "string" + }, + "timestamp2": { + "type": "string" + }, + "id2": { + "type": "integer" + }, + "rating2": { + "type": "number" + }, + "complete2": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/self_reference.go b/plugins/restapi/jsonschema/converter/testdata/self_reference.go new file mode 100644 index 0000000000..234be70556 --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/self_reference.go @@ -0,0 +1,26 @@ +package testdata + +const SelfReference = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "Foo", + "definitions": { + "Foo": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "bar": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "Foo" + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object", + "id": "Foo" + } + } +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/timestamp.go b/plugins/restapi/jsonschema/converter/testdata/timestamp.go new file mode 100644 index 0000000000..9ac216227b --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/timestamp.go @@ -0,0 +1,13 @@ +package testdata + +const Timestamp = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "timestamp": { + "type": "string", + "format": "date-time" + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/testdata/wellknown.go b/plugins/restapi/jsonschema/converter/testdata/wellknown.go new file mode 100644 index 0000000000..af44b9fa6a --- /dev/null +++ b/plugins/restapi/jsonschema/converter/testdata/wellknown.go @@ -0,0 +1,32 @@ +package testdata + +const WellKnown = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "string_value": { + "additionalProperties": true, + "type": "string" + }, + "map_of_integers": { + "additionalProperties": { + "additionalProperties": true, + "type": "integer" + }, + "type": "object" + }, + "map_of_scalar_integers": { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + }, + "list_of_integers": { + "items": { + "type": "integer" + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object" +}` diff --git a/plugins/restapi/jsonschema/converter/types.go b/plugins/restapi/jsonschema/converter/types.go new file mode 100644 index 0000000000..135df2bb9e --- /dev/null +++ b/plugins/restapi/jsonschema/converter/types.go @@ -0,0 +1,531 @@ +package converter + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/alecthomas/jsonschema" + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/protoc-gen-go/descriptor" + "github.com/iancoleman/orderedmap" + "github.com/xeipuuv/gojsonschema" +) + +var ( + globalPkg = newProtoPackage(nil, "") + + wellKnownTypes = map[string]bool{ + "DoubleValue": true, + "FloatValue": true, + "Int64Value": true, + "UInt64Value": true, + "Int32Value": true, + "UInt32Value": true, + "BoolValue": true, + "StringValue": true, + "BytesValue": true, + "Value": true, + } +) + +func (c *Converter) registerEnum(pkgName *string, enum *descriptor.EnumDescriptorProto) { + pkg := globalPkg + if pkgName != nil { + for _, node := range strings.Split(*pkgName, ".") { + if pkg == globalPkg && node == "" { + // Skips leading "." + continue + } + child, ok := pkg.children[node] + if !ok { + child = newProtoPackage(pkg, node) + pkg.children[node] = child + } + pkg = child + } + } + pkg.enums[enum.GetName()] = enum +} + +func (c *Converter) registerType(pkgName *string, msg *descriptor.DescriptorProto) { + pkg := globalPkg + if pkgName != nil { + for _, node := range strings.Split(*pkgName, ".") { + if pkg == globalPkg && node == "" { + // Skips leading "." + continue + } + child, ok := pkg.children[node] + if !ok { + child = newProtoPackage(pkg, node) + pkg.children[node] = child + } + pkg = child + } + } + pkg.types[msg.GetName()] = msg +} + +// Convert a proto "field" (essentially a type-switch with some recursion): +func (c *Converter) convertField(curPkg *ProtoPackage, desc *descriptor.FieldDescriptorProto, msg *descriptor.DescriptorProto, duplicatedMessages map[*descriptor.DescriptorProto]string) (*jsonschema.Type, error) { + // Prepare a new jsonschema.Type for our eventual return value: + jsonSchemaType := &jsonschema.Type{} + + // Generate a description from src comments (if available) + if src := c.sourceInfo.GetField(desc); src != nil { + jsonSchemaType.Description = formatDescription(src) + } + + // Switch the types, and pick a JSONSchema equivalent: + switch desc.GetType() { + case descriptor.FieldDescriptorProto_TYPE_DOUBLE, + descriptor.FieldDescriptorProto_TYPE_FLOAT: + if c.AllowNullValues { + jsonSchemaType.OneOf = []*jsonschema.Type{ + {Type: gojsonschema.TYPE_NULL}, + {Type: gojsonschema.TYPE_NUMBER}, + } + } else { + jsonSchemaType.Type = gojsonschema.TYPE_NUMBER + } + + case descriptor.FieldDescriptorProto_TYPE_INT32, + descriptor.FieldDescriptorProto_TYPE_UINT32, + descriptor.FieldDescriptorProto_TYPE_FIXED32, + descriptor.FieldDescriptorProto_TYPE_SFIXED32, + descriptor.FieldDescriptorProto_TYPE_SINT32: + if c.AllowNullValues { + jsonSchemaType.OneOf = []*jsonschema.Type{ + {Type: gojsonschema.TYPE_NULL}, + {Type: gojsonschema.TYPE_INTEGER}, + } + } else { + jsonSchemaType.Type = gojsonschema.TYPE_INTEGER + } + + case descriptor.FieldDescriptorProto_TYPE_INT64, + descriptor.FieldDescriptorProto_TYPE_UINT64, + descriptor.FieldDescriptorProto_TYPE_FIXED64, + descriptor.FieldDescriptorProto_TYPE_SFIXED64, + descriptor.FieldDescriptorProto_TYPE_SINT64: + if c.AllowNullValues { + jsonSchemaType.OneOf = []*jsonschema.Type{ + {Type: gojsonschema.TYPE_STRING}, + {Type: gojsonschema.TYPE_NULL}, + } + } else { + jsonSchemaType.Type = gojsonschema.TYPE_STRING + } + + if c.DisallowBigIntsAsStrings { + jsonSchemaType.Type = gojsonschema.TYPE_INTEGER + } + + case descriptor.FieldDescriptorProto_TYPE_STRING, + descriptor.FieldDescriptorProto_TYPE_BYTES: + if c.AllowNullValues { + jsonSchemaType.OneOf = []*jsonschema.Type{ + {Type: gojsonschema.TYPE_NULL}, + {Type: gojsonschema.TYPE_STRING}, + } + } else { + jsonSchemaType.Type = gojsonschema.TYPE_STRING + } + + case descriptor.FieldDescriptorProto_TYPE_ENUM: + jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: gojsonschema.TYPE_STRING}) + jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: gojsonschema.TYPE_INTEGER}) + if c.AllowNullValues { + jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: gojsonschema.TYPE_NULL}) + } + + // Go through all the enums we have, see if we can match any to this field. + fullEnumIdentifier := strings.TrimPrefix(desc.GetTypeName(), ".") + matchedEnum, _, ok := c.lookupEnum(curPkg, fullEnumIdentifier) + if !ok { + return nil, fmt.Errorf("unable to resolve enum type: %s", desc.GetType().String()) + } + + // We have found an enum, append its values. + for _, value := range matchedEnum.Value { + jsonSchemaType.Enum = append(jsonSchemaType.Enum, value.Name) + jsonSchemaType.Enum = append(jsonSchemaType.Enum, value.Number) + } + + case descriptor.FieldDescriptorProto_TYPE_BOOL: + if c.AllowNullValues { + jsonSchemaType.OneOf = []*jsonschema.Type{ + {Type: gojsonschema.TYPE_NULL}, + {Type: gojsonschema.TYPE_BOOLEAN}, + } + } else { + jsonSchemaType.Type = gojsonschema.TYPE_BOOLEAN + } + + case descriptor.FieldDescriptorProto_TYPE_GROUP, descriptor.FieldDescriptorProto_TYPE_MESSAGE: + switch desc.GetTypeName() { + case ".google.protobuf.Timestamp": + jsonSchemaType.Type = gojsonschema.TYPE_STRING + jsonSchemaType.Format = "date-time" + default: + jsonSchemaType.Type = gojsonschema.TYPE_OBJECT + if desc.GetLabel() == descriptor.FieldDescriptorProto_LABEL_OPTIONAL { + jsonSchemaType.AdditionalProperties = []byte("true") + } + if desc.GetLabel() == descriptor.FieldDescriptorProto_LABEL_REQUIRED { + jsonSchemaType.AdditionalProperties = []byte("false") + } + } + + default: + return nil, fmt.Errorf("unrecognized field type: %s", desc.GetType().String()) + } + + // Recurse array of primitive types: + if desc.GetLabel() == descriptor.FieldDescriptorProto_LABEL_REPEATED && jsonSchemaType.Type != gojsonschema.TYPE_OBJECT { + jsonSchemaType.Items = &jsonschema.Type{} + + if len(jsonSchemaType.Enum) > 0 { + jsonSchemaType.Items.Enum = jsonSchemaType.Enum + jsonSchemaType.Enum = nil + jsonSchemaType.Items.OneOf = nil + } else { + jsonSchemaType.Items.Type = jsonSchemaType.Type + jsonSchemaType.Items.OneOf = jsonSchemaType.OneOf + } + + if c.AllowNullValues { + jsonSchemaType.OneOf = []*jsonschema.Type{ + {Type: gojsonschema.TYPE_NULL}, + {Type: gojsonschema.TYPE_ARRAY}, + } + } else { + jsonSchemaType.Type = gojsonschema.TYPE_ARRAY + jsonSchemaType.OneOf = []*jsonschema.Type{} + } + return jsonSchemaType, nil + } + + // Recurse nested objects / arrays of objects (if necessary): + if jsonSchemaType.Type == gojsonschema.TYPE_OBJECT { + + recordType, pkgName, ok := c.lookupType(curPkg, desc.GetTypeName()) + if !ok { + return nil, fmt.Errorf("no such message type named %s", desc.GetTypeName()) + } + + // Recurse the recordType: + recursedJSONSchemaType, err := c.recursiveConvertMessageType(curPkg, recordType, pkgName, duplicatedMessages, false) + if err != nil { + return nil, err + } + + // Maps, arrays, and objects are structured in different ways: + switch { + + // Maps: + case recordType.Options.GetMapEntry(): + c.logger. + WithField("field_name", recordType.GetName()). + WithField("msg_name", *msg.Name). + Tracef("Is a map") + + // Make sure we have a "value": + value, valuePresent := recursedJSONSchemaType.Properties.Get("value") + if !valuePresent { + return nil, fmt.Errorf("Unable to find 'value' property of MAP type") + } + + // Marshal the "value" properties to JSON (because that's how we can pass on AdditionalProperties): + additionalPropertiesJSON, err := json.Marshal(value) + if err != nil { + return nil, err + } + jsonSchemaType.AdditionalProperties = additionalPropertiesJSON + + // Arrays: + case desc.GetLabel() == descriptor.FieldDescriptorProto_LABEL_REPEATED: + jsonSchemaType.Items = recursedJSONSchemaType + jsonSchemaType.Type = gojsonschema.TYPE_ARRAY + + // Build up the list of required fields: + if c.AllFieldsRequired && recursedJSONSchemaType.Properties != nil { + for _, property := range recursedJSONSchemaType.Properties.Keys() { + jsonSchemaType.Items.Required = append(jsonSchemaType.Items.Required, property) + } + } + + // Not maps, not arrays: + default: + + // If we've got optional types then just take those: + if recursedJSONSchemaType.OneOf != nil { + return recursedJSONSchemaType, nil + } + + // If we're not an object then set the type from whatever we recursed: + if recursedJSONSchemaType.Type != gojsonschema.TYPE_OBJECT { + jsonSchemaType.Type = recursedJSONSchemaType.Type + } + + // Assume the attrbutes of the recursed value: + jsonSchemaType.Properties = recursedJSONSchemaType.Properties + jsonSchemaType.Ref = recursedJSONSchemaType.Ref + jsonSchemaType.Required = recursedJSONSchemaType.Required + + // Build up the list of required fields: + if c.AllFieldsRequired && recursedJSONSchemaType.Properties != nil { + for _, property := range recursedJSONSchemaType.Properties.Keys() { + jsonSchemaType.Required = append(jsonSchemaType.Required, property) + } + } + } + + // Optionally allow NULL values: + if c.AllowNullValues { + jsonSchemaType.OneOf = []*jsonschema.Type{ + {Type: gojsonschema.TYPE_NULL}, + {Type: jsonSchemaType.Type}, + } + jsonSchemaType.Type = "" + } + } + + jsonSchemaType.Required = dedupe(jsonSchemaType.Required) + + return jsonSchemaType, nil +} + +// Converts a proto "MESSAGE" into a JSON-Schema: +func (c *Converter) convertMessageType(curPkg *ProtoPackage, msg *descriptor.DescriptorProto) (*jsonschema.Schema, error) { + + // first, recursively find messages that appear more than once - in particular, that will break cycles + duplicatedMessages, err := c.findDuplicatedNestedMessages(curPkg, msg) + if err != nil { + return nil, err + } + + // main schema for the message + rootType, err := c.recursiveConvertMessageType(curPkg, msg, "", duplicatedMessages, false) + if err != nil { + return nil, err + } + + // and then generate the sub-schema for each duplicated message + definitions := jsonschema.Definitions{} + for refMsg, name := range duplicatedMessages { + refType, err := c.recursiveConvertMessageType(curPkg, refMsg, "", duplicatedMessages, true) + if err != nil { + return nil, err + } + + // need to give that schema an ID + if refType.Extras == nil { + refType.Extras = make(map[string]interface{}) + } + refType.Extras["id"] = name + definitions[name] = refType + } + + newJSONSchema := &jsonschema.Schema{ + Type: rootType, + Definitions: definitions, + } + + // Look for required fields (either by proto2 required flag, or the AllFieldsRequired option): + for _, fieldDesc := range msg.GetField() { + if c.AllFieldsRequired || fieldDesc.GetLabel() == descriptor.FieldDescriptorProto_LABEL_REQUIRED { + newJSONSchema.Required = append(newJSONSchema.Required, fieldDesc.GetName()) + } + } + + newJSONSchema.Required = dedupe(newJSONSchema.Required) + + return newJSONSchema, nil +} + +// findDuplicatedNestedMessages takes a message, and returns a map mapping pointers to messages that appear more than once +// (typically because they're part of a reference cycle) to the sub-schema name that we give them. +func (c *Converter) findDuplicatedNestedMessages(curPkg *ProtoPackage, msg *descriptor.DescriptorProto) (map[*descriptor.DescriptorProto]string, error) { + all := make(map[*descriptor.DescriptorProto]*nameAndCounter) + if err := c.recursiveFindDuplicatedNestedMessages(curPkg, msg, msg.GetName(), all); err != nil { + return nil, err + } + + result := make(map[*descriptor.DescriptorProto]string) + for m, nameAndCounter := range all { + if nameAndCounter.counter > 1 && !strings.HasPrefix(nameAndCounter.name, ".google.protobuf.") { + result[m] = strings.TrimLeft(nameAndCounter.name, ".") + } + } + + return result, nil +} + +type nameAndCounter struct { + name string + counter int +} + +func (c *Converter) recursiveFindDuplicatedNestedMessages(curPkg *ProtoPackage, msg *descriptor.DescriptorProto, typeName string, alreadySeen map[*descriptor.DescriptorProto]*nameAndCounter) error { + if nameAndCounter, present := alreadySeen[msg]; present { + nameAndCounter.counter++ + return nil + } + alreadySeen[msg] = &nameAndCounter{ + name: typeName, + counter: 1, + } + + for _, desc := range msg.GetField() { + descType := desc.GetType() + if descType != descriptor.FieldDescriptorProto_TYPE_MESSAGE && descType != descriptor.FieldDescriptorProto_TYPE_GROUP { + // no nested messages + continue + } + + typeName := desc.GetTypeName() + recordType, _, ok := c.lookupType(curPkg, typeName) + if !ok { + return fmt.Errorf("no such message type named %s", typeName) + } + if err := c.recursiveFindDuplicatedNestedMessages(curPkg, recordType, typeName, alreadySeen); err != nil { + return err + } + } + + return nil +} + +func (c *Converter) recursiveConvertMessageType(curPkg *ProtoPackage, msg *descriptor.DescriptorProto, pkgName string, duplicatedMessages map[*descriptor.DescriptorProto]string, ignoreDuplicatedMessages bool) (*jsonschema.Type, error) { + + // Handle google's well-known types: + if msg.Name != nil && wellKnownTypes[*msg.Name] && pkgName == ".google.protobuf" { + var schemaType string + switch *msg.Name { + case "DoubleValue", "FloatValue": + schemaType = gojsonschema.TYPE_NUMBER + case "Int32Value", "UInt32Value", "Int64Value", "UInt64Value": + schemaType = gojsonschema.TYPE_INTEGER + case "BoolValue": + schemaType = gojsonschema.TYPE_BOOLEAN + case "BytesValue", "StringValue": + schemaType = gojsonschema.TYPE_STRING + case "Value": + schemaType = gojsonschema.TYPE_OBJECT + } + + // If we're allowing nulls then prepare a OneOf: + if c.AllowNullValues { + return &jsonschema.Type{ + OneOf: []*jsonschema.Type{ + {Type: gojsonschema.TYPE_NULL}, + {Type: schemaType}, + }, + }, nil + } + + // Otherwise just return this simple type: + return &jsonschema.Type{ + Type: schemaType, + }, nil + } + + if refName, ok := duplicatedMessages[msg]; ok && !ignoreDuplicatedMessages { + return &jsonschema.Type{ + Version: jsonschema.Version, + Ref: refName, + }, nil + } + + // Prepare a new jsonschema: + jsonSchemaType := &jsonschema.Type{ + Properties: orderedmap.New(), + Version: jsonschema.Version, + } + + // Generate a description from src comments (if available) + if src := c.sourceInfo.GetMessage(msg); src != nil { + jsonSchemaType.Description = formatDescription(src) + } + + // Optionally allow NULL values: + if c.AllowNullValues { + jsonSchemaType.OneOf = []*jsonschema.Type{ + {Type: gojsonschema.TYPE_NULL}, + {Type: gojsonschema.TYPE_OBJECT}, + } + } else { + jsonSchemaType.Type = gojsonschema.TYPE_OBJECT + } + + // disallowAdditionalProperties will prevent validation where extra fields are found (outside of the schema): + if c.DisallowAdditionalProperties { + jsonSchemaType.AdditionalProperties = []byte("false") + } else { + jsonSchemaType.AdditionalProperties = []byte("true") + } + + c.logger.WithField("message_str", proto.MarshalTextString(msg)).Trace("Converting message") + for _, fieldDesc := range msg.GetField() { + recursedJSONSchemaType, err := c.convertField(curPkg, fieldDesc, msg, duplicatedMessages) + if err != nil { + c.logger.WithError(err).WithField("field_name", fieldDesc.GetName()).WithField("message_name", msg.GetName()).Error("Failed to convert field") + return nil, err + } + c.logger.WithField("field_name", fieldDesc.GetName()).WithField("type", recursedJSONSchemaType.Type).Trace("Converted field") + + // Figure out which field names we want to use: + switch { + case c.UseJSONFieldnamesOnly: + jsonSchemaType.Properties.Set(fieldDesc.GetJsonName(), recursedJSONSchemaType) + case c.UseProtoAndJSONFieldnames: + jsonSchemaType.Properties.Set(fieldDesc.GetName(), recursedJSONSchemaType) + jsonSchemaType.Properties.Set(fieldDesc.GetJsonName(), recursedJSONSchemaType) + default: + jsonSchemaType.Properties.Set(fieldDesc.GetName(), recursedJSONSchemaType) + } + + // Look for required fields (either by proto2 required flag, or the AllFieldsRequired option): + if fieldDesc.GetLabel() == descriptor.FieldDescriptorProto_LABEL_REQUIRED { + jsonSchemaType.Required = append(jsonSchemaType.Required, fieldDesc.GetName()) + } + } + + // Remove empty properties to keep the final output as clean as possible: + if len(jsonSchemaType.Properties.Keys()) == 0 { + jsonSchemaType.Properties = nil + } + + return jsonSchemaType, nil +} + +func formatDescription(sl *descriptor.SourceCodeInfo_Location) string { + var lines []string + for _, str := range sl.GetLeadingDetachedComments() { + if s := strings.TrimSpace(str); s != "" { + lines = append(lines, s) + } + } + if s := strings.TrimSpace(sl.GetLeadingComments()); s != "" { + lines = append(lines, s) + } + if s := strings.TrimSpace(sl.GetTrailingComments()); s != "" { + lines = append(lines, s) + } + return strings.Join(lines, "\n\n") +} + +func dedupe(inputStrings []string) []string { + appended := make(map[string]bool) + outputStrings := []string{} + + for _, inputString := range inputStrings { + if !appended[inputString] { + outputStrings = append(outputStrings, inputString) + appended[inputString] = true + } + } + return outputStrings +} diff --git a/plugins/restapi/jsonschema/jsonschemas/ArrayOfEnums.jsonschema b/plugins/restapi/jsonschema/jsonschemas/ArrayOfEnums.jsonschema new file mode 100644 index 0000000000..c393d8874f --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/ArrayOfEnums.jsonschema @@ -0,0 +1,25 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "description": { + "type": "string" + }, + "stuff": { + "items": { + "enum": [ + "FOO", + 0, + "BAR", + 1, + "FIZZ", + 2, + "BUZZ", + 3 + ] + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/ArrayOfMessages.jsonschema b/plugins/restapi/jsonschema/jsonschemas/ArrayOfMessages.jsonschema new file mode 100644 index 0000000000..3f7ea01b76 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/ArrayOfMessages.jsonschema @@ -0,0 +1,125 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "payload": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "timestamp": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "id": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] + }, + "rating": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "number" + } + ] + }, + "complete": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "boolean" + } + ] + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": true, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + } + }, + "additionalProperties": true, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ] +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/ArrayOfObjects.jsonschema b/plugins/restapi/jsonschema/jsonschemas/ArrayOfObjects.jsonschema new file mode 100644 index 0000000000..3f7ea01b76 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/ArrayOfObjects.jsonschema @@ -0,0 +1,125 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "payload": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "timestamp": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "id": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] + }, + "rating": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "number" + } + ] + }, + "complete": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "boolean" + } + ] + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": true, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + } + }, + "additionalProperties": true, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ] +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/ArrayOfPrimitives.jsonschema b/plugins/restapi/jsonschema/jsonschemas/ArrayOfPrimitives.jsonschema new file mode 100644 index 0000000000..3f95bed373 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/ArrayOfPrimitives.jsonschema @@ -0,0 +1,100 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "luckyNumbers": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + }, + "luckyBigNumbers": { + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + }, + "keyWords": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + }, + "big_number": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": true, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ] +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/Enumception.jsonschema b/plugins/restapi/jsonschema/jsonschemas/Enumception.jsonschema new file mode 100644 index 0000000000..7f40e6aa73 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/Enumception.jsonschema @@ -0,0 +1,109 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "failureMode": { + "enum": [ + "RECURSION_ERROR", + 0, + "SYNTAX_ERROR", + 1 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "payload": { + "$ref": "samples.PayloadMessage", + "additionalProperties": true, + "type": "object" + }, + "payloads": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "samples.PayloadMessage" + }, + "type": "array" + }, + "importedEnum": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": false, + "type": "object", + "definitions": { + "samples.PayloadMessage": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": false, + "type": "object", + "id": "samples.PayloadMessage" + } + } +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/FirstEnum.jsonschema b/plugins/restapi/jsonschema/jsonschemas/FirstEnum.jsonschema new file mode 100644 index 0000000000..f48c31a12f --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/FirstEnum.jsonschema @@ -0,0 +1,21 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "enum": [ + "VALUE_0", + 0, + "VALUE_1", + 1, + "VALUE_2", + 2, + "VALUE_3", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/FirstMessage.jsonschema b/plugins/restapi/jsonschema/jsonschemas/FirstMessage.jsonschema new file mode 100644 index 0000000000..55b54424a2 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/FirstMessage.jsonschema @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name1": { + "type": "string" + }, + "timestamp1": { + "type": "string" + }, + "id1": { + "type": "integer" + }, + "rating1": { + "type": "number" + }, + "complete1": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/GoogleValue.jsonschema b/plugins/restapi/jsonschema/jsonschemas/GoogleValue.jsonschema new file mode 100644 index 0000000000..7b7f376784 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/GoogleValue.jsonschema @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "arg": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ] + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/ImportedEnum.jsonschema b/plugins/restapi/jsonschema/jsonschemas/ImportedEnum.jsonschema new file mode 100644 index 0000000000..f48c31a12f --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/ImportedEnum.jsonschema @@ -0,0 +1,21 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "enum": [ + "VALUE_0", + 0, + "VALUE_1", + 1, + "VALUE_2", + 2, + "VALUE_3", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/JSONFields.jsonschema b/plugins/restapi/jsonschema/jsonschemas/JSONFields.jsonschema new file mode 100644 index 0000000000..702fb8d4f9 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/JSONFields.jsonschema @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "identifier": { + "type": "integer" + }, + "someThing": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "snakeNumb": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ] + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/Maps.jsonschema b/plugins/restapi/jsonschema/jsonschemas/Maps.jsonschema new file mode 100644 index 0000000000..1ca1a25263 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/Maps.jsonschema @@ -0,0 +1,67 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "map_of_strings": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "map_of_ints": { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + }, + "map_of_messages": { + "additionalProperties": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" + }, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/MessageKind10.jsonschema b/plugins/restapi/jsonschema/jsonschemas/MessageKind10.jsonschema new file mode 100644 index 0000000000..827aac0032 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/MessageKind10.jsonschema @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/MessageKind11.jsonschema b/plugins/restapi/jsonschema/jsonschemas/MessageKind11.jsonschema new file mode 100644 index 0000000000..19dd2f0a21 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/MessageKind11.jsonschema @@ -0,0 +1,110 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "ones": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + "kind2": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "isa": { + "type": "boolean" + }, + "hasa": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" + }, + "kind3": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "someProp": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "kind4": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "special": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/MessageKind12.jsonschema b/plugins/restapi/jsonschema/jsonschemas/MessageKind12.jsonschema new file mode 100644 index 0000000000..6146e4b973 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/MessageKind12.jsonschema @@ -0,0 +1,198 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "f": { + "properties": { + "name": { + "type": "string" + }, + "ones": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + "kind2": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "isa": { + "type": "boolean" + }, + "hasa": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" + }, + "kind3": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "someProp": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "kind4": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "special": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" + }, + "kind5": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "foo": { + "type": "number" + } + }, + "additionalProperties": true, + "type": "object" + }, + "kind6": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "bar": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "kind7": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "baz": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ] + } + }, + "additionalProperties": true, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/MessageWithComments.jsonschema b/plugins/restapi/jsonschema/jsonschemas/MessageWithComments.jsonschema new file mode 100644 index 0000000000..60e1744cd5 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/MessageWithComments.jsonschema @@ -0,0 +1,12 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name1": { + "type": "string", + "description": "This field is supposed to represent blahblahblah" + } + }, + "additionalProperties": true, + "type": "object", + "description": "This is a message level comment and talks about what this message is and why you should care about it!" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/NestedMessage.jsonschema b/plugins/restapi/jsonschema/jsonschemas/NestedMessage.jsonschema new file mode 100644 index 0000000000..88cf76ee8a --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/NestedMessage.jsonschema @@ -0,0 +1,55 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "payload": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/NestedObject.jsonschema b/plugins/restapi/jsonschema/jsonschemas/NestedObject.jsonschema new file mode 100644 index 0000000000..c17488deeb --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/NestedObject.jsonschema @@ -0,0 +1,55 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "payload": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/PayloadMessage.jsonschema b/plugins/restapi/jsonschema/jsonschemas/PayloadMessage.jsonschema new file mode 100644 index 0000000000..bcc0a0fe44 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/PayloadMessage.jsonschema @@ -0,0 +1,46 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/PayloadMessage2.jsonschema b/plugins/restapi/jsonschema/jsonschemas/PayloadMessage2.jsonschema new file mode 100644 index 0000000000..1cb26ee8b2 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/PayloadMessage2.jsonschema @@ -0,0 +1,54 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "required": [ + "name", + "timestamp", + "id", + "rating", + "complete", + "topology" + ], + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/Proto2NestedMessage.jsonschema b/plugins/restapi/jsonschema/jsonschemas/Proto2NestedMessage.jsonschema new file mode 100644 index 0000000000..8de78e6a82 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/Proto2NestedMessage.jsonschema @@ -0,0 +1,62 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "required": [ + "payload" + ], + "properties": { + "payload": { + "required": [ + "name", + "id" + ], + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": false, + "type": "object" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/Proto2NestedObject.jsonschema b/plugins/restapi/jsonschema/jsonschemas/Proto2NestedObject.jsonschema new file mode 100644 index 0000000000..1f8b4f3e3f --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/Proto2NestedObject.jsonschema @@ -0,0 +1,67 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "required": [ + "payload", + "description" + ], + "properties": { + "payload": { + "required": [ + "name", + "id", + "timestamp", + "rating", + "complete", + "topology" + ], + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": false, + "type": "object" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/Proto2PayloadMessage.jsonschema b/plugins/restapi/jsonschema/jsonschemas/Proto2PayloadMessage.jsonschema new file mode 100644 index 0000000000..be928fdf6d --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/Proto2PayloadMessage.jsonschema @@ -0,0 +1,50 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "required": [ + "name", + "id" + ], + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/Proto2Required.jsonschema b/plugins/restapi/jsonschema/jsonschemas/Proto2Required.jsonschema new file mode 100644 index 0000000000..8a79bf2b12 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/Proto2Required.jsonschema @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "required": [ + "query" + ], + "properties": { + "query": { + "type": "string" + }, + "page_number": { + "type": "integer" + }, + "result_per_page": { + "type": "integer" + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/SecondEnum.jsonschema b/plugins/restapi/jsonschema/jsonschemas/SecondEnum.jsonschema new file mode 100644 index 0000000000..e57d4908d5 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/SecondEnum.jsonschema @@ -0,0 +1,21 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "enum": [ + "VALUE_4", + 0, + "VALUE_5", + 1, + "VALUE_6", + 2, + "VALUE_7", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/SecondMessage.jsonschema b/plugins/restapi/jsonschema/jsonschemas/SecondMessage.jsonschema new file mode 100644 index 0000000000..edbc1c86d5 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/SecondMessage.jsonschema @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "name2": { + "type": "string" + }, + "timestamp2": { + "type": "string" + }, + "id2": { + "type": "integer" + }, + "rating2": { + "type": "number" + }, + "complete2": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/Timestamp.jsonschema b/plugins/restapi/jsonschema/jsonschemas/Timestamp.jsonschema new file mode 100644 index 0000000000..a8d4b78208 --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/Timestamp.jsonschema @@ -0,0 +1,11 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "timestamp": { + "type": "string", + "format": "date-time" + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/WellKnown.jsonschema b/plugins/restapi/jsonschema/jsonschemas/WellKnown.jsonschema new file mode 100644 index 0000000000..9b3f3b1bcd --- /dev/null +++ b/plugins/restapi/jsonschema/jsonschemas/WellKnown.jsonschema @@ -0,0 +1,49 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "string_value": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "map_of_integers": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] + }, + "type": "object" + }, + "map_of_scalar_integers": { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + }, + "list_of_integers": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object" +} \ No newline at end of file From a0e3ec63413d4f5659bbce1a76416653981c94c5 Mon Sep 17 00:00:00 2001 From: Filip Gschwandtner Date: Thu, 4 Feb 2021 18:51:57 +0100 Subject: [PATCH 02/10] feat: added REST API for retrieving JSON schema of VPP-Agent configuration Signed-off-by: Filip Gschwandtner --- plugins/restapi/handlers.go | 128 ++++++++++++++++++++++++++++++ plugins/restapi/plugin_restapi.go | 18 +++-- plugins/restapi/resturl/urls.go | 4 + 3 files changed, 142 insertions(+), 8 deletions(-) diff --git a/plugins/restapi/handlers.go b/plugins/restapi/handlers.go index 531cac4581..428b63bb98 100644 --- a/plugins/restapi/handlers.go +++ b/plugins/restapi/handlers.go @@ -17,19 +17,29 @@ package restapi import ( + "bytes" "context" "fmt" "net/http" "runtime" + "strings" "github.com/go-errors/errors" + "github.com/golang/protobuf/proto" + protoc_plugin "github.com/golang/protobuf/protoc-gen-go/plugin" "github.com/unrolled/render" + "go.ligato.io/cn-infra/v2/logging/logrus" + "go.ligato.io/vpp-agent/v3/client" "go.ligato.io/vpp-agent/v3/cmd/agentctl/api/types" "go.ligato.io/vpp-agent/v3/pkg/version" "go.ligato.io/vpp-agent/v3/plugins/configurator" + "go.ligato.io/vpp-agent/v3/plugins/restapi/jsonschema/converter" "go.ligato.io/vpp-agent/v3/plugins/restapi/resturl" interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" + "google.golang.org/protobuf/reflect/protodesc" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/descriptorpb" ) var ( @@ -40,6 +50,7 @@ var ( func (p *Plugin) registerInfoHandlers() { p.HTTPHandlers.RegisterHTTPHandler(resturl.Version, p.versionHandler, GET) + p.HTTPHandlers.RegisterHTTPHandler(resturl.JSONSchema, p.jsonSchemaHandler, GET) } // Registers ABF REST handler @@ -315,6 +326,123 @@ func (p *Plugin) registerHTTPHandler(key, method string, f func() (interface{}, p.HTTPHandlers.RegisterHTTPHandler(key, handlerFunc, method) } +// jsonSchemaHandler returns JSON schema of VPP-Agent configuration. +func (p *Plugin) jsonSchemaHandler(formatter *render.Render) http.HandlerFunc { + return func(w http.ResponseWriter, req *http.Request) { + // create FileDescriptorProto for dynamic Config holding all VPP-Agent configuration + knownModels, err := client.LocalClient.KnownModels("config") // locally registered models + if err != nil { + errMsg := fmt.Sprintf("500 Internal server error: "+ + "can't get registered models: %v\n", err) + p.Log.Error(errMsg) + p.logError(formatter.JSON(w, http.StatusInternalServerError, errMsg)) + return + } + config, err := client.NewDynamicConfig(knownModels) + if err != nil { + errMsg := fmt.Sprintf("500 Internal server error: "+ + "can't create dynamic config due to: %v\n", err) + p.Log.Error(errMsg) + p.logError(formatter.JSON(w, http.StatusInternalServerError, errMsg)) + return + } + dynConfigFileDescProto := protodesc.ToFileDescriptorProto(config.ProtoReflect().Descriptor().ParentFile()) + + // create list of all FileDescriptorProtos (imports should be before converted proto file -> dynConfig is last) + fileDescriptorProtos := allFileDescriptorProtos(knownModels) + fileDescriptorProtos = append(fileDescriptorProtos, dynConfigFileDescProto) + + // creating input for protoc's plugin (code extracted in plugins/restapi/jsonschema) that can convert + // FileDescriptorProtos to JSONSchema + params := "messages=[Dynamic_config]" + // targeting only the main config message (proto file has also other messages) + ",disallow_additional_properties" + // additional unknown json fields makes configuration applying fail + ",proto_and_json_fieldnames" // allow also proto names for fields + cgReq := &protoc_plugin.CodeGeneratorRequest{ + ProtoFile: fileDescriptorProtos, + FileToGenerate: []string{dynConfigFileDescProto.GetName()}, + Parameter: ¶ms, + CompilerVersion: nil, // compiler version is not need in this protoc plugin + } + cgReqMarshalled, err := proto.Marshal(cgReq) + if err != nil { + fmt.Errorf("can't proto marshal to: %w", err) + errMsg := fmt.Sprintf("500 Internal server error: "+ + "can't proto marshal CodeGeneratorRequest: %v\n", err) + p.Log.Error(errMsg) + p.logError(formatter.JSON(w, http.StatusInternalServerError, errMsg)) + return + } + + // use JSON schema converter and handle error cases + p.Log.Debug("Processing code generator request") + protoConverter := converter.New(logrus.DefaultLogger().StandardLogger()) + res, err := protoConverter.ConvertFrom(bytes.NewReader(cgReqMarshalled)) + if err != nil { + if res == nil { + errMsg := fmt.Sprintf("500 Internal server error: "+ + "failed to read registered model configuration input: %v\n", err) + p.Log.Error(errMsg) + p.logError(formatter.JSON(w, http.StatusInternalServerError, errMsg)) + return + } + errMsg := fmt.Sprintf("500 Internal server error: "+ + "failed generate JSON schema: %v (%v)\n", res.Error, err) + p.Log.Error(errMsg) + p.logError(formatter.JSON(w, http.StatusInternalServerError, errMsg)) + return + } + + // extract json schema + // (protoc_plugin.CodeGeneratorResponse could have cut the file content into multiple pieces + // for performance optimization (due to godoc), but we know that all pieces are only one file + // due to requesting one file -> join all content together) + var sb strings.Builder + for _, file := range res.File { + sb.WriteString(file.GetContent()) + } + + // writing response + // (jsonschema is in raw form (string) and non of the available format renders supports raw data output + // with customizable content type setting in header -> custom handling) + w.Header().Set(render.ContentType, render.ContentJSON+"; charset=UTF-8") + w.Write([]byte(sb.String())) // will also call WriteHeader(http.StatusOK) automatically + } +} + +// allImports retrieves all imports from given FileDescriptor including transitive imports (import +// duplication can occur) +func allImports(fileDesc protoreflect.FileDescriptor) []protoreflect.FileDescriptor { + result := make([]protoreflect.FileDescriptor, 0) + imports := fileDesc.Imports() + for i := 0; i < imports.Len(); i++ { + currentImport := imports.Get(i).FileDescriptor + result = append(result, currentImport) + result = append(result, allImports(currentImport)...) + } + return result +} + +// allFileDescriptorProtos retrieves all FileDescriptorProtos related to given models (including +// all imported proto files) +func allFileDescriptorProtos(knownModels []*client.ModelInfo) []*descriptorpb.FileDescriptorProto { + // extract all FileDescriptors for given known models (including direct and transitive file imports) + fileDescriptors := make(map[string]protoreflect.FileDescriptor) // using map for deduplication + for _, knownModel := range knownModels { + protoFile := knownModel.MessageDescriptor.ParentFile() + fileDescriptors[protoFile.Path()] = protoFile + for _, importProtoFile := range allImports(protoFile) { + fileDescriptors[importProtoFile.Path()] = importProtoFile + } + } + + // convert retrieved FileDescriptors to FileDescriptorProtos + fileDescriptorProtos := make([]*descriptorpb.FileDescriptorProto, 0, len(knownModels)) + for _, fileDescriptor := range fileDescriptors { + fileDescriptorProtos = append(fileDescriptorProtos, protodesc.ToFileDescriptorProto(fileDescriptor)) + } + return fileDescriptorProtos +} + // versionHandler returns version of Agent. func (p *Plugin) versionHandler(formatter *render.Render) http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { diff --git a/plugins/restapi/plugin_restapi.go b/plugins/restapi/plugin_restapi.go index 452473f464..2d7da82733 100644 --- a/plugins/restapi/plugin_restapi.go +++ b/plugins/restapi/plugin_restapi.go @@ -68,14 +68,14 @@ type Plugin struct { vpeHandler vpevppcalls.VppCoreAPI teleHandler telemetryvppcalls.TelemetryVppAPI // VPP Handlers - abfHandler abfvppcalls.ABFVppRead - aclHandler aclvppcalls.ACLVppRead - ifHandler ifvppcalls.InterfaceVppRead - natHandler natvppcalls.NatVppRead - l2Handler l2vppcalls.L2VppAPI - l3Handler l3vppcalls.L3VppAPI - ipSecHandler ipsecvppcalls.IPSecVPPRead - puntHandler puntvppcalls.PuntVPPRead + abfHandler abfvppcalls.ABFVppRead + aclHandler aclvppcalls.ACLVppRead + ifHandler ifvppcalls.InterfaceVppRead + natHandler natvppcalls.NatVppRead + l2Handler l2vppcalls.L2VppAPI + l3Handler l3vppcalls.L3VppAPI + ipSecHandler ipsecvppcalls.IPSecVPPRead + puntHandler puntvppcalls.PuntVPPRead wireguardHandler wireguardvppcalls.WgVppRead // Linux handlers linuxIfHandler iflinuxcalls.NetlinkAPIRead @@ -224,6 +224,7 @@ func getIndexPageItems() map[string][]indexItem { idxMap := map[string][]indexItem{ "Info": { {Name: "Version", Path: resturl.Version}, + {Name: "JSONSchema", Path: resturl.JSONSchema}, }, "ACL plugin": { {Name: "IP-type access lists", Path: resturl.ACLIP}, @@ -270,6 +271,7 @@ func getPermissionsGroups() []*access.PermissionGroup { Permissions: []*access.PermissionGroup_Permissions{ newPermission("/", GET), newPermission(resturl.Version, GET), + newPermission(resturl.JSONSchema, GET), }, } tracerPg := &access.PermissionGroup{ diff --git a/plugins/restapi/resturl/urls.go b/plugins/restapi/resturl/urls.go index f6db401cb7..bc546e4549 100644 --- a/plugins/restapi/resturl/urls.go +++ b/plugins/restapi/resturl/urls.go @@ -18,6 +18,10 @@ package resturl const ( // Version is a path for retrieving information about version of Agent. Version = "/info/version" + + // JSONSchema is a path for retrieving JSON Schema for VPP-Agent configuration (dynamically created + // container of all registered configuration models). + JSONSchema = "/info/configuration/jsonschema" ) // Linux Dumps From 92ead9ce9c1210c4866ee4431c94c25c28f67977 Mon Sep 17 00:00:00 2001 From: Filip Gschwandtner Date: Thu, 4 Feb 2021 19:08:56 +0100 Subject: [PATCH 03/10] refactor: removed unusable unit tests (need to remove dependency on external protoc program and other tweaks to fully integrate into ligato) Signed-off-by: Filip Gschwandtner --- .../jsonschema/converter/converter_test.go | 317 ------------------ .../converter/sourcecodeinfo_test.go | 53 --- .../jsonschema/converter/testdata/README.md | 6 - .../converter/testdata/array_of_enums.go | 27 -- .../converter/testdata/array_of_messages.go | 61 ---- .../converter/testdata/array_of_objects.go | 127 ------- .../converter/testdata/array_of_primitives.go | 201 ----------- .../converter/testdata/cyclical_reference.go | 185 ---------- .../converter/testdata/enum_ception.go | 120 ------- .../converter/testdata/enum_imported.go | 29 -- .../testdata/enum_nested_reference.go | 33 -- .../converter/testdata/enum_with_message.go | 27 -- .../converter/testdata/first_enum.go | 23 -- .../converter/testdata/first_message.go | 24 -- .../converter/testdata/google_value.go | 13 - .../converter/testdata/imported_enum.go | 23 -- .../converter/testdata/json_fields.go | 28 -- .../jsonschema/converter/testdata/maps.go | 69 ---- .../converter/testdata/message_kind_10.go | 25 -- .../converter/testdata/message_kind_11.go | 113 ------- .../converter/testdata/message_kind_12.go | 194 ----------- .../testdata/message_with_comments.go | 14 - .../converter/testdata/nested_message.go | 57 ---- .../converter/testdata/nested_object.go | 57 ---- .../converter/testdata/payload_message.go | 48 --- .../converter/testdata/payload_message_2.go | 56 ---- .../testdata/proto/ArrayOfEnums.proto | 13 - .../testdata/proto/ArrayOfMessages.proto | 9 - .../testdata/proto/ArrayOfObjects.proto | 26 -- .../testdata/proto/ArrayOfPrimitives.proto | 10 - .../testdata/proto/CyclicalReference.proto | 21 -- .../testdata/proto/EnumNestedReference.proto | 8 - .../testdata/proto/EnumWithMessage.proto | 12 - .../testdata/proto/Enumception.proto | 22 -- .../testdata/proto/GoogleValue.proto | 8 - .../converter/testdata/proto/ImportEnum.proto | 8 - .../testdata/proto/ImportedEnum.proto | 9 - .../converter/testdata/proto/JSONFields.proto | 11 - .../converter/testdata/proto/Maps.proto | 10 - .../testdata/proto/MessageWithComments.proto | 9 - .../testdata/proto/NestedMessage.proto | 9 - .../testdata/proto/NestedObject.proto | 25 -- .../converter/testdata/proto/NoPackage.proto | 9 - .../testdata/proto/PayloadMessage.proto | 20 -- .../testdata/proto/PayloadMessage2.proto | 20 -- .../testdata/proto/Proto2NestedMessage.proto | 25 -- .../testdata/proto/Proto2NestedObject.proto | 25 -- .../testdata/proto/Proto2Required.proto | 8 - .../testdata/proto/SelfReference.proto | 7 - .../testdata/proto/SeveralEnums.proto | 16 - .../testdata/proto/SeveralMessages.proto | 18 - .../converter/testdata/proto/Timestamp.proto | 8 - .../testdata/proto/TwelveMessages.proto | 109 ------ .../converter/testdata/proto/WellKnown.proto | 11 - .../testdata/proto2_nested_message.go | 64 ---- .../testdata/proto2_nested_object.go | 69 ---- .../testdata/proto2_payload_message.go | 52 --- .../converter/testdata/proto2_required.go | 21 -- .../converter/testdata/second_enum.go | 23 -- .../converter/testdata/second_message.go | 24 -- .../converter/testdata/self_reference.go | 26 -- .../converter/testdata/timestamp.go | 13 - .../converter/testdata/wellknown.go | 32 -- 63 files changed, 2740 deletions(-) delete mode 100644 plugins/restapi/jsonschema/converter/converter_test.go delete mode 100644 plugins/restapi/jsonschema/converter/sourcecodeinfo_test.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/README.md delete mode 100644 plugins/restapi/jsonschema/converter/testdata/array_of_enums.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/array_of_messages.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/array_of_objects.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/array_of_primitives.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/cyclical_reference.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/enum_ception.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/enum_imported.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/enum_nested_reference.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/enum_with_message.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/first_enum.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/first_message.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/google_value.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/imported_enum.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/json_fields.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/maps.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/message_kind_10.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/message_kind_11.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/message_kind_12.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/message_with_comments.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/nested_message.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/nested_object.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/payload_message.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/payload_message_2.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfEnums.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfMessages.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfObjects.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfPrimitives.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/CyclicalReference.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/EnumNestedReference.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/EnumWithMessage.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/Enumception.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/GoogleValue.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/ImportEnum.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/ImportedEnum.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/JSONFields.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/Maps.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/MessageWithComments.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/NestedMessage.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/NestedObject.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/NoPackage.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage2.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedMessage.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedObject.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/Proto2Required.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/SelfReference.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/SeveralEnums.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/SeveralMessages.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/Timestamp.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/TwelveMessages.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto/WellKnown.proto delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto2_nested_message.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto2_nested_object.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto2_payload_message.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/proto2_required.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/second_enum.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/second_message.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/self_reference.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/timestamp.go delete mode 100644 plugins/restapi/jsonschema/converter/testdata/wellknown.go diff --git a/plugins/restapi/jsonschema/converter/converter_test.go b/plugins/restapi/jsonschema/converter/converter_test.go deleted file mode 100644 index 8ed4e632ab..0000000000 --- a/plugins/restapi/jsonschema/converter/converter_test.go +++ /dev/null @@ -1,317 +0,0 @@ -package converter - -import ( - "bytes" - "fmt" - "os" - "os/exec" - "strings" - "testing" - - "github.com/golang/protobuf/proto" - "github.com/golang/protobuf/protoc-gen-go/descriptor" - plugin "github.com/golang/protobuf/protoc-gen-go/plugin" - "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" - - "go.ligato.io/vpp-agent/v3/examples/customize/custom_api_model/json_schema/converter/testdata" -) - -const ( - sampleProtoDirectory = "testdata/proto" -) - -type sampleProto struct { - AllFieldsRequired bool - AllowNullValues bool - ExpectedJSONSchema []string - FilesToGenerate []string - PrefixSchemaFilesWithPackage bool - ProtoFileName string - UseJSONFieldnamesOnly bool - UseProtoAndJSONFieldNames bool - TargetedMessages []string -} - -func TestGenerateJsonSchema(t *testing.T) { - - // Configure the list of sample protos to test, and their expected JSON-Schemas: - sampleProtos := configureSampleProtos() - - // Convert the protos, compare the results against the expected JSON-Schemas: - for name, sampleProto := range sampleProtos { - t.Run(name, func(t *testing.T) { - testConvertSampleProto(t, sampleProto) - }) - } -} - -func testConvertSampleProto(t *testing.T, sampleProto sampleProto) { - t.Helper() - - // Make a Logrus logger: - logger := logrus.New() - logger.SetLevel(logrus.ErrorLevel) - logger.SetOutput(os.Stderr) - - // Use the logger to make a Converter: - protoConverter := New(logger) - protoConverter.AllFieldsRequired = sampleProto.AllFieldsRequired - protoConverter.AllowNullValues = sampleProto.AllowNullValues - protoConverter.UseJSONFieldnamesOnly = sampleProto.UseJSONFieldnamesOnly - protoConverter.UseProtoAndJSONFieldnames = sampleProto.UseProtoAndJSONFieldNames - protoConverter.PrefixSchemaFilesWithPackage = sampleProto.PrefixSchemaFilesWithPackage - - // Open the sample proto file: - sampleProtoFileName := fmt.Sprintf("%v/%v", sampleProtoDirectory, sampleProto.ProtoFileName) - fileDescriptorSet := mustReadProtoFiles(t, sampleProtoDirectory, sampleProto.ProtoFileName) - - // Prepare a request: - codeGeneratorRequest := plugin.CodeGeneratorRequest{ - FileToGenerate: sampleProto.FilesToGenerate, - ProtoFile: fileDescriptorSet.GetFile(), - } - - if len(sampleProto.TargetedMessages) > 0 { - arg := fmt.Sprintf("messages=[%s]", strings.Join(sampleProto.TargetedMessages, messageDelimiter)) - codeGeneratorRequest.Parameter = &arg - } - - // Perform the conversion: - response, err := protoConverter.convert(&codeGeneratorRequest) - assert.NoError(t, err, "Unable to convert sample proto file (%v)", sampleProtoFileName) - assert.Equal(t, len(sampleProto.ExpectedJSONSchema), len(response.File), "Incorrect number of JSON-Schema files returned for sample proto file (%v)", sampleProtoFileName) - if len(sampleProto.ExpectedJSONSchema) != len(response.File) { - t.Fail() - } else { - for responseFileIndex, responseFile := range response.File { - assert.Equal(t, strings.TrimSpace(sampleProto.ExpectedJSONSchema[responseFileIndex]), *responseFile.Content, "Incorrect JSON-Schema returned for sample proto file (%v)", sampleProtoFileName) - } - } - - // Return now if we have no files: - if len(response.File) == 0 { - return - } - - // Check for the correct prefix: - if protoConverter.PrefixSchemaFilesWithPackage { - assert.Contains(t, response.File[0].GetName(), "samples") - } else { - assert.NotContains(t, response.File[0].GetName(), "samples") - } -} - -func configureSampleProtos() map[string]sampleProto { - return map[string]sampleProto{ - "ArrayOfMessages": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.PayloadMessage, testdata.ArrayOfMessages}, - FilesToGenerate: []string{"ArrayOfMessages.proto", "PayloadMessage.proto"}, - ProtoFileName: "ArrayOfMessages.proto", - }, - "ArrayOfObjects": { - AllowNullValues: true, - ExpectedJSONSchema: []string{testdata.ArrayOfObjects}, - FilesToGenerate: []string{"ArrayOfObjects.proto"}, - ProtoFileName: "ArrayOfObjects.proto", - }, - "ArrayOfPrimitives": { - AllowNullValues: true, - ExpectedJSONSchema: []string{testdata.ArrayOfPrimitives}, - FilesToGenerate: []string{"ArrayOfPrimitives.proto"}, - ProtoFileName: "ArrayOfPrimitives.proto", - }, - "ArrayOfPrimitivesDouble": { - AllowNullValues: true, - ExpectedJSONSchema: []string{testdata.ArrayOfPrimitivesDouble}, - FilesToGenerate: []string{"ArrayOfPrimitives.proto"}, - ProtoFileName: "ArrayOfPrimitives.proto", - UseProtoAndJSONFieldNames: true, - }, - "EnumNestedReference": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.EnumNestedReference}, - FilesToGenerate: []string{"EnumNestedReference.proto"}, - ProtoFileName: "EnumNestedReference.proto", - }, - "EnumWithMessage": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.EnumWithMessage}, - FilesToGenerate: []string{"EnumWithMessage.proto"}, - ProtoFileName: "EnumWithMessage.proto", - }, - "EnumImport": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.EnumImport}, - FilesToGenerate: []string{"ImportEnum.proto"}, - ProtoFileName: "ImportEnum.proto", - }, - "EnumCeption": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.PayloadMessage, testdata.ImportedEnum, testdata.EnumCeption}, - FilesToGenerate: []string{"Enumception.proto", "PayloadMessage.proto", "ImportedEnum.proto"}, - ProtoFileName: "Enumception.proto", - }, - "ImportedEnum": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.ImportedEnum}, - FilesToGenerate: []string{"ImportedEnum.proto"}, - ProtoFileName: "ImportedEnum.proto", - }, - "NestedMessage": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.PayloadMessage, testdata.NestedMessage}, - FilesToGenerate: []string{"NestedMessage.proto", "PayloadMessage.proto"}, - ProtoFileName: "NestedMessage.proto", - }, - "NestedObject": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.NestedObject}, - FilesToGenerate: []string{"NestedObject.proto"}, - ProtoFileName: "NestedObject.proto", - }, - "PayloadMessage": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.PayloadMessage}, - FilesToGenerate: []string{"PayloadMessage.proto"}, - ProtoFileName: "PayloadMessage.proto", - }, - "SeveralEnums": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.FirstEnum, testdata.SecondEnum}, - FilesToGenerate: []string{"SeveralEnums.proto"}, - ProtoFileName: "SeveralEnums.proto", - }, - "SeveralMessages": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.FirstMessage, testdata.SecondMessage}, - FilesToGenerate: []string{"SeveralMessages.proto"}, - ProtoFileName: "SeveralMessages.proto", - }, - "ArrayOfEnums": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.ArrayOfEnums}, - FilesToGenerate: []string{"ArrayOfEnums.proto"}, - ProtoFileName: "ArrayOfEnums.proto", - }, - "Maps": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.Maps}, - FilesToGenerate: []string{"Maps.proto"}, - ProtoFileName: "Maps.proto", - }, - "Comments": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.MessageWithComments}, - FilesToGenerate: []string{"MessageWithComments.proto"}, - ProtoFileName: "MessageWithComments.proto", - }, - "SelfReference": { - ExpectedJSONSchema: []string{testdata.SelfReference}, - FilesToGenerate: []string{"SelfReference.proto"}, - ProtoFileName: "SelfReference.proto", - }, - "CyclicalReference": { - ExpectedJSONSchema: []string{testdata.CyclicalReferenceMessageM, testdata.CyclicalReferenceMessageFoo, testdata.CyclicalReferenceMessageBar, testdata.CyclicalReferenceMessageBaz}, - FilesToGenerate: []string{"CyclicalReference.proto"}, - ProtoFileName: "CyclicalReference.proto", - }, - "WellKnown": { - ExpectedJSONSchema: []string{testdata.WellKnown}, - FilesToGenerate: []string{"WellKnown.proto"}, - ProtoFileName: "WellKnown.proto", - }, - "Timestamp": { - ExpectedJSONSchema: []string{testdata.Timestamp}, - FilesToGenerate: []string{"Timestamp.proto"}, - ProtoFileName: "Timestamp.proto", - }, - "NoPackage": { - ExpectedJSONSchema: []string{}, - FilesToGenerate: []string{}, - ProtoFileName: "NoPackage.proto", - }, - "PackagePrefix": { - ExpectedJSONSchema: []string{testdata.Timestamp}, - FilesToGenerate: []string{"Timestamp.proto"}, - ProtoFileName: "Timestamp.proto", - PrefixSchemaFilesWithPackage: true, - }, - "Proto2Required": { - ExpectedJSONSchema: []string{testdata.Proto2Required}, - FilesToGenerate: []string{"Proto2Required.proto"}, - ProtoFileName: "Proto2Required.proto", - }, - "AllRequired": { - AllFieldsRequired: true, - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.PayloadMessage2}, - FilesToGenerate: []string{"PayloadMessage2.proto"}, - ProtoFileName: "PayloadMessage2.proto", - }, - "Proto2NestedMessage": { - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.Proto2PayloadMessage, testdata.Proto2NestedMessage}, - FilesToGenerate: []string{"Proto2PayloadMessage.proto", "Proto2NestedMessage.proto"}, - ProtoFileName: "Proto2NestedMessage.proto", - }, - "Proto2NestedObject": { - AllFieldsRequired: true, - AllowNullValues: false, - ExpectedJSONSchema: []string{testdata.Proto2NestedObject}, - FilesToGenerate: []string{"Proto2NestedObject.proto"}, - ProtoFileName: "Proto2NestedObject.proto", - }, - "TargetedMessages": { - TargetedMessages: []string{"MessageKind10", "MessageKind11", "MessageKind12"}, - ExpectedJSONSchema: []string{testdata.MessageKind10, testdata.MessageKind11, testdata.MessageKind12}, - FilesToGenerate: []string{"TwelveMessages.proto"}, - ProtoFileName: "TwelveMessages.proto", - }, - "GoogleValue": { - ExpectedJSONSchema: []string{testdata.GoogleValue}, - FilesToGenerate: []string{"GoogleValue.proto"}, - ProtoFileName: "GoogleValue.proto", - }, - "JSONFields": { - ExpectedJSONSchema: []string{testdata.JSONFields}, - FilesToGenerate: []string{"JSONFields.proto"}, - ProtoFileName: "JSONFields.proto", - UseJSONFieldnamesOnly: true, - }, - } -} - -// Load the specified .proto files into a FileDescriptorSet. Any errors in loading/parsing will -// immediately fail the test. -func mustReadProtoFiles(t *testing.T, includePath string, filenames ...string) *descriptor.FileDescriptorSet { - protocBinary, err := exec.LookPath("protoc") - if err != nil { - t.Fatalf("Can't find 'protoc' binary in $PATH: %s", err.Error()) - } - - // Use protoc to output descriptor info for the specified .proto files. - var args []string - args = append(args, "--descriptor_set_out=/dev/stdout") - args = append(args, "--include_source_info") - args = append(args, "--include_imports") - args = append(args, "--proto_path="+includePath) - args = append(args, filenames...) - cmd := exec.Command(protocBinary, args...) - stdoutBuf := bytes.Buffer{} - stderrBuf := bytes.Buffer{} - cmd.Stdout = &stdoutBuf - cmd.Stderr = &stderrBuf - err = cmd.Run() - if err != nil { - t.Fatalf("failed to load descriptor set (%s): %s: %s", - strings.Join(cmd.Args, " "), err.Error(), stderrBuf.String()) - } - fds := &descriptor.FileDescriptorSet{} - err = proto.Unmarshal(stdoutBuf.Bytes(), fds) - if err != nil { - t.Fatalf("failed to parse protoc output as FileDescriptorSet: %s", err.Error()) - } - return fds -} diff --git a/plugins/restapi/jsonschema/converter/sourcecodeinfo_test.go b/plugins/restapi/jsonschema/converter/sourcecodeinfo_test.go deleted file mode 100644 index 657453189e..0000000000 --- a/plugins/restapi/jsonschema/converter/sourcecodeinfo_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package converter - -import ( - "testing" - - "github.com/golang/protobuf/protoc-gen-go/descriptor" -) - -func TestSourceInfoLookup(t *testing.T) { - // Read in the test file & get references to the things we've declared. - // Note that the hardcoded indexes must reflect the declaration order in - // the .proto file. - fds := mustReadProtoFiles(t, sampleProtoDirectory, "MessageWithComments.proto") - protoFile := fds.File[0] - msgWithComments := protoFile.MessageType[0] - msgWithComments_name1 := msgWithComments.Field[0] - - // Create an instance of our thing and test that it returns the expected - // source data for each of our above declarations. - src := newSourceCodeInfo(fds.File) - assertCommentsMatch(t, src.GetMessage(msgWithComments), &descriptor.SourceCodeInfo_Location{ - LeadingComments: strPtr(" This is a message level comment and talks about what this message is and why you should care about it!\n"), - }) - assertCommentsMatch(t, src.GetField(msgWithComments_name1), &descriptor.SourceCodeInfo_Location{ - LeadingComments: strPtr(" This field is supposed to represent blahblahblah\n"), - }) -} - -func assertCommentsMatch(t *testing.T, actual, expected *descriptor.SourceCodeInfo_Location) { - if len(actual.LeadingDetachedComments) != len(expected.LeadingDetachedComments) { - t.Fatalf("Wrong value for LeadingDetachedComments.\n got: %v\n want: %v", - actual.LeadingDetachedComments, expected.LeadingDetachedComments) - } - for i := 0; i < len(actual.LeadingDetachedComments); i++ { - if actual.LeadingDetachedComments[i] != expected.LeadingDetachedComments[i] { - t.Fatalf("Wrong value for LeadingDetachedComments.\n got: %v\n want: %v", - actual.LeadingDetachedComments, expected.LeadingDetachedComments) - } - } - if actual.GetTrailingComments() != expected.GetTrailingComments() { - t.Fatalf("Wrong value for TrailingComments.\n got: %q\n want: %q", - actual.GetTrailingComments(), expected.GetTrailingComments()) - } - if actual.GetLeadingComments() != expected.GetLeadingComments() { - t.Fatalf("Wrong value for LeadingComments.\n got: %q\n want: %q", - actual.GetLeadingComments(), expected.GetLeadingComments()) - } -} - -// Go doesn't have syntax for addressing a string literal, so this is the next best thing. -func strPtr(s string) *string { - return &s -} diff --git a/plugins/restapi/jsonschema/converter/testdata/README.md b/plugins/restapi/jsonschema/converter/testdata/README.md deleted file mode 100644 index f617cdbd65..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/README.md +++ /dev/null @@ -1,6 +0,0 @@ -Test Data -========= - -This package contains constants two sets of test data: -1) Proto definitions for various test cases. These define different types of messages and proto payloads which the test suite will attempt to compile. -2) The GoLang files contain consts which define the exact JSONSchemas which are expected to be generated by the tests. diff --git a/plugins/restapi/jsonschema/converter/testdata/array_of_enums.go b/plugins/restapi/jsonschema/converter/testdata/array_of_enums.go deleted file mode 100644 index d7ab881ca3..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/array_of_enums.go +++ /dev/null @@ -1,27 +0,0 @@ -package testdata - -const ArrayOfEnums = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "type": "string" - }, - "stuff": { - "items": { - "enum": [ - "FOO", - 0, - "BAR", - 1, - "FIZZ", - 2, - "BUZZ", - 3 - ] - }, - "type": "array" - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/array_of_messages.go b/plugins/restapi/jsonschema/converter/testdata/array_of_messages.go deleted file mode 100644 index 86d002dd58..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/array_of_messages.go +++ /dev/null @@ -1,61 +0,0 @@ -package testdata - -const ArrayOfMessages = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "type": "string" - }, - "payload": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" - }, - "type": "array" - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/array_of_objects.go b/plugins/restapi/jsonschema/converter/testdata/array_of_objects.go deleted file mode 100644 index 4f1560ea60..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/array_of_objects.go +++ /dev/null @@ -1,127 +0,0 @@ -package testdata - -const ArrayOfObjects = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "payload": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "timestamp": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "id": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "integer" - } - ] - }, - "rating": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "complete": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] - }, - "oneOf": [ - { - "type": "null" - }, - { - "type": "array" - } - ] - } - }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/array_of_primitives.go b/plugins/restapi/jsonschema/converter/testdata/array_of_primitives.go deleted file mode 100644 index cb0eb4f0ef..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/array_of_primitives.go +++ /dev/null @@ -1,201 +0,0 @@ -package testdata - -const ArrayOfPrimitives = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "luckyNumbers": { - "items": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "integer" - } - ] - }, - "oneOf": [ - { - "type": "null" - }, - { - "type": "array" - } - ] - }, - "luckyBigNumbers": { - "items": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "oneOf": [ - { - "type": "null" - }, - { - "type": "array" - } - ] - }, - "keyWords": { - "items": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "oneOf": [ - { - "type": "null" - }, - { - "type": "array" - } - ] - }, - "big_number": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] -}` - -const ArrayOfPrimitivesDouble = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "luckyNumbers": { - "items": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "integer" - } - ] - }, - "oneOf": [ - { - "type": "null" - }, - { - "type": "array" - } - ] - }, - "luckyBigNumbers": { - "items": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "oneOf": [ - { - "type": "null" - }, - { - "type": "array" - } - ] - }, - "keyWords": { - "items": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "oneOf": [ - { - "type": "null" - }, - { - "type": "array" - } - ] - }, - "big_number": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "bigNumber": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/cyclical_reference.go b/plugins/restapi/jsonschema/converter/testdata/cyclical_reference.go deleted file mode 100644 index 0f39c168ff..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/cyclical_reference.go +++ /dev/null @@ -1,185 +0,0 @@ -package testdata - -const ( - CyclicalReferenceMessageM = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "foo": { - "$ref": "samples.Foo", - "additionalProperties": true - } - }, - "additionalProperties": true, - "type": "object", - "definitions": { - "samples.Foo": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "bar": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "id": { - "type": "integer" - }, - "baz": { - "properties": { - "enabled": { - "type": "boolean" - }, - "foo": { - "$ref": "samples.Foo", - "additionalProperties": true - } - }, - "additionalProperties": true, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object" - }, - "type": "array" - } - }, - "additionalProperties": true, - "type": "object", - "id": "samples.Foo" - } - } -}` - - CyclicalReferenceMessageFoo = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "Foo", - "definitions": { - "Foo": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "bar": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "id": { - "type": "integer" - }, - "baz": { - "properties": { - "enabled": { - "type": "boolean" - }, - "foo": { - "$ref": "Foo", - "additionalProperties": true - } - }, - "additionalProperties": true, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object" - }, - "type": "array" - } - }, - "additionalProperties": true, - "type": "object", - "id": "Foo" - } - } -}` - - CyclicalReferenceMessageBar = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "Bar", - "definitions": { - "Bar": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "id": { - "type": "integer" - }, - "baz": { - "properties": { - "enabled": { - "type": "boolean" - }, - "foo": { - "properties": { - "name": { - "type": "string" - }, - "bar": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "Bar" - }, - "type": "array" - } - }, - "additionalProperties": true, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object", - "id": "Bar" - } - } -}` - - CyclicalReferenceMessageBaz = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "Baz", - "definitions": { - "Baz": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "enabled": { - "type": "boolean" - }, - "foo": { - "properties": { - "name": { - "type": "string" - }, - "bar": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "id": { - "type": "integer" - }, - "baz": { - "$ref": "Baz", - "additionalProperties": true - } - }, - "additionalProperties": true, - "type": "object" - }, - "type": "array" - } - }, - "additionalProperties": true, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object", - "id": "Baz" - } - } -}` -) diff --git a/plugins/restapi/jsonschema/converter/testdata/enum_ception.go b/plugins/restapi/jsonschema/converter/testdata/enum_ception.go deleted file mode 100644 index 4db6ff0165..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/enum_ception.go +++ /dev/null @@ -1,120 +0,0 @@ -package testdata - -const EnumCeption = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "failureMode": { - "enum": [ - "RECURSION_ERROR", - 0, - "SYNTAX_ERROR", - 1 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - }, - "payload": { - "$ref": "samples.PayloadMessage", - "additionalProperties": true - }, - "payloads": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "samples.PayloadMessage" - }, - "type": "array" - }, - "importedEnum": { - "enum": [ - "VALUE_0", - 0, - "VALUE_1", - 1, - "VALUE_2", - 2, - "VALUE_3", - 3 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object", - "definitions": { - "samples.PayloadMessage": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object", - "id": "samples.PayloadMessage" - } - } -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/enum_imported.go b/plugins/restapi/jsonschema/converter/testdata/enum_imported.go deleted file mode 100644 index c15e08699b..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/enum_imported.go +++ /dev/null @@ -1,29 +0,0 @@ -package testdata - -const EnumImport = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "importedEnum": { - "enum": [ - "VALUE_0", - 0, - "VALUE_1", - 1, - "VALUE_2", - 2, - "VALUE_3", - 3 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/enum_nested_reference.go b/plugins/restapi/jsonschema/converter/testdata/enum_nested_reference.go deleted file mode 100644 index 1f456e3beb..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/enum_nested_reference.go +++ /dev/null @@ -1,33 +0,0 @@ -package testdata - -const EnumNestedReference = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "nestedEnumField": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/enum_with_message.go b/plugins/restapi/jsonschema/converter/testdata/enum_with_message.go deleted file mode 100644 index 68f7548acb..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/enum_with_message.go +++ /dev/null @@ -1,27 +0,0 @@ -package testdata - -const EnumWithMessage = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "enumField": { - "enum": [ - "Foo", - 0, - "Bar", - 1, - "Baz", - 2 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/first_enum.go b/plugins/restapi/jsonschema/converter/testdata/first_enum.go deleted file mode 100644 index 3c046a836c..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/first_enum.go +++ /dev/null @@ -1,23 +0,0 @@ -package testdata - -const FirstEnum = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "enum": [ - "VALUE_0", - 0, - "VALUE_1", - 1, - "VALUE_2", - 2, - "VALUE_3", - 3 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/first_message.go b/plugins/restapi/jsonschema/converter/testdata/first_message.go deleted file mode 100644 index fac59444e6..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/first_message.go +++ /dev/null @@ -1,24 +0,0 @@ -package testdata - -const FirstMessage = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name1": { - "type": "string" - }, - "timestamp1": { - "type": "string" - }, - "id1": { - "type": "integer" - }, - "rating1": { - "type": "number" - }, - "complete1": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/google_value.go b/plugins/restapi/jsonschema/converter/testdata/google_value.go deleted file mode 100644 index 511464e1df..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/google_value.go +++ /dev/null @@ -1,13 +0,0 @@ -package testdata - -const GoogleValue = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "arg": { - "additionalProperties": true, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/imported_enum.go b/plugins/restapi/jsonschema/converter/testdata/imported_enum.go deleted file mode 100644 index fbc17be22c..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/imported_enum.go +++ /dev/null @@ -1,23 +0,0 @@ -package testdata - -const ImportedEnum = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "enum": [ - "VALUE_0", - 0, - "VALUE_1", - 1, - "VALUE_2", - 2, - "VALUE_3", - 3 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/json_fields.go b/plugins/restapi/jsonschema/converter/testdata/json_fields.go deleted file mode 100644 index 13a537f82b..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/json_fields.go +++ /dev/null @@ -1,28 +0,0 @@ -package testdata - -const JSONFields = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "identifier": { - "type": "integer" - }, - "someThing": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "snakeNumb": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" -} -` diff --git a/plugins/restapi/jsonschema/converter/testdata/maps.go b/plugins/restapi/jsonschema/converter/testdata/maps.go deleted file mode 100644 index d2d10ea7f8..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/maps.go +++ /dev/null @@ -1,69 +0,0 @@ -package testdata - -const Maps = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "map_of_strings": { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - "map_of_ints": { - "additionalProperties": { - "type": "integer" - }, - "type": "object" - }, - "map_of_messages": { - "additionalProperties": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" - }, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/message_kind_10.go b/plugins/restapi/jsonschema/converter/testdata/message_kind_10.go deleted file mode 100644 index 40adf17045..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/message_kind_10.go +++ /dev/null @@ -1,25 +0,0 @@ -package testdata - -const MessageKind10 = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" -} -` diff --git a/plugins/restapi/jsonschema/converter/testdata/message_kind_11.go b/plugins/restapi/jsonschema/converter/testdata/message_kind_11.go deleted file mode 100644 index 6529e54f58..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/message_kind_11.go +++ /dev/null @@ -1,113 +0,0 @@ -package testdata - -const MessageKind11 = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "ones": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" - }, - "type": "array" - }, - "kind2": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "isa": { - "type": "boolean" - }, - "hasa": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" - }, - "kind3": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "someProp": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" - }, - "kind4": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "special": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object" -} -` diff --git a/plugins/restapi/jsonschema/converter/testdata/message_kind_12.go b/plugins/restapi/jsonschema/converter/testdata/message_kind_12.go deleted file mode 100644 index 0743a51dc8..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/message_kind_12.go +++ /dev/null @@ -1,194 +0,0 @@ -package testdata - -const MessageKind12 = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "f": { - "properties": { - "name": { - "type": "string" - }, - "ones": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" - }, - "type": "array" - }, - "kind2": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "isa": { - "type": "boolean" - }, - "hasa": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" - }, - "kind3": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "someProp": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" - }, - "kind4": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "special": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object" - }, - "kind5": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "foo": { - "type": "number" - } - }, - "additionalProperties": true, - "type": "object" - }, - "kind6": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "bar": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" - }, - "kind7": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "baz": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object" -} -` diff --git a/plugins/restapi/jsonschema/converter/testdata/message_with_comments.go b/plugins/restapi/jsonschema/converter/testdata/message_with_comments.go deleted file mode 100644 index b14b869b89..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/message_with_comments.go +++ /dev/null @@ -1,14 +0,0 @@ -package testdata - -const MessageWithComments = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name1": { - "type": "string", - "description": "This field is supposed to represent blahblahblah" - } - }, - "additionalProperties": true, - "type": "object", - "description": "This is a message level comment and talks about what this message is and why you should care about it!" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/nested_message.go b/plugins/restapi/jsonschema/converter/testdata/nested_message.go deleted file mode 100644 index 15dba579cb..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/nested_message.go +++ /dev/null @@ -1,57 +0,0 @@ -package testdata - -const NestedMessage = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "payload": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" - }, - "description": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/nested_object.go b/plugins/restapi/jsonschema/converter/testdata/nested_object.go deleted file mode 100644 index 3becb18d8b..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/nested_object.go +++ /dev/null @@ -1,57 +0,0 @@ -package testdata - -const NestedObject = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "payload": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" - }, - "description": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/payload_message.go b/plugins/restapi/jsonschema/converter/testdata/payload_message.go deleted file mode 100644 index 8cf27a4eba..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/payload_message.go +++ /dev/null @@ -1,48 +0,0 @@ -package testdata - -const PayloadMessage = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/payload_message_2.go b/plugins/restapi/jsonschema/converter/testdata/payload_message_2.go deleted file mode 100644 index 69e7730cc5..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/payload_message_2.go +++ /dev/null @@ -1,56 +0,0 @@ -package testdata - -const PayloadMessage2 = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "name", - "timestamp", - "id", - "rating", - "complete", - "topology" - ], - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfEnums.proto b/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfEnums.proto deleted file mode 100644 index d72aab75fa..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfEnums.proto +++ /dev/null @@ -1,13 +0,0 @@ -syntax = "proto3"; -package samples; - -message ArrayOfEnums { - string description = 1; - enum inline { - FOO = 0; - BAR = 1; - FIZZ = 2; - BUZZ = 3; - } - repeated inline stuff = 2; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfMessages.proto b/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfMessages.proto deleted file mode 100644 index 16e286f87b..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfMessages.proto +++ /dev/null @@ -1,9 +0,0 @@ -syntax = "proto3"; -package samples; - -import "PayloadMessage.proto"; - -message ArrayOfMessages { - string description = 1; - repeated PayloadMessage payload = 2; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfObjects.proto b/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfObjects.proto deleted file mode 100644 index 5121474671..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfObjects.proto +++ /dev/null @@ -1,26 +0,0 @@ -syntax = "proto3"; -package samples; - -message ArrayOfObjects { - - message RepeatedPayload { - enum Topology { - FLAT = 0; - NESTED_OBJECT = 1; - NESTED_MESSAGE = 2; - ARRAY_OF_TYPE = 3; - ARRAY_OF_OBJECT = 4; - ARRAY_OF_MESSAGE = 5; - } - - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; - Topology topology = 6; - } - - string description = 1; - repeated RepeatedPayload payload = 2; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfPrimitives.proto b/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfPrimitives.proto deleted file mode 100644 index 08da80288c..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/ArrayOfPrimitives.proto +++ /dev/null @@ -1,10 +0,0 @@ -syntax = "proto3"; -package samples; - -message ArrayOfPrimitives { - string description = 1; - repeated int32 luckyNumbers = 2; - repeated int64 luckyBigNumbers = 3; - repeated string keyWords = 4; - int64 big_number = 5; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/CyclicalReference.proto b/plugins/restapi/jsonschema/converter/testdata/proto/CyclicalReference.proto deleted file mode 100644 index 77e9647d85..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/CyclicalReference.proto +++ /dev/null @@ -1,21 +0,0 @@ -syntax = "proto3"; -package samples; - -message M { - Foo foo = 1; -} - -message Foo { - string name = 1; - repeated Bar bar = 2; -} - -message Bar { - uint32 id = 1; - Baz baz = 2; -} - -message Baz { - bool enabled = 1; - Foo foo = 2; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/EnumNestedReference.proto b/plugins/restapi/jsonschema/converter/testdata/proto/EnumNestedReference.proto deleted file mode 100644 index cfea653ba9..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/EnumNestedReference.proto +++ /dev/null @@ -1,8 +0,0 @@ -syntax = "proto3"; -package samples; - -import "PayloadMessage.proto"; - -message Msg { - PayloadMessage.Topology nestedEnumField = 1; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/EnumWithMessage.proto b/plugins/restapi/jsonschema/converter/testdata/proto/EnumWithMessage.proto deleted file mode 100644 index f0e0ef8be8..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/EnumWithMessage.proto +++ /dev/null @@ -1,12 +0,0 @@ -syntax = "proto3"; -package samples; - -enum FooBarBaz { - Foo = 0; - Bar = 1; - Baz = 2; -} - -message WithFooBarBaz { - FooBarBaz enumField = 1; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/Enumception.proto b/plugins/restapi/jsonschema/converter/testdata/proto/Enumception.proto deleted file mode 100644 index f2bdb180f5..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/Enumception.proto +++ /dev/null @@ -1,22 +0,0 @@ -syntax = "proto3"; -package samples; - -import "PayloadMessage.proto"; -import "ImportedEnum.proto"; - -message Enumception { - enum FailureModes { - RECURSION_ERROR = 0; - SYNTAX_ERROR = 1; - } - - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; - FailureModes failureMode = 6; - PayloadMessage payload = 7; - repeated PayloadMessage payloads = 8; - ImportedEnum importedEnum = 9; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/GoogleValue.proto b/plugins/restapi/jsonschema/converter/testdata/proto/GoogleValue.proto deleted file mode 100644 index 4fe3988637..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/GoogleValue.proto +++ /dev/null @@ -1,8 +0,0 @@ -syntax = "proto3"; -package samples; - -import "google/protobuf/struct.proto"; - -message GoogleValue { - google.protobuf.Value arg = 1; -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/ImportEnum.proto b/plugins/restapi/jsonschema/converter/testdata/proto/ImportEnum.proto deleted file mode 100644 index 09424642f4..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/ImportEnum.proto +++ /dev/null @@ -1,8 +0,0 @@ -syntax = "proto3"; -package samples; - -import "ImportedEnum.proto"; - -message UseImportedEnum { - ImportedEnum importedEnum = 1; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/ImportedEnum.proto b/plugins/restapi/jsonschema/converter/testdata/proto/ImportedEnum.proto deleted file mode 100644 index 0e8212a53f..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/ImportedEnum.proto +++ /dev/null @@ -1,9 +0,0 @@ -syntax = "proto3"; -package samples; - -enum ImportedEnum { - VALUE_0 = 0; - VALUE_1 = 1; - VALUE_2 = 2; - VALUE_3 = 3; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/JSONFields.proto b/plugins/restapi/jsonschema/converter/testdata/proto/JSONFields.proto deleted file mode 100644 index 8556d5a0bc..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/JSONFields.proto +++ /dev/null @@ -1,11 +0,0 @@ -syntax = "proto3"; -package samples; - -message JSONFields { - string name = 1; - string timestamp = 2; - int32 id = 3 [json_name="identifier"]; - float some_thing = 4 [json_name="someThing"]; - bool complete = 5; - int64 snake_numb = 6; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/Maps.proto b/plugins/restapi/jsonschema/converter/testdata/proto/Maps.proto deleted file mode 100644 index 18565f9a36..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/Maps.proto +++ /dev/null @@ -1,10 +0,0 @@ -syntax = "proto3"; -package samples; - -import "PayloadMessage.proto"; - -message Maps { - map map_of_strings = 1; - map map_of_ints = 2; - map map_of_messages = 3; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/MessageWithComments.proto b/plugins/restapi/jsonschema/converter/testdata/proto/MessageWithComments.proto deleted file mode 100644 index 43958911ac..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/MessageWithComments.proto +++ /dev/null @@ -1,9 +0,0 @@ -syntax = "proto3"; -package samples; - -// This is a message level comment and talks about what this message is and why you should care about it! -message MessageWithComments { - - // This field is supposed to represent blahblahblah - string name1 = 1; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/NestedMessage.proto b/plugins/restapi/jsonschema/converter/testdata/proto/NestedMessage.proto deleted file mode 100644 index 0245f0875f..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/NestedMessage.proto +++ /dev/null @@ -1,9 +0,0 @@ -syntax = "proto3"; -package samples; - -import "PayloadMessage.proto"; - -message NestedMessage { - PayloadMessage payload = 1; - string description = 2; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/NestedObject.proto b/plugins/restapi/jsonschema/converter/testdata/proto/NestedObject.proto deleted file mode 100644 index 9ffd03205f..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/NestedObject.proto +++ /dev/null @@ -1,25 +0,0 @@ -syntax = "proto3"; -package samples; - -message NestedObject { - message NestedPayload { - enum Topology { - FLAT = 0; - NESTED_OBJECT = 1; - NESTED_MESSAGE = 2; - ARRAY_OF_TYPE = 3; - ARRAY_OF_OBJECT = 4; - ARRAY_OF_MESSAGE = 5; - } - - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; - Topology topology = 6; - } - - NestedPayload payload = 1; - string description = 2; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/NoPackage.proto b/plugins/restapi/jsonschema/converter/testdata/proto/NoPackage.proto deleted file mode 100644 index 88fa892261..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/NoPackage.proto +++ /dev/null @@ -1,9 +0,0 @@ -syntax = "proto3"; - -message NoPackage { - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage.proto b/plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage.proto deleted file mode 100644 index c5922eb68c..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage.proto +++ /dev/null @@ -1,20 +0,0 @@ -syntax = "proto3"; -package samples; - -message PayloadMessage { - enum Topology { - FLAT = 0; - NESTED_OBJECT = 1; - NESTED_MESSAGE = 2; - ARRAY_OF_TYPE = 3; - ARRAY_OF_OBJECT = 4; - ARRAY_OF_MESSAGE = 5; - } - - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; - Topology topology = 6; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage2.proto b/plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage2.proto deleted file mode 100644 index 77579692cc..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/PayloadMessage2.proto +++ /dev/null @@ -1,20 +0,0 @@ -syntax = "proto3"; -package samples; - -message PayloadMessage2 { - enum Topology { - FLAT = 0; - NESTED_OBJECT = 1; - NESTED_MESSAGE = 2; - ARRAY_OF_TYPE = 3; - ARRAY_OF_OBJECT = 4; - ARRAY_OF_MESSAGE = 5; - } - - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; - Topology topology = 6; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedMessage.proto b/plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedMessage.proto deleted file mode 100644 index 096cca95b7..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedMessage.proto +++ /dev/null @@ -1,25 +0,0 @@ -syntax = "proto2"; -package samples; - -message Proto2PayloadMessage { - enum Topology { - FLAT = 0; - NESTED_OBJECT = 1; - NESTED_MESSAGE = 2; - ARRAY_OF_TYPE = 3; - ARRAY_OF_OBJECT = 4; - ARRAY_OF_MESSAGE = 5; - } - - required string name = 1; - optional string timestamp = 2; - required int32 id = 3; - optional float rating = 4; - optional bool complete = 5; - optional Topology topology = 6; -} - -message Proto2NestedMessage { - required Proto2PayloadMessage payload = 1; - optional string description = 2; -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedObject.proto b/plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedObject.proto deleted file mode 100644 index 09f9aea9a2..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/Proto2NestedObject.proto +++ /dev/null @@ -1,25 +0,0 @@ -syntax = "proto2"; -package samples; - -message Proto2NestedObject { - message NestedPayload { - enum Topology { - FLAT = 0; - NESTED_OBJECT = 1; - NESTED_MESSAGE = 2; - ARRAY_OF_TYPE = 3; - ARRAY_OF_OBJECT = 4; - ARRAY_OF_MESSAGE = 5; - } - - required string name = 1; - optional string timestamp = 2; - required int32 id = 3; - optional float rating = 4; - optional bool complete = 5; - optional Topology topology = 6; - } - - required NestedPayload payload = 1; - optional string description = 2; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/Proto2Required.proto b/plugins/restapi/jsonschema/converter/testdata/proto/Proto2Required.proto deleted file mode 100644 index 8d2aec389b..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/Proto2Required.proto +++ /dev/null @@ -1,8 +0,0 @@ -syntax = "proto2"; -package samples; - -message Proto2Required { - required string query = 1; - optional int32 page_number = 2; - optional int32 result_per_page = 3; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/SelfReference.proto b/plugins/restapi/jsonschema/converter/testdata/proto/SelfReference.proto deleted file mode 100644 index bfd6bb824b..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/SelfReference.proto +++ /dev/null @@ -1,7 +0,0 @@ -syntax = "proto3"; -package samples; - -message Foo { - string name = 1; - repeated Foo bar = 2; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/SeveralEnums.proto b/plugins/restapi/jsonschema/converter/testdata/proto/SeveralEnums.proto deleted file mode 100644 index a487c473b2..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/SeveralEnums.proto +++ /dev/null @@ -1,16 +0,0 @@ -syntax = "proto3"; -package samples; - -enum FirstEnum { - VALUE_0 = 0; - VALUE_1 = 1; - VALUE_2 = 2; - VALUE_3 = 3; -} - -enum SecondEnum { - VALUE_4 = 0; - VALUE_5 = 1; - VALUE_6 = 2; - VALUE_7 = 3; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/SeveralMessages.proto b/plugins/restapi/jsonschema/converter/testdata/proto/SeveralMessages.proto deleted file mode 100644 index 351f0283ab..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/SeveralMessages.proto +++ /dev/null @@ -1,18 +0,0 @@ -syntax = "proto3"; -package samples; - -message FirstMessage { - string name1 = 1; - string timestamp1 = 2; - int32 id1 = 3; - float rating1 = 4; - bool complete1 = 5; -} - -message SecondMessage { - string name2 = 1; - string timestamp2 = 2; - int32 id2 = 3; - float rating2 = 4; - bool complete2 = 5; -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/Timestamp.proto b/plugins/restapi/jsonschema/converter/testdata/proto/Timestamp.proto deleted file mode 100644 index 1606edb6a9..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/Timestamp.proto +++ /dev/null @@ -1,8 +0,0 @@ -syntax = "proto3"; -package samples; - -import "google/protobuf/timestamp.proto"; - -message Timestamp { - google.protobuf.Timestamp timestamp = 1; -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/TwelveMessages.proto b/plugins/restapi/jsonschema/converter/testdata/proto/TwelveMessages.proto deleted file mode 100644 index 2c525312f2..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/TwelveMessages.proto +++ /dev/null @@ -1,109 +0,0 @@ -syntax = "proto3"; -package samples; - -message MessageKind1 { - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; -} - -message MessageKind2 { - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; - bool isa = 6; - bool hasa = 7; -} - -message MessageKind3 { - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; - string someProp = 6; -} - -message MessageKind4 { - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; - string special = 6; -} - -message MessageKind5 { - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; - double foo = 6; -} - -message MessageKind6 { - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; - string bar = 6; -} - -message MessageKind7 { - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; - int64 baz = 6; -} - -message MessageKind8 { - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; -} - -message MessageKind9 { - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; -} - -message MessageKind10 { - string name = 1; - string timestamp = 2; - int32 id = 3; - float rating = 4; - bool complete = 5; -} - -message MessageKind11 { - string name = 1; - repeated MessageKind1 ones = 2; - oneof iface { - MessageKind2 kind2 = 3; - MessageKind3 kind3 = 4; - MessageKind4 kind4 = 5; - } -} - -message MessageKind12 { - string name = 1; - MessageKind11 f = 2; - oneof iface { - MessageKind5 kind5 = 3; - MessageKind6 kind6 = 4; - MessageKind7 kind7 = 5; - } -} diff --git a/plugins/restapi/jsonschema/converter/testdata/proto/WellKnown.proto b/plugins/restapi/jsonschema/converter/testdata/proto/WellKnown.proto deleted file mode 100644 index f2ff5aff70..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto/WellKnown.proto +++ /dev/null @@ -1,11 +0,0 @@ -syntax = "proto3"; -package samples; -import "google/protobuf/wrappers.proto"; - -message WellKnown { - google.protobuf.StringValue string_value = 1; - map map_of_integers = 2; - map map_of_scalar_integers = 3; - repeated google.protobuf.Int32Value list_of_integers = 4; -} - diff --git a/plugins/restapi/jsonschema/converter/testdata/proto2_nested_message.go b/plugins/restapi/jsonschema/converter/testdata/proto2_nested_message.go deleted file mode 100644 index 018ca62f3c..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto2_nested_message.go +++ /dev/null @@ -1,64 +0,0 @@ -package testdata - -const Proto2NestedMessage = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "payload" - ], - "properties": { - "payload": { - "required": [ - "name", - "id" - ], - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": false, - "type": "object" - }, - "description": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/proto2_nested_object.go b/plugins/restapi/jsonschema/converter/testdata/proto2_nested_object.go deleted file mode 100644 index 2da65bca41..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto2_nested_object.go +++ /dev/null @@ -1,69 +0,0 @@ -package testdata - -const Proto2NestedObject = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "payload", - "description" - ], - "properties": { - "payload": { - "required": [ - "name", - "id", - "timestamp", - "rating", - "complete", - "topology" - ], - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": false, - "type": "object" - }, - "description": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/proto2_payload_message.go b/plugins/restapi/jsonschema/converter/testdata/proto2_payload_message.go deleted file mode 100644 index ba780c161f..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto2_payload_message.go +++ /dev/null @@ -1,52 +0,0 @@ -package testdata - -const Proto2PayloadMessage = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "name", - "id" - ], - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/proto2_required.go b/plugins/restapi/jsonschema/converter/testdata/proto2_required.go deleted file mode 100644 index 24c4d80e62..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/proto2_required.go +++ /dev/null @@ -1,21 +0,0 @@ -package testdata - -const Proto2Required = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "query" - ], - "properties": { - "query": { - "type": "string" - }, - "page_number": { - "type": "integer" - }, - "result_per_page": { - "type": "integer" - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/second_enum.go b/plugins/restapi/jsonschema/converter/testdata/second_enum.go deleted file mode 100644 index e3142f775e..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/second_enum.go +++ /dev/null @@ -1,23 +0,0 @@ -package testdata - -const SecondEnum = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "enum": [ - "VALUE_4", - 0, - "VALUE_5", - 1, - "VALUE_6", - 2, - "VALUE_7", - 3 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/second_message.go b/plugins/restapi/jsonschema/converter/testdata/second_message.go deleted file mode 100644 index a66933ef10..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/second_message.go +++ /dev/null @@ -1,24 +0,0 @@ -package testdata - -const SecondMessage = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name2": { - "type": "string" - }, - "timestamp2": { - "type": "string" - }, - "id2": { - "type": "integer" - }, - "rating2": { - "type": "number" - }, - "complete2": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/self_reference.go b/plugins/restapi/jsonschema/converter/testdata/self_reference.go deleted file mode 100644 index 234be70556..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/self_reference.go +++ /dev/null @@ -1,26 +0,0 @@ -package testdata - -const SelfReference = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "Foo", - "definitions": { - "Foo": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "bar": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "Foo" - }, - "type": "array" - } - }, - "additionalProperties": true, - "type": "object", - "id": "Foo" - } - } -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/timestamp.go b/plugins/restapi/jsonschema/converter/testdata/timestamp.go deleted file mode 100644 index 9ac216227b..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/timestamp.go +++ /dev/null @@ -1,13 +0,0 @@ -package testdata - -const Timestamp = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "timestamp": { - "type": "string", - "format": "date-time" - } - }, - "additionalProperties": true, - "type": "object" -}` diff --git a/plugins/restapi/jsonschema/converter/testdata/wellknown.go b/plugins/restapi/jsonschema/converter/testdata/wellknown.go deleted file mode 100644 index af44b9fa6a..0000000000 --- a/plugins/restapi/jsonschema/converter/testdata/wellknown.go +++ /dev/null @@ -1,32 +0,0 @@ -package testdata - -const WellKnown = `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "string_value": { - "additionalProperties": true, - "type": "string" - }, - "map_of_integers": { - "additionalProperties": { - "additionalProperties": true, - "type": "integer" - }, - "type": "object" - }, - "map_of_scalar_integers": { - "additionalProperties": { - "type": "integer" - }, - "type": "object" - }, - "list_of_integers": { - "items": { - "type": "integer" - }, - "type": "array" - } - }, - "additionalProperties": true, - "type": "object" -}` From a5449135ce0ae225455e3eb25aeae482e4489b81 Mon Sep 17 00:00:00 2001 From: Filip Gschwandtner Date: Fri, 5 Feb 2021 10:37:35 +0100 Subject: [PATCH 04/10] refactor: replaced dependency reference to original jsonschema library with its dependencies Signed-off-by: Filip Gschwandtner --- go.mod | 3 ++- go.sum | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 3d76d64bad..91a827d57a 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/Shopify/sarama v1.20.1 // indirect github.com/alecthomas/jsonschema v0.0.0-20200217214135-7152f22193c9 github.com/alicebob/miniredis v2.5.0+incompatible // indirect - github.com/chrusty/protoc-gen-jsonschema v0.0.0-20201201182816-de75f1b59c4e github.com/common-nighthawk/go-figure v0.0.0-20200609044655-c4b36f998cf2 github.com/coreos/bbolt v1.3.3 // indirect github.com/coreos/etcd v3.3.13+incompatible @@ -47,6 +46,8 @@ require ( github.com/unrolled/render v0.0.0-20180914162206-b9786414de4d github.com/vishvananda/netlink v0.0.0-20180910184128-56b1bd27a9a3 github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.1.0 github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036 // indirect go.ligato.io/cn-infra/v2 v2.5.0-alpha.0.20200313154441-b0d4c1b11c73 diff --git a/go.sum b/go.sum index 1f6eb84092..ac1975fd5a 100644 --- a/go.sum +++ b/go.sum @@ -474,6 +474,8 @@ github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmF github.com/willfaught/gockle v0.0.0-20160623235217-4f254e1e0f0a/go.mod h1:NLcF+3nDpXVIZatjn5Z97gKzFFVU7TzgbAcs8G7/Jrs= github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA= github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.1.0 h1:ngVtJC9TY/lg0AA/1k48FYhBrhRoFlEmWzsehpNAaZg= From e443d6b481a248d4aac0cf4ebc5cc03b7fb934e5 Mon Sep 17 00:00:00 2001 From: Filip Gschwandtner Date: Fri, 5 Feb 2021 11:32:43 +0100 Subject: [PATCH 05/10] docs: added proper README documentation and licensing for included tool Signed-off-by: Filip Gschwandtner --- LICENSE | 6 + README.md | 6 + plugins/restapi/jsonschema/LICENSE | 202 +++++++++++++++++++++++++++ plugins/restapi/jsonschema/README.md | 21 ++- 4 files changed, 231 insertions(+), 4 deletions(-) create mode 100644 plugins/restapi/jsonschema/LICENSE diff --git a/LICENSE b/LICENSE index 8dada3edaf..cee7d3d815 100644 --- a/LICENSE +++ b/LICENSE @@ -199,3 +199,9 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + + +Licenses for 3rd party libraries included in code: + +1. library protoc-gen-jsonschema (https://github.com/chrusty/protoc-gen-jsonschema) - +License: Apache License Version 2.0, January 2004 (full license included in plugins/restapi/jsonschema/LICENSE) diff --git a/README.md b/README.md index 5fd3b489a5..9a4b252974 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,10 @@ If you are interested in contributing, please see the [contribution guidelines][ [![GitHub license](https://img.shields.io/badge/license-Apache%20license%202.0-blue.svg)](https://github.com/ligato/vpp-agent/blob/master/LICENSE) +## Modified 3rd party tools included + + - [protoc-gen-jsonschema][tool-included-jsonchema] ([code location in this repository][local-place-for-jsonchema]) + [agentctl]: cmd/agentctl [cn-infra]: https://github.com/ligato/cn-infra [contiv-vpp]: https://github.com/contiv/vpp @@ -131,3 +135,5 @@ If you are interested in contributing, please see the [contribution guidelines][ [vpp]: https://fd.io/vppproject/vpptech/ [vpp-agent]: https://hub.docker.com/r/ligato/vpp-agent [vpp-agent-arm64]: https://hub.docker.com/r/ligato/vpp-agent-arm64 +[tool-included-jsonchema]: https://github.com/chrusty/protoc-gen-jsonschema/tree/de75f1b59c4e0f5d5edf7be2a18d1c8e4d81b17a +[local-place-for-jsonchema]: plugins/restapi/jsonschema \ No newline at end of file diff --git a/plugins/restapi/jsonschema/LICENSE b/plugins/restapi/jsonschema/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/plugins/restapi/jsonschema/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/plugins/restapi/jsonschema/README.md b/plugins/restapi/jsonschema/README.md index 61b363597c..0487066ca1 100644 --- a/plugins/restapi/jsonschema/README.md +++ b/plugins/restapi/jsonschema/README.md @@ -1,6 +1,19 @@ +# Protoc-gen-jsonschema +Content of this package and subpackages is modified code of 3rd party library [protoc-gen-jsonschema](https://github.com/chrusty/protoc-gen-jsonschema). +The purpose of the tool is to provide proto to JSON schema conversion in the form of protoc plugin. +The customization for ligato is not touching the conversion functionality, but only removes the protoc +dependency and enables it to be used as library (internal packages in original repository). + + +## Changes tracking +The base code for ligato modifications is [here](https://github.com/chrusty/protoc-gen-jsonschema/tree/de75f1b59c4e0f5d5edf7be2a18d1c8e4d81b17a). Initial commit changes: -extracted convertor out of internal package to be able to use it -removed convertor tests -relaxed some info level logging to debug level logging (proto_package.go, lines 78 and 121) -other changes can be tracked by git changes in this package and its subpackages \ No newline at end of file +- removed all unnecessary parts + - project root files except License + - CMD part for protoc connection + - convertor tests (they are dependent on protoc at test runtime) +- extracted convertor out of internal package to be able to use it +- relaxed some info level logging to debug level logging (proto_package.go, lines 78 and 121) + +Other changes can be tracked by git changes in this package and its subpackages \ No newline at end of file From f6a76c33946765dca460571c47eeb21e228dca99 Mon Sep 17 00:00:00 2001 From: Filip Gschwandtner Date: Fri, 5 Feb 2021 15:26:58 +0100 Subject: [PATCH 06/10] fix: relaxed enum type safety to fix issues with 3rd party json example createor (enum is still safe enough due to value enumeration of all possible values) Signed-off-by: Filip Gschwandtner --- plugins/restapi/jsonschema/converter/converter.go | 9 +++++++-- plugins/restapi/jsonschema/converter/types.go | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/plugins/restapi/jsonschema/converter/converter.go b/plugins/restapi/jsonschema/converter/converter.go index e2a1451f7b..6c0dc6866a 100644 --- a/plugins/restapi/jsonschema/converter/converter.go +++ b/plugins/restapi/jsonschema/converter/converter.go @@ -107,9 +107,14 @@ func (c *Converter) convertEnumType(enum *descriptor.EnumDescriptorProto) (jsons jsonSchemaType.Description = formatDescription(src) } + // Note: not setting type specification(oneof string and integer), because explicitly saying which + // values are valid (and any other is invalid) is enough specification what can be used + // (this also overcome bug in example creator https://json-schema-faker.js.org/ that doesn't select + // correct type for enum value but rather chooses random type from oneof and cast value to that type) + // // Allow both strings and integers: - jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: "string"}) - jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: "integer"}) + //jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: "string"}) + //jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: "integer"}) // Add the allowed values: for _, enumValue := range enum.Value { diff --git a/plugins/restapi/jsonschema/converter/types.go b/plugins/restapi/jsonschema/converter/types.go index 135df2bb9e..e99a2a47ad 100644 --- a/plugins/restapi/jsonschema/converter/types.go +++ b/plugins/restapi/jsonschema/converter/types.go @@ -134,8 +134,13 @@ func (c *Converter) convertField(curPkg *ProtoPackage, desc *descriptor.FieldDes } case descriptor.FieldDescriptorProto_TYPE_ENUM: - jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: gojsonschema.TYPE_STRING}) - jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: gojsonschema.TYPE_INTEGER}) + // Note: not setting type specification(oneof string and integer), because explicitly saying which + // values are valid (and any other is invalid) is enough specification what can be used + // (this also overcome bug in example creator https://json-schema-faker.js.org/ that doesn't select + // correct type for enum value but rather chooses random type from oneof and cast value to that type) + // + //jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: gojsonschema.TYPE_STRING}) + //jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: gojsonschema.TYPE_INTEGER}) if c.AllowNullValues { jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: gojsonschema.TYPE_NULL}) } From 443ce2f8590c559e32914d8d9c6d5ad55a5a797e Mon Sep 17 00:00:00 2001 From: Filip Gschwandtner Date: Fri, 5 Feb 2021 15:55:31 +0100 Subject: [PATCH 07/10] refactor: removed jsonschema files that seemed like templates for generation but serve no purpose at all (probably generated by test or something and commited into repo) Signed-off-by: Filip Gschwandtner --- .../jsonschemas/ArrayOfEnums.jsonschema | 25 --- .../jsonschemas/ArrayOfMessages.jsonschema | 125 ----------- .../jsonschemas/ArrayOfObjects.jsonschema | 125 ----------- .../jsonschemas/ArrayOfPrimitives.jsonschema | 100 --------- .../jsonschemas/Enumception.jsonschema | 109 ---------- .../jsonschemas/FirstEnum.jsonschema | 21 -- .../jsonschemas/FirstMessage.jsonschema | 22 -- .../jsonschemas/GoogleValue.jsonschema | 17 -- .../jsonschemas/ImportedEnum.jsonschema | 21 -- .../jsonschemas/JSONFields.jsonschema | 32 --- .../jsonschema/jsonschemas/Maps.jsonschema | 67 ------ .../jsonschemas/MessageKind10.jsonschema | 22 -- .../jsonschemas/MessageKind11.jsonschema | 110 ---------- .../jsonschemas/MessageKind12.jsonschema | 198 ------------------ .../MessageWithComments.jsonschema | 12 -- .../jsonschemas/NestedMessage.jsonschema | 55 ----- .../jsonschemas/NestedObject.jsonschema | 55 ----- .../jsonschemas/PayloadMessage.jsonschema | 46 ---- .../jsonschemas/PayloadMessage2.jsonschema | 54 ----- .../Proto2NestedMessage.jsonschema | 62 ------ .../jsonschemas/Proto2NestedObject.jsonschema | 67 ------ .../Proto2PayloadMessage.jsonschema | 50 ----- .../jsonschemas/Proto2Required.jsonschema | 19 -- .../jsonschemas/SecondEnum.jsonschema | 21 -- .../jsonschemas/SecondMessage.jsonschema | 22 -- .../jsonschemas/Timestamp.jsonschema | 11 - .../jsonschemas/WellKnown.jsonschema | 49 ----- 27 files changed, 1517 deletions(-) delete mode 100644 plugins/restapi/jsonschema/jsonschemas/ArrayOfEnums.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/ArrayOfMessages.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/ArrayOfObjects.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/ArrayOfPrimitives.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/Enumception.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/FirstEnum.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/FirstMessage.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/GoogleValue.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/ImportedEnum.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/JSONFields.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/Maps.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/MessageKind10.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/MessageKind11.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/MessageKind12.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/MessageWithComments.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/NestedMessage.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/NestedObject.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/PayloadMessage.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/PayloadMessage2.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/Proto2NestedMessage.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/Proto2NestedObject.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/Proto2PayloadMessage.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/Proto2Required.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/SecondEnum.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/SecondMessage.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/Timestamp.jsonschema delete mode 100644 plugins/restapi/jsonschema/jsonschemas/WellKnown.jsonschema diff --git a/plugins/restapi/jsonschema/jsonschemas/ArrayOfEnums.jsonschema b/plugins/restapi/jsonschema/jsonschemas/ArrayOfEnums.jsonschema deleted file mode 100644 index c393d8874f..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/ArrayOfEnums.jsonschema +++ /dev/null @@ -1,25 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "type": "string" - }, - "stuff": { - "items": { - "enum": [ - "FOO", - 0, - "BAR", - 1, - "FIZZ", - 2, - "BUZZ", - 3 - ] - }, - "type": "array" - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/ArrayOfMessages.jsonschema b/plugins/restapi/jsonschema/jsonschemas/ArrayOfMessages.jsonschema deleted file mode 100644 index 3f7ea01b76..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/ArrayOfMessages.jsonschema +++ /dev/null @@ -1,125 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "payload": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "timestamp": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "id": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "integer" - } - ] - }, - "rating": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "complete": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] - }, - "oneOf": [ - { - "type": "null" - }, - { - "type": "array" - } - ] - } - }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/ArrayOfObjects.jsonschema b/plugins/restapi/jsonschema/jsonschemas/ArrayOfObjects.jsonschema deleted file mode 100644 index 3f7ea01b76..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/ArrayOfObjects.jsonschema +++ /dev/null @@ -1,125 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "payload": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "timestamp": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "id": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "integer" - } - ] - }, - "rating": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "complete": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] - }, - "oneOf": [ - { - "type": "null" - }, - { - "type": "array" - } - ] - } - }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/ArrayOfPrimitives.jsonschema b/plugins/restapi/jsonschema/jsonschemas/ArrayOfPrimitives.jsonschema deleted file mode 100644 index 3f95bed373..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/ArrayOfPrimitives.jsonschema +++ /dev/null @@ -1,100 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "luckyNumbers": { - "items": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "integer" - } - ] - }, - "oneOf": [ - { - "type": "null" - }, - { - "type": "array" - } - ] - }, - "luckyBigNumbers": { - "items": { - "oneOf": [ - { - "type": "integer" - }, - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "oneOf": [ - { - "type": "null" - }, - { - "type": "array" - } - ] - }, - "keyWords": { - "items": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "oneOf": [ - { - "type": "null" - }, - { - "type": "array" - } - ] - }, - "big_number": { - "oneOf": [ - { - "type": "integer" - }, - { - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/Enumception.jsonschema b/plugins/restapi/jsonschema/jsonschemas/Enumception.jsonschema deleted file mode 100644 index 7f40e6aa73..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/Enumception.jsonschema +++ /dev/null @@ -1,109 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "failureMode": { - "enum": [ - "RECURSION_ERROR", - 0, - "SYNTAX_ERROR", - 1 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - }, - "payload": { - "$ref": "samples.PayloadMessage", - "additionalProperties": true, - "type": "object" - }, - "payloads": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "samples.PayloadMessage" - }, - "type": "array" - }, - "importedEnum": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": false, - "type": "object", - "definitions": { - "samples.PayloadMessage": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": false, - "type": "object", - "id": "samples.PayloadMessage" - } - } -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/FirstEnum.jsonschema b/plugins/restapi/jsonschema/jsonschemas/FirstEnum.jsonschema deleted file mode 100644 index f48c31a12f..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/FirstEnum.jsonschema +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "enum": [ - "VALUE_0", - 0, - "VALUE_1", - 1, - "VALUE_2", - 2, - "VALUE_3", - 3 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/FirstMessage.jsonschema b/plugins/restapi/jsonschema/jsonschemas/FirstMessage.jsonschema deleted file mode 100644 index 55b54424a2..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/FirstMessage.jsonschema +++ /dev/null @@ -1,22 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name1": { - "type": "string" - }, - "timestamp1": { - "type": "string" - }, - "id1": { - "type": "integer" - }, - "rating1": { - "type": "number" - }, - "complete1": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/GoogleValue.jsonschema b/plugins/restapi/jsonschema/jsonschemas/GoogleValue.jsonschema deleted file mode 100644 index 7b7f376784..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/GoogleValue.jsonschema +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "arg": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/ImportedEnum.jsonschema b/plugins/restapi/jsonschema/jsonschemas/ImportedEnum.jsonschema deleted file mode 100644 index f48c31a12f..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/ImportedEnum.jsonschema +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "enum": [ - "VALUE_0", - 0, - "VALUE_1", - 1, - "VALUE_2", - 2, - "VALUE_3", - 3 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/JSONFields.jsonschema b/plugins/restapi/jsonschema/jsonschemas/JSONFields.jsonschema deleted file mode 100644 index 702fb8d4f9..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/JSONFields.jsonschema +++ /dev/null @@ -1,32 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "identifier": { - "type": "integer" - }, - "someThing": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "snakeNumb": { - "oneOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ] - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/Maps.jsonschema b/plugins/restapi/jsonschema/jsonschemas/Maps.jsonschema deleted file mode 100644 index 1ca1a25263..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/Maps.jsonschema +++ /dev/null @@ -1,67 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "map_of_strings": { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - "map_of_ints": { - "additionalProperties": { - "type": "integer" - }, - "type": "object" - }, - "map_of_messages": { - "additionalProperties": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" - }, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/MessageKind10.jsonschema b/plugins/restapi/jsonschema/jsonschemas/MessageKind10.jsonschema deleted file mode 100644 index 827aac0032..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/MessageKind10.jsonschema +++ /dev/null @@ -1,22 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/MessageKind11.jsonschema b/plugins/restapi/jsonschema/jsonschemas/MessageKind11.jsonschema deleted file mode 100644 index 19dd2f0a21..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/MessageKind11.jsonschema +++ /dev/null @@ -1,110 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "ones": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" - }, - "type": "array" - }, - "kind2": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "isa": { - "type": "boolean" - }, - "hasa": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" - }, - "kind3": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "someProp": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" - }, - "kind4": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "special": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/MessageKind12.jsonschema b/plugins/restapi/jsonschema/jsonschemas/MessageKind12.jsonschema deleted file mode 100644 index 6146e4b973..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/MessageKind12.jsonschema +++ /dev/null @@ -1,198 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "f": { - "properties": { - "name": { - "type": "string" - }, - "ones": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" - }, - "type": "array" - }, - "kind2": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "isa": { - "type": "boolean" - }, - "hasa": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" - }, - "kind3": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "someProp": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" - }, - "kind4": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "special": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object" - }, - "kind5": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "foo": { - "type": "number" - } - }, - "additionalProperties": true, - "type": "object" - }, - "kind6": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "bar": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" - }, - "kind7": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "baz": { - "oneOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ] - } - }, - "additionalProperties": true, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/MessageWithComments.jsonschema b/plugins/restapi/jsonschema/jsonschemas/MessageWithComments.jsonschema deleted file mode 100644 index 60e1744cd5..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/MessageWithComments.jsonschema +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name1": { - "type": "string", - "description": "This field is supposed to represent blahblahblah" - } - }, - "additionalProperties": true, - "type": "object", - "description": "This is a message level comment and talks about what this message is and why you should care about it!" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/NestedMessage.jsonschema b/plugins/restapi/jsonschema/jsonschemas/NestedMessage.jsonschema deleted file mode 100644 index 88cf76ee8a..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/NestedMessage.jsonschema +++ /dev/null @@ -1,55 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "payload": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" - }, - "description": { - "type": "string" - } - }, - "additionalProperties": false, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/NestedObject.jsonschema b/plugins/restapi/jsonschema/jsonschemas/NestedObject.jsonschema deleted file mode 100644 index c17488deeb..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/NestedObject.jsonschema +++ /dev/null @@ -1,55 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "payload": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" - }, - "description": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/PayloadMessage.jsonschema b/plugins/restapi/jsonschema/jsonschemas/PayloadMessage.jsonschema deleted file mode 100644 index bcc0a0fe44..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/PayloadMessage.jsonschema +++ /dev/null @@ -1,46 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/PayloadMessage2.jsonschema b/plugins/restapi/jsonschema/jsonschemas/PayloadMessage2.jsonschema deleted file mode 100644 index 1cb26ee8b2..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/PayloadMessage2.jsonschema +++ /dev/null @@ -1,54 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "name", - "timestamp", - "id", - "rating", - "complete", - "topology" - ], - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/Proto2NestedMessage.jsonschema b/plugins/restapi/jsonschema/jsonschemas/Proto2NestedMessage.jsonschema deleted file mode 100644 index 8de78e6a82..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/Proto2NestedMessage.jsonschema +++ /dev/null @@ -1,62 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "payload" - ], - "properties": { - "payload": { - "required": [ - "name", - "id" - ], - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": false, - "type": "object" - }, - "description": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/Proto2NestedObject.jsonschema b/plugins/restapi/jsonschema/jsonschemas/Proto2NestedObject.jsonschema deleted file mode 100644 index 1f8b4f3e3f..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/Proto2NestedObject.jsonschema +++ /dev/null @@ -1,67 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "payload", - "description" - ], - "properties": { - "payload": { - "required": [ - "name", - "id", - "timestamp", - "rating", - "complete", - "topology" - ], - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": false, - "type": "object" - }, - "description": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/Proto2PayloadMessage.jsonschema b/plugins/restapi/jsonschema/jsonschemas/Proto2PayloadMessage.jsonschema deleted file mode 100644 index be928fdf6d..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/Proto2PayloadMessage.jsonschema +++ /dev/null @@ -1,50 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "name", - "id" - ], - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/Proto2Required.jsonschema b/plugins/restapi/jsonschema/jsonschemas/Proto2Required.jsonschema deleted file mode 100644 index 8a79bf2b12..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/Proto2Required.jsonschema +++ /dev/null @@ -1,19 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "query" - ], - "properties": { - "query": { - "type": "string" - }, - "page_number": { - "type": "integer" - }, - "result_per_page": { - "type": "integer" - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/SecondEnum.jsonschema b/plugins/restapi/jsonschema/jsonschemas/SecondEnum.jsonschema deleted file mode 100644 index e57d4908d5..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/SecondEnum.jsonschema +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "enum": [ - "VALUE_4", - 0, - "VALUE_5", - 1, - "VALUE_6", - 2, - "VALUE_7", - 3 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/SecondMessage.jsonschema b/plugins/restapi/jsonschema/jsonschemas/SecondMessage.jsonschema deleted file mode 100644 index edbc1c86d5..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/SecondMessage.jsonschema +++ /dev/null @@ -1,22 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name2": { - "type": "string" - }, - "timestamp2": { - "type": "string" - }, - "id2": { - "type": "integer" - }, - "rating2": { - "type": "number" - }, - "complete2": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/Timestamp.jsonschema b/plugins/restapi/jsonschema/jsonschemas/Timestamp.jsonschema deleted file mode 100644 index a8d4b78208..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/Timestamp.jsonschema +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "timestamp": { - "type": "string", - "format": "date-time" - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file diff --git a/plugins/restapi/jsonschema/jsonschemas/WellKnown.jsonschema b/plugins/restapi/jsonschema/jsonschemas/WellKnown.jsonschema deleted file mode 100644 index 9b3f3b1bcd..0000000000 --- a/plugins/restapi/jsonschema/jsonschemas/WellKnown.jsonschema +++ /dev/null @@ -1,49 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "string_value": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "map_of_integers": { - "additionalProperties": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "integer" - } - ] - }, - "type": "object" - }, - "map_of_scalar_integers": { - "additionalProperties": { - "type": "integer" - }, - "type": "object" - }, - "list_of_integers": { - "items": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "integer" - } - ] - }, - "type": "array" - } - }, - "additionalProperties": true, - "type": "object" -} \ No newline at end of file From 04b25e84dda5f6a8364582cae881a439cb6b31be Mon Sep 17 00:00:00 2001 From: Filip Gschwandtner Date: Fri, 5 Feb 2021 15:59:21 +0100 Subject: [PATCH 08/10] doc: updated initial changes in README.md for last 2 commits Signed-off-by: Filip Gschwandtner --- plugins/restapi/jsonschema/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/restapi/jsonschema/README.md b/plugins/restapi/jsonschema/README.md index 0487066ca1..e264665af9 100644 --- a/plugins/restapi/jsonschema/README.md +++ b/plugins/restapi/jsonschema/README.md @@ -15,5 +15,6 @@ Initial commit changes: - convertor tests (they are dependent on protoc at test runtime) - extracted convertor out of internal package to be able to use it - relaxed some info level logging to debug level logging (proto_package.go, lines 78 and 121) +- removed "oneof" type from enums to provide compatibility with external json example generator (types.go line 137 and converter.go line 116) Other changes can be tracked by git changes in this package and its subpackages \ No newline at end of file From cd093279785a4b0ce46f06cc6b03e9d21bd12a76 Mon Sep 17 00:00:00 2001 From: Filip Gschwandtner Date: Fri, 5 Feb 2021 16:18:55 +0100 Subject: [PATCH 09/10] fix: removed duplicite and unnecessary http status print into http response body and removed unused code Signed-off-by: Filip Gschwandtner --- plugins/restapi/handlers.go | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/plugins/restapi/handlers.go b/plugins/restapi/handlers.go index 428b63bb98..c432e93f03 100644 --- a/plugins/restapi/handlers.go +++ b/plugins/restapi/handlers.go @@ -42,6 +42,8 @@ import ( "google.golang.org/protobuf/types/descriptorpb" ) +const internalErrorLogPrefix = "500 Internal server error: " + var ( // ErrHandlerUnavailable represents error returned when particular // handler is not available @@ -332,17 +334,15 @@ func (p *Plugin) jsonSchemaHandler(formatter *render.Render) http.HandlerFunc { // create FileDescriptorProto for dynamic Config holding all VPP-Agent configuration knownModels, err := client.LocalClient.KnownModels("config") // locally registered models if err != nil { - errMsg := fmt.Sprintf("500 Internal server error: "+ - "can't get registered models: %v\n", err) - p.Log.Error(errMsg) + errMsg := fmt.Sprintf("can't get registered models: %v\n", err) + p.Log.Error(internalErrorLogPrefix + errMsg) p.logError(formatter.JSON(w, http.StatusInternalServerError, errMsg)) return } config, err := client.NewDynamicConfig(knownModels) if err != nil { - errMsg := fmt.Sprintf("500 Internal server error: "+ - "can't create dynamic config due to: %v\n", err) - p.Log.Error(errMsg) + errMsg := fmt.Sprintf("can't create dynamic config due to: %v\n", err) + p.Log.Error(internalErrorLogPrefix + errMsg) p.logError(formatter.JSON(w, http.StatusInternalServerError, errMsg)) return } @@ -365,10 +365,8 @@ func (p *Plugin) jsonSchemaHandler(formatter *render.Render) http.HandlerFunc { } cgReqMarshalled, err := proto.Marshal(cgReq) if err != nil { - fmt.Errorf("can't proto marshal to: %w", err) - errMsg := fmt.Sprintf("500 Internal server error: "+ - "can't proto marshal CodeGeneratorRequest: %v\n", err) - p.Log.Error(errMsg) + errMsg := fmt.Sprintf("can't proto marshal CodeGeneratorRequest: %v\n", err) + p.Log.Error(internalErrorLogPrefix + errMsg) p.logError(formatter.JSON(w, http.StatusInternalServerError, errMsg)) return } @@ -379,15 +377,13 @@ func (p *Plugin) jsonSchemaHandler(formatter *render.Render) http.HandlerFunc { res, err := protoConverter.ConvertFrom(bytes.NewReader(cgReqMarshalled)) if err != nil { if res == nil { - errMsg := fmt.Sprintf("500 Internal server error: "+ - "failed to read registered model configuration input: %v\n", err) - p.Log.Error(errMsg) + errMsg := fmt.Sprintf("failed to read registered model configuration input: %v\n", err) + p.Log.Error(internalErrorLogPrefix + errMsg) p.logError(formatter.JSON(w, http.StatusInternalServerError, errMsg)) return } - errMsg := fmt.Sprintf("500 Internal server error: "+ - "failed generate JSON schema: %v (%v)\n", res.Error, err) - p.Log.Error(errMsg) + errMsg := fmt.Sprintf("failed generate JSON schema: %v (%v)\n", res.Error, err) + p.Log.Error(internalErrorLogPrefix + errMsg) p.logError(formatter.JSON(w, http.StatusInternalServerError, errMsg)) return } From 2a816d477f1d6ad57ca21b9e7d631e8ae43c5a8f Mon Sep 17 00:00:00 2001 From: Filip Gschwandtner Date: Fri, 12 Feb 2021 14:30:35 +0100 Subject: [PATCH 10/10] feat: added URL parameter for JSON schema REST API to be able to change what kind of field names are used (proto names/json names/both) Signed-off-by: Filip Gschwandtner --- plugins/restapi/handlers.go | 41 ++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/plugins/restapi/handlers.go b/plugins/restapi/handlers.go index c432e93f03..c4073f1c88 100644 --- a/plugins/restapi/handlers.go +++ b/plugins/restapi/handlers.go @@ -42,7 +42,17 @@ import ( "google.golang.org/protobuf/types/descriptorpb" ) -const internalErrorLogPrefix = "500 Internal server error: " +const ( + // URLFieldNamingParamName is URL parameter name for JSON schema http handler's setting + // to output field names using proto/json/both names for fields + URLFieldNamingParamName = "fieldnames" + // OnlyProtoFieldNames is URL parameter value for JSON schema http handler to use only proto names as field names + OnlyProtoFieldNames = "onlyproto" + // OnlyJSONFieldNames is URL parameter value for JSON schema http handler to use only JSON names as field names + OnlyJSONFieldNames = "onlyjson" + + internalErrorLogPrefix = "500 Internal server error: " +) var ( // ErrHandlerUnavailable represents error returned when particular @@ -329,6 +339,12 @@ func (p *Plugin) registerHTTPHandler(key, method string, f func() (interface{}, } // jsonSchemaHandler returns JSON schema of VPP-Agent configuration. +// This handler also accepts URL query parameters changing the exported field names of proto messages. By default, +// proto message fields are exported twice in JSON scheme. Once with proto name and once with JSON name. This should +// allow to use any of the 2 forms in JSON/YAML configuration when used JSON schema for validation. However, +// this behaviour can be modified by URLFieldNamingParamName URL query parameter, that force to export only +// proto named fields (OnlyProtoFieldNames URL query parameter value) or JSON named fields (OnlyJSONFieldNames +// URL query parameter value). func (p *Plugin) jsonSchemaHandler(formatter *render.Render) http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { // create FileDescriptorProto for dynamic Config holding all VPP-Agent configuration @@ -354,13 +370,28 @@ func (p *Plugin) jsonSchemaHandler(formatter *render.Render) http.HandlerFunc { // creating input for protoc's plugin (code extracted in plugins/restapi/jsonschema) that can convert // FileDescriptorProtos to JSONSchema - params := "messages=[Dynamic_config]" + // targeting only the main config message (proto file has also other messages) - ",disallow_additional_properties" + // additional unknown json fields makes configuration applying fail - ",proto_and_json_fieldnames" // allow also proto names for fields + params := []string{ + "messages=[Dynamic_config]", // targeting only the main config message (proto file has also other messages) + "disallow_additional_properties", // additional unknown json fields makes configuration applying fail + } + fieldNamesConverterParam := "proto_and_json_fieldnames" // create proto and json named fields by default + if fieldNames, found := req.URL.Query()[URLFieldNamingParamName]; found && len(fieldNames) > 0 { + // converting REST API request params to 3rd party tool params + switch fieldNames[0] { + case OnlyProtoFieldNames: + fieldNamesConverterParam = "" + case OnlyJSONFieldNames: + fieldNamesConverterParam = "json_fieldnames" + } + } + if fieldNamesConverterParam != "" { + params = append(params, fieldNamesConverterParam) + } + paramsStr := strings.Join(params, ",") cgReq := &protoc_plugin.CodeGeneratorRequest{ ProtoFile: fileDescriptorProtos, FileToGenerate: []string{dynConfigFileDescProto.GetName()}, - Parameter: ¶ms, + Parameter: ¶msStr, CompilerVersion: nil, // compiler version is not need in this protoc plugin } cgReqMarshalled, err := proto.Marshal(cgReq)