1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

- update vendor - add profiling library

This commit is contained in:
Shuting Zhao 2019-08-02 11:20:56 -07:00
parent eec1939b17
commit 1ecf92a634
915 changed files with 65238 additions and 21591 deletions
pkg
annotations
controller
event
gencontroller
vendor/github.com
golang
googleapis/gnostic
json-iterator/go
minio/minio

View file

@ -46,7 +46,7 @@ func (c *controller) Run(stopCh <-chan struct{}) {
}
func (c *controller) Stop() {
defer c.queue.ShutDown()
c.queue.ShutDown()
glog.Info("Shutting down annotation controller workers")
}

View file

@ -123,9 +123,10 @@ func (pc *PolicyController) Run(stopCh <-chan struct{}) error {
//Stop to perform actions when controller is stopped
func (pc *PolicyController) Stop() {
defer pc.queue.ShutDown()
pc.queue.ShutDown()
glog.Info("shutting down policy controller workers")
}
func (pc *PolicyController) runWorker() {
for pc.processNextWorkItem() {
}

View file

@ -88,7 +88,7 @@ func (c *controller) Run(stopCh <-chan struct{}) {
}
func (c *controller) Stop() {
defer c.queue.ShutDown()
c.queue.ShutDown()
glog.Info("Shutting down eventbuilder controller workers")
}

View file

@ -93,7 +93,7 @@ func (c *Controller) Run(stopCh <-chan struct{}) error {
//Stop to stop the controller
func (c *Controller) Stop() {
defer c.workqueue.ShutDown()
c.workqueue.ShutDown()
glog.Info("shutting down namespace controller workers")
}

View file

@ -245,7 +245,7 @@ func (g *Group) load(ctx Context, key string, dest Sink) (value ByteView, destPo
// be only one entry for this key.
//
// Consider the following serialized event ordering for two
// goroutines in which this callback gets called twice for hte
// goroutines in which this callback gets called twice for the
// same key:
// 1: Get("key")
// 2: Get("key")

View file

@ -57,6 +57,7 @@ import (
)
const secondInNanos = int64(time.Second / time.Nanosecond)
const maxSecondsInDuration = 315576000000
// Marshaler is a configurable object for converting between
// protocol buffer objects and a JSON representation for them.
@ -182,7 +183,12 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU
return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err)
}
js["@type"] = (*json.RawMessage)(&turl)
if b, err = json.Marshal(js); err != nil {
if m.Indent != "" {
b, err = json.MarshalIndent(js, indent, m.Indent)
} else {
b, err = json.Marshal(js)
}
if err != nil {
return err
}
}
@ -206,19 +212,26 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU
// Any is a bit more involved.
return m.marshalAny(out, v, indent)
case "Duration":
// "Generated output always contains 0, 3, 6, or 9 fractional digits,
// depending on required precision."
s, ns := s.Field(0).Int(), s.Field(1).Int()
if s < -maxSecondsInDuration || s > maxSecondsInDuration {
return fmt.Errorf("seconds out of range %v", s)
}
if ns <= -secondInNanos || ns >= secondInNanos {
return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos)
}
if (s > 0 && ns < 0) || (s < 0 && ns > 0) {
return errors.New("signs of seconds and nanos do not match")
}
if s < 0 {
// Generated output always contains 0, 3, 6, or 9 fractional digits,
// depending on required precision, followed by the suffix "s".
f := "%d.%09d"
if ns < 0 {
ns = -ns
if s == 0 {
f = "-%d.%09d"
}
}
x := fmt.Sprintf("%d.%09d", s, ns)
x := fmt.Sprintf(f, s, ns)
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, ".000")

View file

@ -473,10 +473,17 @@ var marshalingTests = []struct {
{"Any with message and indent", marshalerAllOptions, anySimple, anySimplePrettyJSON},
{"Any with WKT", marshaler, anyWellKnown, anyWellKnownJSON},
{"Any with WKT and indent", marshalerAllOptions, anyWellKnown, anyWellKnownPrettyJSON},
{"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}, `{"dur":"3s"}`},
{"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3, Nanos: 1e6}}, `{"dur":"3.001s"}`},
{"Duration beyond float64 precision", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 100000000, Nanos: 1}}, `{"dur":"100000000.000000001s"}`},
{"negative Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: -123, Nanos: -456}}, `{"dur":"-123.000000456s"}`},
{"Duration empty", marshaler, &durpb.Duration{}, `"0s"`},
{"Duration with secs", marshaler, &durpb.Duration{Seconds: 3}, `"3s"`},
{"Duration with -secs", marshaler, &durpb.Duration{Seconds: -3}, `"-3s"`},
{"Duration with nanos", marshaler, &durpb.Duration{Nanos: 1e6}, `"0.001s"`},
{"Duration with -nanos", marshaler, &durpb.Duration{Nanos: -1e6}, `"-0.001s"`},
{"Duration with large secs", marshaler, &durpb.Duration{Seconds: 1e10, Nanos: 1}, `"10000000000.000000001s"`},
{"Duration with 6-digit nanos", marshaler, &durpb.Duration{Nanos: 1e4}, `"0.000010s"`},
{"Duration with 3-digit nanos", marshaler, &durpb.Duration{Nanos: 1e6}, `"0.001s"`},
{"Duration with -secs -nanos", marshaler, &durpb.Duration{Seconds: -123, Nanos: -450}, `"-123.000000450s"`},
{"Duration max value", marshaler, &durpb.Duration{Seconds: 315576000000, Nanos: 999999999}, `"315576000000.999999999s"`},
{"Duration min value", marshaler, &durpb.Duration{Seconds: -315576000000, Nanos: -999999999}, `"-315576000000.999999999s"`},
{"Struct", marshaler, &pb.KnownTypes{St: &stpb.Struct{
Fields: map[string]*stpb.Value{
"one": {Kind: &stpb.Value_StringValue{"loneliest number"}},
@ -549,15 +556,17 @@ func TestMarshalIllegalTime(t *testing.T) {
pb proto.Message
fail bool
}{
{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: 0}}, false},
{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: 0}}, false},
{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: -1}}, true},
{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: 1}}, true},
{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: 1000000000}}, true},
{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: -1000000000}}, true},
{&pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: 1}}, false},
{&pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: -1}}, true},
{&pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: 1000000000}}, true},
{&durpb.Duration{Seconds: 1, Nanos: 0}, false},
{&durpb.Duration{Seconds: -1, Nanos: 0}, false},
{&durpb.Duration{Seconds: 1, Nanos: -1}, true},
{&durpb.Duration{Seconds: -1, Nanos: 1}, true},
{&durpb.Duration{Seconds: 315576000001}, true},
{&durpb.Duration{Seconds: -315576000001}, true},
{&durpb.Duration{Seconds: 1, Nanos: 1000000000}, true},
{&durpb.Duration{Seconds: -1, Nanos: -1000000000}, true},
{&tspb.Timestamp{Seconds: 1, Nanos: 1}, false},
{&tspb.Timestamp{Seconds: 1, Nanos: -1}, true},
{&tspb.Timestamp{Seconds: 1, Nanos: 1000000000}, true},
}
for _, tt := range tests {
_, err := marshaler.MarshalToString(tt.pb)
@ -598,6 +607,28 @@ func TestMarshalAnyJSONPBMarshaler(t *testing.T) {
if str != expected {
t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", str, expected)
}
// Do it again, but this time with indentation:
marshaler := Marshaler{Indent: " "}
str, err = marshaler.MarshalToString(a)
if err != nil {
t.Errorf("an unexpected error occurred when marshalling Any to JSON: %v", err)
}
// same as expected above, but pretty-printed w/ indentation
expected = `{
"@type": "type.googleapis.com/` + dynamicMessageName + `",
"baz": [
0,
1,
2,
3
],
"foo": "bar"
}`
if str != expected {
t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", str, expected)
}
}
func TestMarshalWithCustomValidation(t *testing.T) {

View file

@ -38,7 +38,6 @@ package proto
import (
"fmt"
"log"
"os"
"reflect"
"sort"
"strconv"
@ -194,7 +193,7 @@ func (p *Properties) Parse(s string) {
// "bytes,49,opt,name=foo,def=hello!"
fields := strings.Split(s, ",") // breaks def=, but handled below.
if len(fields) < 2 {
fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
log.Printf("proto: tag has too few fields: %q", s)
return
}
@ -214,7 +213,7 @@ func (p *Properties) Parse(s string) {
p.WireType = WireBytes
// no numeric converter for non-numeric types
default:
fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
log.Printf("proto: tag has unknown wire type: %q", s)
return
}

View file

@ -54,6 +54,8 @@ const generatedCodeVersion = 4
const (
contextPkgPath = "context"
grpcPkgPath = "google.golang.org/grpc"
codePkgPath = "google.golang.org/grpc/codes"
statusPkgPath = "google.golang.org/grpc/status"
)
func init() {
@ -216,6 +218,12 @@ func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.Servi
g.P("}")
g.P()
// Server Unimplemented struct for forward compatability.
if deprecated {
g.P(deprecationComment)
}
g.generateUnimplementedServer(servName, service)
// Server registration.
if deprecated {
g.P(deprecationComment)
@ -269,6 +277,35 @@ func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.Servi
g.P()
}
// generateUnimplementedServer creates the unimplemented server struct
func (g *grpc) generateUnimplementedServer(servName string, service *pb.ServiceDescriptorProto) {
serverType := servName + "Server"
g.P("// Unimplemented", serverType, " can be embedded to have forward compatible implementations.")
g.P("type Unimplemented", serverType, " struct {")
g.P("}")
g.P()
// Unimplemented<service_name>Server's concrete methods
for _, method := range service.Method {
g.generateServerMethodConcrete(servName, method)
}
g.P()
}
// generateServerMethodConcrete returns unimplemented methods which ensure forward compatibility
func (g *grpc) generateServerMethodConcrete(servName string, method *pb.MethodDescriptorProto) {
header := g.generateServerSignatureWithParamNames(servName, method)
g.P("func (*Unimplemented", servName, "Server) ", header, " {")
var nilArg string
if !method.GetServerStreaming() && !method.GetClientStreaming() {
nilArg = "nil, "
}
methName := generator.CamelCase(method.GetName())
statusPkg := string(g.gen.AddImport(statusPkgPath))
codePkg := string(g.gen.AddImport(codePkgPath))
g.P("return ", nilArg, statusPkg, `.Errorf(`, codePkg, `.Unimplemented, "method `, methName, ` not implemented")`)
g.P("}")
}
// generateClientSignature returns the client-side signature for a method.
func (g *grpc) generateClientSignature(servName string, method *pb.MethodDescriptorProto) string {
origMethName := method.GetName()
@ -368,6 +405,30 @@ func (g *grpc) generateClientMethod(servName, fullServName, serviceDescVar strin
}
}
// generateServerSignatureWithParamNames returns the server-side signature for a method with parameter names.
func (g *grpc) generateServerSignatureWithParamNames(servName string, method *pb.MethodDescriptorProto) string {
origMethName := method.GetName()
methName := generator.CamelCase(origMethName)
if reservedClientName[methName] {
methName += "_"
}
var reqArgs []string
ret := "error"
if !method.GetServerStreaming() && !method.GetClientStreaming() {
reqArgs = append(reqArgs, "ctx "+contextPkg+".Context")
ret = "(*" + g.typeName(method.GetOutputType()) + ", error)"
}
if !method.GetClientStreaming() {
reqArgs = append(reqArgs, "req *"+g.typeName(method.GetInputType()))
}
if method.GetServerStreaming() || method.GetClientStreaming() {
reqArgs = append(reqArgs, "srv "+servName+"_"+generator.CamelCase(origMethName)+"Server")
}
return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret
}
// generateServerSignature returns the server-side signature for a method.
func (g *grpc) generateServerSignature(servName string, method *pb.MethodDescriptorProto) string {
origMethName := method.GetName()

View file

@ -10,6 +10,8 @@ import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
math "math"
)
@ -235,6 +237,15 @@ type DeprecatedServiceServer interface {
DeprecatedCall(context.Context, *DeprecatedRequest) (*DeprecatedResponse, error)
}
// Deprecated: Do not use.
// UnimplementedDeprecatedServiceServer can be embedded to have forward compatible implementations.
type UnimplementedDeprecatedServiceServer struct {
}
func (*UnimplementedDeprecatedServiceServer) DeprecatedCall(ctx context.Context, req *DeprecatedRequest) (*DeprecatedResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeprecatedCall not implemented")
}
// Deprecated: Do not use.
func RegisterDeprecatedServiceServer(s *grpc.Server, srv DeprecatedServiceServer) {
s.RegisterService(&_DeprecatedService_serviceDesc, srv)

View file

@ -8,6 +8,8 @@ import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
math "math"
)
@ -321,6 +323,23 @@ type TestServer interface {
Bidi(Test_BidiServer) error
}
// UnimplementedTestServer can be embedded to have forward compatible implementations.
type UnimplementedTestServer struct {
}
func (*UnimplementedTestServer) UnaryCall(ctx context.Context, req *SimpleRequest) (*SimpleResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UnaryCall not implemented")
}
func (*UnimplementedTestServer) Downstream(req *SimpleRequest, srv Test_DownstreamServer) error {
return status.Errorf(codes.Unimplemented, "method Downstream not implemented")
}
func (*UnimplementedTestServer) Upstream(srv Test_UpstreamServer) error {
return status.Errorf(codes.Unimplemented, "method Upstream not implemented")
}
func (*UnimplementedTestServer) Bidi(srv Test_BidiServer) error {
return status.Errorf(codes.Unimplemented, "method Bidi not implemented")
}
func RegisterTestServer(s *grpc.Server, srv TestServer) {
s.RegisterService(&_Test_serviceDesc, srv)
}

View file

@ -0,0 +1,79 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: grpc/grpc_empty.proto
package testing
import (
context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
func init() { proto.RegisterFile("grpc/grpc_empty.proto", fileDescriptor_c580a37f1c90e9b1) }
var fileDescriptor_c580a37f1c90e9b1 = []byte{
// 125 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4d, 0x2f, 0x2a, 0x48,
0xd6, 0x07, 0x11, 0xf1, 0xa9, 0xb9, 0x05, 0x25, 0x95, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42,
0x3c, 0x20, 0x11, 0xbd, 0x92, 0xd4, 0xe2, 0x92, 0xcc, 0xbc, 0x74, 0x23, 0x3e, 0x2e, 0x1e, 0x57,
0x90, 0x64, 0x70, 0x6a, 0x51, 0x59, 0x66, 0x72, 0xaa, 0x93, 0x43, 0x94, 0x5d, 0x7a, 0x66, 0x49,
0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x7a, 0x7e, 0x4e, 0x62, 0x5e, 0xba, 0x3e, 0x58,
0x63, 0x52, 0x69, 0x1a, 0x84, 0x91, 0xac, 0x9b, 0x9e, 0x9a, 0xa7, 0x9b, 0x9e, 0xaf, 0x0f, 0x32,
0x23, 0x25, 0xb1, 0x24, 0x11, 0x6c, 0x87, 0x35, 0xd4, 0xc4, 0x24, 0x36, 0xb0, 0x22, 0x63, 0x40,
0x00, 0x00, 0x00, 0xff, 0xff, 0x93, 0x1d, 0xf2, 0x47, 0x7f, 0x00, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// EmptyServiceClient is the client API for EmptyService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type EmptyServiceClient interface {
}
type emptyServiceClient struct {
cc *grpc.ClientConn
}
func NewEmptyServiceClient(cc *grpc.ClientConn) EmptyServiceClient {
return &emptyServiceClient{cc}
}
// EmptyServiceServer is the server API for EmptyService service.
type EmptyServiceServer interface {
}
// UnimplementedEmptyServiceServer can be embedded to have forward compatible implementations.
type UnimplementedEmptyServiceServer struct {
}
func RegisterEmptyServiceServer(s *grpc.Server, srv EmptyServiceServer) {
s.RegisterService(&_EmptyService_serviceDesc, srv)
}
var _EmptyService_serviceDesc = grpc.ServiceDesc{
ServiceName: "grpc.testing.EmptyService",
HandlerType: (*EmptyServiceServer)(nil),
Methods: []grpc.MethodDesc{},
Streams: []grpc.StreamDesc{},
Metadata: "grpc/grpc_empty.proto",
}

View file

@ -0,0 +1,38 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2019 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
package grpc.testing;
option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/grpc;testing";
service EmptyService {}

View file

@ -13,12 +13,6 @@
cd
mkdir -p local
# Install swift
SWIFT_URL=https://swift.org/builds/swift-4.0-branch/ubuntu1404/swift-4.0-DEVELOPMENT-SNAPSHOT-2017-09-01-a/swift-4.0-DEVELOPMENT-SNAPSHOT-2017-09-01-a-ubuntu14.04.tar.gz
echo $SWIFT_URL
curl -fSsL $SWIFT_URL -o swift.tar.gz
tar -xzf swift.tar.gz --strip-components=2 --directory=local
# Install protoc
PROTOC_URL=https://github.com/google/protobuf/releases/download/v3.4.0/protoc-3.4.0-linux-x86_64.zip
echo $PROTOC_URL

View file

@ -29,21 +29,3 @@ install:
script:
- go test . -v
- pushd plugins/gnostic-go-generator/examples/v2.0/bookstore
- make test
- popd
- pushd plugins/gnostic-go-generator/examples/v2.0/sample
- make test
- popd
- pushd plugins/gnostic-go-generator/examples/v3.0/bookstore
- make test
- popd
- export PATH=.:$HOME/local/bin:$PATH
- export LD_LIBRARY_PATH=$HOME/local/lib
- pushd plugins/gnostic-swift-generator
- make install
- cd examples/bookstore
- make
- .build/debug/Server &
- make test

View file

@ -8,9 +8,5 @@ build:
cd apps/petstore-builder; go get; go install
cd plugins/gnostic-summary; go get; go install
cd plugins/gnostic-analyze; go get; go install
cd plugins/gnostic-go-generator; go get; go install
rm -f $(GOPATH)/bin/gnostic-go-client $(GOPATH)/bin/gnostic-go-server
ln -s $(GOPATH)/bin/gnostic-go-generator $(GOPATH)/bin/gnostic-go-client
ln -s $(GOPATH)/bin/gnostic-go-generator $(GOPATH)/bin/gnostic-go-server
cd extensions/sample; make

View file

@ -7105,15 +7105,15 @@ func (m *Any) ToRawInfo() interface{} {
// ToRawInfo returns a description of ApiKeySecurity suitable for JSON or YAML export.
func (m *ApiKeySecurity) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Type != "" {
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
if m.In != "" {
info = append(info, yaml.MapItem{Key: "in", Value: m.In})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
// always include this required field.
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
// always include this required field.
info = append(info, yaml.MapItem{Key: "in", Value: m.In})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -7129,9 +7129,11 @@ func (m *ApiKeySecurity) ToRawInfo() interface{} {
// ToRawInfo returns a description of BasicAuthenticationSecurity suitable for JSON or YAML export.
func (m *BasicAuthenticationSecurity) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Type != "" {
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -7147,21 +7149,21 @@ func (m *BasicAuthenticationSecurity) ToRawInfo() interface{} {
// ToRawInfo returns a description of BodyParameter suitable for JSON or YAML export.
func (m *BodyParameter) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
if m.In != "" {
info = append(info, yaml.MapItem{Key: "in", Value: m.In})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
// always include this required field.
info = append(info, yaml.MapItem{Key: "in", Value: m.In})
if m.Required != false {
info = append(info, yaml.MapItem{Key: "required", Value: m.Required})
}
if m.Schema != nil {
info = append(info, yaml.MapItem{Key: "schema", Value: m.Schema.ToRawInfo()})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "schema", Value: m.Schema.ToRawInfo()})
// &{Name:schema Type:Schema StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
if m.VendorExtension != nil {
for _, item := range m.VendorExtension {
@ -7175,6 +7177,9 @@ func (m *BodyParameter) ToRawInfo() interface{} {
// ToRawInfo returns a description of Contact suitable for JSON or YAML export.
func (m *Contact) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7196,6 +7201,9 @@ func (m *Contact) ToRawInfo() interface{} {
// ToRawInfo returns a description of Default suitable for JSON or YAML export.
func (m *Default) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7208,6 +7216,9 @@ func (m *Default) ToRawInfo() interface{} {
// ToRawInfo returns a description of Definitions suitable for JSON or YAML export.
func (m *Definitions) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7220,12 +7231,13 @@ func (m *Definitions) ToRawInfo() interface{} {
// ToRawInfo returns a description of Document suitable for JSON or YAML export.
func (m *Document) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Swagger != "" {
info = append(info, yaml.MapItem{Key: "swagger", Value: m.Swagger})
}
if m.Info != nil {
info = append(info, yaml.MapItem{Key: "info", Value: m.Info.ToRawInfo()})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "swagger", Value: m.Swagger})
// always include this required field.
info = append(info, yaml.MapItem{Key: "info", Value: m.Info.ToRawInfo()})
// &{Name:info Type:Info StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
if m.Host != "" {
info = append(info, yaml.MapItem{Key: "host", Value: m.Host})
@ -7242,9 +7254,8 @@ func (m *Document) ToRawInfo() interface{} {
if len(m.Produces) != 0 {
info = append(info, yaml.MapItem{Key: "produces", Value: m.Produces})
}
if m.Paths != nil {
info = append(info, yaml.MapItem{Key: "paths", Value: m.Paths.ToRawInfo()})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "paths", Value: m.Paths.ToRawInfo()})
// &{Name:paths Type:Paths StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
if m.Definitions != nil {
info = append(info, yaml.MapItem{Key: "definitions", Value: m.Definitions.ToRawInfo()})
@ -7294,6 +7305,9 @@ func (m *Document) ToRawInfo() interface{} {
// ToRawInfo returns a description of Examples suitable for JSON or YAML export.
func (m *Examples) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7306,12 +7320,14 @@ func (m *Examples) ToRawInfo() interface{} {
// ToRawInfo returns a description of ExternalDocs suitable for JSON or YAML export.
func (m *ExternalDocs) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
if m.Url != "" {
info = append(info, yaml.MapItem{Key: "url", Value: m.Url})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "url", Value: m.Url})
if m.VendorExtension != nil {
for _, item := range m.VendorExtension {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7324,6 +7340,9 @@ func (m *ExternalDocs) ToRawInfo() interface{} {
// ToRawInfo returns a description of FileSchema suitable for JSON or YAML export.
func (m *FileSchema) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Format != "" {
info = append(info, yaml.MapItem{Key: "format", Value: m.Format})
}
@ -7340,9 +7359,8 @@ func (m *FileSchema) ToRawInfo() interface{} {
if len(m.Required) != 0 {
info = append(info, yaml.MapItem{Key: "required", Value: m.Required})
}
if m.Type != "" {
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
if m.ReadOnly != false {
info = append(info, yaml.MapItem{Key: "readOnly", Value: m.ReadOnly})
}
@ -7366,6 +7384,9 @@ func (m *FileSchema) ToRawInfo() interface{} {
// ToRawInfo returns a description of FormDataParameterSubSchema suitable for JSON or YAML export.
func (m *FormDataParameterSubSchema) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Required != false {
info = append(info, yaml.MapItem{Key: "required", Value: m.Required})
}
@ -7451,9 +7472,11 @@ func (m *FormDataParameterSubSchema) ToRawInfo() interface{} {
// ToRawInfo returns a description of Header suitable for JSON or YAML export.
func (m *Header) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Type != "" {
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
if m.Format != "" {
info = append(info, yaml.MapItem{Key: "format", Value: m.Format})
}
@ -7524,6 +7547,9 @@ func (m *Header) ToRawInfo() interface{} {
// ToRawInfo returns a description of HeaderParameterSubSchema suitable for JSON or YAML export.
func (m *HeaderParameterSubSchema) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Required != false {
info = append(info, yaml.MapItem{Key: "required", Value: m.Required})
}
@ -7606,6 +7632,9 @@ func (m *HeaderParameterSubSchema) ToRawInfo() interface{} {
// ToRawInfo returns a description of Headers suitable for JSON or YAML export.
func (m *Headers) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7618,12 +7647,13 @@ func (m *Headers) ToRawInfo() interface{} {
// ToRawInfo returns a description of Info suitable for JSON or YAML export.
func (m *Info) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Title != "" {
info = append(info, yaml.MapItem{Key: "title", Value: m.Title})
}
if m.Version != "" {
info = append(info, yaml.MapItem{Key: "version", Value: m.Version})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "title", Value: m.Title})
// always include this required field.
info = append(info, yaml.MapItem{Key: "version", Value: m.Version})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -7650,6 +7680,9 @@ func (m *Info) ToRawInfo() interface{} {
// ToRawInfo returns a description of ItemsItem suitable for JSON or YAML export.
func (m *ItemsItem) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if len(m.Schema) != 0 {
items := make([]interface{}, 0)
for _, item := range m.Schema {
@ -7664,9 +7697,11 @@ func (m *ItemsItem) ToRawInfo() interface{} {
// ToRawInfo returns a description of JsonReference suitable for JSON or YAML export.
func (m *JsonReference) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.XRef != "" {
info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -7676,9 +7711,11 @@ func (m *JsonReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of License suitable for JSON or YAML export.
func (m *License) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
if m.Url != "" {
info = append(info, yaml.MapItem{Key: "url", Value: m.Url})
}
@ -7694,6 +7731,9 @@ func (m *License) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedAny suitable for JSON or YAML export.
func (m *NamedAny) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7704,6 +7744,9 @@ func (m *NamedAny) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedHeader suitable for JSON or YAML export.
func (m *NamedHeader) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7714,6 +7757,9 @@ func (m *NamedHeader) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedParameter suitable for JSON or YAML export.
func (m *NamedParameter) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7724,6 +7770,9 @@ func (m *NamedParameter) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedPathItem suitable for JSON or YAML export.
func (m *NamedPathItem) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7734,6 +7783,9 @@ func (m *NamedPathItem) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedResponse suitable for JSON or YAML export.
func (m *NamedResponse) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7744,6 +7796,9 @@ func (m *NamedResponse) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedResponseValue suitable for JSON or YAML export.
func (m *NamedResponseValue) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7754,6 +7809,9 @@ func (m *NamedResponseValue) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedSchema suitable for JSON or YAML export.
func (m *NamedSchema) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7764,6 +7822,9 @@ func (m *NamedSchema) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedSecurityDefinitionsItem suitable for JSON or YAML export.
func (m *NamedSecurityDefinitionsItem) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7774,6 +7835,9 @@ func (m *NamedSecurityDefinitionsItem) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedString suitable for JSON or YAML export.
func (m *NamedString) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7786,6 +7850,9 @@ func (m *NamedString) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedStringArray suitable for JSON or YAML export.
func (m *NamedStringArray) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7823,22 +7890,21 @@ func (m *NonBodyParameter) ToRawInfo() interface{} {
// ToRawInfo returns a description of Oauth2AccessCodeSecurity suitable for JSON or YAML export.
func (m *Oauth2AccessCodeSecurity) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Type != "" {
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
}
if m.Flow != "" {
info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
// always include this required field.
info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow})
if m.Scopes != nil {
info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()})
}
// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
if m.AuthorizationUrl != "" {
info = append(info, yaml.MapItem{Key: "authorizationUrl", Value: m.AuthorizationUrl})
}
if m.TokenUrl != "" {
info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "authorizationUrl", Value: m.AuthorizationUrl})
// always include this required field.
info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -7854,19 +7920,19 @@ func (m *Oauth2AccessCodeSecurity) ToRawInfo() interface{} {
// ToRawInfo returns a description of Oauth2ApplicationSecurity suitable for JSON or YAML export.
func (m *Oauth2ApplicationSecurity) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Type != "" {
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
}
if m.Flow != "" {
info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
// always include this required field.
info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow})
if m.Scopes != nil {
info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()})
}
// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
if m.TokenUrl != "" {
info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -7882,19 +7948,19 @@ func (m *Oauth2ApplicationSecurity) ToRawInfo() interface{} {
// ToRawInfo returns a description of Oauth2ImplicitSecurity suitable for JSON or YAML export.
func (m *Oauth2ImplicitSecurity) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Type != "" {
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
}
if m.Flow != "" {
info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
// always include this required field.
info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow})
if m.Scopes != nil {
info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()})
}
// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
if m.AuthorizationUrl != "" {
info = append(info, yaml.MapItem{Key: "authorizationUrl", Value: m.AuthorizationUrl})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "authorizationUrl", Value: m.AuthorizationUrl})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -7910,19 +7976,19 @@ func (m *Oauth2ImplicitSecurity) ToRawInfo() interface{} {
// ToRawInfo returns a description of Oauth2PasswordSecurity suitable for JSON or YAML export.
func (m *Oauth2PasswordSecurity) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Type != "" {
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
}
if m.Flow != "" {
info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
// always include this required field.
info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow})
if m.Scopes != nil {
info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()})
}
// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
if m.TokenUrl != "" {
info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -7938,6 +8004,9 @@ func (m *Oauth2PasswordSecurity) ToRawInfo() interface{} {
// ToRawInfo returns a description of Oauth2Scopes suitable for JSON or YAML export.
func (m *Oauth2Scopes) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
// &{Name:additionalProperties Type:NamedString StringEnumValues:[] MapType:string Repeated:true Pattern: Implicit:true Description:}
return info
}
@ -7945,6 +8014,9 @@ func (m *Oauth2Scopes) ToRawInfo() interface{} {
// ToRawInfo returns a description of Operation suitable for JSON or YAML export.
func (m *Operation) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if len(m.Tags) != 0 {
info = append(info, yaml.MapItem{Key: "tags", Value: m.Tags})
}
@ -7975,9 +8047,8 @@ func (m *Operation) ToRawInfo() interface{} {
info = append(info, yaml.MapItem{Key: "parameters", Value: items})
}
// &{Name:parameters Type:ParametersItem StringEnumValues:[] MapType: Repeated:true Pattern: Implicit:false Description:The parameters needed to send a valid API call.}
if m.Responses != nil {
info = append(info, yaml.MapItem{Key: "responses", Value: m.Responses.ToRawInfo()})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "responses", Value: m.Responses.ToRawInfo()})
// &{Name:responses Type:Responses StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
if len(m.Schemes) != 0 {
info = append(info, yaml.MapItem{Key: "schemes", Value: m.Schemes})
@ -8022,6 +8093,9 @@ func (m *Parameter) ToRawInfo() interface{} {
// ToRawInfo returns a description of ParameterDefinitions suitable for JSON or YAML export.
func (m *ParameterDefinitions) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -8051,6 +8125,9 @@ func (m *ParametersItem) ToRawInfo() interface{} {
// ToRawInfo returns a description of PathItem suitable for JSON or YAML export.
func (m *PathItem) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.XRef != "" {
info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef})
}
@ -8102,9 +8179,11 @@ func (m *PathItem) ToRawInfo() interface{} {
// ToRawInfo returns a description of PathParameterSubSchema suitable for JSON or YAML export.
func (m *PathParameterSubSchema) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Required != false {
info = append(info, yaml.MapItem{Key: "required", Value: m.Required})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "required", Value: m.Required})
if m.In != "" {
info = append(info, yaml.MapItem{Key: "in", Value: m.In})
}
@ -8184,6 +8263,9 @@ func (m *PathParameterSubSchema) ToRawInfo() interface{} {
// ToRawInfo returns a description of Paths suitable for JSON or YAML export.
func (m *Paths) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.VendorExtension != nil {
for _, item := range m.VendorExtension {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -8202,6 +8284,9 @@ func (m *Paths) ToRawInfo() interface{} {
// ToRawInfo returns a description of PrimitivesItems suitable for JSON or YAML export.
func (m *PrimitivesItems) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Type != "" {
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
}
@ -8272,6 +8357,9 @@ func (m *PrimitivesItems) ToRawInfo() interface{} {
// ToRawInfo returns a description of Properties suitable for JSON or YAML export.
func (m *Properties) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -8284,6 +8372,9 @@ func (m *Properties) ToRawInfo() interface{} {
// ToRawInfo returns a description of QueryParameterSubSchema suitable for JSON or YAML export.
func (m *QueryParameterSubSchema) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Required != false {
info = append(info, yaml.MapItem{Key: "required", Value: m.Required})
}
@ -8369,9 +8460,11 @@ func (m *QueryParameterSubSchema) ToRawInfo() interface{} {
// ToRawInfo returns a description of Response suitable for JSON or YAML export.
func (m *Response) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
if m.Schema != nil {
info = append(info, yaml.MapItem{Key: "schema", Value: m.Schema.ToRawInfo()})
}
@ -8396,6 +8489,9 @@ func (m *Response) ToRawInfo() interface{} {
// ToRawInfo returns a description of ResponseDefinitions suitable for JSON or YAML export.
func (m *ResponseDefinitions) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -8425,6 +8521,9 @@ func (m *ResponseValue) ToRawInfo() interface{} {
// ToRawInfo returns a description of Responses suitable for JSON or YAML export.
func (m *Responses) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.ResponseCode != nil {
for _, item := range m.ResponseCode {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -8443,6 +8542,9 @@ func (m *Responses) ToRawInfo() interface{} {
// ToRawInfo returns a description of Schema suitable for JSON or YAML export.
func (m *Schema) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.XRef != "" {
info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef})
}
@ -8588,6 +8690,9 @@ func (m *SchemaItem) ToRawInfo() interface{} {
// ToRawInfo returns a description of SecurityDefinitions suitable for JSON or YAML export.
func (m *SecurityDefinitions) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -8637,6 +8742,9 @@ func (m *SecurityDefinitionsItem) ToRawInfo() interface{} {
// ToRawInfo returns a description of SecurityRequirement suitable for JSON or YAML export.
func (m *SecurityRequirement) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -8654,9 +8762,11 @@ func (m *StringArray) ToRawInfo() interface{} {
// ToRawInfo returns a description of Tag suitable for JSON or YAML export.
func (m *Tag) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -8676,6 +8786,9 @@ func (m *Tag) ToRawInfo() interface{} {
// ToRawInfo returns a description of TypeItem suitable for JSON or YAML export.
func (m *TypeItem) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if len(m.Value) != 0 {
info = append(info, yaml.MapItem{Key: "value", Value: m.Value})
}
@ -8685,6 +8798,9 @@ func (m *TypeItem) ToRawInfo() interface{} {
// ToRawInfo returns a description of VendorExtension suitable for JSON or YAML export.
func (m *VendorExtension) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -8697,6 +8813,9 @@ func (m *VendorExtension) ToRawInfo() interface{} {
// ToRawInfo returns a description of Xml suitable for JSON or YAML export.
func (m *Xml) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}

View file

@ -6714,6 +6714,9 @@ func (m *AnyOrExpression) ToRawInfo() interface{} {
// ToRawInfo returns a description of AnysOrExpressions suitable for JSON or YAML export.
func (m *AnysOrExpressions) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -6726,6 +6729,9 @@ func (m *AnysOrExpressions) ToRawInfo() interface{} {
// ToRawInfo returns a description of Callback suitable for JSON or YAML export.
func (m *Callback) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Path != nil {
for _, item := range m.Path {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -6761,6 +6767,9 @@ func (m *CallbackOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of CallbacksOrReferences suitable for JSON or YAML export.
func (m *CallbacksOrReferences) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -6773,6 +6782,9 @@ func (m *CallbacksOrReferences) ToRawInfo() interface{} {
// ToRawInfo returns a description of Components suitable for JSON or YAML export.
func (m *Components) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Schemas != nil {
info = append(info, yaml.MapItem{Key: "schemas", Value: m.Schemas.ToRawInfo()})
}
@ -6821,6 +6833,9 @@ func (m *Components) ToRawInfo() interface{} {
// ToRawInfo returns a description of Contact suitable for JSON or YAML export.
func (m *Contact) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -6861,9 +6876,11 @@ func (m *DefaultType) ToRawInfo() interface{} {
// ToRawInfo returns a description of Discriminator suitable for JSON or YAML export.
func (m *Discriminator) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.PropertyName != "" {
info = append(info, yaml.MapItem{Key: "propertyName", Value: m.PropertyName})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "propertyName", Value: m.PropertyName})
if m.Mapping != nil {
info = append(info, yaml.MapItem{Key: "mapping", Value: m.Mapping.ToRawInfo()})
}
@ -6874,12 +6891,13 @@ func (m *Discriminator) ToRawInfo() interface{} {
// ToRawInfo returns a description of Document suitable for JSON or YAML export.
func (m *Document) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Openapi != "" {
info = append(info, yaml.MapItem{Key: "openapi", Value: m.Openapi})
}
if m.Info != nil {
info = append(info, yaml.MapItem{Key: "info", Value: m.Info.ToRawInfo()})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "openapi", Value: m.Openapi})
// always include this required field.
info = append(info, yaml.MapItem{Key: "info", Value: m.Info.ToRawInfo()})
// &{Name:info Type:Info StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
if len(m.Servers) != 0 {
items := make([]interface{}, 0)
@ -6889,9 +6907,8 @@ func (m *Document) ToRawInfo() interface{} {
info = append(info, yaml.MapItem{Key: "servers", Value: items})
}
// &{Name:servers Type:Server StringEnumValues:[] MapType: Repeated:true Pattern: Implicit:false Description:}
if m.Paths != nil {
info = append(info, yaml.MapItem{Key: "paths", Value: m.Paths.ToRawInfo()})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "paths", Value: m.Paths.ToRawInfo()})
// &{Name:paths Type:Paths StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
if m.Components != nil {
info = append(info, yaml.MapItem{Key: "components", Value: m.Components.ToRawInfo()})
@ -6929,6 +6946,9 @@ func (m *Document) ToRawInfo() interface{} {
// ToRawInfo returns a description of Encoding suitable for JSON or YAML export.
func (m *Encoding) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.ContentType != "" {
info = append(info, yaml.MapItem{Key: "contentType", Value: m.ContentType})
}
@ -6957,6 +6977,9 @@ func (m *Encoding) ToRawInfo() interface{} {
// ToRawInfo returns a description of Encodings suitable for JSON or YAML export.
func (m *Encodings) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -6969,6 +6992,9 @@ func (m *Encodings) ToRawInfo() interface{} {
// ToRawInfo returns a description of Example suitable for JSON or YAML export.
func (m *Example) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Summary != "" {
info = append(info, yaml.MapItem{Key: "summary", Value: m.Summary})
}
@ -7008,6 +7034,9 @@ func (m *ExampleOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of ExamplesOrReferences suitable for JSON or YAML export.
func (m *ExamplesOrReferences) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7020,6 +7049,9 @@ func (m *ExamplesOrReferences) ToRawInfo() interface{} {
// ToRawInfo returns a description of Expression suitable for JSON or YAML export.
func (m *Expression) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7032,12 +7064,14 @@ func (m *Expression) ToRawInfo() interface{} {
// ToRawInfo returns a description of ExternalDocs suitable for JSON or YAML export.
func (m *ExternalDocs) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
if m.Url != "" {
info = append(info, yaml.MapItem{Key: "url", Value: m.Url})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "url", Value: m.Url})
if m.SpecificationExtension != nil {
for _, item := range m.SpecificationExtension {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7050,6 +7084,9 @@ func (m *ExternalDocs) ToRawInfo() interface{} {
// ToRawInfo returns a description of Header suitable for JSON or YAML export.
func (m *Header) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -7116,6 +7153,9 @@ func (m *HeaderOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of HeadersOrReferences suitable for JSON or YAML export.
func (m *HeadersOrReferences) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7128,9 +7168,11 @@ func (m *HeadersOrReferences) ToRawInfo() interface{} {
// ToRawInfo returns a description of Info suitable for JSON or YAML export.
func (m *Info) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Title != "" {
info = append(info, yaml.MapItem{Key: "title", Value: m.Title})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "title", Value: m.Title})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -7145,9 +7187,8 @@ func (m *Info) ToRawInfo() interface{} {
info = append(info, yaml.MapItem{Key: "license", Value: m.License.ToRawInfo()})
}
// &{Name:license Type:License StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
if m.Version != "" {
info = append(info, yaml.MapItem{Key: "version", Value: m.Version})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "version", Value: m.Version})
if m.SpecificationExtension != nil {
for _, item := range m.SpecificationExtension {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7160,6 +7201,9 @@ func (m *Info) ToRawInfo() interface{} {
// ToRawInfo returns a description of ItemsItem suitable for JSON or YAML export.
func (m *ItemsItem) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if len(m.SchemaOrReference) != 0 {
items := make([]interface{}, 0)
for _, item := range m.SchemaOrReference {
@ -7174,9 +7218,11 @@ func (m *ItemsItem) ToRawInfo() interface{} {
// ToRawInfo returns a description of License suitable for JSON or YAML export.
func (m *License) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
if m.Url != "" {
info = append(info, yaml.MapItem{Key: "url", Value: m.Url})
}
@ -7192,6 +7238,9 @@ func (m *License) ToRawInfo() interface{} {
// ToRawInfo returns a description of Link suitable for JSON or YAML export.
func (m *Link) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.OperationRef != "" {
info = append(info, yaml.MapItem{Key: "operationRef", Value: m.OperationRef})
}
@ -7242,6 +7291,9 @@ func (m *LinkOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of LinksOrReferences suitable for JSON or YAML export.
func (m *LinksOrReferences) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7254,6 +7306,9 @@ func (m *LinksOrReferences) ToRawInfo() interface{} {
// ToRawInfo returns a description of MediaType suitable for JSON or YAML export.
func (m *MediaType) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Schema != nil {
info = append(info, yaml.MapItem{Key: "schema", Value: m.Schema.ToRawInfo()})
}
@ -7282,6 +7337,9 @@ func (m *MediaType) ToRawInfo() interface{} {
// ToRawInfo returns a description of MediaTypes suitable for JSON or YAML export.
func (m *MediaTypes) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7294,6 +7352,9 @@ func (m *MediaTypes) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedAny suitable for JSON or YAML export.
func (m *NamedAny) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7304,6 +7365,9 @@ func (m *NamedAny) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedAnyOrExpression suitable for JSON or YAML export.
func (m *NamedAnyOrExpression) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7314,6 +7378,9 @@ func (m *NamedAnyOrExpression) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedCallbackOrReference suitable for JSON or YAML export.
func (m *NamedCallbackOrReference) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7324,6 +7391,9 @@ func (m *NamedCallbackOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedEncoding suitable for JSON or YAML export.
func (m *NamedEncoding) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7334,6 +7404,9 @@ func (m *NamedEncoding) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedExampleOrReference suitable for JSON or YAML export.
func (m *NamedExampleOrReference) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7344,6 +7417,9 @@ func (m *NamedExampleOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedHeaderOrReference suitable for JSON or YAML export.
func (m *NamedHeaderOrReference) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7354,6 +7430,9 @@ func (m *NamedHeaderOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedLinkOrReference suitable for JSON or YAML export.
func (m *NamedLinkOrReference) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7364,6 +7443,9 @@ func (m *NamedLinkOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedMediaType suitable for JSON or YAML export.
func (m *NamedMediaType) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7374,6 +7456,9 @@ func (m *NamedMediaType) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedParameterOrReference suitable for JSON or YAML export.
func (m *NamedParameterOrReference) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7384,6 +7469,9 @@ func (m *NamedParameterOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedPathItem suitable for JSON or YAML export.
func (m *NamedPathItem) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7394,6 +7482,9 @@ func (m *NamedPathItem) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedRequestBodyOrReference suitable for JSON or YAML export.
func (m *NamedRequestBodyOrReference) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7404,6 +7495,9 @@ func (m *NamedRequestBodyOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedResponseOrReference suitable for JSON or YAML export.
func (m *NamedResponseOrReference) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7414,6 +7508,9 @@ func (m *NamedResponseOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedSchemaOrReference suitable for JSON or YAML export.
func (m *NamedSchemaOrReference) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7424,6 +7521,9 @@ func (m *NamedSchemaOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedSecuritySchemeOrReference suitable for JSON or YAML export.
func (m *NamedSecuritySchemeOrReference) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7434,6 +7534,9 @@ func (m *NamedSecuritySchemeOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedServerVariable suitable for JSON or YAML export.
func (m *NamedServerVariable) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7444,6 +7547,9 @@ func (m *NamedServerVariable) ToRawInfo() interface{} {
// ToRawInfo returns a description of NamedString suitable for JSON or YAML export.
func (m *NamedString) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
@ -7456,6 +7562,9 @@ func (m *NamedString) ToRawInfo() interface{} {
// ToRawInfo returns a description of OauthFlow suitable for JSON or YAML export.
func (m *OauthFlow) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AuthorizationUrl != "" {
info = append(info, yaml.MapItem{Key: "authorizationUrl", Value: m.AuthorizationUrl})
}
@ -7481,6 +7590,9 @@ func (m *OauthFlow) ToRawInfo() interface{} {
// ToRawInfo returns a description of OauthFlows suitable for JSON or YAML export.
func (m *OauthFlows) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Implicit != nil {
info = append(info, yaml.MapItem{Key: "implicit", Value: m.Implicit.ToRawInfo()})
}
@ -7509,6 +7621,9 @@ func (m *OauthFlows) ToRawInfo() interface{} {
// ToRawInfo returns a description of Object suitable for JSON or YAML export.
func (m *Object) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7521,6 +7636,9 @@ func (m *Object) ToRawInfo() interface{} {
// ToRawInfo returns a description of Operation suitable for JSON or YAML export.
func (m *Operation) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if len(m.Tags) != 0 {
info = append(info, yaml.MapItem{Key: "tags", Value: m.Tags})
}
@ -7549,9 +7667,8 @@ func (m *Operation) ToRawInfo() interface{} {
info = append(info, yaml.MapItem{Key: "requestBody", Value: m.RequestBody.ToRawInfo()})
}
// &{Name:requestBody Type:RequestBodyOrReference StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
if m.Responses != nil {
info = append(info, yaml.MapItem{Key: "responses", Value: m.Responses.ToRawInfo()})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "responses", Value: m.Responses.ToRawInfo()})
// &{Name:responses Type:Responses StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
if m.Callbacks != nil {
info = append(info, yaml.MapItem{Key: "callbacks", Value: m.Callbacks.ToRawInfo()})
@ -7588,12 +7705,13 @@ func (m *Operation) ToRawInfo() interface{} {
// ToRawInfo returns a description of Parameter suitable for JSON or YAML export.
func (m *Parameter) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}
if m.In != "" {
info = append(info, yaml.MapItem{Key: "in", Value: m.In})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
// always include this required field.
info = append(info, yaml.MapItem{Key: "in", Value: m.In})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -7660,6 +7778,9 @@ func (m *ParameterOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of ParametersOrReferences suitable for JSON or YAML export.
func (m *ParametersOrReferences) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7672,6 +7793,9 @@ func (m *ParametersOrReferences) ToRawInfo() interface{} {
// ToRawInfo returns a description of PathItem suitable for JSON or YAML export.
func (m *PathItem) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.XRef != "" {
info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef})
}
@ -7741,6 +7865,9 @@ func (m *PathItem) ToRawInfo() interface{} {
// ToRawInfo returns a description of Paths suitable for JSON or YAML export.
func (m *Paths) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Path != nil {
for _, item := range m.Path {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7759,6 +7886,9 @@ func (m *Paths) ToRawInfo() interface{} {
// ToRawInfo returns a description of Properties suitable for JSON or YAML export.
func (m *Properties) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7771,15 +7901,20 @@ func (m *Properties) ToRawInfo() interface{} {
// ToRawInfo returns a description of Reference suitable for JSON or YAML export.
func (m *Reference) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.XRef != "" {
info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef})
return info
}
// ToRawInfo returns a description of RequestBodiesOrReferences suitable for JSON or YAML export.
func (m *RequestBodiesOrReferences) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7792,12 +7927,14 @@ func (m *RequestBodiesOrReferences) ToRawInfo() interface{} {
// ToRawInfo returns a description of RequestBody suitable for JSON or YAML export.
func (m *RequestBody) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
if m.Content != nil {
info = append(info, yaml.MapItem{Key: "content", Value: m.Content.ToRawInfo()})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "content", Value: m.Content.ToRawInfo()})
// &{Name:content Type:MediaTypes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
if m.Required != false {
info = append(info, yaml.MapItem{Key: "required", Value: m.Required})
@ -7831,9 +7968,11 @@ func (m *RequestBodyOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of Response suitable for JSON or YAML export.
func (m *Response) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
if m.Headers != nil {
info = append(info, yaml.MapItem{Key: "headers", Value: m.Headers.ToRawInfo()})
}
@ -7875,6 +8014,9 @@ func (m *ResponseOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of Responses suitable for JSON or YAML export.
func (m *Responses) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Default != nil {
info = append(info, yaml.MapItem{Key: "default", Value: m.Default.ToRawInfo()})
}
@ -7897,6 +8039,9 @@ func (m *Responses) ToRawInfo() interface{} {
// ToRawInfo returns a description of ResponsesOrReferences suitable for JSON or YAML export.
func (m *ResponsesOrReferences) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -7909,6 +8054,9 @@ func (m *ResponsesOrReferences) ToRawInfo() interface{} {
// ToRawInfo returns a description of Schema suitable for JSON or YAML export.
func (m *Schema) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Nullable != false {
info = append(info, yaml.MapItem{Key: "nullable", Value: m.Nullable})
}
@ -8076,6 +8224,9 @@ func (m *SchemaOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of SchemasOrReferences suitable for JSON or YAML export.
func (m *SchemasOrReferences) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -8088,15 +8239,20 @@ func (m *SchemasOrReferences) ToRawInfo() interface{} {
// ToRawInfo returns a description of SecurityRequirement suitable for JSON or YAML export.
func (m *SecurityRequirement) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
return info
}
// ToRawInfo returns a description of SecurityScheme suitable for JSON or YAML export.
func (m *SecurityScheme) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Type != "" {
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -8148,6 +8304,9 @@ func (m *SecuritySchemeOrReference) ToRawInfo() interface{} {
// ToRawInfo returns a description of SecuritySchemesOrReferences suitable for JSON or YAML export.
func (m *SecuritySchemesOrReferences) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -8160,9 +8319,11 @@ func (m *SecuritySchemesOrReferences) ToRawInfo() interface{} {
// ToRawInfo returns a description of Server suitable for JSON or YAML export.
func (m *Server) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Url != "" {
info = append(info, yaml.MapItem{Key: "url", Value: m.Url})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "url", Value: m.Url})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -8182,12 +8343,14 @@ func (m *Server) ToRawInfo() interface{} {
// ToRawInfo returns a description of ServerVariable suitable for JSON or YAML export.
func (m *ServerVariable) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if len(m.Enum) != 0 {
info = append(info, yaml.MapItem{Key: "enum", Value: m.Enum})
}
if m.Default != "" {
info = append(info, yaml.MapItem{Key: "default", Value: m.Default})
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "default", Value: m.Default})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -8203,6 +8366,9 @@ func (m *ServerVariable) ToRawInfo() interface{} {
// ToRawInfo returns a description of ServerVariables suitable for JSON or YAML export.
func (m *ServerVariables) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.AdditionalProperties != nil {
for _, item := range m.AdditionalProperties {
info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()})
@ -8239,6 +8405,9 @@ func (m *StringArray) ToRawInfo() interface{} {
// ToRawInfo returns a description of Strings suitable for JSON or YAML export.
func (m *Strings) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
// &{Name:additionalProperties Type:NamedString StringEnumValues:[] MapType:string Repeated:true Pattern: Implicit:true Description:}
return info
}
@ -8246,9 +8415,11 @@ func (m *Strings) ToRawInfo() interface{} {
// ToRawInfo returns a description of Tag suitable for JSON or YAML export.
func (m *Tag) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
if m == nil {
return info
}
// always include this required field.
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
if m.Description != "" {
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
}
@ -8268,6 +8439,9 @@ func (m *Tag) ToRawInfo() interface{} {
// ToRawInfo returns a description of Xml suitable for JSON or YAML export.
func (m *Xml) ToRawInfo() interface{} {
info := yaml.MapSlice{}
if m == nil {
return info
}
if m.Name != "" {
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
}

View file

@ -93,12 +93,9 @@ Protocol Buffer description. This is mainly for use in testing and debugging.
go install github.com/googleapis/gnostic/apps/report
report petstore.pb
8. **gnostic** supports plugins. This builds and runs a sample plugin
that reports some basic information about an API. The "-" causes the plugin to
write its output to stdout.
go install github.com/googleapis/gnostic/plugins/gnostic-go-sample
gnostic examples/v2.0/json/petstore.json --go-sample-out=-
8. **gnostic** supports plugins. Some are already implemented in the `plugins` directory.
Others, like [gnostic-go-generator](https://github.com/googleapis/gnostic-go-generator),
are separated into their own repositories.
## Copyright

View file

@ -285,8 +285,10 @@ func OpenAPIv3(api *discovery.Document) (*openapi3.Document, error) {
d.Components = &openapi3.Components{}
d.Components.Schemas = &openapi3.SchemasOrReferences{}
for _, pair := range api.Schemas.AdditionalProperties {
addOpenAPI3SchemaForSchema(d, pair.Name, pair.Value)
if api.Schemas != nil {
for _, pair := range api.Schemas.AdditionalProperties {
addOpenAPI3SchemaForSchema(d, pair.Name, pair.Value)
}
}
d.Paths = &openapi3.Paths{}

View file

@ -20,6 +20,7 @@ import (
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"github.com/golang/protobuf/proto"
@ -28,18 +29,17 @@ import (
pb "github.com/googleapis/gnostic/OpenAPIv2"
)
func readDocumentFromFileWithName(filename string) *pb.Document {
func readDocumentFromFileWithName(filename string) (*pb.Document, error) {
data, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Printf("File error: %v\n", err)
os.Exit(1)
return nil, err
}
document := &pb.Document{}
err = proto.Unmarshal(data, document)
if err != nil {
panic(err)
return nil, err
}
return document
return document, nil
}
func printDocument(code *printer.Code, document *pb.Document) {
@ -229,8 +229,12 @@ func main() {
return
}
document := readDocumentFromFileWithName(args[0])
document, err := readDocumentFromFileWithName(args[0])
if err != nil {
log.Printf("Error reading %s. This sample expects OpenAPI v2.", args[0])
os.Exit(-1)
}
code := &printer.Code{}
code.Print("API REPORT")
code.Print("----------")

View file

@ -17,13 +17,14 @@ package compiler
import (
"errors"
"fmt"
"gopkg.in/yaml.v2"
"io/ioutil"
"log"
"net/http"
"net/url"
"path/filepath"
"strings"
yaml "gopkg.in/yaml.v2"
)
var fileCache map[string][]byte
@ -31,6 +32,8 @@ var infoCache map[string]interface{}
var count int64
var verboseReader = false
var fileCacheEnable = true
var infoCacheEnable = true
func initializeFileCache() {
if fileCache == nil {
@ -44,29 +47,56 @@ func initializeInfoCache() {
}
}
func DisableFileCache() {
fileCacheEnable = false
}
func DisableInfoCache() {
infoCacheEnable = false
}
func RemoveFromFileCache(fileurl string) {
if !fileCacheEnable {
return
}
initializeFileCache()
delete(fileCache, fileurl)
}
func RemoveFromInfoCache(filename string) {
if !infoCacheEnable {
return
}
initializeInfoCache()
delete(infoCache, filename)
}
// FetchFile gets a specified file from the local filesystem or a remote location.
func FetchFile(fileurl string) ([]byte, error) {
var bytes []byte
initializeFileCache()
bytes, ok := fileCache[fileurl]
if ok {
if verboseReader {
log.Printf("Cache hit %s", fileurl)
if fileCacheEnable {
bytes, ok := fileCache[fileurl]
if ok {
if verboseReader {
log.Printf("Cache hit %s", fileurl)
}
return bytes, nil
}
if verboseReader {
log.Printf("Fetching %s", fileurl)
}
return bytes, nil
}
if verboseReader {
log.Printf("Fetching %s", fileurl)
}
response, err := http.Get(fileurl)
if err != nil {
return nil, err
}
defer response.Body.Close()
if response.StatusCode != 200 {
return nil, errors.New(fmt.Sprintf("Error downloading %s: %s", fileurl, response.Status))
}
defer response.Body.Close()
bytes, err = ioutil.ReadAll(response.Body)
if err == nil {
if fileCacheEnable && err == nil {
fileCache[fileurl] = bytes
}
return bytes, err
@ -95,22 +125,24 @@ func ReadBytesForFile(filename string) ([]byte, error) {
// ReadInfoFromBytes unmarshals a file as a yaml.MapSlice.
func ReadInfoFromBytes(filename string, bytes []byte) (interface{}, error) {
initializeInfoCache()
cachedInfo, ok := infoCache[filename]
if ok {
if verboseReader {
log.Printf("Cache hit info for file %s", filename)
if infoCacheEnable {
cachedInfo, ok := infoCache[filename]
if ok {
if verboseReader {
log.Printf("Cache hit info for file %s", filename)
}
return cachedInfo, nil
}
if verboseReader {
log.Printf("Reading info for file %s", filename)
}
return cachedInfo, nil
}
if verboseReader {
log.Printf("Reading info for file %s", filename)
}
var info yaml.MapSlice
err := yaml.Unmarshal(bytes, &info)
if err != nil {
return nil, err
}
if len(filename) > 0 {
if infoCacheEnable && len(filename) > 0 {
infoCache[filename] = info
}
return info, nil
@ -119,7 +151,7 @@ func ReadInfoFromBytes(filename string, bytes []byte) (interface{}, error) {
// ReadInfoForRef reads a file and return the fragment needed to resolve a $ref.
func ReadInfoForRef(basefile string, ref string) (interface{}, error) {
initializeInfoCache()
{
if infoCacheEnable {
info, ok := infoCache[ref]
if ok {
if verboseReader {
@ -127,9 +159,9 @@ func ReadInfoForRef(basefile string, ref string) (interface{}, error) {
}
return info, nil
}
}
if verboseReader {
log.Printf("Reading info for ref %s#%s", basefile, ref)
if verboseReader {
log.Printf("Reading info for ref %s#%s", basefile, ref)
}
}
count = count + 1
basedir, _ := filepath.Split(basefile)
@ -170,6 +202,8 @@ func ReadInfoForRef(basefile string, ref string) (interface{}, error) {
}
}
}
infoCache[ref] = info
if infoCacheEnable {
infoCache[ref] = info
}
return info, nil
}

View file

@ -0,0 +1,82 @@
package compiler
import (
. "gopkg.in/check.v1"
"io"
"net/http"
"testing"
)
// Hook up gocheck into the "go test" runner.
func Test(t *testing.T) {
TestingT(t)
}
var mockSever *http.Server
type ReaderTestingSuite struct{}
var _ = Suite(&ReaderTestingSuite{})
func (s *ReaderTestingSuite) SetUpSuite(c *C) {
mockSever = &http.Server{Addr: "127.0.0.1:8080", Handler:
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
yamlBytes, err := ReadBytesForFile("testdata/petstore.yaml")
c.Assert(err, IsNil)
io.WriteString(w, string(yamlBytes))
})}
go func() {
mockSever.ListenAndServe()
}()
}
func (s *ReaderTestingSuite) TearDownSuite(c *C) {
mockSever.Close()
}
func (s *ReaderTestingSuite) TestRemoveFromInfoCache(c *C) {
fileName := "testdata/petstore.yaml"
yamlBytes, err := ReadBytesForFile(fileName)
c.Assert(err, IsNil)
c.Assert(len(yamlBytes) > 0, Equals, true)
petstore, err := ReadInfoFromBytes(fileName, yamlBytes)
c.Assert(err, IsNil)
c.Assert(petstore, NotNil)
c.Assert(len(infoCache), Equals, 1)
RemoveFromInfoCache(fileName)
c.Assert(len(infoCache), Equals, 0)
}
func (s *ReaderTestingSuite) TestDisableInfoCache(c *C) {
fileName := "testdata/petstore.yaml"
yamlBytes, err := ReadBytesForFile(fileName)
c.Assert(err, IsNil)
c.Assert(len(yamlBytes) > 0, Equals, true)
DisableInfoCache()
petstore, err := ReadInfoFromBytes(fileName, yamlBytes)
c.Assert(err, IsNil)
c.Assert(petstore, NotNil)
c.Assert(len(infoCache), Equals, 0)
}
func (s *ReaderTestingSuite) TestRemoveFromFileCache(c *C) {
fileUrl := "http://127.0.0.1:8080/petstore"
yamlBytes, err := FetchFile(fileUrl)
c.Assert(err, IsNil)
c.Assert(len(yamlBytes) > 0, Equals, true)
c.Assert(len(fileCache), Equals, 1)
RemoveFromFileCache(fileUrl)
c.Assert(len(fileCache), Equals, 0)
}
func (s *ReaderTestingSuite) TestDisableFileCache(c *C) {
DisableFileCache()
fileUrl := "http://127.0.0.1:8080/petstore"
yamlBytes, err := FetchFile(fileUrl)
c.Assert(err, IsNil)
c.Assert(len(yamlBytes) > 0, Equals, true)
c.Assert(len(fileCache), Equals, 0)
}

View file

@ -0,0 +1,110 @@
openapi: "3.0"
info:
version: 1.0.0
title: OpenAPI Petstore
license:
name: MIT
servers:
- url: https://petstore.openapis.org/v1
description: Development server
paths:
/pets:
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
format: int32
responses:
"200":
description: An paged array of pets
headers:
x-next:
schema:
type: string
description: A link to the next page of responses
content:
application/json:
schema:
$ref: '#/components/schemas/Pets'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
summary: Create a pet
operationId: createPets
tags:
- pets
responses:
"201":
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/pets/{petId}:
get:
summary: Info for a specific pet
operationId: showPetById
tags:
- pets
parameters:
- name: petId
in: path
required: true
description: The id of the pet to retrieve
schema:
type: string
responses:
"200":
description: Expected response to a valid request
content:
application/json:
schema:
$ref: '#/components/schemas/Pets'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
Pet:
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
Pets:
type: array
items:
$ref: '#/components/schemas/Pet'
Error:
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string

View file

@ -0,0 +1,6 @@
swagger: "2.0"
info:
version: ""
title: ""
description: ""
paths:

View file

@ -0,0 +1,6 @@
openapi: "3.0"
info:
version:
title:
description:
paths:

View file

@ -1,24 +1,12 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: extension.proto
/*
Package openapiextension_v1 is a generated protocol buffer package.
It is generated from these files:
extension.proto
It has these top-level messages:
Version
ExtensionHandlerRequest
ExtensionHandlerResponse
Wrapper
*/
package openapiextension_v1
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import google_protobuf "github.com/golang/protobuf/ptypes/any"
import any "github.com/golang/protobuf/ptypes/any"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
@ -33,18 +21,40 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
// The version number of OpenAPI compiler.
type Version struct {
Major int32 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"`
Minor int32 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"`
Patch int32 `protobuf:"varint,3,opt,name=patch" json:"patch,omitempty"`
Major int32 `protobuf:"varint,1,opt,name=major,proto3" json:"major,omitempty"`
Minor int32 `protobuf:"varint,2,opt,name=minor,proto3" json:"minor,omitempty"`
Patch int32 `protobuf:"varint,3,opt,name=patch,proto3" json:"patch,omitempty"`
// A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
// be empty for mainline stable releases.
Suffix string `protobuf:"bytes,4,opt,name=suffix" json:"suffix,omitempty"`
Suffix string `protobuf:"bytes,4,opt,name=suffix,proto3" json:"suffix,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Version) Reset() { *m = Version{} }
func (m *Version) String() string { return proto.CompactTextString(m) }
func (*Version) ProtoMessage() {}
func (*Version) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *Version) Reset() { *m = Version{} }
func (m *Version) String() string { return proto.CompactTextString(m) }
func (*Version) ProtoMessage() {}
func (*Version) Descriptor() ([]byte, []int) {
return fileDescriptor_extension_d25f09c742c58c90, []int{0}
}
func (m *Version) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Version.Unmarshal(m, b)
}
func (m *Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Version.Marshal(b, m, deterministic)
}
func (dst *Version) XXX_Merge(src proto.Message) {
xxx_messageInfo_Version.Merge(dst, src)
}
func (m *Version) XXX_Size() int {
return xxx_messageInfo_Version.Size(m)
}
func (m *Version) XXX_DiscardUnknown() {
xxx_messageInfo_Version.DiscardUnknown(m)
}
var xxx_messageInfo_Version proto.InternalMessageInfo
func (m *Version) GetMajor() int32 {
if m != nil {
@ -78,15 +88,37 @@ func (m *Version) GetSuffix() string {
type ExtensionHandlerRequest struct {
// The OpenAPI descriptions that were explicitly listed on the command line.
// The specifications will appear in the order they are specified to gnostic.
Wrapper *Wrapper `protobuf:"bytes,1,opt,name=wrapper" json:"wrapper,omitempty"`
Wrapper *Wrapper `protobuf:"bytes,1,opt,name=wrapper,proto3" json:"wrapper,omitempty"`
// The version number of openapi compiler.
CompilerVersion *Version `protobuf:"bytes,3,opt,name=compiler_version,json=compilerVersion" json:"compiler_version,omitempty"`
CompilerVersion *Version `protobuf:"bytes,3,opt,name=compiler_version,json=compilerVersion,proto3" json:"compiler_version,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ExtensionHandlerRequest) Reset() { *m = ExtensionHandlerRequest{} }
func (m *ExtensionHandlerRequest) String() string { return proto.CompactTextString(m) }
func (*ExtensionHandlerRequest) ProtoMessage() {}
func (*ExtensionHandlerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *ExtensionHandlerRequest) Reset() { *m = ExtensionHandlerRequest{} }
func (m *ExtensionHandlerRequest) String() string { return proto.CompactTextString(m) }
func (*ExtensionHandlerRequest) ProtoMessage() {}
func (*ExtensionHandlerRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_extension_d25f09c742c58c90, []int{1}
}
func (m *ExtensionHandlerRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ExtensionHandlerRequest.Unmarshal(m, b)
}
func (m *ExtensionHandlerRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ExtensionHandlerRequest.Marshal(b, m, deterministic)
}
func (dst *ExtensionHandlerRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_ExtensionHandlerRequest.Merge(dst, src)
}
func (m *ExtensionHandlerRequest) XXX_Size() int {
return xxx_messageInfo_ExtensionHandlerRequest.Size(m)
}
func (m *ExtensionHandlerRequest) XXX_DiscardUnknown() {
xxx_messageInfo_ExtensionHandlerRequest.DiscardUnknown(m)
}
var xxx_messageInfo_ExtensionHandlerRequest proto.InternalMessageInfo
func (m *ExtensionHandlerRequest) GetWrapper() *Wrapper {
if m != nil {
@ -105,7 +137,7 @@ func (m *ExtensionHandlerRequest) GetCompilerVersion() *Version {
// The extensions writes an encoded ExtensionHandlerResponse to stdout.
type ExtensionHandlerResponse struct {
// true if the extension is handled by the extension handler; false otherwise
Handled bool `protobuf:"varint,1,opt,name=handled" json:"handled,omitempty"`
Handled bool `protobuf:"varint,1,opt,name=handled,proto3" json:"handled,omitempty"`
// Error message. If non-empty, the extension handling failed.
// The extension handler process should exit with status code zero
// even if it reports an error in this way.
@ -115,15 +147,37 @@ type ExtensionHandlerResponse struct {
// itself -- such as the input Document being unparseable -- should be
// reported by writing a message to stderr and exiting with a non-zero
// status code.
Error []string `protobuf:"bytes,2,rep,name=error" json:"error,omitempty"`
Error []string `protobuf:"bytes,2,rep,name=error,proto3" json:"error,omitempty"`
// text output
Value *google_protobuf.Any `protobuf:"bytes,3,opt,name=value" json:"value,omitempty"`
Value *any.Any `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ExtensionHandlerResponse) Reset() { *m = ExtensionHandlerResponse{} }
func (m *ExtensionHandlerResponse) String() string { return proto.CompactTextString(m) }
func (*ExtensionHandlerResponse) ProtoMessage() {}
func (*ExtensionHandlerResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func (m *ExtensionHandlerResponse) Reset() { *m = ExtensionHandlerResponse{} }
func (m *ExtensionHandlerResponse) String() string { return proto.CompactTextString(m) }
func (*ExtensionHandlerResponse) ProtoMessage() {}
func (*ExtensionHandlerResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_extension_d25f09c742c58c90, []int{2}
}
func (m *ExtensionHandlerResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ExtensionHandlerResponse.Unmarshal(m, b)
}
func (m *ExtensionHandlerResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ExtensionHandlerResponse.Marshal(b, m, deterministic)
}
func (dst *ExtensionHandlerResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_ExtensionHandlerResponse.Merge(dst, src)
}
func (m *ExtensionHandlerResponse) XXX_Size() int {
return xxx_messageInfo_ExtensionHandlerResponse.Size(m)
}
func (m *ExtensionHandlerResponse) XXX_DiscardUnknown() {
xxx_messageInfo_ExtensionHandlerResponse.DiscardUnknown(m)
}
var xxx_messageInfo_ExtensionHandlerResponse proto.InternalMessageInfo
func (m *ExtensionHandlerResponse) GetHandled() bool {
if m != nil {
@ -139,7 +193,7 @@ func (m *ExtensionHandlerResponse) GetError() []string {
return nil
}
func (m *ExtensionHandlerResponse) GetValue() *google_protobuf.Any {
func (m *ExtensionHandlerResponse) GetValue() *any.Any {
if m != nil {
return m.Value
}
@ -148,17 +202,39 @@ func (m *ExtensionHandlerResponse) GetValue() *google_protobuf.Any {
type Wrapper struct {
// version of the OpenAPI specification in which this extension was written.
Version string `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"`
Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"`
// Name of the extension
ExtensionName string `protobuf:"bytes,2,opt,name=extension_name,json=extensionName" json:"extension_name,omitempty"`
ExtensionName string `protobuf:"bytes,2,opt,name=extension_name,json=extensionName,proto3" json:"extension_name,omitempty"`
// Must be a valid yaml for the proto
Yaml string `protobuf:"bytes,3,opt,name=yaml" json:"yaml,omitempty"`
Yaml string `protobuf:"bytes,3,opt,name=yaml,proto3" json:"yaml,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Wrapper) Reset() { *m = Wrapper{} }
func (m *Wrapper) String() string { return proto.CompactTextString(m) }
func (*Wrapper) ProtoMessage() {}
func (*Wrapper) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (m *Wrapper) Reset() { *m = Wrapper{} }
func (m *Wrapper) String() string { return proto.CompactTextString(m) }
func (*Wrapper) ProtoMessage() {}
func (*Wrapper) Descriptor() ([]byte, []int) {
return fileDescriptor_extension_d25f09c742c58c90, []int{3}
}
func (m *Wrapper) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Wrapper.Unmarshal(m, b)
}
func (m *Wrapper) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Wrapper.Marshal(b, m, deterministic)
}
func (dst *Wrapper) XXX_Merge(src proto.Message) {
xxx_messageInfo_Wrapper.Merge(dst, src)
}
func (m *Wrapper) XXX_Size() int {
return xxx_messageInfo_Wrapper.Size(m)
}
func (m *Wrapper) XXX_DiscardUnknown() {
xxx_messageInfo_Wrapper.DiscardUnknown(m)
}
var xxx_messageInfo_Wrapper proto.InternalMessageInfo
func (m *Wrapper) GetVersion() string {
if m != nil {
@ -188,9 +264,9 @@ func init() {
proto.RegisterType((*Wrapper)(nil), "openapiextension.v1.Wrapper")
}
func init() { proto.RegisterFile("extension.proto", fileDescriptor0) }
func init() { proto.RegisterFile("extension.proto", fileDescriptor_extension_d25f09c742c58c90) }
var fileDescriptor0 = []byte{
var fileDescriptor_extension_d25f09c742c58c90 = []byte{
// 357 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0x4d, 0x4b, 0xc3, 0x40,
0x18, 0x84, 0x49, 0xbf, 0x62, 0x56, 0x6c, 0x65, 0x2d, 0x1a, 0xc5, 0x43, 0x09, 0x08, 0x45, 0x64,

View file

@ -798,14 +798,17 @@ func (domain *Domain) generateToRawInfoMethodForType(code *printer.Code, typeNam
code.Print("return nil")
} else {
code.Print("info := yaml.MapSlice{}")
code.Print("if m == nil {return info}")
for _, propertyModel := range typeModel.Properties {
isRequired := typeModel.IsRequired(propertyModel.Name)
switch propertyModel.Type {
case "string":
propertyName := propertyModel.Name
if !propertyModel.Repeated {
code.Print("if m.%s != \"\" {", propertyModel.FieldName())
code.PrintIf(isRequired, "// always include this required field.")
code.PrintIf(!isRequired, "if m.%s != \"\" {", propertyModel.FieldName())
code.Print("info = append(info, yaml.MapItem{Key:\"%s\", Value:m.%s})", propertyName, propertyModel.FieldName())
code.Print("}")
code.PrintIf(!isRequired, "}")
} else {
code.Print("if len(m.%s) != 0 {", propertyModel.FieldName())
code.Print("info = append(info, yaml.MapItem{Key:\"%s\", Value:m.%s})", propertyName, propertyModel.FieldName())
@ -814,9 +817,10 @@ func (domain *Domain) generateToRawInfoMethodForType(code *printer.Code, typeNam
case "bool":
propertyName := propertyModel.Name
if !propertyModel.Repeated {
code.Print("if m.%s != false {", propertyModel.FieldName())
code.PrintIf(isRequired, "// always include this required field.")
code.PrintIf(!isRequired, "if m.%s != false {", propertyModel.FieldName())
code.Print("info = append(info, yaml.MapItem{Key:\"%s\", Value:m.%s})", propertyName, propertyModel.FieldName())
code.Print("}")
code.PrintIf(!isRequired, "}")
} else {
code.Print("if len(m.%s) != 0 {", propertyModel.FieldName())
code.Print("info = append(info, yaml.MapItem{Key:\"%s\", Value:m.%s})", propertyName, propertyModel.FieldName())
@ -825,9 +829,10 @@ func (domain *Domain) generateToRawInfoMethodForType(code *printer.Code, typeNam
case "int":
propertyName := propertyModel.Name
if !propertyModel.Repeated {
code.Print("if m.%s != 0 {", propertyModel.FieldName())
code.PrintIf(isRequired, "// always include this required field.")
code.PrintIf(!isRequired, "if m.%s != 0 {", propertyModel.FieldName())
code.Print("info = append(info, yaml.MapItem{Key:\"%s\", Value:m.%s})", propertyName, propertyModel.FieldName())
code.Print("}")
code.PrintIf(!isRequired, "}")
} else {
code.Print("if len(m.%s) != 0 {", propertyModel.FieldName())
code.Print("info = append(info, yaml.MapItem{Key:\"%s\", Value:m.%s})", propertyName, propertyModel.FieldName())
@ -836,9 +841,10 @@ func (domain *Domain) generateToRawInfoMethodForType(code *printer.Code, typeNam
case "float":
propertyName := propertyModel.Name
if !propertyModel.Repeated {
code.Print("if m.%s != 0.0 {", propertyModel.FieldName())
code.PrintIf(isRequired, "// always include this required field.")
code.PrintIf(!isRequired, "if m.%s != 0.0 {", propertyModel.FieldName())
code.Print("info = append(info, yaml.MapItem{Key:\"%s\", Value:m.%s})", propertyName, propertyModel.FieldName())
code.Print("}")
code.PrintIf(!isRequired, "}")
} else {
code.Print("if len(m.%s) != 0 {", propertyModel.FieldName())
code.Print("info = append(info, yaml.MapItem{Key:\"%s\", Value:m.%s})", propertyName, propertyModel.FieldName())
@ -849,7 +855,8 @@ func (domain *Domain) generateToRawInfoMethodForType(code *printer.Code, typeNam
if propertyName == "value" {
code.Print("// %+v", propertyModel)
} else if !propertyModel.Repeated {
code.Print("if m.%s != nil {", propertyModel.FieldName())
code.PrintIf(isRequired, "// always include this required field.")
code.PrintIf(!isRequired, "if m.%s != nil {", propertyModel.FieldName())
if propertyModel.Type == "TypeItem" {
code.Print("if len(m.Type.Value) == 1 {")
code.Print("info = append(info, yaml.MapItem{Key:\"type\", Value:m.Type.Value[0]})")
@ -870,7 +877,7 @@ func (domain *Domain) generateToRawInfoMethodForType(code *printer.Code, typeNam
code.Print("info = append(info, yaml.MapItem{Key:\"%s\", Value:m.%s.ToRawInfo()})",
propertyName, propertyModel.FieldName())
}
code.Print("}")
code.PrintIf(!isRequired, "}")
code.Print("// %+v", propertyModel)
} else if propertyModel.MapType == "string" {
code.Print("// %+v", propertyModel)

View file

@ -130,3 +130,12 @@ func NewTypeModel() *TypeModel {
typeModel.Properties = make([]*TypeProperty, 0)
return typeModel
}
func (typeModel *TypeModel) IsRequired(propertyName string) bool {
for _, requiredName := range typeModel.Required {
if requiredName == propertyName {
return true
}
}
return false
}

View file

@ -186,8 +186,10 @@ func (p *pluginCall) perform(document proto.Message, sourceFormat int, sourceNam
// any logging messages are written to stderr only.
return nil, errors.New("Invalid plugin response (plugins must write log messages to stderr, not stdout).")
}
plugins.HandleResponse(response, outputLocation)
return response.Messages, nil
err = plugins.HandleResponse(response, outputLocation)
return response.Messages, err
}
return nil, nil
}

View file

@ -10,17 +10,18 @@ import (
)
func testCompiler(t *testing.T, inputFile string, referenceFile string, expectErrors bool) {
textFile := strings.Replace(filepath.Base(inputFile), filepath.Ext(inputFile), ".text", 1)
outputFormat := filepath.Ext(referenceFile)[1:]
outputFile := strings.Replace(filepath.Base(inputFile), filepath.Ext(inputFile), "."+outputFormat, 1)
errorsFile := strings.Replace(filepath.Base(inputFile), filepath.Ext(inputFile), ".errors", 1)
// remove any preexisting output files
os.Remove(textFile)
os.Remove(outputFile)
os.Remove(errorsFile)
// run the compiler
var err error
var cmd = exec.Command(
"gnostic",
inputFile,
"--text-out=.",
"--"+outputFormat+"-out=.",
"--errors-out=.",
"--resolve-refs")
//t.Log(cmd.Args)
@ -30,19 +31,19 @@ func testCompiler(t *testing.T, inputFile string, referenceFile string, expectEr
t.FailNow()
}
// verify the output against a reference
var outputFile string
var testFile string
if expectErrors {
outputFile = errorsFile
testFile = errorsFile
} else {
outputFile = textFile
testFile = outputFile
}
err = exec.Command("diff", outputFile, referenceFile).Run()
err = exec.Command("diff", testFile, referenceFile).Run()
if err != nil {
t.Logf("Diff failed: %+v", err)
t.FailNow()
} else {
// if the test succeeded, clean up
os.Remove(textFile)
os.Remove(outputFile)
os.Remove(errorsFile)
}
}
@ -451,3 +452,17 @@ func TestPetstoreJSON_30(t *testing.T) {
"examples/v3.0/json/petstore.json",
"test/v3.0/petstore.text")
}
// Test that empty required fields are exported.
func TestEmptyRequiredFields_v2(t *testing.T) {
testNormal(t,
"examples/v2.0/yaml/empty-v2.yaml",
"test/v2.0/json/empty-v2.json")
}
func TestEmptyRequiredFields_v3(t *testing.T) {
testNormal(t,
"examples/v3.0/yaml/empty-v3.yaml",
"test/v3.0/json/empty-v3.json")
}

View file

@ -105,7 +105,7 @@ When the -plugin option is specified, these flags are ignored.`)
env.Request.AddModel("openapi.v2.Document", documentv2)
// include experimental API surface model
surfaceModel, err := surface.NewModelFromOpenAPI2(documentv2)
if err != nil {
if err == nil {
env.Request.AddModel("surface.v1.Model", surfaceModel)
}
return env, err
@ -117,7 +117,7 @@ When the -plugin option is specified, these flags are ignored.`)
env.Request.AddModel("openapi.v3.Document", documentv3)
// include experimental API surface model
surfaceModel, err := surface.NewModelFromOpenAPI3(documentv3)
if err != nil {
if err == nil {
env.Request.AddModel("surface.v1.Model", surfaceModel)
}
return env, err

View file

@ -1,9 +0,0 @@
build:
go get golang.org/x/tools/cmd/goimports
go install github.com/googleapis/gnostic
go install github.com/googleapis/gnostic/plugins/gnostic-go-generator
rm -f $(GOPATH)/bin/gnostic-go-client $(GOPATH)/bin/gnostic-go-server
ln -s $(GOPATH)/bin/gnostic-go-generator $(GOPATH)/bin/gnostic-go-client
ln -s $(GOPATH)/bin/gnostic-go-generator $(GOPATH)/bin/gnostic-go-server

View file

@ -1,18 +0,0 @@
# Go Generator Plugin
This directory contains a `gnostic` plugin that can be used to generate a Go client library and scaffolding for a Go server for an API with an OpenAPI description.
The plugin can be invoked like this:
gnostic bookstore.json --go-generator-out=bookstore
`bookstore` is the name of a directory where the generated code will be written.
`bookstore` will also be the package name used for generated code.
By default, both client and server code will be generated. If the `gnostic-go-generator` binary is also linked from the names `gnostic-go-client` and `gnostic-go-server`, then only client or only server code can be generated as follows:
gnostic bookstore.json --go-client-out=bookstore
gnostic bookstore.json --go-server-out=bookstore
For example usage, see the [examples/v2.0/bookstore](examples/v2.0/bookstore) directory.

View file

@ -1,31 +0,0 @@
# googleauth
This directory contains support code that can be used to get an OAuth2 token for a Google API user.
It is designed to work on computers with attached displays.
Use it to write command-line tools and test programs that call Google APIs.
## Instructions
Import this package and make the following call to request a token.
client, err := googleauth.NewOAuth2Client(scopes)
`scopes` should be a string containing the OAuth scopes needed by the APIs to be called.
For example, the URL Shortener API would require "https://www.googleapis.com/auth/urlshortener".
This call will then open a local browser that will redirect to a Google signin page
with information about the app that is requesting a token.
## Application Credentials
To use this package, you need to download a "client secrets" file and
save it as `client_secrets.json` in the directory where your tool is run.
To get this file, visit the {{ Google Cloud Console }}{{ https://cloud.google.com/console }}
and create a project. Then go to the API Manager to enable the APIs that you want to use
and create OAuth2 credentials. You'll then be able to download these credentials
as JSON. Save this file as `client_secrets.json`
For more information about the `client_secrets.json` file format, please visit:
https://developers.google.com/api-client-library/python/guide/aaa_client_secrets

View file

@ -1,220 +0,0 @@
//
// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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.
//
package googleauth
import (
"encoding/json"
"errors"
"flag"
"fmt"
"io/ioutil"
"net"
"net/http"
"os"
"os/exec"
"path/filepath"
"runtime"
"golang.org/x/net/context"
"golang.org/x/oauth2"
)
const missingClientSecretsMessage = `
Please configure OAuth 2.0
To make this sample run, you need to populate the client_secrets.json file
found at:
%v
with information from the {{ Google Cloud Console }}
{{ https://cloud.google.com/console }}
For more information about the client_secrets.json file format, please visit:
https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
`
var (
clientSecretsFile = flag.String("secrets", "client_secrets.json", "Client Secrets configuration")
cacheFile = flag.String("cache", "request.token", "Token cache file")
)
// ClientConfig is a data structure definition for the client_secrets.json file.
// The code unmarshals the JSON configuration file into this structure.
type ClientConfig struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
RedirectURIs []string `json:"redirect_uris"`
AuthURI string `json:"auth_uri"`
TokenURI string `json:"token_uri"`
}
// Config is a root-level configuration object.
type Config struct {
Installed ClientConfig `json:"installed"`
Web ClientConfig `json:"web"`
}
// openURL opens a browser window to the specified location.
// This code originally appeared at:
// http://stackoverflow.com/questions/10377243/how-can-i-launch-a-process-that-is-not-a-file-in-go
func openURL(url string) error {
var err error
switch runtime.GOOS {
case "linux":
err = exec.Command("xdg-open", url).Start()
case "windows":
err = exec.Command("rundll32", "url.dll,FileProtocolHandler", "http://localhost:4001/").Start()
case "darwin":
err = exec.Command("open", url).Start()
default:
err = fmt.Errorf("Cannot open URL %s on this platform", url)
}
return err
}
// readConfig reads the configuration from clientSecretsFile.
// It returns an oauth configuration object for use with the Google API client.
func readConfig(scopes []string) (*oauth2.Config, error) {
// Read the secrets file
data, err := ioutil.ReadFile(*clientSecretsFile)
if err != nil {
pwd, _ := os.Getwd()
fullPath := filepath.Join(pwd, *clientSecretsFile)
return nil, fmt.Errorf(missingClientSecretsMessage, fullPath)
}
cfg := new(Config)
err = json.Unmarshal(data, &cfg)
if err != nil {
return nil, err
}
var redirectURI string
if len(cfg.Web.RedirectURIs) > 0 {
redirectURI = cfg.Web.RedirectURIs[0]
} else if len(cfg.Installed.RedirectURIs) > 0 {
redirectURI = cfg.Installed.RedirectURIs[0]
} else {
return nil, errors.New("Must specify a redirect URI in config file or when creating OAuth client")
}
return &oauth2.Config{
ClientID: cfg.Installed.ClientID,
ClientSecret: cfg.Installed.ClientSecret,
Scopes: scopes,
Endpoint: oauth2.Endpoint{cfg.Installed.AuthURI, cfg.Installed.TokenURI},
RedirectURL: redirectURI,
}, nil
}
// startWebServer starts a web server that listens on http://localhost:8080.
// The webserver waits for an oauth code in the three-legged auth flow.
func startWebServer() (codeCh chan string, err error) {
listener, err := net.Listen("tcp", "localhost:8080")
if err != nil {
return nil, err
}
codeCh = make(chan string)
go http.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
code := r.FormValue("code")
codeCh <- code // send code to OAuth flow
listener.Close()
w.Header().Set("Content-Type", "text/plain")
fmt.Fprintf(w, "Received code: %v\r\nYou can now safely close this browser window.", code)
}))
return codeCh, nil
}
// NewOAuth2Client takes the user through the three-legged OAuth flow.
// It opens a browser in the native OS or outputs a URL, then blocks until
// the redirect completes to the /oauth2callback URI.
// It returns an instance of an HTTP client that can be passed to the
// constructor of an OAuth client.
// scopes is a variable number of OAuth scopes
func NewOAuth2Client(scopes ...string) (*http.Client, error) {
var ctx context.Context
tokenSource, err := NewOAuth2TokenSource(scopes...)
if err == nil {
return oauth2.NewClient(ctx, tokenSource), nil
}
return nil, err
}
// NewOAuth2TokenSource takes the user through the three-legged OAuth flow.
// It opens a browser in the native OS or outputs a URL, then blocks until
// the redirect completes to the /oauth2callback URI.
// It returns an instance of an OAuth token source that can be passed to the
// constructor of an OAuth client.
// scopes is a variable number of OAuth scopes
func NewOAuth2TokenSource(scopes ...string) (oauth2.TokenSource, error) {
config, err := readConfig(scopes)
if err != nil {
msg := fmt.Sprintf("Cannot read configuration file: %v", err)
return nil, errors.New(msg)
}
var ctx context.Context
// Try to read the token from the cache file.
// If an error occurs, do the three-legged OAuth flow because
// the token is invalid or doesn't exist.
//token, err := config.TokenCache.Token()
var token *oauth2.Token
data, err := ioutil.ReadFile(*cacheFile)
if err == nil {
err = json.Unmarshal(data, &token)
}
if (err != nil) || !token.Valid() {
// Start web server.
// This is how this program receives the authorization code
// when the browser redirects.
codeCh, err := startWebServer()
if err != nil {
return nil, err
}
// Open url in browser
url := config.AuthCodeURL("")
err = openURL(url)
if err != nil {
fmt.Println("Visit the URL below to get a code.",
" This program will pause until the site is visted.")
} else {
fmt.Println("Your browser has been opened to an authorization URL.",
" This program will resume once authorization has been provided.\n")
}
fmt.Println(url)
// Wait for the web server to get the code.
code := <-codeCh
// This code caches the authorization code on the local
// filesystem, if necessary, as long as the TokenCache
// attribute in the config is set.
token, err = config.Exchange(ctx, code)
if err != nil {
return nil, err
}
data, err := json.Marshal(token)
ioutil.WriteFile(*cacheFile, data, 0644)
}
return oauth2.StaticTokenSource(token), nil
}

View file

@ -1,4 +0,0 @@
all:
gnostic swagger.yaml --go-client-out=apis_guru
go install

View file

@ -1,45 +0,0 @@
// +build ignore
// This file is omitted when getting with `go get github.com/googleapis/gnostic/...`
package main
import (
"fmt"
"sort"
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v2.0/apis_guru/apis_guru"
)
func main() {
c := apis_guru.NewClient("http://api.apis.guru/v2")
metrics, err := c.GetMetrics()
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", metrics)
apis, err := c.ListAPIs()
if err != nil {
panic(err)
}
keys := make([]string, 0)
for key, _ := range *apis.OK {
keys = append(keys, key)
}
sort.Strings(keys)
for _, key := range keys {
api := (*apis.OK)[key]
versions := make([]string, 0)
for key, _ := range api.Versions {
versions = append(versions, key)
}
sort.Strings(versions)
fmt.Printf("[%s]:%+v\n", key, versions)
}
api := (*apis.OK)["xkcd.com"].Versions["1.0.0"]
fmt.Printf("%+v\n", api.SwaggerUrl)
}

View file

@ -1,186 +0,0 @@
swagger: '2.0'
schemes:
- https
host: api.apis.guru
basePath: /v2/
info:
contact:
email: founders@apis.guru
name: APIs.guru
url: 'http://APIs.guru'
description: |
Wikipedia for Web APIs. Repository of API specs in OpenAPI(fka Swagger) 2.0 format.
**Warning**: If you want to be notified about changes in advance please subscribe to our [Gitter channel](https://gitter.im/APIs-guru/api-models).
Client sample: [[Demo]](https://apis.guru/simple-ui) [[Repo]](https://github.com/APIs-guru/simple-ui)
license:
name: CC0 1.0
url: 'https://github.com/APIs-guru/api-models#licenses'
title: APIs.guru
version: '2.0'
x-logo:
url: 'https://apis.guru/branding/logo_vertical.svg'
externalDocs:
url: 'https://github.com/APIs-guru/api-models/blob/master/API.md'
produces:
- application/json
security: []
paths:
/list.json:
get:
description: |
List all APIs in the directory.
Returns links to OpenAPI specification for each API in the directory.
If API exist in multiply versions `preferred` one is explicitly marked.
Some basic info from OpenAPI spec is cached inside each object.
This allows to generate some simple views without need to fetch OpenAPI spec for each API.
operationId: listAPIs
responses:
'200':
description: OK
schema:
$ref: '#/definitions/APIs'
summary: List all APIs
/metrics.json:
get:
description: |
Some basic metrics for the entire directory.
Just stunning numbers to put on a front page and are intended purely for WoW effect :)
operationId: getMetrics
responses:
'200':
description: OK
schema:
$ref: '#/definitions/Metrics'
summary: Get basic metrics
definitions:
API:
additionalProperties: false
description: Meta information about API
properties:
added:
description: Timestamp when the API was first added to the directory
format: date-time
type: string
preferred:
description: Recommended version
type: string
versions:
additionalProperties:
$ref: '#/definitions/ApiVersion'
description: List of supported versions of the API
minProperties: 1
type: object
required:
- added
- preferred
- versions
type: object
APIs:
additionalProperties:
$ref: '#/definitions/API'
description: |
List of API details.
It is a JSON object with API IDs(`<provider>[:<service>]`) as keys.
example:
'googleapis.com:drive':
added: '2015-02-22T20:00:45.000Z'
preferred: v3
versions:
v2:
added: '2015-02-22T20:00:45.000Z'
info:
title: Drive
version: v2
x-apiClientRegistration:
url: 'https://console.developers.google.com'
x-logo:
url: 'https://api.apis.guru/v2/cache/logo/https_www.gstatic.com_images_icons_material_product_2x_drive_32dp.png'
x-origin:
format: google
url: 'https://www.googleapis.com/discovery/v1/apis/drive/v2/rest'
version: v1
x-preferred: false
x-providerName: googleapis.com
x-serviceName: drive
swaggerUrl: 'https://api.apis.guru/v2/specs/googleapis.com/drive/v2/swagger.json'
swaggerYamlUrl: 'https://api.apis.guru/v2/specs/googleapis.com/drive/v2/swagger.yaml'
updated: '2016-06-17T00:21:44.000Z'
v3:
added: '2015-12-12T00:25:13.000Z'
info:
title: Drive
version: v3
x-apiClientRegistration:
url: 'https://console.developers.google.com'
x-logo:
url: 'https://api.apis.guru/v2/cache/logo/https_www.gstatic.com_images_icons_material_product_2x_drive_32dp.png'
x-origin:
format: google
url: 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest'
version: v1
x-preferred: true
x-providerName: googleapis.com
x-serviceName: drive
swaggerUrl: 'https://api.apis.guru/v2/specs/googleapis.com/drive/v3/swagger.json'
swaggerYamlUrl: 'https://api.apis.guru/v2/specs/googleapis.com/drive/v3/swagger.yaml'
updated: '2016-06-17T00:21:44.000Z'
minProperties: 1
type: object
ApiVersion:
additionalProperties: false
properties:
added:
description: Timestamp when the version was added
format: date-time
type: string
info:
description: Copy of `info` section from Swagger spec
minProperties: 1
type: object
swaggerUrl:
description: URL to Swagger spec in JSON format
format: url
type: string
swaggerYamlUrl:
description: URL to Swagger spec in YAML format
format: url
type: string
updated:
description: Timestamp when the version was updated
format: date-time
type: string
required:
- added
- updated
- swaggerUrl
- swaggerYamlUrl
- info
type: object
Metrics:
additionalProperties: false
description: List of basic metrics
example:
numAPIs: 238
numEndpoints: 6448
numSpecs: 302
properties:
numAPIs:
description: Number of APIs
minimum: 1
type: integer
numEndpoints:
description: Total number of endpoints inside all specifications
minimum: 1
type: integer
numSpecs:
description: Number of API specifications including different versions of the same API
minimum: 1
type: integer
required:
- numSpecs
- numAPIs
- numEndpoints
type: object

View file

@ -1,20 +0,0 @@
build:
go get golang.org/x/tools/cmd/goimports
go install github.com/googleapis/gnostic
go install github.com/googleapis/gnostic/plugins/gnostic-go-generator
rm -f $(GOPATH)/bin/gnostic-go-client $(GOPATH)/bin/gnostic-go-server
ln -s $(GOPATH)/bin/gnostic-go-generator $(GOPATH)/bin/gnostic-go-client
ln -s $(GOPATH)/bin/gnostic-go-generator $(GOPATH)/bin/gnostic-go-server
all: build
gnostic bookstore.json --go-generator-out=bookstore
clean:
rm -rf bookstore bookstore.text service/service
test: all
killall service; true # ignore errors due to no matching processes
cd service; go get .; go build; ./service &
go test
killall service

View file

@ -1,23 +0,0 @@
# Bookstore Example
This directory contains an OpenAPI description of a simple bookstore API.
Use this example to try the `gnostic-go-generator` plugin, which implements
`gnostic-go-client` and `gnostic-go-server` for generating API client and
server code, respectively.
Run "make all" to build and install `gnostic` and the Go plugins.
It will generate both client and server code. The API client and
server code will be in the `bookstore` package.
The `service` directory contains additional code that completes the server.
To build and run the service, `cd service` and do the following:
go get .
go build
./service &
To test the service with the generated client, go back up to the top-level
directory and run `go test`. The test in `bookstore_test.go` uses client
code generated in `bookstore` to verify the service.

View file

@ -1,357 +0,0 @@
{
"swagger": "2.0",
"info": {
"description": "A simple Bookstore API example.",
"title": "Bookstore",
"version": "1.0.0"
},
"host": "generated-bookstore.appspot.com",
"basePath": "/",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"schemes": [
"https"
],
"paths": {
"/shelves": {
"get": {
"description": "Return all shelves in the bookstore.",
"operationId": "listShelves",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "List of shelves in the bookstore.",
"schema": {
"$ref": "#/definitions/listShelvesResponse"
}
}
},
"security": [
]
},
"post": {
"description": "Create a new shelf in the bookstore.",
"operationId": "createShelf",
"parameters": [
{
"description": "A shelf resource to create.",
"in": "body",
"name": "shelf",
"required": true,
"schema": {
"$ref": "#/definitions/shelf"
}
}
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "A newly created shelf resource.",
"schema": {
"$ref": "#/definitions/shelf"
}
}
}
},
"delete": {
"description": "Delete all shelves.",
"operationId": "deleteShelves",
"responses": {
"default": {
"description": "An empty response body."
}
}
}
},
"/shelves/{shelf}": {
"get": {
"description": "Get a single shelf resource with the given ID.",
"operationId": "getShelf",
"parameters": [
{
"description": "ID of the shelf to get.",
"format": "int64",
"in": "path",
"name": "shelf",
"required": true,
"type": "integer"
}
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "A shelf resource.",
"schema": {
"$ref": "#/definitions/shelf"
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/error"
}
}
}
},
"delete": {
"description": "Delete a single shelf with the given ID.",
"operationId": "deleteShelf",
"parameters": [
{
"description": "ID of the shelf to delete.",
"format": "int64",
"in": "path",
"name": "shelf",
"required": true,
"type": "integer"
}
],
"responses": {
"default": {
"description": "An empty response body."
}
}
}
},
"/shelves/{shelf}/books": {
"get": {
"description": "Return all books in a shelf with the given ID.",
"operationId": "listBooks",
"parameters": [
{
"description": "ID of the shelf whose books should be returned.",
"format": "int64",
"in": "path",
"name": "shelf",
"required": true,
"type": "integer"
}
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "List of books on the specified shelf.",
"schema": {
"$ref": "#/definitions/listBooksResponse"
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/error"
}
}
}
},
"post": {
"description": "Create a new book on the shelf.",
"operationId": "createBook",
"parameters": [
{
"description": "ID of the shelf where the book should be created.",
"format": "int64",
"in": "path",
"name": "shelf",
"required": true,
"type": "integer"
},
{
"description": "Book to create.",
"in": "body",
"name": "book",
"required": true,
"schema": {
"$ref": "#/definitions/book"
}
}
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "A newly created book resource.",
"schema": {
"$ref": "#/definitions/book"
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/error"
}
}
}
}
},
"/shelves/{shelf}/books/{book}": {
"get": {
"description": "Get a single book with a given ID from a shelf.",
"operationId": "getBook",
"parameters": [
{
"description": "ID of the shelf from which to get the book.",
"format": "int64",
"in": "path",
"name": "shelf",
"required": true,
"type": "integer"
},
{
"description": "ID of the book to get from the shelf.",
"format": "int64",
"in": "path",
"name": "book",
"required": true,
"type": "integer"
}
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "A book resource.",
"schema": {
"$ref": "#/definitions/book"
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/error"
}
}
}
},
"delete": {
"description": "Delete a single book with a given ID from a shelf.",
"operationId": "deleteBook",
"parameters": [
{
"description": "ID of the shelf from which to delete the book.",
"format": "int64",
"in": "path",
"name": "shelf",
"required": true,
"type": "integer"
},
{
"description": "ID of the book to delete from the shelf.",
"format": "int64",
"in": "path",
"name": "book",
"required": true,
"type": "integer"
}
],
"responses": {
"default": {
"description": "An empty response body."
}
}
}
}
},
"definitions": {
"book": {
"properties": {
"author": {
"type": "string"
},
"name": {
"type": "string"
},
"title": {
"type": "string"
}
},
"required": [
"name",
"author",
"title"
]
},
"listBooksResponse": {
"properties": {
"books": {
"items": {
"$ref": "#/definitions/book"
},
"type": "array"
}
},
"required": [
"books"
],
"type": "object"
},
"listShelvesResponse": {
"properties": {
"shelves": {
"items": {
"$ref": "#/definitions/shelf"
},
"type": "array"
}
},
"type": "object"
},
"shelf": {
"properties": {
"name": {
"type": "string"
},
"theme": {
"type": "string"
}
},
"required": [
"name",
"theme"
]
},
"error": {
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
},
"security": [
{
"api_key": [
]
}
],
"securityDefinitions": {
"api_key": {
"in": "query",
"name": "key",
"type": "apiKey"
}
}
}

View file

@ -1,19 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
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.
*/
// Package bookstore exists to allow this repo to work with recursive go get.
// It will be filled in with auto generated code.
package bookstore

View file

@ -1,239 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
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.
*/
package test
import (
"fmt"
"net/http"
"strings"
"testing"
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v2.0/bookstore/bookstore"
)
const service = "http://localhost:8080"
//const service = "http://generated-bookstore.appspot.com"
func TestBookstore(t *testing.T) {
// create a client
b := bookstore.NewClient(service, nil)
// reset the service by deleting all shelves
{
err := b.DeleteShelves()
if err != nil {
t.Log("delete shelves failed")
t.Fail()
}
}
// verify that the service has no shelves
{
response, err := b.ListShelves()
if err != nil {
t.Log("list shelves failed")
t.Fail()
}
if (response == nil) || (response.OK == nil) || (response.OK.Shelves != nil) {
t.Log(fmt.Sprintf("list shelves failed %+v", response.OK))
t.Log(fmt.Sprintf("list shelves failed len=%d", len(response.OK.Shelves)))
t.Fail()
}
}
// attempting to get a shelf should return an error
{
_, err := b.GetShelf(1)
if err == nil {
t.Log("get shelf failed to return an error")
t.Fail()
}
}
// attempting to get a book should return an error
{
_, err := b.GetBook(1, 2)
if err == nil {
t.Log("get book failed to return an error")
t.Fail()
}
}
// add a shelf
{
var shelf bookstore.Shelf
shelf.Theme = "mysteries"
response, err := b.CreateShelf(shelf)
if err != nil {
t.Log("create shelf mysteries failed")
t.Fail()
}
if (response.OK.Name != "shelves/1") ||
(response.OK.Theme != "mysteries") {
t.Log("create shelf mysteries failed")
t.Fail()
}
}
// add another shelf
{
var shelf bookstore.Shelf
shelf.Theme = "comedies"
response, err := b.CreateShelf(shelf)
if err != nil {
t.Log("create shelf comedies failed")
t.Fail()
}
if (response.OK.Name != "shelves/2") ||
(response.OK.Theme != "comedies") {
t.Log("create shelf comedies failed")
t.Fail()
}
}
// get the first shelf that was added
{
response, err := b.GetShelf(1)
if err != nil {
t.Log("get shelf mysteries failed")
t.Fail()
}
if (response.OK.Name != "shelves/1") ||
(response.OK.Theme != "mysteries") {
t.Log("get shelf mysteries failed")
t.Fail()
}
}
// list shelves and verify that there are 2
{
response, err := b.ListShelves()
if err != nil {
t.Log("list shelves failed")
t.Fail()
}
if len(response.OK.Shelves) != 2 {
t.Log("list shelves failed")
t.Fail()
}
}
// delete a shelf
{
err := b.DeleteShelf(2)
if err != nil {
t.Log("delete shelf failed")
t.Fail()
}
}
// list shelves and verify that there is only 1
{
response, err := b.ListShelves()
if err != nil {
t.Log("list shelves failed")
t.Fail()
}
if len(response.OK.Shelves) != 1 {
t.Log("list shelves failed")
t.Fail()
}
}
// list books on a shelf, verify that there are none
{
response, err := b.ListBooks(1)
if err != nil {
t.Log("list books failed")
t.Fail()
}
if len(response.OK.Books) != 0 {
t.Log("list books failed")
t.Fail()
}
}
// create a book
{
var book bookstore.Book
book.Author = "Agatha Christie"
book.Title = "And Then There Were None"
_, err := b.CreateBook(1, book)
if err != nil {
t.Log("create book failed")
t.Fail()
}
}
// create another book
{
var book bookstore.Book
book.Author = "Agatha Christie"
book.Title = "Murder on the Orient Express"
_, err := b.CreateBook(1, book)
if err != nil {
t.Log("create book failed")
t.Fail()
}
}
// get the first book that was added
{
_, err := b.GetBook(1, 1)
if err != nil {
t.Log("get book failed")
t.Fail()
}
}
// list the books on a shelf and verify that there are 2
{
response, err := b.ListBooks(1)
if err != nil {
t.Log("list books failed")
t.Fail()
}
if len(response.OK.Books) != 2 {
t.Log("list books failed")
t.Fail()
}
}
// delete a book
{
err := b.DeleteBook(1, 2)
if err != nil {
t.Log("delete book failed")
t.Fail()
}
}
// list the books on a shelf and verify that is only 1
{
response, err := b.ListBooks(1)
if err != nil {
t.Log("list books failed")
t.Fail()
}
if len(response.OK.Books) != 1 {
t.Log("list books failed")
t.Fail()
}
}
// verify the handling of a badly-formed request
{
req, err := http.NewRequest("POST", service+"/shelves", strings.NewReader(""))
if err != nil {
t.Log("bad request failed")
return
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return
}
// we expect a 400 (Bad Request) code
if resp.StatusCode != 400 {
t.Log("bad request failed")
t.Fail()
}
return
}
}

View file

@ -1,9 +0,0 @@
application: bookstore
version: 1
runtime: go
api_version: go1
handlers:
- url: /.*
script: _go_app
- url: /
static_dir: static

View file

@ -1,27 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
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.
*/
package main
import (
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v2.0/bookstore/bookstore"
)
// init() is called when the package is loaded
// this allows this app to be trivially deployed to Google App Engine, which does not call main()
func init() {
bookstore.Initialize(NewService())
}

View file

@ -1,34 +0,0 @@
// +build !appengine
// This file is omitted when the app is built for Google App Engine
/*
Copyright 2017 Google Inc. All Rights Reserved.
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.
*/
package main
import (
"log"
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v2.0/bookstore/bookstore"
)
func main() {
err := bookstore.ServeHTTP(":8080")
if err != nil {
log.Printf("%v", err)
}
}

View file

@ -1,195 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
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.
*/
package main
import (
"errors"
"fmt"
"net/http"
"sync"
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v2.0/bookstore/bookstore"
)
//
// The Service type implements a bookstore service.
// All objects are managed in an in-memory non-persistent store.
//
type Service struct {
// shelves are stored in a map keyed by shelf id
// books are stored in a two level map, keyed first by shelf id and then by book id
Shelves map[int64]*bookstore.Shelf
Books map[int64]map[int64]*bookstore.Book
LastShelfID int64 // the id of the last shelf that was added
LastBookID int64 // the id of the last book that was added
Mutex sync.Mutex // global mutex to synchronize service access
}
func NewService() *Service {
return &Service{
Shelves: make(map[int64]*bookstore.Shelf),
Books: make(map[int64]map[int64]*bookstore.Book),
}
}
func (service *Service) ListShelves(responses *bookstore.ListShelvesResponses) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// copy shelf ids from Shelves map keys
shelves := make([]bookstore.Shelf, 0, len(service.Shelves))
for _, shelf := range service.Shelves {
shelves = append(shelves, *shelf)
}
response := &bookstore.ListShelvesResponse{}
response.Shelves = shelves
(*responses).OK = response
return err
}
func (service *Service) CreateShelf(parameters *bookstore.CreateShelfParameters, responses *bookstore.CreateShelfResponses) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// assign an id and name to a shelf and add it to the Shelves map.
shelf := parameters.Shelf
service.LastShelfID++
sid := service.LastShelfID
shelf.Name = fmt.Sprintf("shelves/%d", sid)
service.Shelves[sid] = &shelf
(*responses).OK = &shelf
return err
}
func (service *Service) DeleteShelves() (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// delete everything by reinitializing the Shelves and Books maps.
service.Shelves = make(map[int64]*bookstore.Shelf)
service.Books = make(map[int64]map[int64]*bookstore.Book)
service.LastShelfID = 0
service.LastBookID = 0
return nil
}
func (service *Service) GetShelf(parameters *bookstore.GetShelfParameters, responses *bookstore.GetShelfResponses) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// look up a shelf from the Shelves map.
shelf, err := service.getShelf(parameters.Shelf)
if err != nil {
(*responses).Default = &bookstore.Error{Code: int32(http.StatusNotFound), Message: err.Error()}
return nil
} else {
(*responses).OK = shelf
return nil
}
}
func (service *Service) DeleteShelf(parameters *bookstore.DeleteShelfParameters) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// delete a shelf by removing the shelf from the Shelves map and the associated books from the Books map.
delete(service.Shelves, parameters.Shelf)
delete(service.Books, parameters.Shelf)
return nil
}
func (service *Service) ListBooks(parameters *bookstore.ListBooksParameters, responses *bookstore.ListBooksResponses) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// list the books in a shelf
_, err = service.getShelf(parameters.Shelf)
if err != nil {
(*responses).Default = &bookstore.Error{Code: int32(http.StatusNotFound), Message: err.Error()}
return nil
}
shelfBooks := service.Books[parameters.Shelf]
books := make([]bookstore.Book, 0, len(shelfBooks))
for _, book := range shelfBooks {
books = append(books, *book)
}
response := &bookstore.ListBooksResponse{}
response.Books = books
(*responses).OK = response
return nil
}
func (service *Service) CreateBook(parameters *bookstore.CreateBookParameters, responses *bookstore.CreateBookResponses) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// return "not found" if the shelf doesn't exist
shelf, err := service.getShelf(parameters.Shelf)
if err != nil {
(*responses).Default = &bookstore.Error{Code: int32(http.StatusNotFound), Message: err.Error()}
return nil
}
// assign an id and name to a book and add it to the Books map.
service.LastBookID++
bid := service.LastBookID
book := parameters.Book
book.Name = fmt.Sprintf("%s/books/%d", shelf.Name, bid)
if service.Books[parameters.Shelf] == nil {
service.Books[parameters.Shelf] = make(map[int64]*bookstore.Book)
}
service.Books[parameters.Shelf][bid] = &book
(*responses).OK = &book
return err
}
func (service *Service) GetBook(parameters *bookstore.GetBookParameters, responses *bookstore.GetBookResponses) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// get a book from the Books map
book, err := service.getBook(parameters.Shelf, parameters.Book)
if err != nil {
(*responses).Default = &bookstore.Error{Code: int32(http.StatusNotFound), Message: err.Error()}
} else {
(*responses).OK = book
}
return nil
}
func (service *Service) DeleteBook(parameters *bookstore.DeleteBookParameters) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// delete a book by removing the book from the Books map.
delete(service.Books[parameters.Shelf], parameters.Book)
return nil
}
// internal helpers
func (service *Service) getShelf(sid int64) (shelf *bookstore.Shelf, err error) {
shelf, ok := service.Shelves[sid]
if !ok {
return nil, errors.New(fmt.Sprintf("Couldn't find shelf %d", sid))
} else {
return shelf, nil
}
}
func (service *Service) getBook(sid int64, bid int64) (book *bookstore.Book, err error) {
_, err = service.getShelf(sid)
if err != nil {
return nil, err
}
book, ok := service.Books[sid][bid]
if !ok {
return nil, errors.New(fmt.Sprintf("Couldn't find book %d on shelf %d", bid, sid))
} else {
return book, nil
}
}

View file

@ -1,20 +0,0 @@
build:
go get golang.org/x/tools/cmd/goimports
go install github.com/googleapis/gnostic
go install github.com/googleapis/gnostic/plugins/gnostic-go-generator
rm -f $(GOPATH)/bin/gnostic-go-client $(GOPATH)/bin/gnostic-go-server
ln -s $(GOPATH)/bin/gnostic-go-generator $(GOPATH)/bin/gnostic-go-client
ln -s $(GOPATH)/bin/gnostic-go-generator $(GOPATH)/bin/gnostic-go-server
all: build
gnostic sample.yaml --go-generator-out=sample
clean:
rm -rf sample service/service
test: all
killall service; true # ignore errors due to no matching processes
cd service; go get .; go build; ./service &
go test
killall service

View file

@ -1,24 +0,0 @@
# API Sample
This directory contains an OpenAPI description of a sample API
that exercises various OpenAPI features.
Use this example to try the `gnostic-go-generator` plugin, which implements
`gnostic-go-client` and `gnostic-go-server` for generating API client and
server code, respectively.
Run "make all" to build and install `gnostic` and the Go plugins.
It will generate both client and server code. The API client and
server code will be in the `sample` package.
The `service` directory contains additional code that completes the server.
To build and run the service, `cd service` and do the following:
go get .
go build
./service &
To test the service with the generated client, go back up to the top-level
directory and run `go test`. The test in `sample_test.go` uses client
code generated in `sample` to verify the service.

View file

@ -1,67 +0,0 @@
swagger: '2.0'
schemes:
- https
host: sample.io
basePath: /
info:
title: sample.io
version: '1.0'
consumes:
- application/json
produces:
- application/json;charset=UTF-8
securityDefinitions:
api_key:
in: query
name: key
type: apiKey
paths:
/sample/{id}:
get:
operationId: "GetSample"
parameters:
- description: identifier
in: path
name: id
required: true
type: string
responses:
'200':
description: sample response
schema:
$ref: '#/definitions/Sample'
'401':
description: User doesn't have a valid session.
schema:
$ref: '#/definitions/APIError'
'404':
description: Unable to find supplied extractor ID.
schema:
$ref: '#/definitions/APIError'
security:
- api_key: []
summary: Get a sample response
tags:
- sample
- demo
definitions:
APIError:
properties:
code:
description: Internal error code
format: int
type: integer
message:
description: A message containing a brief description of the error
type: string
type: object
Sample:
properties:
id:
type: string
thing:
type: object
count:
format: int32
type: integer
type: object

View file

@ -1,19 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
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.
*/
// Package sample exists to allow this repo to work with recursive go get.
// It will be filled in with auto generated code.
package sample

View file

@ -1,68 +0,0 @@
/*
Copyright 2018 Google Inc. All Rights Reserved.
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.
*/
package test
import (
"fmt"
"net/http"
"strings"
"testing"
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v2.0/sample/sample"
)
const service = "http://localhost:8080"
func TestSample(t *testing.T) {
// create a client
s := sample.NewClient(service, nil)
// verify a sample request
{
message := "hello world"
response, err := s.GetSample(message)
if err != nil {
t.Log("get sample failed")
t.Fail()
}
if response.OK.Id != message || response.OK.Count != int32(len(message)) {
t.Log(fmt.Sprintf("get sample received %+v", response.OK))
t.Fail()
}
if (response == nil) || (response.OK == nil) {
t.Log(fmt.Sprintf("get sample failed %+v", response.OK))
t.Fail()
}
}
// verify the handling of an invalid request
{
req, err := http.NewRequest("GET", service+"/unsupported", strings.NewReader(""))
if err != nil {
t.Log("bad request failed")
return
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return
}
// we expect a 404 (Not Found) code
if resp.StatusCode != 404 {
t.Log("bad request failed")
t.Fail()
}
return
}
}

View file

@ -1,9 +0,0 @@
application: sample
version: 1
runtime: go
api_version: go1
handlers:
- url: /.*
script: _go_app
- url: /
static_dir: static

View file

@ -1,27 +0,0 @@
/*
Copyright 2018 Google Inc. All Rights Reserved.
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.
*/
package main
import (
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v2.0/sample/sample"
)
// init() is called when the package is loaded
// this allows this app to be trivially deployed to Google App Engine, which does not call main()
func init() {
sample.Initialize(NewService())
}

View file

@ -1,34 +0,0 @@
// +build !appengine
// This file is omitted when the app is built for Google App Engine
/*
Copyright 2018 Google Inc. All Rights Reserved.
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.
*/
package main
import (
"log"
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v2.0/sample/sample"
)
func main() {
err := sample.ServeHTTP(":8080")
if err != nil {
log.Printf("%v", err)
}
}

View file

@ -1,38 +0,0 @@
/*
Copyright 2018 Google Inc. All Rights Reserved.
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.
*/
package main
import (
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v2.0/sample/sample"
)
//
// The Service type implements a sample service.
//
type Service struct{}
func NewService() *Service {
return &Service{}
}
func (service *Service) GetSample(parameters *sample.GetSampleParameters, responses *sample.GetSampleResponses) (err error) {
(*responses).OK = &sample.Sample{
Id: parameters.Id,
Thing: map[string]interface{}{"thing": 123},
Count: int32(len(parameters.Id))}
return err
}

View file

@ -1,3 +0,0 @@
all:
gnostic swagger.json --go-client-out=xkcd
go install

View file

@ -1,23 +0,0 @@
package main
import (
"fmt"
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v2.0/xkcd/xkcd"
)
func main() {
c := xkcd.NewClient("http://xkcd.com")
comic, err := c.Get_info_0_json()
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", comic)
comic, err = c.Get_comicId_info_0_json(1800)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", comic)
}

View file

@ -1,111 +0,0 @@
{
"swagger": "2.0",
"schemes": [
"http"
],
"host": "xkcd.com",
"basePath": "/",
"info": {
"description": "Webcomic of romance, sarcasm, math, and language.",
"title": "XKCD",
"version": "1.0.0",
"x-apisguru-categories": [
"media"
],
"x-logo": {
"url": "https://api.apis.guru/v2/cache/logo/http_imgs.xkcd.com_static_terrible_small_logo.png"
},
"x-origin": {
"format": "swagger",
"url": "https://raw.githubusercontent.com/APIs-guru/unofficial_openapi_specs/master/xkcd.com/1.0.0/swagger.yaml",
"version": "2.0"
},
"x-preferred": true,
"x-providerName": "xkcd.com",
"x-tags": [
"humor",
"comics"
],
"x-unofficialSpec": true
},
"externalDocs": {
"url": "https://xkcd.com/json.html"
},
"securityDefinitions": {},
"paths": {
"/info.0.json": {
"get": {
"description": "Fetch current comic and metadata.\n",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/comic"
}
}
}
}
},
"/{comicId}/info.0.json": {
"get": {
"description": "Fetch comics and metadata by comic id.\n",
"parameters": [
{
"in": "path",
"name": "comicId",
"required": true,
"type": "number"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/comic"
}
}
}
}
}
},
"definitions": {
"comic": {
"properties": {
"alt": {
"type": "string"
},
"day": {
"type": "string"
},
"img": {
"type": "string"
},
"link": {
"type": "string"
},
"month": {
"type": "string"
},
"news": {
"type": "string"
},
"num": {
"type": "number"
},
"safe_title": {
"type": "string"
},
"title": {
"type": "string"
},
"transcript": {
"type": "string"
},
"year": {
"type": "string"
}
},
"type": "object"
}
}
}

View file

@ -1,19 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
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.
*/
// Package xkcd exists to allow this repo to work with recursive go get.
// It will be filled in with auto generated code.
package xkcd

View file

@ -1,20 +0,0 @@
build:
go get golang.org/x/tools/cmd/goimports
go install github.com/googleapis/gnostic
go install github.com/googleapis/gnostic/plugins/gnostic-go-generator
rm -f $(GOPATH)/bin/gnostic-go-client $(GOPATH)/bin/gnostic-go-server
ln -s $(GOPATH)/bin/gnostic-go-generator $(GOPATH)/bin/gnostic-go-client
ln -s $(GOPATH)/bin/gnostic-go-generator $(GOPATH)/bin/gnostic-go-server
all: build
gnostic bookstore.json --go-generator-out=bookstore
clean:
rm -rf bookstore bookstore.text service/service
test: all
killall service; true # ignore errors due to no matching processes
cd service; go get .; go build; ./service &
go test
killall service

View file

@ -1,23 +0,0 @@
# Bookstore Example
This directory contains an OpenAPI description of a simple bookstore API.
Use this example to try the `gnostic-go-generator` plugin, which implements
`gnostic-go-client` and `gnostic-go-server` for generating API client and
server code, respectively.
Run "make all" to build and install `gnostic` and the Go plugins.
It will generate both client and server code. The API client and
server code will be in the `bookstore` package.
The `service` directory contains additional code that completes the server.
To build and run the service, `cd service` and do the following:
go get .
go build
./service &
To test the service with the generated client, go back up to the top-level
directory and run `go test`. The test in `bookstore_test.go` uses client
code generated in `bookstore` to verify the service.

View file

@ -1,392 +0,0 @@
{
"openapi": "3.0.0",
"servers": [
{
"url": "https://generated-bookstore.appspot.com/"
}
],
"info": {
"description": "A simple Bookstore API example.",
"title": "Bookstore",
"version": "1.0.0"
},
"paths": {
"/shelves": {
"get": {
"description": "Return all shelves in the bookstore.",
"operationId": "listShelves",
"responses": {
"200": {
"description": "List of shelves in the bookstore.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/listShelvesResponse"
}
}
}
}
},
"security": []
},
"post": {
"description": "Create a new shelf in the bookstore.",
"operationId": "createShelf",
"responses": {
"200": {
"description": "A newly created shelf resource.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/shelf"
}
}
}
}
},
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/shelf"
}
}
},
"description": "A shelf resource to create.",
"required": true
}
},
"delete": {
"description": "Delete all shelves.",
"operationId": "deleteShelves",
"responses": {
"default": {
"description": "An empty response body."
}
}
}
},
"/shelves/{shelf}": {
"get": {
"description": "Get a single shelf resource with the given ID.",
"operationId": "getShelf",
"parameters": [
{
"description": "ID of the shelf to get.",
"in": "path",
"name": "shelf",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"200": {
"description": "A shelf resource.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/shelf"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
}
}
}
}
}
},
"delete": {
"description": "Delete a single shelf with the given ID.",
"operationId": "deleteShelf",
"parameters": [
{
"description": "ID of the shelf to delete.",
"in": "path",
"name": "shelf",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"default": {
"description": "An empty response body."
}
}
}
},
"/shelves/{shelf}/books": {
"get": {
"description": "Return all books in a shelf with the given ID.",
"operationId": "listBooks",
"parameters": [
{
"description": "ID of the shelf whose books should be returned.",
"in": "path",
"name": "shelf",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"200": {
"description": "List of books on the specified shelf.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/listBooksResponse"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
}
}
}
}
}
},
"post": {
"description": "Create a new book on the shelf.",
"operationId": "createBook",
"parameters": [
{
"description": "ID of the shelf where the book should be created.",
"in": "path",
"name": "shelf",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"200": {
"description": "A newly created book resource.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/book"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
}
}
}
}
},
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/book"
}
}
},
"description": "Book to create.",
"required": true
}
}
},
"/shelves/{shelf}/books/{book}": {
"get": {
"description": "Get a single book with a given ID from a shelf.",
"operationId": "getBook",
"parameters": [
{
"description": "ID of the shelf from which to get the book.",
"in": "path",
"name": "shelf",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
},
{
"description": "ID of the book to get from the shelf.",
"in": "path",
"name": "book",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"200": {
"description": "A book resource.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/book"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
}
}
}
}
}
},
"delete": {
"description": "Delete a single book with a given ID from a shelf.",
"operationId": "deleteBook",
"parameters": [
{
"description": "ID of the shelf from which to delete the book.",
"in": "path",
"name": "shelf",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
},
{
"description": "ID of the book to delete from the shelf.",
"in": "path",
"name": "book",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"default": {
"description": "An empty response body."
}
}
}
}
},
"security": [
{
"api_key": []
}
],
"components": {
"schemas": {
"book": {
"properties": {
"author": {
"type": "string"
},
"name": {
"type": "string"
},
"title": {
"type": "string"
}
},
"required": [
"name",
"author",
"title"
],
"type": "object"
},
"listBooksResponse": {
"properties": {
"books": {
"items": {
"$ref": "#/components/schemas/book"
},
"type": "array"
}
},
"required": [
"books"
],
"type": "object"
},
"listShelvesResponse": {
"properties": {
"shelves": {
"items": {
"$ref": "#/components/schemas/shelf"
},
"type": "array"
}
},
"type": "object"
},
"shelf": {
"properties": {
"name": {
"type": "string"
},
"theme": {
"type": "string"
}
},
"required": [
"name",
"theme"
],
"type": "object"
},
"error": {
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
},
"type": "object"
}
},
"securitySchemes": {
"api_key": {
"in": "query",
"name": "key",
"type": "apiKey"
}
}
}
}

View file

@ -1,19 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
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.
*/
// Package bookstore exists to allow this repo to work with recursive go get.
// It will be filled in with auto generated code.
package bookstore

View file

@ -1,239 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
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.
*/
package test
import (
"fmt"
"net/http"
"strings"
"testing"
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v3.0/bookstore/bookstore"
)
const service = "http://localhost:8080"
//const service = "http://generated-bookstore.appspot.com"
func TestBookstore(t *testing.T) {
// create a client
b := bookstore.NewClient(service, nil)
// reset the service by deleting all shelves
{
err := b.DeleteShelves()
if err != nil {
t.Log("delete shelves failed")
t.Fail()
}
}
// verify that the service has no shelves
{
response, err := b.ListShelves()
if err != nil {
t.Log("list shelves failed")
t.Fail()
}
if (response == nil) || (response.OK == nil) || (response.OK.Shelves != nil) {
t.Log(fmt.Sprintf("list shelves failed %+v", response.OK))
t.Log(fmt.Sprintf("list shelves failed len=%d", len(response.OK.Shelves)))
t.Fail()
}
}
// attempting to get a shelf should return an error
{
response, err := b.GetShelf(1)
if err == nil {
t.Logf("get shelf failed to return an error (%+v)", response.OK)
t.Fail()
}
}
// attempting to get a book should return an error
{
response, err := b.GetBook(1, 2)
if err == nil {
t.Logf("get book failed to return an error (%+v)", response.OK)
t.Fail()
}
}
// add a shelf
{
var shelf bookstore.Shelf
shelf.Theme = "mysteries"
response, err := b.CreateShelf(shelf)
if err != nil {
t.Log("create shelf mysteries failed")
t.Fail()
}
if (response.OK.Name != "shelves/1") ||
(response.OK.Theme != "mysteries") {
t.Log("create shelf mysteries failed")
t.Fail()
}
}
// add another shelf
{
var shelf bookstore.Shelf
shelf.Theme = "comedies"
response, err := b.CreateShelf(shelf)
if err != nil {
t.Log("create shelf comedies failed")
t.Fail()
}
if (response.OK.Name != "shelves/2") ||
(response.OK.Theme != "comedies") {
t.Log("create shelf comedies failed")
t.Fail()
}
}
// get the first shelf that was added
{
response, err := b.GetShelf(1)
if err != nil {
t.Log("get shelf mysteries failed")
t.Fail()
}
if (response.OK.Name != "shelves/1") ||
(response.OK.Theme != "mysteries") {
t.Log("get shelf mysteries failed")
t.Fail()
}
}
// list shelves and verify that there are 2
{
response, err := b.ListShelves()
if err != nil {
t.Log("list shelves failed")
t.Fail()
}
if len(response.OK.Shelves) != 2 {
t.Log("list shelves failed")
t.Fail()
}
}
// delete a shelf
{
err := b.DeleteShelf(2)
if err != nil {
t.Log("delete shelf failed")
t.Fail()
}
}
// list shelves and verify that there is only 1
{
response, err := b.ListShelves()
if err != nil {
t.Log("list shelves failed")
t.Fail()
}
if len(response.OK.Shelves) != 1 {
t.Log("list shelves failed")
t.Fail()
}
}
// list books on a shelf, verify that there are none
{
response, err := b.ListBooks(1)
if err != nil {
t.Log("list books failed")
t.Fail()
}
if len(response.OK.Books) != 0 {
t.Log("list books failed")
t.Fail()
}
}
// create a book
{
var book bookstore.Book
book.Author = "Agatha Christie"
book.Title = "And Then There Were None"
_, err := b.CreateBook(1, book)
if err != nil {
t.Log("create book failed")
t.Fail()
}
}
// create another book
{
var book bookstore.Book
book.Author = "Agatha Christie"
book.Title = "Murder on the Orient Express"
_, err := b.CreateBook(1, book)
if err != nil {
t.Log("create book failed")
t.Fail()
}
}
// get the first book that was added
{
_, err := b.GetBook(1, 1)
if err != nil {
t.Log("get book failed")
t.Fail()
}
}
// list the books on a shelf and verify that there are 2
{
response, err := b.ListBooks(1)
if err != nil {
t.Log("list books failed")
t.Fail()
}
if len(response.OK.Books) != 2 {
t.Log("list books failed")
t.Fail()
}
}
// delete a book
{
err := b.DeleteBook(1, 2)
if err != nil {
t.Log("delete book failed")
t.Fail()
}
}
// list the books on a shelf and verify that is only 1
{
response, err := b.ListBooks(1)
if err != nil {
t.Log("list books failed")
t.Fail()
}
if len(response.OK.Books) != 1 {
t.Log("list books failed")
t.Fail()
}
}
// verify the handling of a badly-formed request
{
req, err := http.NewRequest("POST", service+"/shelves", strings.NewReader(""))
if err != nil {
t.Log("bad request failed")
return
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return
}
// we expect a 400 (Bad Request) code
if resp.StatusCode != 400 {
t.Log("bad request failed")
t.Fail()
}
return
}
}

View file

@ -1,9 +0,0 @@
application: bookstore
version: 1
runtime: go
api_version: go1
handlers:
- url: /.*
script: _go_app
- url: /
static_dir: static

View file

@ -1,27 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
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.
*/
package main
import (
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v3.0/bookstore/bookstore"
)
// init() is called when the package is loaded
// this allows this app to be trivially deployed to Google App Engine, which does not call main()
func init() {
bookstore.Initialize(NewService())
}

View file

@ -1,34 +0,0 @@
// +build !appengine
// This file is omitted when the app is built for Google App Engine
/*
Copyright 2017 Google Inc. All Rights Reserved.
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.
*/
package main
import (
"log"
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v3.0/bookstore/bookstore"
)
func main() {
err := bookstore.ServeHTTP(":8080")
if err != nil {
log.Printf("%v", err)
}
}

View file

@ -1,195 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
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.
*/
package main
import (
"errors"
"fmt"
"net/http"
"sync"
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v3.0/bookstore/bookstore"
)
//
// The Service type implements a bookstore service.
// All objects are managed in an in-memory non-persistent store.
//
type Service struct {
// shelves are stored in a map keyed by shelf id
// books are stored in a two level map, keyed first by shelf id and then by book id
Shelves map[int64]*bookstore.Shelf
Books map[int64]map[int64]*bookstore.Book
LastShelfID int64 // the id of the last shelf that was added
LastBookID int64 // the id of the last book that was added
Mutex sync.Mutex // global mutex to synchronize service access
}
func NewService() *Service {
return &Service{
Shelves: make(map[int64]*bookstore.Shelf),
Books: make(map[int64]map[int64]*bookstore.Book),
}
}
func (service *Service) ListShelves(responses *bookstore.ListShelvesResponses) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// copy shelf ids from Shelves map keys
shelves := make([]bookstore.Shelf, 0, len(service.Shelves))
for _, shelf := range service.Shelves {
shelves = append(shelves, *shelf)
}
response := &bookstore.ListShelvesResponse{}
response.Shelves = shelves
(*responses).OK = response
return err
}
func (service *Service) CreateShelf(parameters *bookstore.CreateShelfParameters, responses *bookstore.CreateShelfResponses) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// assign an id and name to a shelf and add it to the Shelves map.
shelf := parameters.Shelf
service.LastShelfID++
sid := service.LastShelfID
shelf.Name = fmt.Sprintf("shelves/%d", sid)
service.Shelves[sid] = &shelf
(*responses).OK = &shelf
return err
}
func (service *Service) DeleteShelves() (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// delete everything by reinitializing the Shelves and Books maps.
service.Shelves = make(map[int64]*bookstore.Shelf)
service.Books = make(map[int64]map[int64]*bookstore.Book)
service.LastShelfID = 0
service.LastBookID = 0
return nil
}
func (service *Service) GetShelf(parameters *bookstore.GetShelfParameters, responses *bookstore.GetShelfResponses) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// look up a shelf from the Shelves map.
shelf, err := service.getShelf(parameters.Shelf)
if err != nil {
(*responses).Default = &bookstore.Error{Code: int32(http.StatusNotFound), Message: err.Error()}
return nil
} else {
(*responses).OK = shelf
return nil
}
}
func (service *Service) DeleteShelf(parameters *bookstore.DeleteShelfParameters) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// delete a shelf by removing the shelf from the Shelves map and the associated books from the Books map.
delete(service.Shelves, parameters.Shelf)
delete(service.Books, parameters.Shelf)
return nil
}
func (service *Service) ListBooks(parameters *bookstore.ListBooksParameters, responses *bookstore.ListBooksResponses) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// list the books in a shelf
_, err = service.getShelf(parameters.Shelf)
if err != nil {
(*responses).Default = &bookstore.Error{Code: int32(http.StatusNotFound), Message: err.Error()}
return nil
}
shelfBooks := service.Books[parameters.Shelf]
books := make([]bookstore.Book, 0, len(shelfBooks))
for _, book := range shelfBooks {
books = append(books, *book)
}
response := &bookstore.ListBooksResponse{}
response.Books = books
(*responses).OK = response
return nil
}
func (service *Service) CreateBook(parameters *bookstore.CreateBookParameters, responses *bookstore.CreateBookResponses) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// return "not found" if the shelf doesn't exist
shelf, err := service.getShelf(parameters.Shelf)
if err != nil {
(*responses).Default = &bookstore.Error{Code: int32(http.StatusNotFound), Message: err.Error()}
return nil
}
// assign an id and name to a book and add it to the Books map.
service.LastBookID++
bid := service.LastBookID
book := parameters.Book
book.Name = fmt.Sprintf("%s/books/%d", shelf.Name, bid)
if service.Books[parameters.Shelf] == nil {
service.Books[parameters.Shelf] = make(map[int64]*bookstore.Book)
}
service.Books[parameters.Shelf][bid] = &book
(*responses).OK = &book
return err
}
func (service *Service) GetBook(parameters *bookstore.GetBookParameters, responses *bookstore.GetBookResponses) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// get a book from the Books map
book, err := service.getBook(parameters.Shelf, parameters.Book)
if err != nil {
(*responses).Default = &bookstore.Error{Code: int32(http.StatusNotFound), Message: err.Error()}
} else {
(*responses).OK = book
}
return nil
}
func (service *Service) DeleteBook(parameters *bookstore.DeleteBookParameters) (err error) {
service.Mutex.Lock()
defer service.Mutex.Unlock()
// delete a book by removing the book from the Books map.
delete(service.Books[parameters.Shelf], parameters.Book)
return nil
}
// internal helpers
func (service *Service) getShelf(sid int64) (shelf *bookstore.Shelf, err error) {
shelf, ok := service.Shelves[sid]
if !ok {
return nil, errors.New(fmt.Sprintf("Couldn't find shelf %d", sid))
} else {
return shelf, nil
}
}
func (service *Service) getBook(sid int64, bid int64) (book *bookstore.Book, err error) {
_, err = service.getShelf(sid)
if err != nil {
return nil, err
}
book, ok := service.Books[sid][bid]
if !ok {
return nil, errors.New(fmt.Sprintf("Couldn't find book %d on shelf %d", bid, sid))
} else {
return book, nil
}
}

View file

@ -1,26 +0,0 @@
# urlshortener sample client
## Steps to run:
1. Generate the OpenAPI 3.0 description using `disco` (in the `gnostic/apps` directory).
disco get urlshortener --openapi3
2. (optional) View the JSON OpenAPI 3.0 description.
gnostic openapi3-urlshortener-v1.pb --json-out=-
3. Generate the urlshortener client.
gnostic openapi3-urlshortener-v1.pb --go-client-out=urlshortener
4. Build the client.
go install
5. Download `client_secrets.json` from the Google Cloud Developer Console.
6. Run the client
urlshortener

View file

@ -1,62 +0,0 @@
package main
import (
"fmt"
"log"
"github.com/docopt/docopt-go"
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/googleauth"
"github.com/googleapis/gnostic/plugins/gnostic-go-generator/examples/v3.0/urlshortener/urlshortener"
)
func main() {
usage := `
Usage:
urlshortener get <url>
urlshortener list
urlshortener insert <url>
`
arguments, err := docopt.Parse(usage, nil, false, "URL Shortener 1.0", false)
if err != nil {
log.Fatalf("%+v", err)
}
path := "https://www.googleapis.com/urlshortener/v1" // this should be generated
client, err := googleauth.NewOAuth2Client("https://www.googleapis.com/auth/urlshortener")
if err != nil {
log.Fatalf("Error building OAuth client: %v", err)
}
c := urlshortener.NewClient(path, client)
// get
if arguments["get"].(bool) {
response, err := c.Urlshortener_Url_Get("FULL", arguments["<url>"].(string))
if err != nil {
log.Fatalf("%+v", err)
}
fmt.Println(response.Default.LongUrl)
}
// list
if arguments["list"].(bool) {
response, err := c.Urlshortener_Url_List("", "")
if err != nil {
log.Fatalf("%+v", err)
}
for _, item := range response.Default.Items {
fmt.Printf("%-40s %s\n", item.Id, item.LongUrl)
}
}
// insert
if arguments["insert"].(bool) {
var url urlshortener.Url
url.LongUrl = arguments["<url>"].(string)
response, err := c.Urlshortener_Url_Insert(url)
if err != nil {
log.Fatalf("%+v", err)
}
fmt.Printf("%+v\n", response.Default.Id)
}
}

View file

@ -1,19 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
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.
*/
// Package urlshortener exists to allow this repo to work with recursive go get.
// It will be filled in with auto generated code.
package urlshortener

View file

@ -1,50 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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.
package main
import (
"io/ioutil"
"log"
"os"
"os/exec"
"strings"
)
// Run goimports to format and update imports statements in generated code.
func goimports(filename string, inputBytes []byte) (outputBytes []byte, err error) {
if false {
return inputBytes, nil
}
cmd := exec.Command(os.Getenv("GOPATH") + "/bin/goimports")
input, _ := cmd.StdinPipe()
output, _ := cmd.StdoutPipe()
cmderr, _ := cmd.StderrPipe()
err = cmd.Start()
if err != nil {
return
}
input.Write(inputBytes)
input.Close()
outputBytes, _ = ioutil.ReadAll(output)
errors, _ := ioutil.ReadAll(cmderr)
if len(errors) > 0 {
errors := strings.Replace(string(errors), "<standard input>", filename, -1)
log.Printf("Syntax errors in generated code:\n%s", errors)
return inputBytes, nil
}
return
}

View file

@ -1,123 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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.
package main
import (
surface "github.com/googleapis/gnostic/surface"
"strings"
"unicode"
)
type GoLanguageModel struct{}
func NewGoLanguageModel() *GoLanguageModel {
return &GoLanguageModel{}
}
// Prepare sets language-specific properties for all types and methods.
func (language *GoLanguageModel) Prepare(model *surface.Model) {
for _, t := range model.Types {
// determine the type used for Go language implementation of the type
t.TypeName = strings.Title(filteredTypeName(t.Name))
for _, f := range t.Fields {
f.FieldName = goFieldName(f.Name)
f.ParameterName = goParameterName(f.Name)
switch f.Type {
case "number":
f.NativeType = "int"
case "integer":
switch f.Format {
case "int32":
f.NativeType = "int32"
case "int64":
f.NativeType = "int64"
default:
f.NativeType = "int64"
}
case "object":
f.NativeType = "interface{}"
case "string":
f.NativeType = "string"
default:
f.NativeType = strings.Title(f.Type)
}
}
}
for _, m := range model.Methods {
m.HandlerName = "Handle" + m.Name
m.ProcessorName = m.Name
m.ClientName = m.Name
}
}
func goParameterName(name string) string {
// lowercase first letter
a := []rune(name)
a[0] = unicode.ToLower(a[0])
name = string(a)
// replace dots with underscores
name = strings.Replace(name, ".", "_", -1)
// replaces dashes with underscores
name = strings.Replace(name, "-", "_", -1)
// avoid reserved words
if name == "type" {
return "myType"
}
return name
}
func goFieldName(name string) string {
name = strings.Replace(name, ".", "_", -1)
name = strings.Replace(name, "-", "_", -1)
name = snakeCaseToCamelCaseWithCapitalizedFirstLetter(name)
// avoid integers
if name == "200" {
return "OK"
} else if unicode.IsDigit(rune(name[0])) {
return "Code" + name
}
return name
}
func snakeCaseToCamelCaseWithCapitalizedFirstLetter(snakeCase string) (camelCase string) {
isToUpper := false
for _, runeValue := range snakeCase {
if isToUpper {
camelCase += strings.ToUpper(string(runeValue))
isToUpper = false
} else {
if runeValue == '_' {
isToUpper = true
} else {
camelCase += string(runeValue)
}
}
}
camelCase = strings.Title(camelCase)
return
}
func filteredTypeName(typeName string) (name string) {
// first take the last path segment
parts := strings.Split(typeName, "/")
name = parts[len(parts)-1]
// then take the last part of a dotted name
parts = strings.Split(name, ".")
name = parts[len(parts)-1]
return name
}

View file

@ -1,29 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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.
package main
import "bytes"
type LineWriter struct {
bytes.Buffer
}
func NewLineWriter() *LineWriter {
return &LineWriter{}
}
func (w *LineWriter) WriteLine(line string) {
w.WriteString(line + "\n")
}

View file

@ -1,76 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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.
// gnostic_go_generator is a sample Gnostic plugin that generates Go
// code that supports an API.
package main
import (
"encoding/json"
"errors"
"strings"
"github.com/golang/protobuf/proto"
plugins "github.com/googleapis/gnostic/plugins"
surface "github.com/googleapis/gnostic/surface"
)
// This is the main function for the code generation plugin.
func main() {
env, err := plugins.NewEnvironment()
env.RespondAndExitIfError(err)
packageName := env.Request.OutputPath
// Use the name used to run the plugin to decide which files to generate.
var files []string
switch {
case strings.Contains(env.Invocation, "gnostic-go-client"):
files = []string{"client.go", "types.go", "constants.go"}
case strings.Contains(env.Invocation, "gnostic-go-server"):
files = []string{"server.go", "provider.go", "types.go", "constants.go"}
default:
files = []string{"client.go", "server.go", "provider.go", "types.go", "constants.go"}
}
for _, model := range env.Request.Models {
switch model.TypeUrl {
case "surface.v1.Model":
surfaceModel := &surface.Model{}
err = proto.Unmarshal(model.Value, surfaceModel)
if err == nil {
// Customize the code surface model for Go
NewGoLanguageModel().Prepare(surfaceModel)
modelJSON, _ := json.MarshalIndent(surfaceModel, "", " ")
modelFile := &plugins.File{Name: "model.json", Data: modelJSON}
env.Response.Files = append(env.Response.Files, modelFile)
// Create the renderer.
renderer, err := NewServiceRenderer(surfaceModel)
renderer.Package = packageName
env.RespondAndExitIfError(err)
// Run the renderer to generate files and add them to the response object.
err = renderer.Render(env.Response, files)
env.RespondAndExitIfError(err)
// Return with success.
env.RespondAndExit()
}
}
}
err = errors.New("No generated code surface model is available.")
env.RespondAndExitIfError(err)
}

View file

@ -1,178 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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.
package main
import (
"strings"
surface "github.com/googleapis/gnostic/surface"
)
// ParameterList returns a string representation of a method's parameters
func ParameterList(parametersType *surface.Type) string {
result := ""
if parametersType != nil {
for _, field := range parametersType.Fields {
result += field.ParameterName + " " + field.NativeType + "," + "\n"
}
}
return result
}
func (renderer *Renderer) RenderClient() ([]byte, error) {
f := NewLineWriter()
f.WriteLine("// GENERATED FILE: DO NOT EDIT!")
f.WriteLine(``)
f.WriteLine("package " + renderer.Package)
// imports will be automatically added by goimports
f.WriteLine(`// Client represents an API client.`)
f.WriteLine(`type Client struct {`)
f.WriteLine(` service string`)
f.WriteLine(` APIKey string`)
f.WriteLine(` client *http.Client`)
f.WriteLine(`}`)
f.WriteLine(`// NewClient creates an API client.`)
f.WriteLine(`func NewClient(service string, c *http.Client) *Client {`)
f.WriteLine(` client := &Client{}`)
f.WriteLine(` client.service = service`)
f.WriteLine(` if c != nil {`)
f.WriteLine(` client.client = c`)
f.WriteLine(` } else {`)
f.WriteLine(` client.client = http.DefaultClient`)
f.WriteLine(` }`)
f.WriteLine(` return client`)
f.WriteLine(`}`)
for _, method := range renderer.Model.Methods {
parametersType := renderer.Model.TypeWithTypeName(method.ParametersTypeName)
responsesType := renderer.Model.TypeWithTypeName(method.ResponsesTypeName)
f.WriteLine(commentForText(method.Description))
f.WriteLine(`func (client *Client) ` + method.ClientName + `(`)
f.WriteLine(ParameterList(parametersType) + `) (`)
if method.ResponsesTypeName == "" {
f.WriteLine(`err error,`)
} else {
f.WriteLine(`response *` + method.ResponsesTypeName + `,`)
f.WriteLine(`err error,`)
}
f.WriteLine(` ) {`)
path := method.Path
path = strings.Replace(path, "{+", "{", -1)
f.WriteLine(`path := client.service + "` + path + `"`)
if parametersType != nil {
if parametersType.HasFieldWithPosition(surface.Position_PATH) {
for _, field := range parametersType.Fields {
if field.Position == surface.Position_PATH {
f.WriteLine(`path = strings.Replace(path, "{` + field.Name + `}", fmt.Sprintf("%v", ` +
field.ParameterName + `), 1)`)
}
}
}
if parametersType.HasFieldWithPosition(surface.Position_QUERY) {
f.WriteLine(`v := url.Values{}`)
for _, field := range parametersType.Fields {
if field.Position == surface.Position_QUERY {
if field.NativeType == "string" {
f.WriteLine(`if (` + field.ParameterName + ` != "") {`)
f.WriteLine(` v.Set("` + field.Name + `", ` + field.ParameterName + `)`)
f.WriteLine(`}`)
}
}
}
f.WriteLine(`if client.APIKey != "" {`)
f.WriteLine(` v.Set("key", client.APIKey)`)
f.WriteLine(`}`)
f.WriteLine(`if len(v) > 0 {`)
f.WriteLine(` path = path + "?" + v.Encode()`)
f.WriteLine(`}`)
}
}
if method.Method == "POST" {
f.WriteLine(`body := new(bytes.Buffer)`)
if parametersType != nil {
f.WriteLine(`json.NewEncoder(body).Encode(` + parametersType.FieldWithPosition(surface.Position_BODY).Name + `)`)
}
f.WriteLine(`req, err := http.NewRequest("` + method.Method + `", path, body)`)
f.WriteLine(`reqHeaders := make(http.Header)`)
f.WriteLine(`reqHeaders.Set("Content-Type", "application/json")`)
f.WriteLine(`req.Header = reqHeaders`)
} else {
f.WriteLine(`req, err := http.NewRequest("` + method.Method + `", path, nil)`)
}
f.WriteLine(`if err != nil {return}`)
f.WriteLine(`resp, err := client.client.Do(req)`)
f.WriteLine(`if err != nil {return}`)
f.WriteLine(`defer resp.Body.Close()`)
f.WriteLine(`if resp.StatusCode != 200 {`)
if responsesType != nil {
f.WriteLine(` return nil, errors.New(resp.Status)`)
} else {
f.WriteLine(` return errors.New(resp.Status)`)
}
f.WriteLine(`}`)
if responsesType != nil {
f.WriteLine(`response = &` + responsesType.Name + `{}`)
f.WriteLine(`switch {`)
// first handle everything that isn't "default"
for _, responseField := range responsesType.Fields {
if responseField.Name != "default" {
f.WriteLine(`case resp.StatusCode == ` + responseField.Name + `:`)
f.WriteLine(` body, err := ioutil.ReadAll(resp.Body)`)
f.WriteLine(` if err != nil {return nil, err}`)
f.WriteLine(` result := &` + responseField.NativeType + `{}`)
f.WriteLine(` err = json.Unmarshal(body, result)`)
f.WriteLine(` if err != nil {return nil, err}`)
f.WriteLine(` response.` + responseField.FieldName + ` = result`)
}
}
// then handle "default"
hasDefault := false
for _, responseField := range responsesType.Fields {
if responseField.Name == "default" {
hasDefault = true
f.WriteLine(`default:`)
f.WriteLine(` defer resp.Body.Close()`)
f.WriteLine(` body, err := ioutil.ReadAll(resp.Body)`)
f.WriteLine(` if err != nil {return nil, err}`)
f.WriteLine(` result := &` + responseField.NativeType + `{}`)
f.WriteLine(` err = json.Unmarshal(body, result)`)
f.WriteLine(` if err != nil {return nil, err}`)
f.WriteLine(` response.` + responseField.FieldName + ` = result`)
}
}
if !hasDefault {
f.WriteLine(`default:`)
f.WriteLine(` break`)
}
f.WriteLine(`}`) // close switch statement
}
f.WriteLine("return")
f.WriteLine("}")
}
return f.Bytes(), nil
}

View file

@ -1,30 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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.
package main
func (renderer *Renderer) RenderConstants() ([]byte, error) {
f := NewLineWriter()
f.WriteLine("// GENERATED FILE: DO NOT EDIT!")
f.WriteLine(``)
f.WriteLine("package " + renderer.Package)
f.WriteLine(``)
f.WriteLine(`// ServicePath is the base URL of the service.`)
f.WriteLine(`const ServicePath = "` + `"`)
f.WriteLine(``)
f.WriteLine(`// OAuthScopes lists the OAuth scopes required by the service.`)
f.WriteLine(`const OAuthScopes = "` + `"`)
return f.Bytes(), nil
}

View file

@ -1,64 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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.
package main
import (
"strings"
)
func (renderer *Renderer) RenderProvider() ([]byte, error) {
f := NewLineWriter()
f.WriteLine("// GENERATED FILE: DO NOT EDIT!\n")
f.WriteLine("package " + renderer.Package)
f.WriteLine(``)
f.WriteLine(`// To create a server, first write a class that implements this interface.`)
f.WriteLine(`// Then pass an instance of it to Initialize().`)
f.WriteLine(`type Provider interface {`)
for _, method := range renderer.Model.Methods {
parametersType := renderer.Model.TypeWithTypeName(method.ParametersTypeName)
responsesType := renderer.Model.TypeWithTypeName(method.ResponsesTypeName)
f.WriteLine(``)
f.WriteLine(commentForText(method.Description))
if parametersType != nil {
if responsesType != nil {
f.WriteLine(method.ProcessorName +
`(parameters *` + parametersType.Name +
`, responses *` + responsesType.Name + `) (err error)`)
} else {
f.WriteLine(method.ProcessorName + `(parameters *` + parametersType.Name + `) (err error)`)
}
} else {
if responsesType != nil {
f.WriteLine(method.ProcessorName + `(responses *` + responsesType.Name + `) (err error)`)
} else {
f.WriteLine(method.ProcessorName + `() (err error)`)
}
}
}
f.WriteLine(`}`)
return f.Bytes(), nil
}
func commentForText(text string) string {
result := ""
lines := strings.Split(text, "\n")
for i, line := range lines {
if i > 0 {
result += "\n"
}
result += "// " + line
}
return result
}

View file

@ -1,168 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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.
package main
import (
"fmt"
surface "github.com/googleapis/gnostic/surface"
)
func (renderer *Renderer) RenderServer() ([]byte, error) {
f := NewLineWriter()
f.WriteLine("// GENERATED FILE: DO NOT EDIT!")
f.WriteLine(``)
f.WriteLine("package " + renderer.Package)
f.WriteLine(``)
imports := []string{
"github.com/gorilla/mux",
"net/http",
}
f.WriteLine(``)
f.WriteLine(`import (`)
for _, imp := range imports {
f.WriteLine(`"` + imp + `"`)
}
f.WriteLine(`)`)
f.WriteLine(`func intValue(s string) (v int64) {`)
f.WriteLine(` v, _ = strconv.ParseInt(s, 10, 64)`)
f.WriteLine(` return v`)
f.WriteLine(`}`)
f.WriteLine(``)
f.WriteLine(`// This package-global variable holds the user-written Provider for API services.`)
f.WriteLine(`// See the Provider interface for details.`)
f.WriteLine(`var provider Provider`)
f.WriteLine(``)
f.WriteLine(`// These handlers serve API methods.`)
f.WriteLine(``)
for _, method := range renderer.Model.Methods {
parametersType := renderer.Model.TypeWithTypeName(method.ParametersTypeName)
responsesType := renderer.Model.TypeWithTypeName(method.ResponsesTypeName)
f.WriteLine(`// Handler`)
f.WriteLine(commentForText(method.Description))
f.WriteLine(`func ` + method.HandlerName + `(w http.ResponseWriter, r *http.Request) {`)
f.WriteLine(` var err error`)
if parametersType != nil {
f.WriteLine(`// instantiate the parameters structure`)
f.WriteLine(`parameters := &` + parametersType.Name + `{}`)
if method.Method == "POST" {
f.WriteLine(`// deserialize request from post data`)
f.WriteLine(`decoder := json.NewDecoder(r.Body)`)
f.WriteLine(`err = decoder.Decode(&parameters.` +
parametersType.FieldWithPosition(surface.Position_BODY).FieldName + `)`)
f.WriteLine(`if err != nil {`)
f.WriteLine(` w.WriteHeader(http.StatusBadRequest)`)
f.WriteLine(` w.Write([]byte(err.Error() + "\n"))`)
f.WriteLine(` return`)
f.WriteLine(`}`)
}
f.WriteLine(`// get request fields in path and query parameters`)
if parametersType.HasFieldWithPosition(surface.Position_PATH) {
f.WriteLine(`vars := mux.Vars(r)`)
}
if parametersType.HasFieldWithPosition(surface.Position_FORMDATA) {
f.WriteLine(`r.ParseForm()`)
}
for _, field := range parametersType.Fields {
if field.Position == surface.Position_PATH {
if field.Type == "string" {
f.WriteLine(fmt.Sprintf("// %+v", field))
f.WriteLine(`if value, ok := vars["` + field.Name + `"]; ok {`)
f.WriteLine(` parameters.` + field.FieldName + ` = value`)
f.WriteLine(`}`)
} else {
f.WriteLine(`if value, ok := vars["` + field.Name + `"]; ok {`)
f.WriteLine(` parameters.` + field.FieldName + ` = intValue(value)`)
f.WriteLine(`}`)
}
} else if field.Position == surface.Position_FORMDATA {
f.WriteLine(`if len(r.Form["` + field.Name + `"]) > 0 {`)
f.WriteLine(` parameters.` + field.FieldName + ` = intValue(r.Form["` + field.Name + `"][0])`)
f.WriteLine(`}`)
}
}
}
if responsesType != nil {
f.WriteLine(`// instantiate the responses structure`)
f.WriteLine(`responses := &` + method.ResponsesTypeName + `{}`)
}
f.WriteLine(`// call the service provider`)
callLine := `err = provider.` + method.ProcessorName
if parametersType != nil {
if responsesType != nil {
callLine += `(parameters, responses)`
} else {
callLine += `(parameters)`
}
} else {
if responsesType != nil {
callLine += `(responses)`
} else {
callLine += `()`
}
}
f.WriteLine(callLine)
f.WriteLine(`if err == nil {`)
if responsesType != nil {
if responsesType.HasFieldWithName("OK") {
f.WriteLine(`if responses.OK != nil {`)
f.WriteLine(` // write the normal response`)
f.WriteLine(` encoder := json.NewEncoder(w)`)
f.WriteLine(` encoder.Encode(responses.OK)`)
f.WriteLine(` return`)
f.WriteLine(`}`)
}
if responsesType.HasFieldWithName("Default") {
f.WriteLine(`if responses.Default != nil {`)
f.WriteLine(` // write the error response`)
if responsesType.FieldWithName("Default").ServiceType(renderer.Model).FieldWithName("Code") != nil {
f.WriteLine(` w.WriteHeader(int(responses.Default.Code))`)
}
f.WriteLine(` encoder := json.NewEncoder(w)`)
f.WriteLine(` encoder.Encode(responses.Default)`)
f.WriteLine(` return`)
f.WriteLine(`}`)
}
}
f.WriteLine(`} else {`)
f.WriteLine(` w.WriteHeader(http.StatusInternalServerError)`)
f.WriteLine(` w.Write([]byte(err.Error() + "\n"))`)
f.WriteLine(` return`)
f.WriteLine(`}`)
f.WriteLine(`}`)
f.WriteLine(``)
}
f.WriteLine(`// Initialize the API service.`)
f.WriteLine(`func Initialize(p Provider) {`)
f.WriteLine(` provider = p`)
f.WriteLine(` var router = mux.NewRouter()`)
for _, method := range renderer.Model.Methods {
f.WriteLine(`router.HandleFunc("` + method.Path + `", ` + method.HandlerName + `).Methods("` + method.Method + `")`)
}
f.WriteLine(` http.Handle("/", router)`)
f.WriteLine(`}`)
f.WriteLine(``)
f.WriteLine(`// Provide the API service over HTTP.`)
f.WriteLine(`func ServeHTTP(address string) error {`)
f.WriteLine(` if provider == nil {`)
f.WriteLine(` return errors.New("Use ` + renderer.Package + `.Initialize() to set a service provider.")`)
f.WriteLine(` }`)
f.WriteLine(` return http.ListenAndServe(address, nil)`)
f.WriteLine(`}`)
return f.Bytes(), nil
}

View file

@ -1,57 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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.
package main
import (
surface "github.com/googleapis/gnostic/surface"
)
func (renderer *Renderer) RenderTypes() ([]byte, error) {
f := NewLineWriter()
f.WriteLine(`// GENERATED FILE: DO NOT EDIT!`)
f.WriteLine(``)
f.WriteLine(`package ` + renderer.Package)
f.WriteLine(`// Types used by the API.`)
for _, modelType := range renderer.Model.Types {
f.WriteLine(`// ` + modelType.Description)
if modelType.Kind == surface.TypeKind_STRUCT {
f.WriteLine(`type ` + modelType.TypeName + ` struct {`)
for _, field := range modelType.Fields {
prefix := ""
if field.Kind == surface.FieldKind_REFERENCE {
prefix = "*"
} else if field.Kind == surface.FieldKind_ARRAY {
prefix = "[]"
} else if field.Kind == surface.FieldKind_MAP {
prefix = "map[string]"
}
f.WriteLine(field.FieldName + ` ` + prefix + field.NativeType + jsonTag(field))
}
f.WriteLine(`}`)
} else if modelType.Kind == surface.TypeKind_OBJECT {
f.WriteLine(`type ` + modelType.TypeName + ` map[string]` + modelType.ContentType)
} else {
f.WriteLine(`type ` + modelType.TypeName + ` interface {}`)
}
}
return f.Bytes(), nil
}
func jsonTag(field *surface.Field) string {
if field.Serialize {
return " `json:" + `"` + field.Name + `,omitempty"` + "`"
}
return ""
}

View file

@ -1,67 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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.
package main
import (
"fmt"
_ "os"
"path/filepath"
plugins "github.com/googleapis/gnostic/plugins"
surface "github.com/googleapis/gnostic/surface"
)
// Renderer generates code for a surface.Model.
type Renderer struct {
Model *surface.Model
Package string // package name
}
// NewServiceRenderer creates a renderer.
func NewServiceRenderer(model *surface.Model) (renderer *Renderer, err error) {
renderer = &Renderer{}
renderer.Model = model
return renderer, nil
}
// Generate runs the renderer to generate the named files.
func (renderer *Renderer) Render(response *plugins.Response, files []string) (err error) {
for _, filename := range files {
file := &plugins.File{Name: filename}
switch filename {
case "client.go":
file.Data, err = renderer.RenderClient()
case "types.go":
file.Data, err = renderer.RenderTypes()
case "provider.go":
file.Data, err = renderer.RenderProvider()
case "server.go":
file.Data, err = renderer.RenderServer()
case "constants.go":
file.Data, err = renderer.RenderConstants()
default:
file.Data = nil
}
if err != nil {
response.Errors = append(response.Errors, fmt.Sprintf("ERROR %v", err))
}
// run generated Go files through goimports
if filepath.Ext(file.Name) == ".go" {
file.Data, err = goimports(file.Name, file.Data)
}
response.Files = append(response.Files, file)
}
return
}

View file

@ -38,6 +38,20 @@ func (c *Code) Print(args ...interface{}) {
c.text += "\n"
}
// PrintIf adds a line of code using the current indentation if a condition is true. Accepts printf-style format strings and arguments.
func (c *Code) PrintIf(condition bool, args ...interface{}) {
if !condition {
return
}
if len(args) > 0 {
for i := 0; i < c.indent; i++ {
c.text += indentation
}
c.text += fmt.Sprintf(args[0].(string), args[1:]...)
}
c.text += "\n"
}
// String returns the accumulated code as a string.
func (c *Code) String() string {
return c.text

View file

@ -58,19 +58,21 @@ func (b *OpenAPI2Builder) build(document *openapiv2.Document) (err error) {
}
}
// Collect service method descriptions from Paths section.
for _, pair := range document.Paths.Path {
v := pair.Value
if v.Get != nil {
b.buildMethodFromOperation(v.Get, "GET", pair.Name)
}
if v.Post != nil {
b.buildMethodFromOperation(v.Post, "POST", pair.Name)
}
if v.Put != nil {
b.buildMethodFromOperation(v.Put, "PUT", pair.Name)
}
if v.Delete != nil {
b.buildMethodFromOperation(v.Delete, "DELETE", pair.Name)
if document.Paths != nil {
for _, pair := range document.Paths.Path {
v := pair.Value
if v.Get != nil {
b.buildMethodFromOperation(v.Get, "GET", pair.Name)
}
if v.Post != nil {
b.buildMethodFromOperation(v.Post, "POST", pair.Name)
}
if v.Put != nil {
b.buildMethodFromOperation(v.Put, "PUT", pair.Name)
}
if v.Delete != nil {
b.buildMethodFromOperation(v.Delete, "DELETE", pair.Name)
}
}
}
return err
@ -229,6 +231,9 @@ func (b *OpenAPI2Builder) typeForSchema(schema *openapiv2.Schema) (kind FieldKin
if len(types) == 1 && types[0] == "number" {
return FieldKind_SCALAR, "number", format
}
if len(types) == 1 && types[0] == "boolean" {
return FieldKind_SCALAR, "boolean", format
}
if len(types) == 1 && types[0] == "array" && schema.Items != nil {
// we have an array.., but of what?
items := schema.Items.Schema

View file

@ -24,6 +24,8 @@ import (
openapiv3 "github.com/googleapis/gnostic/OpenAPIv3"
)
var knownTypes = map[string]bool{"string": true, "integer": true, "number": true, "boolean": true, "array": true, "object": true}
// NewModelFromOpenAPIv3 builds a model of an API service for use in code generation.
func NewModelFromOpenAPI3(document *openapiv3.Document) (*Model, error) {
return newOpenAPI3Builder().buildModel(document)
@ -51,9 +53,30 @@ func (b *OpenAPI3Builder) buildModel(document *openapiv3.Document) (*Model, erro
// build builds an API service description, preprocessing its types and methods for code generation.
func (b *OpenAPI3Builder) build(document *openapiv3.Document) (err error) {
err = b.buildTypesFromComponents(document.Components)
if err != nil {
return err
}
// Collect service method descriptions from each PathItem.
if document.Paths != nil {
for _, pair := range document.Paths.Path {
b.buildMethodFromPathItem(pair.Name, pair.Value)
}
}
return err
}
// buildTypesFromComponents builds multiple service type description from the "Components" section
// in the OpenAPI specification.
func (b *OpenAPI3Builder) buildTypesFromComponents(components *openapiv3.Components) (err error) {
if components == nil {
return nil
}
// Collect service type descriptions from Components/Schemas.
if document.Components != nil && document.Components.Schemas != nil {
for _, pair := range document.Components.Schemas.AdditionalProperties {
if components.Schemas != nil {
for _, pair := range components.Schemas.AdditionalProperties {
t, err := b.buildTypeFromSchemaOrReference(pair.Name, pair.Value)
if err != nil {
return err
@ -63,10 +86,38 @@ func (b *OpenAPI3Builder) build(document *openapiv3.Document) (err error) {
}
}
}
// Collect service method descriptions from each PathItem.
for _, pair := range document.Paths.Path {
b.buildMethodFromPathItem(pair.Name, pair.Value)
// Collect service type descriptions from Components/Parameters.
if components.Parameters != nil {
for _, pair := range components.Parameters.AdditionalProperties {
parameters := []*openapiv3.ParameterOrReference{pair.Value}
_, err := b.buildTypeFromParameters(pair.Name, parameters, nil, true)
if err != nil {
return err
}
}
}
// Collect service type descriptions from Components/requestBodies
if components.RequestBodies != nil {
for _, pair := range components.RequestBodies.AdditionalProperties {
t, err := b.buildTypeFromRequestBody(pair.Name, pair.Value, nil)
if err != nil {
return err
}
if t != nil {
b.model.addType(t)
}
}
}
// Collect service type descriptions from Components/responses
if components.Responses != nil {
for _, pair := range components.Responses.AdditionalProperties {
namedResponseOrReference := []*openapiv3.NamedResponseOrReference{pair}
responses := &openapiv3.Responses{ResponseOrReference: namedResponseOrReference}
b.buildTypeFromResponses(pair.Name, responses, true)
}
}
return err
}
@ -84,13 +135,14 @@ func (b *OpenAPI3Builder) buildTypeFromSchemaOrReference(
// If the schema has properties, generate a struct.
t.Kind = TypeKind_STRUCT
}
for _, pair2 := range schema.Properties.AdditionalProperties {
if schema := pair2.Value; schema != nil {
var f Field
f.Name = pair2.Name
for _, pair := range schema.Properties.AdditionalProperties {
if schema := pair.Value; schema != nil {
f := &Field{
Name: pair.Name,
Serialize: true,
}
f.Kind, f.Type, f.Format = b.typeForSchemaOrReference(schema)
f.Serialize = true
t.addField(&f)
t.addField(f)
}
}
}
@ -133,18 +185,19 @@ func (b *OpenAPI3Builder) buildMethodFromPathItem(
op = pathItem.Trace
}
if op != nil {
var m Method
m.Operation = op.OperationId
m.Path = path
m.Method = method
m.Name = sanitizeOperationName(op.OperationId)
m := &Method{
Operation: op.OperationId,
Path: path,
Method: method,
Name: sanitizeOperationName(op.OperationId),
Description: op.Description,
}
if m.Name == "" {
m.Name = generateOperationName(method, path)
}
m.Description = op.Description
m.ParametersTypeName, err = b.buildTypeFromParameters(m.Name, op.Parameters, op.RequestBody)
m.ResponsesTypeName, err = b.buildTypeFromResponses(&m, m.Name, op.Responses)
b.model.addMethod(&m)
m.ParametersTypeName, err = b.buildTypeFromParameters(m.Name, op.Parameters, op.RequestBody, false)
m.ResponsesTypeName, err = b.buildTypeFromResponses(m.Name, op.Responses, false)
b.model.addMethod(m)
}
}
return err
@ -154,15 +207,25 @@ func (b *OpenAPI3Builder) buildMethodFromPathItem(
func (b *OpenAPI3Builder) buildTypeFromParameters(
name string,
parameters []*openapiv3.ParameterOrReference,
requestBody *openapiv3.RequestBodyOrReference) (typeName string, err error) {
t := &Type{}
t.Name = name + "Parameters"
t.Description = t.Name + " holds parameters to " + name
t.Kind = TypeKind_STRUCT
t.Fields = make([]*Field, 0)
requestBody *openapiv3.RequestBodyOrReference,
fromComponent bool) (typeName string, err error) {
pName := name + "Parameters"
t := &Type{
Name: pName,
Kind: TypeKind_STRUCT,
Fields: make([]*Field, 0),
Description: pName + " holds parameters to " + name,
}
if fromComponent {
t.Name = name
t.Description = t.Name + " is a parameter"
}
for _, parametersItem := range parameters {
var f Field
f.Type = fmt.Sprintf("%+v", parametersItem)
f := Field{
Type: fmt.Sprintf("%+v", parametersItem),
}
parameter := parametersItem.GetParameter()
if parameter != nil {
switch parameter.In {
@ -183,21 +246,16 @@ func (b *OpenAPI3Builder) buildTypeFromParameters(
}
f.Serialize = true
t.addField(&f)
} else if parameterRef := parametersItem.GetReference(); parameterRef != nil {
f.Type = typeForRef(parameterRef.GetXRef())
f.Name = strings.ToLower(f.Type)
f.Kind = FieldKind_REFERENCE
t.addField(&f)
}
}
if requestBody != nil {
content := requestBody.GetRequestBody().GetContent()
if content != nil {
for _, pair2 := range content.GetAdditionalProperties() {
var f Field
f.Position = Position_BODY
f.Kind, f.Type, f.Format = b.typeForSchemaOrReference(pair2.GetValue().GetSchema())
f.Name = strings.ToLower(f.Type) // use the schema name as the parameter name, since none is directly specified
f.Serialize = true
t.addField(&f)
}
}
}
_, err = b.buildTypeFromRequestBody(name, requestBody, t)
if len(t.Fields) > 0 {
b.model.addType(t)
return t.Name, err
@ -205,28 +263,79 @@ func (b *OpenAPI3Builder) buildTypeFromParameters(
return "", err
}
// buildTypeFromRequestBody builds a service type description from the request bodies of an OpenAPI
// description. If tIn is not given, a new type is created. Otherwise tIn is used.
func (b *OpenAPI3Builder) buildTypeFromRequestBody(name string, requestBody *openapiv3.RequestBodyOrReference, tIn *Type) (tOut *Type, err error) {
tOut = &Type{
Name: name,
}
if tIn != nil {
tOut = tIn
}
if requestBody != nil {
content := requestBody.GetRequestBody().GetContent()
f := &Field{
Position: Position_BODY,
Serialize: true,
}
if content != nil {
for _, pair := range content.GetAdditionalProperties() {
if pair.Name != "application/json" {
log.Printf("unimplemented: %q requestBody(%s)", name, pair.Name)
continue
}
f.Kind, f.Type, f.Format = b.typeForSchemaOrReference(pair.GetValue().GetSchema())
f.Name = strings.ToLower(f.Type) // use the schema name as the parameter name, since none is directly specified
tOut.addField(f)
}
} else if reference := requestBody.GetReference(); reference != nil {
schemaOrReference := openapiv3.SchemaOrReference{&openapiv3.SchemaOrReference_Reference{Reference: reference}}
f.Kind, f.Type, f.Format = b.typeForSchemaOrReference(&schemaOrReference)
f.Name = strings.ToLower(f.Type) // use the schema name as the parameter name, since none is directly specified
tOut.addField(f)
}
}
return tOut, err
}
// buildTypeFromResponses builds a service type description from the responses of an API method
func (b *OpenAPI3Builder) buildTypeFromResponses(
m *Method,
name string,
responses *openapiv3.Responses) (typeName string, err error) {
t := &Type{}
t.Name = name + "Responses"
t.Description = t.Name + " holds responses of " + name
t.Kind = TypeKind_STRUCT
t.Fields = make([]*Field, 0)
responses *openapiv3.Responses,
fromComponent bool) (typeName string, err error) {
rName := name + "Responses"
t := &Type{
Name: name + "Responses",
Kind: TypeKind_STRUCT,
Fields: make([]*Field, 0),
Description: rName + " holds responses of " + name,
}
if fromComponent {
t.Name = name
t.Description = t.Name + " is a response"
}
addResponse := func(name string, value *openapiv3.ResponseOrReference) {
var f Field
f.Name = name
f.Serialize = false
f := Field{
Name: name,
Serialize: false,
}
response := value.GetResponse()
if response != nil && response.GetContent() != nil {
for _, pair2 := range response.GetContent().GetAdditionalProperties() {
f.Kind, f.Type, f.Format = b.typeForSchemaOrReference(pair2.GetValue().GetSchema())
f.Kind = FieldKind_REFERENCE
t.addField(&f)
}
} else if responseRef := value.GetReference(); responseRef != nil {
schemaOrReference := openapiv3.SchemaOrReference{&openapiv3.SchemaOrReference_Reference{Reference: responseRef}}
f.Kind, f.Type, f.Format = b.typeForSchemaOrReference(&schemaOrReference)
t.addField(&f)
}
}
@ -250,7 +359,7 @@ func (b *OpenAPI3Builder) typeForSchemaOrReference(value *openapiv3.SchemaOrRefe
return b.typeForSchema(value.GetSchema())
}
if value.GetReference() != nil {
return FieldKind_SCALAR, typeForRef(value.GetReference().XRef), ""
return FieldKind_REFERENCE, typeForRef(value.GetReference().XRef), ""
}
return FieldKind_SCALAR, "todo", ""
}
@ -276,10 +385,9 @@ func (b *OpenAPI3Builder) typeForSchema(schema *openapiv3.Schema) (kind FieldKin
a := items.GetSchemaOrReference()
if a[0].GetReference().GetXRef() != "" {
return FieldKind_ARRAY, typeForRef(a[0].GetReference().GetXRef()), format
} else if a[0].GetSchema().Type == "string" {
return FieldKind_ARRAY, "string", format
} else if a[0].GetSchema().Type == "object" {
return FieldKind_ARRAY, "interface{}", format
} else if knownTypes[a[0].GetSchema().Type] {
// The items of the array is one of the known types.
return FieldKind_ARRAY, a[0].GetSchema().Type, a[0].GetSchema().Format
}
}
}
@ -287,6 +395,8 @@ func (b *OpenAPI3Builder) typeForSchema(schema *openapiv3.Schema) (kind FieldKin
if schema.AdditionalProperties == nil {
return FieldKind_MAP, "object", format
}
case "any":
return FieldKind_ANY, "any", format
default:
}
@ -299,7 +409,7 @@ func (b *OpenAPI3Builder) typeForSchema(schema *openapiv3.Schema) (kind FieldKin
}
}
}
// this function is incomplete... return a string representing anything that we don't handle
// this function is incomplete... use generic interface{} for now
log.Printf("unimplemented: %v", schema)
return FieldKind_SCALAR, fmt.Sprintf("unimplemented: %v", schema), ""
return FieldKind_SCALAR, "object", ""
}

View file

@ -38,6 +38,7 @@ const (
FieldKind_MAP FieldKind = 1
FieldKind_ARRAY FieldKind = 2
FieldKind_REFERENCE FieldKind = 3
FieldKind_ANY FieldKind = 4
)
var FieldKind_name = map[int32]string{
@ -45,12 +46,14 @@ var FieldKind_name = map[int32]string{
1: "MAP",
2: "ARRAY",
3: "REFERENCE",
4: "ANY",
}
var FieldKind_value = map[string]int32{
"SCALAR": 0,
"MAP": 1,
"ARRAY": 2,
"REFERENCE": 3,
"ANY": 4,
}
func (x FieldKind) String() string {
@ -384,41 +387,41 @@ func init() {
func init() { proto.RegisterFile("surface.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 573 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x54, 0x5f, 0x6f, 0xd3, 0x3e,
0x14, 0x5d, 0xfe, 0x36, 0xb9, 0xfd, 0xf5, 0xa7, 0xcc, 0x02, 0x14, 0x21, 0x84, 0xa2, 0x0a, 0xa1,
0xae, 0x9a, 0x2a, 0x18, 0x6f, 0xbc, 0x65, 0x6d, 0xaa, 0x09, 0xe8, 0x5a, 0x4c, 0xf6, 0xd0, 0xc7,
0xd0, 0xb8, 0x6a, 0x44, 0x1b, 0x87, 0x38, 0x4c, 0x82, 0x0f, 0xc4, 0xc7, 0x81, 0xaf, 0x84, 0x7c,
0x93, 0xb4, 0xde, 0xda, 0x37, 0xfb, 0xdc, 0xe3, 0x6b, 0x9f, 0x73, 0x6e, 0x02, 0x3d, 0xf1, 0xa3,
0x5c, 0x27, 0x2b, 0x36, 0x2a, 0x4a, 0x5e, 0x71, 0x02, 0xed, 0xf6, 0xfe, 0x6d, 0xff, 0xb7, 0x0e,
0xd6, 0x34, 0x63, 0xdb, 0x94, 0x10, 0x30, 0xf3, 0x64, 0xc7, 0x7c, 0x2d, 0xd0, 0x06, 0x2e, 0xc5,
0xb5, 0xc4, 0xaa, 0x9f, 0x05, 0xf3, 0xf5, 0x1a, 0x93, 0x6b, 0x72, 0x01, 0xe6, 0xb7, 0x2c, 0x4f,
0x7d, 0x23, 0xd0, 0x06, 0xff, 0x5f, 0x3d, 0x1d, 0x1d, 0x9a, 0x8d, 0xb0, 0xd1, 0xc7, 0x2c, 0x4f,
0x29, 0x52, 0xc8, 0x33, 0xb0, 0xd7, 0xbc, 0xdc, 0x25, 0x95, 0x6f, 0x62, 0x83, 0x66, 0x47, 0xde,
0x80, 0x53, 0x70, 0x91, 0x55, 0x19, 0xcf, 0x7d, 0x0b, 0xdb, 0x3c, 0x51, 0xdb, 0x2c, 0x9a, 0x1a,
0xdd, 0xb3, 0xc8, 0x4b, 0x80, 0x3c, 0xa9, 0xb2, 0x7b, 0x16, 0xcb, 0xe7, 0xd8, 0xd8, 0x4d, 0x41,
0xc8, 0x0b, 0x70, 0xd7, 0xf2, 0xf2, 0x5b, 0xa9, 0xa0, 0x83, 0xe5, 0x03, 0x40, 0x5e, 0x41, 0xaf,
0x48, 0xca, 0x64, 0xc7, 0x2a, 0x56, 0x22, 0xc3, 0x41, 0xc6, 0x43, 0x50, 0xf6, 0x10, 0xac, 0xcc,
0x92, 0x6d, 0xf6, 0x8b, 0xf9, 0x6e, 0xa0, 0x0d, 0x1c, 0x7a, 0x00, 0xfa, 0x7f, 0x35, 0x30, 0xf1,
0xaa, 0x53, 0x3e, 0x0d, 0x1a, 0x4f, 0xf4, 0x63, 0x31, 0xf2, 0x8c, 0x62, 0x49, 0x00, 0xdd, 0x94,
0x89, 0x55, 0x99, 0x15, 0xa8, 0xde, 0xc0, 0x26, 0x2a, 0x24, 0x19, 0x2b, 0x9e, 0x57, 0x2c, 0xaf,
0x50, 0x6b, 0xed, 0x9c, 0x0a, 0x91, 0x0b, 0xb0, 0x51, 0x9b, 0xf0, 0xad, 0xc0, 0x18, 0x74, 0xaf,
0xce, 0x8f, 0x32, 0xa0, 0x0d, 0x81, 0x3c, 0x07, 0x47, 0x86, 0x86, 0xa2, 0x6b, 0xd7, 0xf6, 0xfb,
0xfe, 0x1f, 0x1d, 0xec, 0x19, 0xab, 0x36, 0x3c, 0x95, 0xd2, 0x79, 0xc1, 0xca, 0x04, 0xdf, 0x54,
0x0b, 0x3b, 0x00, 0x52, 0x71, 0x91, 0x54, 0x9b, 0x76, 0x0a, 0xe4, 0x5a, 0x46, 0xbb, 0xc3, 0xb3,
0x8d, 0x84, 0x66, 0xf7, 0x58, 0x9f, 0x79, 0xac, 0xaf, 0xf5, 0xcf, 0x52, 0xfc, 0x0b, 0xa0, 0xbb,
0x49, 0xf2, 0x74, 0xdb, 0xc4, 0x53, 0xbf, 0x54, 0x85, 0x30, 0xc2, 0x92, 0xaf, 0x98, 0x10, 0xbc,
0x54, 0x42, 0x7e, 0x08, 0xca, 0x31, 0x59, 0x6d, 0x33, 0x96, 0x57, 0x4a, 0xca, 0x0a, 0x42, 0x46,
0x40, 0xf6, 0x99, 0x8b, 0xb8, 0x35, 0xc6, 0x45, 0xde, 0x89, 0x0a, 0xb9, 0x84, 0xf3, 0x92, 0x89,
0x82, 0xe7, 0x82, 0x1d, 0xe8, 0x80, 0xf4, 0xe3, 0x42, 0xff, 0x3b, 0x58, 0x33, 0x9e, 0xb2, 0xed,
0xc9, 0x11, 0x79, 0x0d, 0x96, 0x74, 0x5e, 0xf8, 0x3a, 0x66, 0xe6, 0x3d, 0x9e, 0x11, 0x5a, 0x97,
0xc9, 0x25, 0x74, 0x6a, 0x2b, 0x85, 0x6f, 0x20, 0x93, 0xa8, 0xcc, 0x3a, 0x2f, 0xda, 0x52, 0x86,
0xef, 0xc1, 0xdd, 0x7f, 0x74, 0x04, 0xc0, 0xfe, 0x32, 0x0e, 0x3f, 0x85, 0xd4, 0x3b, 0x23, 0x1d,
0x30, 0x66, 0xe1, 0xc2, 0xd3, 0x88, 0x0b, 0x56, 0x48, 0x69, 0xb8, 0xf4, 0x74, 0xd2, 0x03, 0x97,
0x46, 0xd3, 0x88, 0x46, 0xb7, 0xe3, 0xc8, 0x33, 0x86, 0x7d, 0x70, 0xda, 0xe1, 0xc4, 0xa3, 0x31,
0xbd, 0x1b, 0xc7, 0xde, 0x99, 0x5c, 0xcf, 0xaf, 0x3f, 0x44, 0xe3, 0xd8, 0xd3, 0x86, 0x63, 0x70,
0xda, 0xaf, 0x91, 0x38, 0x60, 0x5e, 0xcf, 0x27, 0xcb, 0x9a, 0x71, 0x13, 0x85, 0x93, 0x88, 0x7a,
0x1a, 0xf9, 0x0f, 0x9c, 0xe9, 0x9c, 0xce, 0x26, 0x61, 0x1c, 0x7a, 0xba, 0xbc, 0xed, 0xf3, 0x5d,
0x44, 0x97, 0x9e, 0x21, 0xe9, 0x8b, 0x30, 0xbe, 0xf1, 0xcc, 0xaf, 0x36, 0xfe, 0x76, 0xde, 0xfd,
0x0b, 0x00, 0x00, 0xff, 0xff, 0x15, 0x52, 0x6a, 0x89, 0x87, 0x04, 0x00, 0x00,
// 576 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0x54, 0xed, 0x6e, 0xd3, 0x30,
0x14, 0x5d, 0x3e, 0x97, 0xdc, 0x31, 0xe4, 0x59, 0x80, 0x22, 0x84, 0x50, 0x54, 0x21, 0xd4, 0x55,
0x53, 0x05, 0xe3, 0x09, 0xb2, 0x34, 0xd5, 0x04, 0xf4, 0x03, 0x93, 0xfd, 0xe8, 0xcf, 0xd0, 0xb8,
0x6a, 0x44, 0x1b, 0x87, 0x38, 0x4c, 0x82, 0x07, 0xe2, 0x71, 0xe0, 0x95, 0x90, 0x6f, 0x92, 0x36,
0x5b, 0xfb, 0xcf, 0x3e, 0xf7, 0xe4, 0xda, 0xe7, 0x9c, 0xeb, 0xc0, 0xb9, 0xfc, 0x59, 0xae, 0x92,
0x25, 0x1f, 0x16, 0xa5, 0xa8, 0x04, 0x85, 0x76, 0x7b, 0xff, 0xbe, 0xf7, 0x47, 0x07, 0x6b, 0x9c,
0xf1, 0x4d, 0x4a, 0x29, 0x98, 0x79, 0xb2, 0xe5, 0x9e, 0xe6, 0x6b, 0x7d, 0x97, 0xe1, 0x5a, 0x61,
0xd5, 0xaf, 0x82, 0x7b, 0x7a, 0x8d, 0xa9, 0x35, 0xbd, 0x04, 0xf3, 0x7b, 0x96, 0xa7, 0x9e, 0xe1,
0x6b, 0xfd, 0xa7, 0xd7, 0xcf, 0x87, 0xfb, 0x66, 0x43, 0x6c, 0xf4, 0x29, 0xcb, 0x53, 0x86, 0x14,
0xfa, 0x02, 0xec, 0x95, 0x28, 0xb7, 0x49, 0xe5, 0x99, 0xd8, 0xa0, 0xd9, 0xd1, 0x77, 0xe0, 0x14,
0x42, 0x66, 0x55, 0x26, 0x72, 0xcf, 0xc2, 0x36, 0xcf, 0xba, 0x6d, 0xe6, 0x4d, 0x8d, 0xed, 0x58,
0xf4, 0x35, 0x40, 0x9e, 0x54, 0xd9, 0x3d, 0x8f, 0xd5, 0x75, 0x6c, 0xec, 0xd6, 0x41, 0xe8, 0x2b,
0x70, 0x57, 0xea, 0xf0, 0xa9, 0x52, 0x70, 0x8a, 0xe5, 0x3d, 0x40, 0xdf, 0xc0, 0x79, 0x91, 0x94,
0xc9, 0x96, 0x57, 0xbc, 0x44, 0x86, 0x83, 0x8c, 0x87, 0xa0, 0xea, 0x21, 0x79, 0x99, 0x25, 0x9b,
0xec, 0x37, 0xf7, 0x5c, 0x5f, 0xeb, 0x3b, 0x6c, 0x0f, 0xf4, 0xfe, 0x69, 0x60, 0xe2, 0x51, 0xc7,
0x7c, 0xea, 0x37, 0x9e, 0xe8, 0x87, 0x62, 0xd4, 0x37, 0x1d, 0x4b, 0x7c, 0x38, 0x4b, 0xb9, 0x5c,
0x96, 0x59, 0x81, 0xea, 0x0d, 0x6c, 0xd2, 0x85, 0x14, 0x63, 0x29, 0xf2, 0x8a, 0xe7, 0x15, 0x6a,
0xad, 0x9d, 0xeb, 0x42, 0xf4, 0x12, 0x6c, 0xd4, 0x26, 0x3d, 0xcb, 0x37, 0xfa, 0x67, 0xd7, 0x17,
0x07, 0x19, 0xb0, 0x86, 0x40, 0x5f, 0x82, 0xa3, 0x42, 0x43, 0xd1, 0xb5, 0x6b, 0xbb, 0x7d, 0xef,
0xaf, 0x0e, 0xf6, 0x84, 0x57, 0x6b, 0x91, 0x2a, 0xe9, 0xa2, 0xe0, 0x65, 0x82, 0x77, 0xaa, 0x85,
0xed, 0x01, 0xa5, 0xb8, 0x48, 0xaa, 0x75, 0x3b, 0x05, 0x6a, 0xad, 0xa2, 0xdd, 0xe2, 0xb7, 0x8d,
0x84, 0x66, 0xf7, 0x58, 0x9f, 0x79, 0xa8, 0xaf, 0xf5, 0xcf, 0xea, 0xf8, 0xe7, 0xc3, 0xd9, 0x3a,
0xc9, 0xd3, 0x4d, 0x13, 0x4f, 0x7d, 0xd3, 0x2e, 0x84, 0x11, 0x96, 0x62, 0xc9, 0xa5, 0x14, 0x65,
0x27, 0xe4, 0x87, 0xa0, 0x1a, 0x93, 0xe5, 0x26, 0xe3, 0x79, 0xd5, 0x49, 0xb9, 0x83, 0xd0, 0x21,
0xd0, 0x5d, 0xe6, 0x32, 0x6e, 0x8d, 0x71, 0x91, 0x77, 0xa4, 0x42, 0xaf, 0xe0, 0xa2, 0xe4, 0xb2,
0x10, 0xb9, 0xe4, 0x7b, 0x3a, 0x20, 0xfd, 0xb0, 0xd0, 0xfb, 0x01, 0xd6, 0x44, 0xa4, 0x7c, 0x73,
0x74, 0x44, 0xde, 0x82, 0xa5, 0x9c, 0x97, 0x9e, 0x8e, 0x99, 0x91, 0xc7, 0x33, 0xc2, 0xea, 0x32,
0xbd, 0x82, 0xd3, 0xda, 0x4a, 0xe9, 0x19, 0xc8, 0xa4, 0x5d, 0x66, 0x9d, 0x17, 0x6b, 0x29, 0x83,
0x10, 0xdc, 0xdd, 0xa3, 0xa3, 0x00, 0xf6, 0xd7, 0x30, 0xf8, 0x1c, 0x30, 0x72, 0x42, 0x4f, 0xc1,
0x98, 0x04, 0x73, 0xa2, 0x51, 0x17, 0xac, 0x80, 0xb1, 0x60, 0x41, 0x74, 0x7a, 0x0e, 0x2e, 0x8b,
0xc6, 0x11, 0x8b, 0xa6, 0x61, 0x44, 0x0c, 0x45, 0x09, 0xa6, 0x0b, 0x62, 0x0e, 0x7a, 0xe0, 0xb4,
0x53, 0x8a, 0x3d, 0x62, 0x76, 0x17, 0xc6, 0xe4, 0x44, 0xad, 0x67, 0x37, 0x1f, 0xa3, 0x30, 0x26,
0xda, 0x20, 0x04, 0xa7, 0x7d, 0x96, 0xd4, 0x01, 0xf3, 0x66, 0x36, 0x5a, 0xd4, 0x8c, 0xdb, 0x28,
0x18, 0x45, 0x8c, 0x68, 0xf4, 0x09, 0x38, 0xe3, 0x19, 0x9b, 0x8c, 0x82, 0x38, 0x20, 0xba, 0x3a,
0xf6, 0xcb, 0x5d, 0xc4, 0x16, 0xc4, 0x50, 0xf4, 0x79, 0x10, 0xdf, 0x12, 0xf3, 0x9b, 0x8d, 0xff,
0x9f, 0x0f, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xcf, 0x90, 0x77, 0x90, 0x04, 0x00, 0x00,
}

View file

@ -23,6 +23,7 @@ enum FieldKind {
MAP = 1;
ARRAY = 2;
REFERENCE = 3;
ANY = 4;
}
enum TypeKind {

View file

@ -91,6 +91,13 @@
"type": "string"
}
}
},
"SimpleDefWithBoolean": {
"properties": {
"active": {
"type": "boolean"
}
}
}
}
}

View file

@ -128,6 +128,21 @@ definitions: <
>
>
>
additional_properties: <
name: "SimpleDefWithBoolean"
value: <
properties: <
additional_properties: <
name: "active"
value: <
type: <
value: "boolean"
>
>
>
>
>
>
>
parameters: <
additional_properties: <

View file

@ -0,0 +1,9 @@
{
"swagger": "2.0",
"info": {
"title": "",
"version": ""
},
"paths": {
}
}

View file

@ -0,0 +1,9 @@
{
"openapi": "3.0",
"info": {
"title": "",
"version": ""
},
"paths": {
}
}

12
vendor/github.com/json-iterator/go/build.sh generated vendored Executable file
View file

@ -0,0 +1,12 @@
#!/bin/bash
set -e
set -x
if [ ! -d /tmp/build-golang/src/github.com/json-iterator ]; then
mkdir -p /tmp/build-golang/src/github.com/json-iterator
ln -s $PWD /tmp/build-golang/src/github.com/json-iterator/go
fi
export GOPATH=/tmp/build-golang
go get -u github.com/golang/dep/cmd/dep
cd /tmp/build-golang/src/github.com/json-iterator/go
exec $GOPATH/bin/dep ensure -update

View file

@ -1,33 +1,19 @@
<!--- Provide a general summary of your changes in the Title above -->
## Description
<!--- Describe your changes in detail -->
## Motivation and Context
<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->
## Regression
<!-- Is this PR fixing a regression? (Yes / No) -->
<!-- If Yes, optionally please include minio version or commit id or PR# that caused this regression, if you have these details. -->
## How Has This Been Tested?
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->
## How to test this PR?
## Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
## Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [ ] My code follows the code style of this project.
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [ ] I have added unit tests to cover my changes.
- [ ] I have added/updated functional tests in [mint](https://github.com/minio/mint). (If yes, add `mint` PR # here: )
- [ ] All new and existing tests passed.
- [ ] Fixes a regression (If yes, please add `commit-id` or `PR #` here)
- [ ] Documentation needed
- [ ] Unit tests needed
- [ ] Functional tests needed (If yes, add [mint](https://github.com/minio/mint) PR # here: )

View file

@ -9,7 +9,6 @@ site/
/.idea/
/Minio.iml
**/access.log
build/
vendor/**/*.js
vendor/**/*.json
release
@ -23,4 +22,4 @@ prime/
stage/
.sia_temp/
config.json
healthcheck
dockerscripts/healthcheck

View file

@ -2,6 +2,14 @@ go_import_path: github.com/minio/minio
language: go
addons:
apt:
packages:
- shellcheck
services:
- docker
# this ensures PRs based on a local branch are not built twice
# the downside is that a PR targeting a different branch is not built
# but as a workaround you can add the branch to this list
@ -26,7 +34,7 @@ matrix:
- $HOME/gopath/pkg/mod
- $HOME/go/pkg/mod
go: 1.12.1
go: 1.12.5
script:
- make
- diff -au <(gofmt -s -d cmd) <(printf "")
@ -37,12 +45,14 @@ matrix:
- make verify
- make coverage
- cd browser && yarn && yarn test && cd ..
- bash -c 'shopt -s globstar; shellcheck mint/**/*.sh'
- os: windows
env:
- ARCH=x86_64
- CGO_ENABLED=0
- GO111MODULE=on
go: 1.12.1
go: 1.12.5
script:
- go build --ldflags="$(go run buildscripts/gen-ldflags.go)" -o %GOPATH%\bin\minio.exe
- bash buildscripts/go-coverage.sh

View file

@ -37,7 +37,7 @@ After your code changes, make sure
- To add test cases for the new code. If you have questions about how to do it, please ask on our [Slack](https://slack.min.io) channel.
- To run `make verifiers`
- To squash your commits into a single commit. `git rebase -i`. It's okay to force update your pull request.
- To run `go test -race ./...` and `go build` completes.
- To run `make test` and `make build` completes.
### Commit changes
After verification, commit your changes. This is a [great post](https://chris.beams.io/posts/git-commit/) on how to write useful commit messages

View file

@ -10,13 +10,14 @@ RUN \
apk add --no-cache git && \
git clone https://github.com/minio/minio && cd minio && \
go install -v -ldflags "$(go run buildscripts/gen-ldflags.go)" && \
cd dockerscripts; go build -ldflags "-s -w" -o /usr/bin/healthcheck healthcheck.go
cd dockerscripts; go build -tags kqueue -ldflags "-s -w" -o /usr/bin/healthcheck healthcheck.go
FROM alpine:3.9
ENV MINIO_UPDATE off
ENV MINIO_ACCESS_KEY_FILE=access_key \
MINIO_SECRET_KEY_FILE=secret_key
MINIO_SECRET_KEY_FILE=secret_key \
MINIO_SSE_MASTER_KEY_FILE=sse_master_key
EXPOSE 9000
@ -25,7 +26,7 @@ COPY --from=0 /usr/bin/healthcheck /usr/bin/healthcheck
COPY dockerscripts/docker-entrypoint.sh /usr/bin/
RUN \
apk add --no-cache ca-certificates 'curl>7.61.0' && \
apk add --no-cache ca-certificates 'curl>7.61.0' 'su-exec>=0.2' && \
echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf
ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"]

View file

@ -7,10 +7,11 @@ COPY minio /usr/bin/
ENV MINIO_UPDATE off
ENV MINIO_ACCESS_KEY_FILE=access_key \
MINIO_SECRET_KEY_FILE=secret_key
MINIO_SECRET_KEY_FILE=secret_key \
MINIO_SSE_MASTER_KEY_FILE=sse_master_key
RUN \
apk add --no-cache ca-certificates 'curl>7.61.0' && \
apk add --no-cache ca-certificates 'curl>7.61.0' 'su-exec>=0.2' && \
echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf && \
chmod +x /usr/bin/minio && \
chmod +x /usr/bin/docker-entrypoint.sh && \

23
vendor/github.com/minio/minio/Dockerfile.mint generated vendored Normal file
View file

@ -0,0 +1,23 @@
FROM ubuntu:16.04
ENV DEBIAN_FRONTEND noninteractive
ENV LANG C.UTF-8
ENV GOROOT /usr/local/go
ENV GOPATH /usr/local
ENV PATH $GOPATH/bin:$GOROOT/bin:$PATH
ENV MINT_ROOT_DIR /mint
COPY mint /mint
RUN apt-get --yes update && apt-get --yes upgrade && \
apt-get --yes --quiet install wget jq curl git dnsmasq && \
cd /mint && /mint/release.sh
WORKDIR /mint
ENTRYPOINT ["/mint/entrypoint.sh"]

Some files were not shown because too many files have changed in this diff Show more