-
Notifications
You must be signed in to change notification settings - Fork 15
/
resolver.go
112 lines (92 loc) · 2.9 KB
/
resolver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package openapi3
import (
"encoding/json"
"fmt"
openapi "github.com/getkin/kin-openapi/openapi3"
"github.com/jexia/semaphore/v2/pkg/broker"
"github.com/jexia/semaphore/v2/pkg/broker/logger"
"github.com/jexia/semaphore/v2/pkg/providers"
"github.com/jexia/semaphore/v2/pkg/specs"
"go.uber.org/zap"
)
const (
// XPackageExtensionField is the name of an info property which is used to define package name.
// Example:
//
// info:
// x-semaphore-package: com.semaphore
// components:
// <the rest of file>
XPackageExtensionField = "x-semaphore-package"
// XModelName is the name of an optional extension property included into response and request objects,
// and defines a custom name for the object.
XModelName = "x-semaphore-model"
)
// a dictionary of file names to swagger documents.
type swaggers map[string]*openapi.Swagger
// collect all the swagger documents from the paths.
// imports is a collection of all the files. The file path might include a mask.
// Example: []string{"/etc/schemas/user.yml", "/etc/schemas/animal_*.yml"} and so on.
func collect(ctx *broker.Context, imports []string) (swaggers, error) {
docs := swaggers{} // used to collect all the loaded & parsed swagger files
loader := openapi.NewSwaggerLoader()
for _, path := range imports {
files, err := providers.ResolvePath(ctx, []string{}, path)
if err != nil {
return nil, fmt.Errorf("failed to resolve path %s: %w", path, err)
}
// iterate over all the files matched by the single import path
for _, file := range files {
doc, err := loader.LoadSwaggerFromFile(file.Path)
if err != nil {
return nil, fmt.Errorf("failed to parse openapi file %s: %w", file.Path, err)
}
docs[file.Path] = doc
}
}
return docs, nil
}
// return canonical name based on the package name (optional extra field info.x-semaphore-package) and the given name
//
// Example:
//
// info:
// x-semaphore-package: com.semaphore
// paths:
// ...
//
// the canonical name for User is `com.semaphore.User`.
// If the package is not defined, the name is `User`.
func getCanonicalName(doc *openapi.Swagger, name string) string {
if doc.Info == nil {
return name
}
prop := doc.Info.Extensions[XPackageExtensionField]
if prop == nil {
return name
}
raw, ok := prop.(json.RawMessage)
if !ok {
return name
}
var pkg string
if err := json.Unmarshal(raw, &pkg); err != nil {
return name
}
return fmt.Sprintf("%s.%s", pkg, name)
}
// SchemaResolver returns a new schemaRef resolver for the given openapi collection
func SchemaResolver(paths []string) providers.SchemaResolver {
return func(ctx *broker.Context) (specs.Schemas, error) {
logger.Debug(ctx, "resolving openapi schemas", zap.Strings("paths", paths))
docs, err := collect(ctx, paths)
if err != nil {
return nil, err
}
schemas, err := newSchemas(docs)
if err != nil {
return nil, fmt.Errorf("failed to build schema: %w", err)
}
return schemas, nil
}
}