-
Notifications
You must be signed in to change notification settings - Fork 2.7k
/
api_handler.go
99 lines (86 loc) · 2.61 KB
/
api_handler.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
// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium
package statedb
import (
"encoding/base64"
"encoding/gob"
"fmt"
"net/http"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
. "github.com/cilium/cilium/api/v1/server/restapi/statedb"
restapi "github.com/cilium/cilium/api/v1/server/restapi/statedb"
"github.com/cilium/cilium/pkg/api"
)
func newDumpHandler(db *DB) restapi.GetStatedbDumpHandler {
return &dumpHandler{db}
}
// REST API handler for the '/statedb/dump' to dump the contents of the database
// as JSON. Available through `cilium statedb dump` and included in sysdumps.
type dumpHandler struct {
db *DB
}
func (h *dumpHandler) Handle(params GetStatedbDumpParams) middleware.Responder {
return middleware.ResponderFunc(func(w http.ResponseWriter, _ runtime.Producer) {
h.db.ReadTxn().WriteJSON(w)
})
}
// REST API handler for '/statedb/query' to perform remote Get() and LowerBound()
// queries against the database from 'cilium-dbg'.
func newQueryHandler(db *DB) restapi.GetStatedbQueryTableHandler {
return &queryHandler{db}
}
type queryHandler struct {
db *DB
}
// /statedb/query
func (h *queryHandler) Handle(params GetStatedbQueryTableParams) middleware.Responder {
queryKey, err := base64.StdEncoding.DecodeString(params.Key)
if err != nil {
return api.Error(GetStatedbQueryTableBadRequestCode, fmt.Errorf("Invalid key: %w", err))
}
txn := h.db.ReadTxn()
indexTxn, err := txn.getTxn().indexReadTxn(params.Table, params.Index)
if err != nil {
return api.Error(GetStatedbQueryTableNotFoundCode, err)
}
return middleware.ResponderFunc(func(w http.ResponseWriter, _ runtime.Producer) {
w.WriteHeader(GetStatedbDumpOKCode)
enc := gob.NewEncoder(w)
onObject := func(obj object) error {
if err := enc.Encode(obj.revision); err != nil {
return err
}
return enc.Encode(obj.data)
}
runQuery(indexTxn, params.Lowerbound, queryKey, onObject)
})
}
func runQuery(indexTxn indexTxn, lowerbound bool, queryKey []byte, onObject func(object) error) {
iter := indexTxn.Root().Iterator()
if lowerbound {
iter.SeekLowerBound(queryKey)
} else {
iter.SeekPrefixWatch(queryKey)
}
var match func([]byte) bool
switch {
case lowerbound:
match = func([]byte) bool { return true }
case indexTxn.entry.unique:
match = func(k []byte) bool { return len(k) == len(queryKey) }
default:
match = func(k []byte) bool {
_, secondary := decodeNonUniqueKey(k)
return len(secondary) == len(queryKey)
}
}
for key, obj, ok := iter.Next(); ok; _, obj, ok = iter.Next() {
if !match(key) {
continue
}
if err := onObject(obj); err != nil {
return
}
}
}