-
Notifications
You must be signed in to change notification settings - Fork 1
/
config_api.go
119 lines (104 loc) · 3.13 KB
/
config_api.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
113
114
115
116
117
118
119
package main
import (
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/30x/changeagent/raft"
"github.com/mholt/binding"
)
const (
configURI = "/config"
)
// ConfigData is the JSON structure for configuration.
// We unfortunately copy that so that the internal "time.Duration"
// (for internal convenience) can be converted to a string
// (for external convenience)
type ConfigData struct {
MinPurgeRecords uint32 `json:"minPurgeRecords"`
MinPurgeDuration string `json:"minPurgeDuration"`
HeartbeatTimeout string `json:"heartbeatTimeout"`
ElectionTimeout string `json:"electionTimeout"`
}
// FieldMap tells the binding package how to validate our input
func (c *ConfigData) FieldMap(req *http.Request) binding.FieldMap {
return binding.FieldMap{
&c.MinPurgeRecords: "minPurgeRecords",
&c.MinPurgeDuration: "minPurgeDuration",
&c.HeartbeatTimeout: "heartbeatTimeout",
&c.ElectionTimeout: "electionTimeout",
}
}
func (a *ChangeAgent) initConfigAPI(prefix string) {
a.router.HandleFunc(prefix+configURI, a.handleGetRaftConfig).Methods("GET")
a.router.HandleFunc(prefix+configURI, a.handleSetRaftConfig).Methods("PUT")
}
func (a *ChangeAgent) handleGetRaftConfig(resp http.ResponseWriter, req *http.Request) {
cfg := a.raft.GetRaftConfig()
cd := ConfigData{
MinPurgeRecords: cfg.MinPurgeRecords,
MinPurgeDuration: cfg.MinPurgeDuration.String(),
HeartbeatTimeout: cfg.HeartbeatTimeout.String(),
ElectionTimeout: cfg.ElectionTimeout.String(),
}
resp.Header().Set("Content-Type", jsonContent)
buf, err := json.MarshalIndent(&cd, indentPrefix, indentSpace)
if err == nil {
resp.Write(buf)
} else {
writeError(resp, http.StatusInternalServerError, err)
}
}
func (a *ChangeAgent) handleSetRaftConfig(resp http.ResponseWriter, req *http.Request) {
var data ConfigData
defer req.Body.Close()
bindingErr := binding.Bind(req, &data)
if bindingErr.Handle(resp) {
return
}
var err error
var purgeDur time.Duration
if data.MinPurgeDuration != "" {
purgeDur, err = time.ParseDuration(data.MinPurgeDuration)
if err != nil {
writeError(resp, http.StatusBadRequest,
fmt.Errorf("Invalid purge duration %s: %s", data.MinPurgeDuration, err))
return
}
}
var hbDur time.Duration
if data.HeartbeatTimeout != "" {
hbDur, err = time.ParseDuration(data.HeartbeatTimeout)
if err != nil {
writeError(resp, http.StatusBadRequest,
fmt.Errorf("Invalid heartbeat timeout %s: %s", data.HeartbeatTimeout, err))
return
}
}
var elDur time.Duration
if data.ElectionTimeout != "" {
elDur, err = time.ParseDuration(data.ElectionTimeout)
if err != nil {
writeError(resp, http.StatusBadRequest,
fmt.Errorf("Invalid election timeout %s: %s", data.ElectionTimeout, err))
return
}
}
cfg := raft.Config{
MinPurgeDuration: purgeDur,
MinPurgeRecords: data.MinPurgeRecords,
ElectionTimeout: elDur,
HeartbeatTimeout: hbDur,
}
ix, err := a.raft.UpdateRaftConfiguration(cfg)
if err != nil {
writeError(resp, http.StatusInternalServerError, err)
return
}
err = a.raft.WaitForCommit(ix)
if err != nil {
writeError(resp, http.StatusInternalServerError, err)
return
}
a.handleGetRaftConfig(resp, req)
}