Skip to content

Commit 3327ff7

Browse files
authored
feat: consistent API errors (#48)
PLAT-86
2 parents 3e353db + 692fb66 commit 3327ff7

File tree

20 files changed

+6176
-5801
lines changed

20 files changed

+6176
-5801
lines changed

api/design/api.go

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,29 @@ var _ = g.API("control-plane", func() {
2222
g.Meta("openapi:operationId", "{method}")
2323

2424
// Common errors
25-
g.Error("cluster_already_initialized")
26-
g.Error("cluster_not_initialized")
27-
g.Error("invalid_join_token")
28-
g.Error("invalid_input")
29-
g.Error("not_found")
30-
g.Error("database_not_modifiable")
25+
g.Error("cluster_already_initialized", APIError)
26+
g.Error("cluster_not_initialized", APIError)
27+
g.Error("database_not_modifiable", APIError)
28+
g.Error("invalid_input", APIError)
29+
g.Error("invalid_join_token", APIError)
30+
g.Error("not_found", APIError)
31+
g.Error("operation_already_in_progress", APIError)
32+
g.Error("server_error", APIError)
3133
g.HTTP(func() {
3234
g.Response("cluster_already_initialized", http.StatusConflict)
3335
g.Response("cluster_not_initialized", http.StatusConflict)
34-
g.Response("invalid_join_token", http.StatusUnauthorized)
36+
g.Response("database_not_modifiable", http.StatusConflict)
3537
g.Response("invalid_input", http.StatusBadRequest)
38+
g.Response("invalid_join_token", http.StatusUnauthorized)
3639
g.Response("not_found", http.StatusNotFound)
37-
g.Response("database_not_modifiable", http.StatusConflict)
40+
g.Response("operation_already_in_progress", http.StatusConflict)
41+
g.Response("server_error", http.StatusInternalServerError)
3842
})
3943
})
4044

4145
var _ = g.Service("control-plane", func() {
46+
g.Error("server_error")
47+
4248
g.Method("init-cluster", func() {
4349
g.Description("Initializes a new cluster.")
4450
g.Result(ClusterJoinToken)
@@ -53,6 +59,7 @@ var _ = g.Service("control-plane", func() {
5359
g.Description("Join this host to an existing cluster.")
5460
g.Payload(ClusterJoinToken)
5561
g.Error("cluster_already_initialized")
62+
g.Error("invalid_join_token")
5663

5764
g.HTTP(func() {
5865
g.POST("/cluster/join")
@@ -86,7 +93,6 @@ var _ = g.Service("control-plane", func() {
8693
g.Description("Returns information about the cluster.")
8794
g.Result(Cluster)
8895
g.Error("cluster_not_initialized")
89-
g.Error("not_found")
9096

9197
g.HTTP(func() {
9298
g.GET("/cluster")
@@ -113,6 +119,7 @@ var _ = g.Service("control-plane", func() {
113119
})
114120
g.Result(Host)
115121
g.Error("cluster_not_initialized")
122+
g.Error("invalid_input")
116123
g.Error("not_found")
117124

118125
g.HTTP(func() {
@@ -129,6 +136,7 @@ var _ = g.Service("control-plane", func() {
129136
})
130137
})
131138
g.Error("cluster_not_initialized")
139+
g.Error("invalid_input")
132140
g.Error("not_found")
133141

134142
g.HTTP(func() {
@@ -153,8 +161,9 @@ var _ = g.Service("control-plane", func() {
153161
g.Payload(CreateDatabaseRequest)
154162
g.Result(CreateDatabaseResponse)
155163
g.Error("cluster_not_initialized")
164+
g.Error("database_already_exists", APIError)
156165
g.Error("invalid_input")
157-
g.Error("database_already_exists")
166+
g.Error("operation_already_in_progress")
158167

159168
g.HTTP(func() {
160169
g.POST("/databases")
@@ -174,6 +183,7 @@ var _ = g.Service("control-plane", func() {
174183
g.View("default")
175184
})
176185
g.Error("cluster_not_initialized")
186+
g.Error("invalid_input")
177187
g.Error("not_found")
178188

179189
g.HTTP(func() {
@@ -196,8 +206,10 @@ var _ = g.Service("control-plane", func() {
196206
})
197207
g.Result(UpdateDatabaseResponse)
198208
g.Error("cluster_not_initialized")
199-
g.Error("not_found")
200209
g.Error("database_not_modifiable")
210+
g.Error("invalid_input")
211+
g.Error("not_found")
212+
g.Error("operation_already_in_progress")
201213

202214
g.HTTP(func() {
203215
g.POST("/databases/{database_id}")
@@ -219,8 +231,10 @@ var _ = g.Service("control-plane", func() {
219231
})
220232
g.Result(DeleteDatabaseResponse)
221233
g.Error("cluster_not_initialized")
222-
g.Error("not_found")
223234
g.Error("database_not_modifiable")
235+
g.Error("invalid_input")
236+
g.Error("not_found")
237+
g.Error("operation_already_in_progress")
224238

225239
g.HTTP(func() {
226240
g.DELETE("/databases/{database_id}")
@@ -245,14 +259,14 @@ var _ = g.Service("control-plane", func() {
245259
})
246260
g.Result(BackupDatabaseNodeResponse)
247261
g.Error("cluster_not_initialized")
248-
g.Error("not_found")
249262
g.Error("database_not_modifiable")
250-
g.Error("backup_already_in_progress")
263+
g.Error("invalid_input")
264+
g.Error("not_found")
265+
g.Error("operation_already_in_progress")
251266

252267
g.HTTP(func() {
253268
g.POST("/databases/{database_id}/nodes/{node_name}/backups")
254269
g.Body("options")
255-
g.Response("backup_already_in_progress", http.StatusConflict)
256270
})
257271
})
258272

@@ -283,6 +297,7 @@ var _ = g.Service("control-plane", func() {
283297
})
284298
g.Result(g.ArrayOf(Task))
285299
g.Error("cluster_not_initialized")
300+
g.Error("invalid_input")
286301
g.Error("not_found")
287302

288303
g.HTTP(func() {
@@ -311,6 +326,7 @@ var _ = g.Service("control-plane", func() {
311326
})
312327
g.Result(Task)
313328
g.Error("cluster_not_initialized")
329+
g.Error("invalid_input")
314330
g.Error("not_found")
315331

316332
g.HTTP(func() {
@@ -345,6 +361,7 @@ var _ = g.Service("control-plane", func() {
345361
})
346362
g.Result(TaskLog)
347363
g.Error("cluster_not_initialized")
364+
g.Error("invalid_input")
348365
g.Error("not_found")
349366

350367
g.HTTP(func() {
@@ -368,9 +385,10 @@ var _ = g.Service("control-plane", func() {
368385
})
369386
g.Result(RestoreDatabaseResponse)
370387
g.Error("cluster_not_initialized")
371-
g.Error("not_found")
372388
g.Error("database_not_modifiable")
373389
g.Error("invalid_input")
390+
g.Error("not_found")
391+
g.Error("operation_already_in_progress")
374392

375393
g.HTTP(func() {
376394
g.POST("/databases/{database_id}/restore")
@@ -390,3 +408,10 @@ var _ = g.Service("control-plane", func() {
390408
// Serves the OpenAPI spec as a static file
391409
g.Files("/openapi.json", "./gen/http/openapi3.json")
392410
})
411+
412+
var APIError = g.Type("APIError", func() {
413+
g.Description("A Control Plane API error.")
414+
g.ErrorName("name", g.String, "The name of the error.")
415+
g.Attribute("message", g.String, "The error message.")
416+
g.Required("name", "message")
417+
})

api/gen/control_plane/client.go

Lines changed: 41 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)