Skip to content

Commit

Permalink
Merge pull request grpc-ecosystem#3 from infobloxopen/fix-protoc-gen-…
Browse files Browse the repository at this point in the history
…swagger-atlas-patch

 * Fixed not-present description
 * Fixed PATCH methods absence
 * Collection operators documentation refactoring
 * Fixed Non-Unqiue Identifier
  • Loading branch information
askurydzin authored Sep 7, 2018
2 parents 74b2663 + 2890d02 commit 0c7b648
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 67 deletions.
146 changes: 83 additions & 63 deletions protoc-gen-swagger/genswagger/atlas_patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import (
)

var (
sw spec.Swagger
seenRefs = map[string]bool{}
sw spec.Swagger
seenRefs = map[string]bool{}
)

func atlasSwagger(b []byte) string {
Expand Down Expand Up @@ -51,79 +51,74 @@ func atlasSwagger(b []byte) string {
if op == nil {
continue
}

fixedParams := []spec.Parameter{}
for _, param := range op.Parameters {

// Fix Collection Operators
if strings.HasPrefix(param.Description, "atlas.api.") {
switch strings.TrimPrefix(param.Description, "atlas.api.") {

case "filtering":
fixedParams = append(fixedParams, *(spec.QueryParam("_filter")).WithDescription(
"A collection of response resources can be filtered by a logical expression " +
"string that includes JSON tag references to values in each resource, literal " +
"values, and logical operators. If a resource does not have the specified tag, " +
"its value is assumed to be null." +
"\n" +
"Literal values include numbers (integer and floating-point), and quoted " +
"(both single- or double-quoted) literal strings, and “null”. The following " +
"operators are commonly used in filter expressions:\n" +
" | Op | Description |\n" +
" | -- | ----------- |\n" +
" | == | Equal |\n" +
" | != | Not Equal |\n" +
" | > | Greater Than |\n" +
" | >= | Greater Than or Equal To |\n" +
" | < | Less Than |\n" +
" | <= | Less Than or Equal To |\n" +
" | and | Logical AND |\n" +
" | ~ | Matches Regex |\n" +
" | !~ | Does Not Match Regex |\n" +
" | or | Logical OR |\n" +
" | not | Logical NOT |\n" +
" | () | Groupping Operators |\n",
).Typed("string", ""))
fixedParams = append(fixedParams, *(spec.QueryParam("_filter")).WithDescription(`
A collection of response resources can be filtered by a logical expression string that includes JSON tag references to values in each resource, literal values, and logical operators. If a resource does not have the specified tag, its value is assumed to be null.
Literal values include numbers (integer and floating-point), and quoted (both single- or double-quoted) literal strings, and 'null'. The following operators are commonly used in filter expressions:
| Op | Description |
| -- | ----------- |
| == | Equal |
| != | Not Equal |
| > | Greater Than |
| >= | Greater Than or Equal To |
| < | Less Than |
| <= | Less Than or Equal To |
| and | Logical AND |
| ~ | Matches Regex |
| !~ | Does Not Match Regex |
| or | Logical OR |
| not | Logical NOT |
| () | Groupping Operators |
`).Typed("string", ""))

case "sorting":
fixedParams = append(fixedParams, *(spec.QueryParam("_order_by")).WithDescription(
"A collection of response resources can be sorted by their JSON tags. For a " +
"“flat” resource, the tag name is straightforward. If sorting is allowed on " +
"non-flat hierarchical resources, the service should implement a qualified " +
"naming scheme such as dot-qualification to reference data down the hierarchy. " +
"If a resource does not have the specified tag, its value is assumed to be null.)" +
"\n\n" +
"Specify this parameter as a comma-separated list of JSON tag names. The sort " +
"direction can be specified by a suffix separated by whitespace before the tag " +
"name. The suffix “asc” sorts the data in ascending order. The suffix “desc” " +
"sorts the data in descending order. If no suffix is specified the data is sorted " +
"in ascending order.",
).Typed("string", ""))
fixedParams = append(fixedParams, *(spec.QueryParam("_order_by")).WithDescription(`
A collection of response resources can be sorted by their JSON tags. For a 'flat' resource, the tag name is straightforward. If sorting is allowed on non-flat hierarchical resources, the service should implement a qualified naming scheme such as dot-qualification to reference data down the hierarchy. If a resource does not have the specified tag, its value is assumed to be null.)
Specify this parameter as a comma-separated list of JSON tag names. The sort direction can be specified by a suffix separated by whitespace before the tag name. The suffix 'asc' sorts the data in ascending order. The suffix 'desc' sorts the data in descending order. If no suffix is specified the data is sorted in ascending order.
`).Typed("string", ""))

case "field_selection":
fixedParams = append(fixedParams, *(spec.QueryParam("_fields")).WithDescription(

"A collection of response resources can be transformed by specifying a set of JSON " +
"tags to be returned. For a “flat” resource, the tag name is straightforward. If " +
"field selection is allowed on non-flat hierarchical resources, the service should " +
"implement a qualified naming scheme such as dot-qualification to reference data down " +
"the hierarchy. If a resource does not have the specified tag, the tag does not appear " +
"in the output resource." +
"\n\n" +
"Specify this parameter as a comma-separated list of JSON tag names.",
).Typed("string", ""))
fixedParams = append(fixedParams, *(spec.QueryParam("_fields")).WithDescription(`
A collection of response resources can be transformed by specifying a set of JSON tags to be returned. For a “flat” resource, the tag name is straightforward. If field selection is allowed on non-flat hierarchical resources, the service should implement a qualified naming scheme such as dot-qualification to reference data down the hierarchy. If a resource does not have the specified tag, the tag does not appear in the output resource.
Specify this parameter as a comma-separated list of JSON tag names.
`).Typed("string", ""))

case "paging":
fixedParams = append(
fixedParams,
*(spec.QueryParam("_offset")).WithDescription(
"The integer index (zero-origin) of the offset into a collection of resources. " +
"If omitted or null the value is assumed to be “0”.",
).Typed("integer", ""),
*(spec.QueryParam("_limit")).WithDescription(
"The integer number of resources to be returned in the response. The " +
"service may impose maximum value. If omitted the service may impose " +
"a default value.",
).Typed("integer", ""),
*(spec.QueryParam("_page_token")).WithDescription(
"The service-defined string used to identify a page of resources. A null value " +
"indicates the first page.",
).Typed("string", ""),
*(spec.QueryParam("_offset")).WithDescription(`
The integer index (zero-origin) of the offset into a collection of resources. If omitted or null the value is assumed to be '0'.
`).Typed("integer", ""),
*(spec.QueryParam("_limit")).WithDescription(`
The integer number of resources to be returned in the response. The service may impose maximum value. If omitted the service may impose a default value.
`).Typed("integer", ""),
*(spec.QueryParam("_page_token")).WithDescription(`
The service-defined string used to identify a page of resources. A null value indicates the first page.
`).Typed("string", ""),
)
// Skip ID
default:
Expand All @@ -145,6 +140,7 @@ func atlasSwagger(b []byte) string {
// Wrap responses
if op.Responses.StatusCodeResponses != nil {
rsp := op.Responses.StatusCodeResponses[200]

if !isNilRef(rsp.Schema.Ref) {
s, _, err := rsp.Schema.Ref.GetPointer().Get(sw)
if err != nil {
Expand All @@ -169,9 +165,16 @@ func atlasSwagger(b []byte) string {

delete(op.Responses.StatusCodeResponses, 200)

if rsp.Description == "" {
rsp.Description = on + " operation response"
}

op.Responses.StatusCodeResponses[opToCode(on)] = rsp
}
}

op.ID = strings.Join(op.Tags, "") + op.ID

}

pitem := fixedPaths[pn]
Expand All @@ -189,6 +192,8 @@ func atlasSwagger(b []byte) string {
pitem.Post = opPtr
case "DELETE":
pitem.Delete = opPtr
case "PATCH":
pitem.Patch = opPtr
}
}
fixedPaths[pn] = pitem
Expand Down Expand Up @@ -266,6 +271,18 @@ func checkRecursion(s spec.Schema, r spec.Ref, path []string) spec.Ref {
}
}

// TBD: common pattern.
if np == "created_time" || np == "updated_time" || np == "id" {
p.ReadOnly = true
}

// FIXME: copy additionalProperties as-is.
if addProps := p.AdditionalProperties; addProps != nil {
if addProps.Schema != nil && !isNilRef(addProps.Schema.Ref) {
seenRefs[trim(addProps.Schema.Ref)] = true
}
}

newProps[np] = p

sr := getPropRef(p)
Expand Down Expand Up @@ -348,6 +365,7 @@ func pathItemAsMap(pi spec.PathItem) map[string]*spec.Operation {
"POST": pi.Post,
"PUT": pi.Put,
"DELETE": pi.Delete,
"PATCH": pi.Patch,
}
}

Expand All @@ -356,6 +374,7 @@ func opToCode(on string) int {
"GET": 200,
"POST": 201,
"PUT": 202,
"PATCH": 202,
"DELETE": 203,
}[on]
}
Expand All @@ -365,6 +384,7 @@ func opToStatus(on string) string {
"GET": "OK",
"POST": "CREATED",
"PUT": "UPDATED",
"PATCH": "UPDATED",
"DELETE": "DELETED",
}[on]
}
34 changes: 30 additions & 4 deletions protoc-gen-swagger/genswagger/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ func schemaOfField(f *descriptor.Field, reg *descriptor.Registry, refs refMap) s
schemaCore: core,
}
if j, err := extractJSONSchemaFromFieldDescriptor(fd); err == nil {
updateSwaggerObjectFromJSONSchema(&ret, j)
updateSwaggerObjectFromJSONSchema(&ret, j, reg)
}
return ret
}
Expand Down Expand Up @@ -1371,15 +1371,15 @@ func protoJSONSchemaToSwaggerSchemaCore(j *swagger_options.JSONSchema, reg *desc
ret.Ref += j.GetRef()
}
} else {
f, t := protoJSONSchemaTypeToFormat(j.GetType())
t, f := protoJSONSchemaTypeToFormat(j.GetType())
ret.Format = f
ret.Type = t
}

return ret
}

func updateSwaggerObjectFromJSONSchema(s *swaggerSchemaObject, j *swagger_options.JSONSchema) {
func updateSwaggerObjectFromJSONSchema(s *swaggerSchemaObject, j *swagger_options.JSONSchema, reg *descriptor.Registry) {
s.Title = j.GetTitle()
s.Description = j.GetDescription()
s.MultipleOf = j.GetMultipleOf()
Expand All @@ -1396,6 +1396,32 @@ func updateSwaggerObjectFromJSONSchema(s *swaggerSchemaObject, j *swagger_option
s.MaxProperties = j.GetMaxProperties()
s.MinProperties = j.GetMinProperties()
s.Required = j.GetRequired()


if arr := j.GetArray(); len(arr) > 0 {
s.Type = "array"
for _, e := range arr {
if v, ok := wktSchemas[e]; ok {
s.Items = (*swaggerItemsObject)(&v)
s.Ref = ""
break
} else if swaggerName := fullyQualifiedNameToSwaggerName(e, reg); swaggerName != "" {
s.Items = (*swaggerItemsObject)(&schemaCore{Type: "object", Ref: "#/definitions/" + swaggerName})
s.Ref = ""
break
} else {
panic("Must be either valid reference or primitive type")
}
}
} else if t, f := protoJSONSchemaTypeToFormat(j.GetType()); t != "" {
s.Type = t
s.Format = f
} else if j.GetRef() != "" {
ref := fullyQualifiedNameToSwaggerName(j.GetRef(), reg)
if ref != "" {
s.Ref = "#/definitions/" + ref
}
}
}

func swaggerSchemaFromProtoSchema(s *swagger_options.Schema, reg *descriptor.Registry, refs refMap) swaggerSchemaObject {
Expand All @@ -1404,7 +1430,7 @@ func swaggerSchemaFromProtoSchema(s *swagger_options.Schema, reg *descriptor.Reg
}

ret.schemaCore = protoJSONSchemaToSwaggerSchemaCore(s.GetJsonSchema(), reg, refs)
updateSwaggerObjectFromJSONSchema(&ret, s.GetJsonSchema())
updateSwaggerObjectFromJSONSchema(&ret, s.GetJsonSchema(), reg)

return ret
}
Expand Down

0 comments on commit 0c7b648

Please sign in to comment.