mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-04-06 01:38:10 +00:00
Check in the vendor directory
Travis seems to be having issues pulling deps, so we'll have to check in the vendor directory and prevent the makefile from trying to regenerate it normally.
This commit is contained in:
parent
98e16bc315
commit
a293b2bf94
2526 changed files with 930931 additions and 4 deletions
467
vendor/github.com/emicklei/go-restful-swagger12/model_builder.go
generated
vendored
Normal file
467
vendor/github.com/emicklei/go-restful-swagger12/model_builder.go
generated
vendored
Normal file
|
|
@ -0,0 +1,467 @@
|
|||
package swagger
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ModelBuildable is used for extending Structs that need more control over
|
||||
// how the Model appears in the Swagger api declaration.
|
||||
type ModelBuildable interface {
|
||||
PostBuildModel(m *Model) *Model
|
||||
}
|
||||
|
||||
type modelBuilder struct {
|
||||
Models *ModelList
|
||||
Config *Config
|
||||
}
|
||||
|
||||
type documentable interface {
|
||||
SwaggerDoc() map[string]string
|
||||
}
|
||||
|
||||
// Check if this structure has a method with signature func (<theModel>) SwaggerDoc() map[string]string
|
||||
// If it exists, retrive the documentation and overwrite all struct tag descriptions
|
||||
func getDocFromMethodSwaggerDoc2(model reflect.Type) map[string]string {
|
||||
if docable, ok := reflect.New(model).Elem().Interface().(documentable); ok {
|
||||
return docable.SwaggerDoc()
|
||||
}
|
||||
return make(map[string]string)
|
||||
}
|
||||
|
||||
// addModelFrom creates and adds a Model to the builder and detects and calls
|
||||
// the post build hook for customizations
|
||||
func (b modelBuilder) addModelFrom(sample interface{}) {
|
||||
if modelOrNil := b.addModel(reflect.TypeOf(sample), ""); modelOrNil != nil {
|
||||
// allow customizations
|
||||
if buildable, ok := sample.(ModelBuildable); ok {
|
||||
modelOrNil = buildable.PostBuildModel(modelOrNil)
|
||||
b.Models.Put(modelOrNil.Id, *modelOrNil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b modelBuilder) addModel(st reflect.Type, nameOverride string) *Model {
|
||||
// Turn pointers into simpler types so further checks are
|
||||
// correct.
|
||||
if st.Kind() == reflect.Ptr {
|
||||
st = st.Elem()
|
||||
}
|
||||
|
||||
modelName := b.keyFrom(st)
|
||||
if nameOverride != "" {
|
||||
modelName = nameOverride
|
||||
}
|
||||
// no models needed for primitive types
|
||||
if b.isPrimitiveType(modelName) {
|
||||
return nil
|
||||
}
|
||||
// golang encoding/json packages says array and slice values encode as
|
||||
// JSON arrays, except that []byte encodes as a base64-encoded string.
|
||||
// If we see a []byte here, treat it at as a primitive type (string)
|
||||
// and deal with it in buildArrayTypeProperty.
|
||||
if (st.Kind() == reflect.Slice || st.Kind() == reflect.Array) &&
|
||||
st.Elem().Kind() == reflect.Uint8 {
|
||||
return nil
|
||||
}
|
||||
// see if we already have visited this model
|
||||
if _, ok := b.Models.At(modelName); ok {
|
||||
return nil
|
||||
}
|
||||
sm := Model{
|
||||
Id: modelName,
|
||||
Required: []string{},
|
||||
Properties: ModelPropertyList{}}
|
||||
|
||||
// reference the model before further initializing (enables recursive structs)
|
||||
b.Models.Put(modelName, sm)
|
||||
|
||||
// check for slice or array
|
||||
if st.Kind() == reflect.Slice || st.Kind() == reflect.Array {
|
||||
b.addModel(st.Elem(), "")
|
||||
return &sm
|
||||
}
|
||||
// check for structure or primitive type
|
||||
if st.Kind() != reflect.Struct {
|
||||
return &sm
|
||||
}
|
||||
|
||||
fullDoc := getDocFromMethodSwaggerDoc2(st)
|
||||
modelDescriptions := []string{}
|
||||
|
||||
for i := 0; i < st.NumField(); i++ {
|
||||
field := st.Field(i)
|
||||
jsonName, modelDescription, prop := b.buildProperty(field, &sm, modelName)
|
||||
if len(modelDescription) > 0 {
|
||||
modelDescriptions = append(modelDescriptions, modelDescription)
|
||||
}
|
||||
|
||||
// add if not omitted
|
||||
if len(jsonName) != 0 {
|
||||
// update description
|
||||
if fieldDoc, ok := fullDoc[jsonName]; ok {
|
||||
prop.Description = fieldDoc
|
||||
}
|
||||
// update Required
|
||||
if b.isPropertyRequired(field) {
|
||||
sm.Required = append(sm.Required, jsonName)
|
||||
}
|
||||
sm.Properties.Put(jsonName, prop)
|
||||
}
|
||||
}
|
||||
|
||||
// We always overwrite documentation if SwaggerDoc method exists
|
||||
// "" is special for documenting the struct itself
|
||||
if modelDoc, ok := fullDoc[""]; ok {
|
||||
sm.Description = modelDoc
|
||||
} else if len(modelDescriptions) != 0 {
|
||||
sm.Description = strings.Join(modelDescriptions, "\n")
|
||||
}
|
||||
|
||||
// update model builder with completed model
|
||||
b.Models.Put(modelName, sm)
|
||||
|
||||
return &sm
|
||||
}
|
||||
|
||||
func (b modelBuilder) isPropertyRequired(field reflect.StructField) bool {
|
||||
required := true
|
||||
if jsonTag := field.Tag.Get("json"); jsonTag != "" {
|
||||
s := strings.Split(jsonTag, ",")
|
||||
if len(s) > 1 && s[1] == "omitempty" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return required
|
||||
}
|
||||
|
||||
func (b modelBuilder) buildProperty(field reflect.StructField, model *Model, modelName string) (jsonName, modelDescription string, prop ModelProperty) {
|
||||
jsonName = b.jsonNameOfField(field)
|
||||
if len(jsonName) == 0 {
|
||||
// empty name signals skip property
|
||||
return "", "", prop
|
||||
}
|
||||
|
||||
if field.Name == "XMLName" && field.Type.String() == "xml.Name" {
|
||||
// property is metadata for the xml.Name attribute, can be skipped
|
||||
return "", "", prop
|
||||
}
|
||||
|
||||
if tag := field.Tag.Get("modelDescription"); tag != "" {
|
||||
modelDescription = tag
|
||||
}
|
||||
|
||||
prop.setPropertyMetadata(field)
|
||||
if prop.Type != nil {
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
fieldType := field.Type
|
||||
|
||||
// check if type is doing its own marshalling
|
||||
marshalerType := reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
||||
if fieldType.Implements(marshalerType) {
|
||||
var pType = "string"
|
||||
if prop.Type == nil {
|
||||
prop.Type = &pType
|
||||
}
|
||||
if prop.Format == "" {
|
||||
prop.Format = b.jsonSchemaFormat(b.keyFrom(fieldType))
|
||||
}
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
|
||||
// check if annotation says it is a string
|
||||
if jsonTag := field.Tag.Get("json"); jsonTag != "" {
|
||||
s := strings.Split(jsonTag, ",")
|
||||
if len(s) > 1 && s[1] == "string" {
|
||||
stringt := "string"
|
||||
prop.Type = &stringt
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
}
|
||||
|
||||
fieldKind := fieldType.Kind()
|
||||
switch {
|
||||
case fieldKind == reflect.Struct:
|
||||
jsonName, prop := b.buildStructTypeProperty(field, jsonName, model)
|
||||
return jsonName, modelDescription, prop
|
||||
case fieldKind == reflect.Slice || fieldKind == reflect.Array:
|
||||
jsonName, prop := b.buildArrayTypeProperty(field, jsonName, modelName)
|
||||
return jsonName, modelDescription, prop
|
||||
case fieldKind == reflect.Ptr:
|
||||
jsonName, prop := b.buildPointerTypeProperty(field, jsonName, modelName)
|
||||
return jsonName, modelDescription, prop
|
||||
case fieldKind == reflect.String:
|
||||
stringt := "string"
|
||||
prop.Type = &stringt
|
||||
return jsonName, modelDescription, prop
|
||||
case fieldKind == reflect.Map:
|
||||
// if it's a map, it's unstructured, and swagger 1.2 can't handle it
|
||||
objectType := "object"
|
||||
prop.Type = &objectType
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
|
||||
fieldTypeName := b.keyFrom(fieldType)
|
||||
if b.isPrimitiveType(fieldTypeName) {
|
||||
mapped := b.jsonSchemaType(fieldTypeName)
|
||||
prop.Type = &mapped
|
||||
prop.Format = b.jsonSchemaFormat(fieldTypeName)
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
modelType := b.keyFrom(fieldType)
|
||||
prop.Ref = &modelType
|
||||
|
||||
if fieldType.Name() == "" { // override type of anonymous structs
|
||||
nestedTypeName := modelName + "." + jsonName
|
||||
prop.Ref = &nestedTypeName
|
||||
b.addModel(fieldType, nestedTypeName)
|
||||
}
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
|
||||
func hasNamedJSONTag(field reflect.StructField) bool {
|
||||
parts := strings.Split(field.Tag.Get("json"), ",")
|
||||
if len(parts) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, s := range parts[1:] {
|
||||
if s == "inline" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return len(parts[0]) > 0
|
||||
}
|
||||
|
||||
func (b modelBuilder) buildStructTypeProperty(field reflect.StructField, jsonName string, model *Model) (nameJson string, prop ModelProperty) {
|
||||
prop.setPropertyMetadata(field)
|
||||
// Check for type override in tag
|
||||
if prop.Type != nil {
|
||||
return jsonName, prop
|
||||
}
|
||||
fieldType := field.Type
|
||||
// check for anonymous
|
||||
if len(fieldType.Name()) == 0 {
|
||||
// anonymous
|
||||
anonType := model.Id + "." + jsonName
|
||||
b.addModel(fieldType, anonType)
|
||||
prop.Ref = &anonType
|
||||
return jsonName, prop
|
||||
}
|
||||
|
||||
if field.Name == fieldType.Name() && field.Anonymous && !hasNamedJSONTag(field) {
|
||||
// embedded struct
|
||||
sub := modelBuilder{new(ModelList), b.Config}
|
||||
sub.addModel(fieldType, "")
|
||||
subKey := sub.keyFrom(fieldType)
|
||||
// merge properties from sub
|
||||
subModel, _ := sub.Models.At(subKey)
|
||||
subModel.Properties.Do(func(k string, v ModelProperty) {
|
||||
model.Properties.Put(k, v)
|
||||
// if subModel says this property is required then include it
|
||||
required := false
|
||||
for _, each := range subModel.Required {
|
||||
if k == each {
|
||||
required = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if required {
|
||||
model.Required = append(model.Required, k)
|
||||
}
|
||||
})
|
||||
// add all new referenced models
|
||||
sub.Models.Do(func(key string, sub Model) {
|
||||
if key != subKey {
|
||||
if _, ok := b.Models.At(key); !ok {
|
||||
b.Models.Put(key, sub)
|
||||
}
|
||||
}
|
||||
})
|
||||
// empty name signals skip property
|
||||
return "", prop
|
||||
}
|
||||
// simple struct
|
||||
b.addModel(fieldType, "")
|
||||
var pType = b.keyFrom(fieldType)
|
||||
prop.Ref = &pType
|
||||
return jsonName, prop
|
||||
}
|
||||
|
||||
func (b modelBuilder) buildArrayTypeProperty(field reflect.StructField, jsonName, modelName string) (nameJson string, prop ModelProperty) {
|
||||
// check for type override in tags
|
||||
prop.setPropertyMetadata(field)
|
||||
if prop.Type != nil {
|
||||
return jsonName, prop
|
||||
}
|
||||
fieldType := field.Type
|
||||
if fieldType.Elem().Kind() == reflect.Uint8 {
|
||||
stringt := "string"
|
||||
prop.Type = &stringt
|
||||
return jsonName, prop
|
||||
}
|
||||
var pType = "array"
|
||||
prop.Type = &pType
|
||||
isPrimitive := b.isPrimitiveType(fieldType.Elem().Name())
|
||||
elemTypeName := b.getElementTypeName(modelName, jsonName, fieldType.Elem())
|
||||
prop.Items = new(Item)
|
||||
if isPrimitive {
|
||||
mapped := b.jsonSchemaType(elemTypeName)
|
||||
prop.Items.Type = &mapped
|
||||
} else {
|
||||
prop.Items.Ref = &elemTypeName
|
||||
}
|
||||
// add|overwrite model for element type
|
||||
if fieldType.Elem().Kind() == reflect.Ptr {
|
||||
fieldType = fieldType.Elem()
|
||||
}
|
||||
if !isPrimitive {
|
||||
b.addModel(fieldType.Elem(), elemTypeName)
|
||||
}
|
||||
return jsonName, prop
|
||||
}
|
||||
|
||||
func (b modelBuilder) buildPointerTypeProperty(field reflect.StructField, jsonName, modelName string) (nameJson string, prop ModelProperty) {
|
||||
prop.setPropertyMetadata(field)
|
||||
// Check for type override in tags
|
||||
if prop.Type != nil {
|
||||
return jsonName, prop
|
||||
}
|
||||
fieldType := field.Type
|
||||
|
||||
// override type of pointer to list-likes
|
||||
if fieldType.Elem().Kind() == reflect.Slice || fieldType.Elem().Kind() == reflect.Array {
|
||||
var pType = "array"
|
||||
prop.Type = &pType
|
||||
isPrimitive := b.isPrimitiveType(fieldType.Elem().Elem().Name())
|
||||
elemName := b.getElementTypeName(modelName, jsonName, fieldType.Elem().Elem())
|
||||
if isPrimitive {
|
||||
primName := b.jsonSchemaType(elemName)
|
||||
prop.Items = &Item{Ref: &primName}
|
||||
} else {
|
||||
prop.Items = &Item{Ref: &elemName}
|
||||
}
|
||||
if !isPrimitive {
|
||||
// add|overwrite model for element type
|
||||
b.addModel(fieldType.Elem().Elem(), elemName)
|
||||
}
|
||||
} else {
|
||||
// non-array, pointer type
|
||||
fieldTypeName := b.keyFrom(fieldType.Elem())
|
||||
var pType = b.jsonSchemaType(fieldTypeName) // no star, include pkg path
|
||||
if b.isPrimitiveType(fieldTypeName) {
|
||||
prop.Type = &pType
|
||||
prop.Format = b.jsonSchemaFormat(fieldTypeName)
|
||||
return jsonName, prop
|
||||
}
|
||||
prop.Ref = &pType
|
||||
elemName := ""
|
||||
if fieldType.Elem().Name() == "" {
|
||||
elemName = modelName + "." + jsonName
|
||||
prop.Ref = &elemName
|
||||
}
|
||||
b.addModel(fieldType.Elem(), elemName)
|
||||
}
|
||||
return jsonName, prop
|
||||
}
|
||||
|
||||
func (b modelBuilder) getElementTypeName(modelName, jsonName string, t reflect.Type) string {
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
if t.Name() == "" {
|
||||
return modelName + "." + jsonName
|
||||
}
|
||||
return b.keyFrom(t)
|
||||
}
|
||||
|
||||
func (b modelBuilder) keyFrom(st reflect.Type) string {
|
||||
key := st.String()
|
||||
if b.Config != nil && b.Config.ModelTypeNameHandler != nil {
|
||||
if name, ok := b.Config.ModelTypeNameHandler(st); ok {
|
||||
key = name
|
||||
}
|
||||
}
|
||||
if len(st.Name()) == 0 { // unnamed type
|
||||
// Swagger UI has special meaning for [
|
||||
key = strings.Replace(key, "[]", "||", -1)
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
// see also https://golang.org/ref/spec#Numeric_types
|
||||
func (b modelBuilder) isPrimitiveType(modelName string) bool {
|
||||
if len(modelName) == 0 {
|
||||
return false
|
||||
}
|
||||
return strings.Contains("uint uint8 uint16 uint32 uint64 int int8 int16 int32 int64 float32 float64 bool string byte rune time.Time", modelName)
|
||||
}
|
||||
|
||||
// jsonNameOfField returns the name of the field as it should appear in JSON format
|
||||
// An empty string indicates that this field is not part of the JSON representation
|
||||
func (b modelBuilder) jsonNameOfField(field reflect.StructField) string {
|
||||
if jsonTag := field.Tag.Get("json"); jsonTag != "" {
|
||||
s := strings.Split(jsonTag, ",")
|
||||
if s[0] == "-" {
|
||||
// empty name signals skip property
|
||||
return ""
|
||||
} else if s[0] != "" {
|
||||
return s[0]
|
||||
}
|
||||
}
|
||||
return field.Name
|
||||
}
|
||||
|
||||
// see also http://json-schema.org/latest/json-schema-core.html#anchor8
|
||||
func (b modelBuilder) jsonSchemaType(modelName string) string {
|
||||
schemaMap := map[string]string{
|
||||
"uint": "integer",
|
||||
"uint8": "integer",
|
||||
"uint16": "integer",
|
||||
"uint32": "integer",
|
||||
"uint64": "integer",
|
||||
|
||||
"int": "integer",
|
||||
"int8": "integer",
|
||||
"int16": "integer",
|
||||
"int32": "integer",
|
||||
"int64": "integer",
|
||||
|
||||
"byte": "integer",
|
||||
"float64": "number",
|
||||
"float32": "number",
|
||||
"bool": "boolean",
|
||||
"time.Time": "string",
|
||||
}
|
||||
mapped, ok := schemaMap[modelName]
|
||||
if !ok {
|
||||
return modelName // use as is (custom or struct)
|
||||
}
|
||||
return mapped
|
||||
}
|
||||
|
||||
func (b modelBuilder) jsonSchemaFormat(modelName string) string {
|
||||
if b.Config != nil && b.Config.SchemaFormatHandler != nil {
|
||||
if mapped := b.Config.SchemaFormatHandler(modelName); mapped != "" {
|
||||
return mapped
|
||||
}
|
||||
}
|
||||
schemaMap := map[string]string{
|
||||
"int": "int32",
|
||||
"int32": "int32",
|
||||
"int64": "int64",
|
||||
"byte": "byte",
|
||||
"uint": "integer",
|
||||
"uint8": "byte",
|
||||
"float64": "double",
|
||||
"float32": "float",
|
||||
"time.Time": "date-time",
|
||||
"*time.Time": "date-time",
|
||||
}
|
||||
mapped, ok := schemaMap[modelName]
|
||||
if !ok {
|
||||
return "" // no format
|
||||
}
|
||||
return mapped
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue