mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-11-23 23:00:19 +00:00
288 lines
8.2 KiB
Go
288 lines
8.2 KiB
Go
|
// 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"
|
||
|
"net/url"
|
||
|
|
||
|
discovery "github.com/googleapis/gnostic/discovery"
|
||
|
openapi2 "github.com/googleapis/gnostic/OpenAPIv2"
|
||
|
)
|
||
|
|
||
|
func addOpenAPI2SchemaForSchema(d *openapi2.Document, name string, schema *discovery.Schema) {
|
||
|
//log.Printf("SCHEMA %s\n", name)
|
||
|
d.Definitions.AdditionalProperties = append(d.Definitions.AdditionalProperties,
|
||
|
&openapi2.NamedSchema{
|
||
|
Name: name,
|
||
|
Value: buildOpenAPI2SchemaForSchema(schema),
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func buildOpenAPI2SchemaForSchema(schema *discovery.Schema) *openapi2.Schema {
|
||
|
s := &openapi2.Schema{}
|
||
|
|
||
|
if description := schema.Description; description != "" {
|
||
|
s.Description = description
|
||
|
}
|
||
|
if typeName := schema.Type; typeName != "" {
|
||
|
s.Type = &openapi2.TypeItem{[]string{typeName}}
|
||
|
}
|
||
|
if ref := schema.XRef; ref != "" {
|
||
|
s.XRef = "#/definitions/" + ref
|
||
|
}
|
||
|
if len(schema.Enum) > 0 {
|
||
|
for _, e := range schema.Enum {
|
||
|
s.Enum = append(s.Enum, &openapi2.Any{Yaml: e})
|
||
|
}
|
||
|
}
|
||
|
if schema.Items != nil {
|
||
|
s2 := buildOpenAPI2SchemaForSchema(schema.Items)
|
||
|
s.Items = &openapi2.ItemsItem{}
|
||
|
s.Items.Schema = append(s.Items.Schema, s2)
|
||
|
}
|
||
|
if schema.Properties != nil {
|
||
|
if len(schema.Properties.AdditionalProperties) > 0 {
|
||
|
s.Properties = &openapi2.Properties{}
|
||
|
for _, pair := range schema.Properties.AdditionalProperties {
|
||
|
s.Properties.AdditionalProperties = append(s.Properties.AdditionalProperties,
|
||
|
&openapi2.NamedSchema{
|
||
|
Name: pair.Name,
|
||
|
Value: buildOpenAPI2SchemaForSchema(pair.Value),
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// assume that all schemas are closed
|
||
|
s.AdditionalProperties = &openapi2.AdditionalPropertiesItem{Oneof: &openapi2.AdditionalPropertiesItem_Boolean{Boolean: false}}
|
||
|
return s
|
||
|
}
|
||
|
|
||
|
func buildOpenAPI2ParameterForParameter(name string, p *discovery.Parameter) *openapi2.Parameter {
|
||
|
//log.Printf("- PARAMETER %+v\n", p.Name)
|
||
|
typeName := p.Type
|
||
|
format := p.Format
|
||
|
location := p.Location
|
||
|
switch location {
|
||
|
case "query":
|
||
|
return &openapi2.Parameter{
|
||
|
Oneof: &openapi2.Parameter_NonBodyParameter{
|
||
|
NonBodyParameter: &openapi2.NonBodyParameter{
|
||
|
Oneof: &openapi2.NonBodyParameter_QueryParameterSubSchema{
|
||
|
QueryParameterSubSchema: &openapi2.QueryParameterSubSchema{
|
||
|
Name: name,
|
||
|
In: "query",
|
||
|
Description: p.Description,
|
||
|
Required: p.Required,
|
||
|
Type: typeName,
|
||
|
Format: format,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
case "path":
|
||
|
return &openapi2.Parameter{
|
||
|
Oneof: &openapi2.Parameter_NonBodyParameter{
|
||
|
NonBodyParameter: &openapi2.NonBodyParameter{
|
||
|
Oneof: &openapi2.NonBodyParameter_PathParameterSubSchema{
|
||
|
PathParameterSubSchema: &openapi2.PathParameterSubSchema{
|
||
|
Name: name,
|
||
|
In: "path",
|
||
|
Description: p.Description,
|
||
|
Required: p.Required,
|
||
|
Type: typeName,
|
||
|
Format: format,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
default:
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func buildOpenAPI2ParameterForRequest(p *discovery.Request) *openapi2.Parameter {
|
||
|
return &openapi2.Parameter{
|
||
|
Oneof: &openapi2.Parameter_BodyParameter{
|
||
|
BodyParameter: &openapi2.BodyParameter{
|
||
|
Name: "resource",
|
||
|
In: "body",
|
||
|
Description: "",
|
||
|
Schema: &openapi2.Schema{XRef: "#/definitions/" + p.XRef},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func buildOpenAPI2ResponseForResponse(response *discovery.Response) *openapi2.Response {
|
||
|
//log.Printf("- RESPONSE %+v\n", schema)
|
||
|
if response == nil {
|
||
|
return &openapi2.Response{
|
||
|
Description: "Successful operation",
|
||
|
}
|
||
|
}
|
||
|
ref := response.XRef
|
||
|
if ref == "" {
|
||
|
log.Printf("WARNING: Unhandled response %+v", response)
|
||
|
}
|
||
|
return &openapi2.Response{
|
||
|
Description: "Successful operation",
|
||
|
Schema: &openapi2.SchemaItem{
|
||
|
Oneof: &openapi2.SchemaItem_Schema{
|
||
|
Schema: &openapi2.Schema{
|
||
|
XRef: "#/definitions/" + ref,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func buildOpenAPI2OperationForMethod(method *discovery.Method) *openapi2.Operation {
|
||
|
//log.Printf("METHOD %s %s %s %s\n", method.Name, method.path(), method.HTTPMethod, method.ID)
|
||
|
//log.Printf("MAP %+v\n", method.JSONMap)
|
||
|
parameters := make([]*openapi2.ParametersItem, 0)
|
||
|
if method.Parameters != nil {
|
||
|
for _, pair := range method.Parameters.AdditionalProperties {
|
||
|
parameters = append(parameters, &openapi2.ParametersItem{
|
||
|
Oneof: &openapi2.ParametersItem_Parameter{
|
||
|
Parameter: buildOpenAPI2ParameterForParameter(pair.Name, pair.Value),
|
||
|
},
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
responses := &openapi2.Responses{
|
||
|
ResponseCode: []*openapi2.NamedResponseValue{
|
||
|
&openapi2.NamedResponseValue{
|
||
|
Name: "default",
|
||
|
Value: &openapi2.ResponseValue{
|
||
|
Oneof: &openapi2.ResponseValue_Response{
|
||
|
Response: buildOpenAPI2ResponseForResponse(method.Response),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
if method.Request != nil {
|
||
|
parameter := buildOpenAPI2ParameterForRequest(method.Request)
|
||
|
parameters = append(parameters, &openapi2.ParametersItem{
|
||
|
Oneof: &openapi2.ParametersItem_Parameter{
|
||
|
Parameter: parameter,
|
||
|
},
|
||
|
})
|
||
|
}
|
||
|
return &openapi2.Operation{
|
||
|
Description: method.Description,
|
||
|
OperationId: method.Id,
|
||
|
Parameters: parameters,
|
||
|
Responses: responses,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func getOpenAPI2PathItemForPath(d *openapi2.Document, path string) *openapi2.PathItem {
|
||
|
// First, try to find a path item with the specified path. If it exists, return it.
|
||
|
for _, item := range d.Paths.Path {
|
||
|
if item.Name == path {
|
||
|
return item.Value
|
||
|
}
|
||
|
}
|
||
|
// Otherwise, create and return a new path item.
|
||
|
pathItem := &openapi2.PathItem{}
|
||
|
d.Paths.Path = append(d.Paths.Path,
|
||
|
&openapi2.NamedPathItem{
|
||
|
Name: path,
|
||
|
Value: pathItem,
|
||
|
},
|
||
|
)
|
||
|
return pathItem
|
||
|
}
|
||
|
|
||
|
func addOpenAPI2PathsForMethod(d *openapi2.Document, name string, method *discovery.Method) {
|
||
|
operation := buildOpenAPI2OperationForMethod(method)
|
||
|
pathItem := getOpenAPI2PathItemForPath(d, pathForMethod(method.Path))
|
||
|
switch method.HttpMethod {
|
||
|
case "GET":
|
||
|
pathItem.Get = operation
|
||
|
case "POST":
|
||
|
pathItem.Post = operation
|
||
|
case "PUT":
|
||
|
pathItem.Put = operation
|
||
|
case "DELETE":
|
||
|
pathItem.Delete = operation
|
||
|
case "PATCH":
|
||
|
pathItem.Patch = operation
|
||
|
default:
|
||
|
log.Printf("WARNING: Unknown HTTP method %s", method.HttpMethod)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func addOpenAPI2PathsForResource(d *openapi2.Document, name string, resource *discovery.Resource) {
|
||
|
//log.Printf("RESOURCE %s (%s)\n", resource.Name, resource.FullName)
|
||
|
if resource.Methods != nil {
|
||
|
for _, pair := range resource.Methods.AdditionalProperties {
|
||
|
addOpenAPI2PathsForMethod(d, pair.Name, pair.Value)
|
||
|
}
|
||
|
}
|
||
|
if resource.Resources != nil {
|
||
|
for _, pair := range resource.Resources.AdditionalProperties {
|
||
|
addOpenAPI2PathsForResource(d, pair.Name, pair.Value)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func removeTrailingSlash(path string) string {
|
||
|
if len(path) > 1 && path[len(path)-1] == '/' {
|
||
|
return path[0: len(path)-1]
|
||
|
}
|
||
|
return path
|
||
|
}
|
||
|
|
||
|
// OpenAPIv2 returns an OpenAPI v2 representation of this Discovery document
|
||
|
func OpenAPIv2(api *discovery.Document) (*openapi2.Document, error) {
|
||
|
d := &openapi2.Document{}
|
||
|
d.Swagger = "2.0"
|
||
|
d.Info = &openapi2.Info{
|
||
|
Title: api.Title,
|
||
|
Version: api.Version,
|
||
|
Description: api.Description,
|
||
|
}
|
||
|
url, _ := url.Parse(api.RootUrl)
|
||
|
d.Host = url.Host
|
||
|
d.BasePath = removeTrailingSlash(api.BasePath)
|
||
|
d.Schemes = []string{url.Scheme}
|
||
|
d.Consumes = []string{"application/json"}
|
||
|
d.Produces = []string{"application/json"}
|
||
|
d.Paths = &openapi2.Paths{}
|
||
|
d.Definitions = &openapi2.Definitions{}
|
||
|
if api.Schemas != nil {
|
||
|
for _, pair := range api.Schemas.AdditionalProperties {
|
||
|
addOpenAPI2SchemaForSchema(d, pair.Name, pair.Value)
|
||
|
}
|
||
|
}
|
||
|
if api.Methods != nil {
|
||
|
for _, pair := range api.Methods.AdditionalProperties {
|
||
|
addOpenAPI2PathsForMethod(d, pair.Name, pair.Value)
|
||
|
}
|
||
|
}
|
||
|
if api.Resources != nil {
|
||
|
for _, pair := range api.Resources.AdditionalProperties {
|
||
|
addOpenAPI2PathsForResource(d, pair.Name, pair.Value)
|
||
|
}
|
||
|
}
|
||
|
return d, nil
|
||
|
}
|