• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

dgraph-io / dgraph / 5262694671

14 Jun 2023 04:17AM UTC coverage: 67.043% (-0.2%) from 67.209%
5262694671

push

web-flow
Merge cc210d63d into 2787cfc58

58203 of 86814 relevant lines covered (67.04%)

2231790.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

50.28
/dgraph/cmd/zero/http.go
1
/*
2
 * Copyright 2023 Dgraph Labs, Inc. and Contributors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package zero
18

19
import (
20
        "context"
21
        "fmt"
22
        "net/http"
23
        "strconv"
24
        "strings"
25
        "time"
26

27
        "github.com/gogo/protobuf/jsonpb"
28
        "github.com/golang/glog"
29

30
        "github.com/dgraph-io/dgraph/protos/pb"
31
        "github.com/dgraph-io/dgraph/x"
32
)
33

34
// intFromQueryParam checks for name as a query param, converts it to uint64 and returns it.
35
// It also writes any errors to w. A bool is returned to indicate if the param was parsed
36
// successfully.
37
func intFromQueryParam(w http.ResponseWriter, r *http.Request, name string) (uint64, bool) {
4,010✔
38
        str := r.URL.Query().Get(name)
4,010✔
39
        if len(str) == 0 {
4,010✔
40
                w.WriteHeader(http.StatusBadRequest)
×
41
                x.SetStatus(w, x.ErrorInvalidRequest, fmt.Sprintf("%s not passed", name))
×
42
                return 0, false
×
43
        }
×
44
        val, err := strconv.ParseUint(str, 0, 64)
4,010✔
45
        if err != nil {
4,010✔
46
                w.WriteHeader(http.StatusBadRequest)
×
47
                x.SetStatus(w, x.ErrorInvalidRequest, fmt.Sprintf("Error while parsing %s", name))
×
48
                return 0, false
×
49
        }
×
50
        return val, true
4,010✔
51
}
52

53
func (st *state) assign(w http.ResponseWriter, r *http.Request) {
1,000✔
54
        x.AddCorsHeaders(w)
1,000✔
55
        w.Header().Set("Content-Type", "application/json")
1,000✔
56
        if r.Method == "OPTIONS" {
1,000✔
57
                return
×
58
        }
×
59
        if r.Method != http.MethodGet {
1,000✔
60
                w.WriteHeader(http.StatusBadRequest)
×
61
                x.SetStatus(w, x.ErrorInvalidMethod, "Invalid method")
×
62
                return
×
63
        }
×
64
        val, ok := intFromQueryParam(w, r, "num")
1,000✔
65
        if !ok {
1,000✔
66
                return
×
67
        }
×
68

69
        num := &pb.Num{Val: val}
1,000✔
70
        ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
1,000✔
71
        defer cancel()
1,000✔
72

1,000✔
73
        var ids *pb.AssignedIds
1,000✔
74
        var err error
1,000✔
75
        what := r.URL.Query().Get("what")
1,000✔
76
        switch what {
1,000✔
77
        case "uids":
1,000✔
78
                num.Type = pb.Num_UID
1,000✔
79
                ids, err = st.zero.AssignIds(ctx, num)
1,000✔
80
        case "timestamps":
×
81
                num.Type = pb.Num_TXN_TS
×
82
                if num.Val == 0 {
×
83
                        num.ReadOnly = true
×
84
                }
×
85
                ids, err = st.zero.Timestamps(ctx, num)
×
86
        case "nsids":
×
87
                num.Type = pb.Num_NS_ID
×
88
                ids, err = st.zero.AssignIds(ctx, num)
×
89
        default:
×
90
                x.SetStatus(w, x.Error,
×
91
                        fmt.Sprintf("Invalid what: [%s]. Must be one of: [uids, timestamps, nsids]", what))
×
92
                return
×
93
        }
94
        if err != nil {
1,000✔
95
                x.SetStatus(w, x.Error, err.Error())
×
96
                return
×
97
        }
×
98

99
        m := jsonpb.Marshaler{EmitDefaults: true}
1,000✔
100
        if err := m.Marshal(w, ids); err != nil {
1,000✔
101
                x.SetStatus(w, x.ErrorNoData, err.Error())
×
102
                return
×
103
        }
×
104
}
105

106
// removeNode can be used to remove a node from the cluster. It takes in the RAFT id of the node
107
// and the group it belongs to. It can be used to remove Dgraph alpha and Zero nodes(group=0).
108
func (st *state) removeNode(w http.ResponseWriter, r *http.Request) {
1,001✔
109
        x.AddCorsHeaders(w)
1,001✔
110
        if r.Method == "OPTIONS" {
1,001✔
111
                return
×
112
        }
×
113
        if r.Method != http.MethodGet {
1,001✔
114
                w.WriteHeader(http.StatusBadRequest)
×
115
                x.SetStatus(w, x.ErrorInvalidMethod, "Invalid method")
×
116
                return
×
117
        }
×
118

119
        nodeId, ok := intFromQueryParam(w, r, "id")
1,001✔
120
        if !ok {
1,001✔
121
                return
×
122
        }
×
123
        groupId, ok := intFromQueryParam(w, r, "group")
1,001✔
124
        if !ok {
1,001✔
125
                return
×
126
        }
×
127

128
        if _, err := st.zero.RemoveNode(
1,001✔
129
                context.Background(),
1,001✔
130
                &pb.RemoveNodeRequest{NodeId: nodeId, GroupId: uint32(groupId)},
1,001✔
131
        ); err != nil {
2,001✔
132
                x.SetStatus(w, x.Error, err.Error())
1,000✔
133
                return
1,000✔
134
        }
1,000✔
135
        _, err := fmt.Fprintf(w, "Removed node with group: %v, idx: %v", groupId, nodeId)
1✔
136
        if err != nil {
1✔
137
                glog.Warningf("Error while writing response: %+v", err)
×
138
        }
×
139
}
140

141
// moveTablet can be used to move a tablet to a specific group. It takes in tablet and group as
142
// argument.
143
func (st *state) moveTablet(w http.ResponseWriter, r *http.Request) {
1,008✔
144
        x.AddCorsHeaders(w)
1,008✔
145
        if r.Method == "OPTIONS" {
1,008✔
146
                return
×
147
        }
×
148
        if r.Method != http.MethodGet {
1,008✔
149
                w.WriteHeader(http.StatusBadRequest)
×
150
                x.SetStatus(w, x.ErrorInvalidMethod, "Invalid method")
×
151
                return
×
152
        }
×
153

154
        if !st.node.AmLeader() {
1,008✔
155
                w.WriteHeader(http.StatusBadRequest)
×
156
                x.SetStatus(w, x.ErrorInvalidRequest,
×
157
                        "This Zero server is not the leader. Re-run command on leader.")
×
158
                return
×
159
        }
×
160

161
        namespace := r.URL.Query().Get("namespace")
1,008✔
162
        namespace = strings.TrimSpace(namespace)
1,008✔
163
        ns := x.GalaxyNamespace
1,008✔
164
        if namespace != "" {
1,008✔
165
                var err error
×
166
                if ns, err = strconv.ParseUint(namespace, 0, 64); err != nil {
×
167
                        w.WriteHeader(http.StatusBadRequest)
×
168
                        x.SetStatus(w, x.ErrorInvalidRequest, "Invalid namespace in query parameter.")
×
169
                        return
×
170
                }
×
171
        }
172

173
        tablet := r.URL.Query().Get("tablet")
1,008✔
174
        if len(tablet) == 0 {
1,008✔
175
                w.WriteHeader(http.StatusBadRequest)
×
176
                x.SetStatus(w, x.ErrorInvalidRequest, "tablet is a mandatory query parameter")
×
177
                return
×
178
        }
×
179

180
        groupId, ok := intFromQueryParam(w, r, "group")
1,008✔
181
        if !ok {
1,008✔
182
                w.WriteHeader(http.StatusBadRequest)
×
183
                x.SetStatus(w, x.ErrorInvalidRequest,
×
184
                        "Query parameter 'group' should contain a valid integer.")
×
185
                return
×
186
        }
×
187
        dstGroup := uint32(groupId)
1,008✔
188

1,008✔
189
        var resp *pb.Status
1,008✔
190
        var err error
1,008✔
191
        if resp, err = st.zero.MoveTablet(
1,008✔
192
                context.Background(),
1,008✔
193
                &pb.MoveTabletRequest{Namespace: ns, Tablet: tablet, DstGroup: dstGroup},
1,008✔
194
        ); err != nil {
2,012✔
195
                if resp.GetMsg() == x.ErrorInvalidRequest {
2,008✔
196
                        w.WriteHeader(http.StatusBadRequest)
1,004✔
197
                        x.SetStatus(w, x.ErrorInvalidRequest, err.Error())
1,004✔
198
                } else {
1,004✔
199
                        w.WriteHeader(http.StatusInternalServerError)
×
200
                        x.SetStatus(w, x.Error, err.Error())
×
201
                }
×
202
                return
1,004✔
203
        }
204
        _, err = fmt.Fprint(w, resp.GetMsg())
4✔
205
        if err != nil {
4✔
206
                glog.Warningf("Error while writing response: %+v", err)
×
207
        }
×
208
}
209

210
func (st *state) getState(w http.ResponseWriter, r *http.Request) {
167✔
211
        x.AddCorsHeaders(w)
167✔
212
        w.Header().Set("Content-Type", "application/json")
167✔
213

167✔
214
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
167✔
215
        defer cancel()
167✔
216
        if err := st.node.WaitLinearizableRead(ctx); err != nil {
167✔
217
                w.WriteHeader(http.StatusInternalServerError)
×
218
                x.SetStatus(w, x.Error, err.Error())
×
219
                return
×
220
        }
×
221
        mstate := st.zero.membershipState()
167✔
222
        if mstate == nil {
167✔
223
                x.SetStatus(w, x.ErrorNoData, "No membership state found.")
×
224
                return
×
225
        }
×
226

227
        m := jsonpb.Marshaler{EmitDefaults: true}
167✔
228
        if err := m.Marshal(w, mstate); err != nil {
167✔
229
                x.SetStatus(w, x.ErrorNoData, err.Error())
×
230
                return
×
231
        }
×
232
}
233

234
func (st *state) pingResponse(w http.ResponseWriter, r *http.Request) {
63✔
235
        x.AddCorsHeaders(w)
63✔
236

63✔
237
        w.WriteHeader(http.StatusOK)
63✔
238
        _, _ = w.Write([]byte("OK"))
63✔
239
}
63✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc