Skip to content

Commit

Permalink
Command line options to emit custom response codes in swagger doc (#3)
Browse files Browse the repository at this point in the history
* Implemented cmd-line options to emit custom response codes in swagger doc

* Addressed reviewer comments

* Addressed reviewer comments

* Addressed reviewer comments

* Addressed reviewer comments
  • Loading branch information
rvinfoblox authored Jul 4, 2023
1 parent d813277 commit f14c5b8
Show file tree
Hide file tree
Showing 11 changed files with 1,628 additions and 54 deletions.
13 changes: 12 additions & 1 deletion cmd/server/config.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
package main

import "github.com/spf13/pflag"
import (
"github.com/spf13/pflag"

svc "github.com/infobloxopen/atlas-openapiv2-patch/pkg/svc"
)

var (
swaggerFiles = pflag.StringSlice("files", []string{}, "input swagger file location")
withPrivate = pflag.Bool("with_private", false, "if unset, generate swagger schema without operations 0 as 'private' work only if atlas_patch set")
withCustomAnnotations = pflag.Bool("with_custom_annotations", false, "if set, you became available to use custom annotations")

// Allow API response codes to be overridden for POST, PUT, PATCH and DELETE calls.
// Note: Since GET always returns a 200, we don't permit overriding the response for that method alone.
withPostResponse = pflag.Int("with_post_response", svc.DefaultPostResponse, "if set, generate swagger doc with the given response code for the POST API")
withPutResponse = pflag.Int("with_put_response", svc.DefaultPutResponse, "if set, generate swagger doc with the given response code for the PUT API")
withPatchResponse = pflag.Int("with_patch_response", svc.DefaultPatchResponse, "if set, generate swagger doc with the given response code for the PATCH API")
withDeleteResponse = pflag.Int("with_delete_response", svc.DefaultDeleteResponse, "if set, generate swagger doc with the given response code for the DELETE API")
)
17 changes: 16 additions & 1 deletion cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
)

func run(reg *descriptor.Registry, swaggerFiles []string) error {
glog.V(1).Infof("Atlas openapiv2 patch - Input args: %+v\n", reg)
for _, file := range swaggerFiles {
fileName := file
var f []byte
Expand All @@ -21,7 +22,17 @@ func run(reg *descriptor.Registry, swaggerFiles []string) error {
if err != nil {
return err
}
resp := genopenapi.AtlasSwagger(f, reg.IsWithPrivateOperations(), reg.IsWithCustomAnnotations())

responseCodesMap := map[string]int{
"GET": genopenapi.DefaultGetResponse,
"POST": reg.PostResponse(),
"PUT": reg.PutResponse(),
"PATCH": reg.PatchResponse(),
"DELETE": reg.DeleteResponse(),
}

resp := genopenapi.AtlasSwagger(f, reg.IsWithPrivateOperations(), reg.IsWithCustomAnnotations(),
responseCodesMap)

if reg.IsWithPrivateOperations() {
err = os.Remove(file)
Expand All @@ -45,6 +56,10 @@ func main() {

reg.SetPrivateOperations(*withPrivate)
reg.SetCustomAnnotations(*withCustomAnnotations)
reg.SetPostResponse(*withPostResponse)
reg.SetPutResponse(*withPutResponse)
reg.SetPatchResponse(*withPatchResponse)
reg.SetDeleteResponse(*withDeleteResponse)
glog.V(1).Info("Processing code generator request")

if len(*swaggerFiles) == 0 {
Expand Down
99 changes: 83 additions & 16 deletions cmd/server/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@ import (
)

const (
succeed = "\u2713"
failed = "\u2717"
red = "\033[31m"
green = "\033[32m"
yellow = "\033[33m"
reset = "\033[0m"
sampleSwaggerFile = "../../internal/testdata/atlaspatch.swagger.json"
succeed = "\u2713"
failed = "\u2717"
red = "\033[31m"
green = "\033[32m"
yellow = "\033[33m"
reset = "\033[0m"
atlasPatchInputSwaggerFile = "../../internal/testdata/atlaspatch.in.swagger.json"
jeepSvcInputSwaggerFile = "../../internal/testdata/jeepsvc.in.swagger.json"
)

func deepCompare(file1, file2 string) (bool, error) {
func deepCompare(t *testing.T, file1, file2 string) (bool, error) {
const chunkSize = 64000

f1, err := os.Open(file1)
Expand Down Expand Up @@ -55,18 +56,21 @@ func deepCompare(file1, file2 string) (bool, error) {
}

if !bytes.Equal(b1, b2) {
t.Logf("Name of file1 %s, Generated contents:\n%s\n-------------\n\nName of file2 name (Wanted contents) %s\n",
file1, string(b1), file2)
return false, nil
}
}
}

func createFiles(fileNames []string) error {
func createFiles(inFile string, fileNames []string) error {
var f []byte
f, err := ioutil.ReadFile(inFile)
if err != nil {
return err
}

for _, file := range fileNames {
var f []byte
f, err := ioutil.ReadFile(sampleSwaggerFile)
if err != nil {
return err
}
err = ioutil.WriteFile(file, f, os.FileMode(0666))
return err
}
Expand All @@ -87,12 +91,17 @@ func Test_run(t *testing.T) {
type args struct {
withPrivate bool
withCustomAnnotations bool
withPostResponse int
withPutResponse int
withPatchResponse int
withDeleteResponse int
files []string
}
tests := []struct {
name string
args args
wantErr bool
inputFile string
wantFile string
generatedFiles []string
}{
Expand All @@ -104,6 +113,7 @@ func Test_run(t *testing.T) {
withCustomAnnotations: false,
files: []string{"../../internal/testdata/atlaspatch.emitted.swagger.json"},
},
inputFile: atlasPatchInputSwaggerFile,
wantFile: "../../internal/testdata/atlaspatch.wanted.swagger.json",
generatedFiles: []string{"../../internal/testdata/atlaspatch.emitted.swagger.json"},
},
Expand All @@ -115,6 +125,7 @@ func Test_run(t *testing.T) {
withCustomAnnotations: true,
files: []string{"../../internal/testdata/atlaspatch.emitted.swagger.json"},
},
inputFile: atlasPatchInputSwaggerFile,
wantFile: "../../internal/testdata/atlaspatch.wanted.swagger.json",
generatedFiles: []string{"../../internal/testdata/atlaspatch.emitted.swagger.json"},
},
Expand All @@ -126,16 +137,72 @@ func Test_run(t *testing.T) {
withCustomAnnotations: false,
files: []string{"../../internal/testdata/atlaspatch.emitted.swagger.json"},
},
inputFile: atlasPatchInputSwaggerFile,
wantFile: "../../internal/testdata/atlaspatch.wanted.private.swagger.json",
generatedFiles: []string{"../../internal/testdata/atlaspatch.emitted.private.swagger.json"},
},
{
name: "with custom HTTP response codes 1 - use non-default response codes",
wantErr: false,
args: args{
withPostResponse: 302,
withPutResponse: 303,
withPatchResponse: 304,
withDeleteResponse: 305,
files: []string{"../../internal/testdata/atlaspatch.emitted.customresponses1.swagger.json"},
},
inputFile: atlasPatchInputSwaggerFile,
wantFile: "../../internal/testdata/atlaspatch.wanted.customresponses1.swagger.json",
generatedFiles: []string{"../../internal/testdata/atlaspatch.emitted.customresponses1.swagger.json"},
},
{
name: "with custom HTTP response codes 2 - use 200 response codes",
wantErr: false,
args: args{
withPostResponse: 200,
withPutResponse: 200,
withPatchResponse: 200,
withDeleteResponse: 200,
files: []string{"../../internal/testdata/atlaspatch.emitted.customresponses2.swagger.json"},
},
inputFile: atlasPatchInputSwaggerFile,
wantFile: "../../internal/testdata/atlaspatch.wanted.customresponses2.swagger.json",
generatedFiles: []string{"../../internal/testdata/atlaspatch.emitted.customresponses2.swagger.json"},
},
{
name: "jeep svc file with custom HTTP response codes - use 200 response codes",
wantErr: false,
args: args{
withPostResponse: 200,
withPutResponse: 200,
withPatchResponse: 200,
withDeleteResponse: 200,
files: []string{"../../internal/testdata/jeepsvc.emitted.customresponses.swagger.json"},
},
inputFile: jeepSvcInputSwaggerFile,
wantFile: "../../internal/testdata/jeepsvc.wanted.customresponses.swagger.json",
generatedFiles: []string{"../../internal/testdata/jeepsvc.emitted.customresponses.swagger.json"},
},
}

reg := descriptor.NewRegistry()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
reg.SetPrivateOperations(tt.args.withPrivate)
reg.SetCustomAnnotations(tt.args.withCustomAnnotations)
err := createFiles(tt.args.files)
if tt.args.withPostResponse > 0 {
reg.SetPostResponse(tt.args.withPostResponse)
}
if tt.args.withPutResponse > 0 {
reg.SetPutResponse(tt.args.withPutResponse)
}
if tt.args.withPatchResponse > 0 {
reg.SetPatchResponse(tt.args.withPatchResponse)
}
if tt.args.withDeleteResponse > 0 {
reg.SetDeleteResponse(tt.args.withDeleteResponse)
}
err := createFiles(tt.inputFile, tt.args.files)
defer deleteFiles(tt.generatedFiles)
defer deleteFiles(tt.args.files)
if err != nil {
Expand All @@ -147,7 +214,7 @@ func Test_run(t *testing.T) {
return
}

isEqual, err := deepCompare(tt.generatedFiles[0], tt.wantFile)
isEqual, err := deepCompare(t, tt.generatedFiles[0], tt.wantFile)
if err != nil {
t.Errorf("Emitted vs wanted files content comparison error: %v", err)
return
Expand Down
59 changes: 57 additions & 2 deletions internal/descriptor/registry.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,71 @@
package descriptor

import "fmt"
import (
"fmt"

genopenapi "github.com/infobloxopen/atlas-openapiv2-patch/pkg/svc"
)

type Registry struct {
// privateOperations if true, respect private annotations and generate separate openapi files for private ops
privateOperations bool

// customAnnotations if true, allow custom annotations in the openapi spec
customAnnotations bool

// Response code for POST API
postResponse int

// Response code for PUT API
putResponse int

// Response code for PATCH API
patchResponse int

// Response code for DELETE API
deleteResponse int
}

func (r *Registry) PutResponse() int {
return r.putResponse
}

func (r *Registry) SetPutResponse(putResponse int) {
r.putResponse = putResponse
}

func (r *Registry) PatchResponse() int {
return r.patchResponse
}

func (r *Registry) SetPatchResponse(patchResponse int) {
r.patchResponse = patchResponse
}

func (r *Registry) PostResponse() int {
return r.postResponse
}

func (r *Registry) SetPostResponse(postResponse int) {
r.postResponse = postResponse
}

func (r *Registry) DeleteResponse() int {
return r.deleteResponse
}

func (r *Registry) SetDeleteResponse(deleteResponse int) {
r.deleteResponse = deleteResponse
}

func NewRegistry() *Registry {
return &Registry{
privateOperations: false,
customAnnotations: false,
postResponse: genopenapi.DefaultPostResponse,
putResponse: genopenapi.DefaultPutResponse,
patchResponse: genopenapi.DefaultPatchResponse,
deleteResponse: genopenapi.DefaultDeleteResponse,
}
}

Expand Down Expand Up @@ -42,6 +94,9 @@ func (r *Registry) String() string {
privateOperations ` + fmt.Sprintf("%t", r.privateOperations) + `
customAnnotations ` + fmt.Sprintf("%t", r.customAnnotations) + `
postResponse ` + fmt.Sprintf("%d", r.postResponse) + `
putResponse ` + fmt.Sprintf("%d", r.putResponse) + `
patchResponse ` + fmt.Sprintf("%d", r.patchResponse) + `
deleteResponse ` + fmt.Sprintf("%d", r.deleteResponse) + `
`
}
File renamed without changes.
Loading

0 comments on commit f14c5b8

Please sign in to comment.