...
1
16
17 package builder
18
19 import (
20 "fmt"
21 "strings"
22
23 "k8s.io/kube-openapi/pkg/aggregator"
24 "k8s.io/kube-openapi/pkg/spec3"
25 "k8s.io/kube-openapi/pkg/validation/spec"
26 )
27
28 const metadataGV = "io.k8s.apimachinery.pkg.apis.meta.v1"
29 const autoscalingGV = "io.k8s.api.autoscaling.v1"
30
31
32
33
34 func MergeSpecs(staticSpec *spec.Swagger, crdSpecs ...*spec.Swagger) (*spec.Swagger, error) {
35
36 specToReturn := *staticSpec
37 if staticSpec.Definitions != nil {
38 specToReturn.Definitions = make(spec.Definitions, len(staticSpec.Definitions))
39 for k, s := range staticSpec.Definitions {
40 specToReturn.Definitions[k] = s
41 }
42 }
43 if staticSpec.Parameters != nil {
44 specToReturn.Parameters = make(map[string]spec.Parameter, len(staticSpec.Parameters))
45 for k, s := range staticSpec.Parameters {
46 specToReturn.Parameters[k] = s
47 }
48 }
49 if staticSpec.Paths != nil {
50 specToReturn.Paths = &spec.Paths{
51 Paths: make(map[string]spec.PathItem, len(staticSpec.Paths.Paths)),
52 }
53 for k, p := range staticSpec.Paths.Paths {
54 specToReturn.Paths.Paths[k] = p
55 }
56 }
57
58 crdSpec := &spec.Swagger{}
59 for _, s := range crdSpecs {
60
61
62 mergeSpec(crdSpec, s)
63 }
64
65
66
67 if err := aggregator.MergeSpecsIgnorePathConflictRenamingDefinitionsAndParameters(&specToReturn, crdSpec); err != nil {
68 return nil, err
69 }
70 return &specToReturn, nil
71 }
72
73
74
75 func mergeSpec(dest, source *spec.Swagger) {
76 if source == nil || source.Paths == nil {
77 return
78 }
79 if dest.Paths == nil {
80 dest.Paths = &spec.Paths{}
81 }
82 for k, v := range source.Definitions {
83 if dest.Definitions == nil {
84 dest.Definitions = make(spec.Definitions, len(source.Definitions))
85 }
86 dest.Definitions[k] = v
87 }
88 for k, v := range source.Parameters {
89 if dest.Parameters == nil {
90 dest.Parameters = make(map[string]spec.Parameter, len(source.Parameters))
91 }
92 dest.Parameters[k] = v
93 }
94 for k, v := range source.Paths.Paths {
95 if dest.Paths.Paths == nil {
96 dest.Paths.Paths = make(map[string]spec.PathItem, len(source.Paths.Paths))
97 }
98 dest.Paths.Paths[k] = v
99 }
100 }
101
102
103
104
105 func MergeSpecsV3(crdSpecs ...*spec3.OpenAPI) (*spec3.OpenAPI, error) {
106 crdSpec := &spec3.OpenAPI{}
107 if len(crdSpecs) > 0 {
108 crdSpec.Version = crdSpecs[0].Version
109 crdSpec.Info = crdSpecs[0].Info
110 }
111 for _, s := range crdSpecs {
112 err := mergeSpecV3(crdSpec, s)
113 if err != nil {
114 return nil, err
115 }
116 }
117 return crdSpec, nil
118 }
119
120
121
122
123 func mergeSpecV3(dest, source *spec3.OpenAPI) error {
124 if source == nil || source.Paths == nil {
125 return nil
126 }
127 if dest.Paths == nil {
128 dest.Paths = &spec3.Paths{}
129 }
130
131 for k, v := range source.Components.Schemas {
132 if dest.Components == nil {
133 dest.Components = &spec3.Components{}
134 }
135 if dest.Components.Schemas == nil {
136 dest.Components.Schemas = map[string]*spec.Schema{}
137 }
138 if _, exists := dest.Components.Schemas[k]; exists {
139 if strings.HasPrefix(k, metadataGV) || strings.HasPrefix(k, autoscalingGV) {
140 continue
141 }
142 return fmt.Errorf("OpenAPI V3 merge schema conflict on %s", k)
143 }
144 dest.Components.Schemas[k] = v
145 }
146 for k, v := range source.Paths.Paths {
147 if dest.Paths.Paths == nil {
148 dest.Paths.Paths = map[string]*spec3.Path{}
149 }
150 dest.Paths.Paths[k] = v
151 }
152 return nil
153 }
154
View as plain text