...
1
16
17 package testing
18
19 import (
20 "encoding/json"
21 "io"
22 "io/fs"
23 "net/http"
24 "net/http/httptest"
25 "os"
26 "path/filepath"
27 "strings"
28 "sync"
29
30 "k8s.io/kube-openapi/pkg/handler3"
31 "k8s.io/kube-openapi/pkg/spec3"
32 )
33
34 type FakeOpenAPIServer struct {
35 HttpServer *httptest.Server
36 ServedDocuments map[string]*spec3.OpenAPI
37 RequestCounters map[string]int
38 }
39
40
41
42
43
44
45
46
47 func NewFakeOpenAPIV3Server(specsPath string) (*FakeOpenAPIServer, error) {
48 mux := &testMux{
49 counts: map[string]int{},
50 }
51 server := httptest.NewServer(mux)
52
53 openAPIVersionedService := handler3.NewOpenAPIService()
54 err := openAPIVersionedService.RegisterOpenAPIV3VersionedService("/openapi/v3", mux)
55 if err != nil {
56 return nil, err
57 }
58
59 grouped := make(map[string][]byte)
60 var testV3Specs = make(map[string]*spec3.OpenAPI)
61
62 addSpec := func(path string) {
63 file, err := os.Open(path)
64 if err != nil {
65 panic(err)
66 }
67
68 defer file.Close()
69 vals, err := io.ReadAll(file)
70 if err != nil {
71 panic(err)
72 }
73
74 rel, err := filepath.Rel(specsPath, path)
75 if err == nil {
76 grouped[rel[:(len(rel)-len(filepath.Ext(rel)))]] = vals
77 }
78 }
79
80 filepath.WalkDir(specsPath, func(path string, d fs.DirEntry, err error) error {
81 if filepath.Ext(path) != ".json" || d.IsDir() {
82 return nil
83 }
84
85 addSpec(path)
86 return nil
87 })
88
89 for gv, jsonSpec := range grouped {
90 spec := &spec3.OpenAPI{}
91 err = json.Unmarshal(jsonSpec, spec)
92 if err != nil {
93 return nil, err
94 }
95
96 testV3Specs[gv] = spec
97 openAPIVersionedService.UpdateGroupVersion(gv, spec)
98 }
99
100 return &FakeOpenAPIServer{
101 HttpServer: server,
102 ServedDocuments: testV3Specs,
103 RequestCounters: mux.counts,
104 }, nil
105 }
106
107
108
109
110
111
112
113 type testMux struct {
114 lock sync.Mutex
115 prefixMap map[string]http.Handler
116 pathMap map[string]http.Handler
117 counts map[string]int
118 }
119
120 func (t *testMux) Handle(path string, handler http.Handler) {
121 t.lock.Lock()
122 defer t.lock.Unlock()
123
124 if t.pathMap == nil {
125 t.pathMap = make(map[string]http.Handler)
126 }
127 t.pathMap[path] = handler
128 }
129
130 func (t *testMux) HandlePrefix(path string, handler http.Handler) {
131 t.lock.Lock()
132 defer t.lock.Unlock()
133
134 if t.prefixMap == nil {
135 t.prefixMap = make(map[string]http.Handler)
136 }
137 t.prefixMap[path] = handler
138 }
139
140 func (t *testMux) ServeHTTP(w http.ResponseWriter, req *http.Request) {
141 t.lock.Lock()
142 defer t.lock.Unlock()
143
144 if t.counts == nil {
145 t.counts = make(map[string]int)
146 }
147
148 if val, exists := t.counts[req.URL.Path]; exists {
149 t.counts[req.URL.Path] = val + 1
150 } else {
151 t.counts[req.URL.Path] = 1
152 }
153
154 if handler, ok := t.pathMap[req.URL.Path]; ok {
155 handler.ServeHTTP(w, req)
156 return
157 }
158
159 for k, v := range t.prefixMap {
160 if strings.HasPrefix(req.URL.Path, k) {
161 v.ServeHTTP(w, req)
162 return
163 }
164 }
165
166 w.WriteHeader(http.StatusNotFound)
167 }
168
View as plain text