Skip to content

Commit cec6749

Browse files
committed
enable httperror for server status code
Signed-off-by: Nitishkumar Singh <[email protected]>
1 parent 8e069b1 commit cec6749

File tree

2 files changed

+144
-33
lines changed

2 files changed

+144
-33
lines changed

client.go

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ func NewClient(gatewayURL *url.URL, auth ClientAuth, client *http.Client) *Clien
3535
}
3636
}
3737

38+
type HttpError struct {
39+
Err error
40+
Status int
41+
}
42+
43+
func (e *HttpError) Error() string {
44+
return e.Err.Error()
45+
}
46+
47+
func createHttpError(err error, statusCode int) *HttpError {
48+
return &HttpError{Err: err, Status: statusCode}
49+
}
50+
3851
// GetNamespaces get openfaas namespaces
3952
func (s *Client) GetNamespaces(ctx context.Context) ([]string, error) {
4053
u := s.GatewayURL
@@ -54,7 +67,7 @@ func (s *Client) GetNamespaces(ctx context.Context) ([]string, error) {
5467

5568
res, err := s.Client.Do(req)
5669
if err != nil {
57-
return namespaces, fmt.Errorf("unable to make request: %w", err)
70+
return namespaces, fmt.Errorf("unable to make HTTP request to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
5871
}
5972

6073
if res.Body != nil {
@@ -66,8 +79,15 @@ func (s *Client) GetNamespaces(ctx context.Context) ([]string, error) {
6679
return namespaces, err
6780
}
6881

69-
if res.StatusCode == http.StatusUnauthorized {
70-
return namespaces, fmt.Errorf("check authorization, status code: %d", res.StatusCode)
82+
switch res.StatusCode {
83+
case http.StatusOK:
84+
break
85+
86+
case http.StatusUnauthorized:
87+
return namespaces, createHttpError(fmt.Errorf("unauthorized action, please setup authentication for this server"), res.StatusCode)
88+
89+
default:
90+
return namespaces, createHttpError(fmt.Errorf("server returned unexpected status code %d, message: %q", res.StatusCode, string(bytesOut)), res.StatusCode)
7191
}
7292

7393
if len(bytesOut) == 0 {
@@ -106,7 +126,7 @@ func (s *Client) GetFunctions(ctx context.Context, namespace string) ([]types.Fu
106126

107127
res, err := s.Client.Do(req)
108128
if err != nil {
109-
return []types.FunctionStatus{}, fmt.Errorf("unable to make HTTP request: %w", err)
129+
return []types.FunctionStatus{}, fmt.Errorf("unable to make HTTP request to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
110130
}
111131

112132
if res.Body != nil {
@@ -115,6 +135,17 @@ func (s *Client) GetFunctions(ctx context.Context, namespace string) ([]types.Fu
115135

116136
body, _ := io.ReadAll(res.Body)
117137

138+
switch res.StatusCode {
139+
case http.StatusAccepted, http.StatusOK:
140+
break
141+
142+
case http.StatusUnauthorized:
143+
return nil, createHttpError(fmt.Errorf("unauthorized action, please setup authentication for this server"), res.StatusCode)
144+
145+
default:
146+
return nil, createHttpError(fmt.Errorf("server returned unexpected status code %d, message: %q", res.StatusCode, string(body)), res.StatusCode)
147+
}
148+
118149
functions := []types.FunctionStatus{}
119150
if err := json.Unmarshal(body, &functions); err != nil {
120151
return []types.FunctionStatus{},
@@ -142,7 +173,7 @@ func (s *Client) GetInfo(ctx context.Context) (SystemInfo, error) {
142173

143174
res, err := s.Client.Do(req)
144175
if err != nil {
145-
return SystemInfo{}, fmt.Errorf("unable to make HTTP request: %w", err)
176+
return SystemInfo{}, fmt.Errorf("unable to make HTTP request to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
146177
}
147178

148179
if res.Body != nil {
@@ -185,7 +216,7 @@ func (s *Client) GetFunction(ctx context.Context, name, namespace string) (types
185216

186217
res, err := s.Client.Do(req)
187218
if err != nil {
188-
return types.FunctionDeployment{}, fmt.Errorf("unable to make HTTP request: %w", err)
219+
return types.FunctionDeployment{}, fmt.Errorf("unable to make HTTP request to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
189220
}
190221

191222
if res.Body != nil {
@@ -194,6 +225,17 @@ func (s *Client) GetFunction(ctx context.Context, name, namespace string) (types
194225

195226
body, _ := io.ReadAll(res.Body)
196227

228+
switch res.StatusCode {
229+
case http.StatusOK:
230+
break
231+
232+
case http.StatusUnauthorized:
233+
return types.FunctionDeployment{}, createHttpError(fmt.Errorf("unauthorized action, please setup authentication for this server"), res.StatusCode)
234+
235+
default:
236+
return types.FunctionDeployment{}, createHttpError(fmt.Errorf("server returned unexpected status code %d, message: %q", res.StatusCode, string(body)), res.StatusCode)
237+
}
238+
197239
functions := types.FunctionDeployment{}
198240
if err := json.Unmarshal(body, &functions); err != nil {
199241
return types.FunctionDeployment{},
@@ -203,20 +245,20 @@ func (s *Client) GetFunction(ctx context.Context, name, namespace string) (types
203245
return functions, nil
204246
}
205247

206-
func (s *Client) Deploy(ctx context.Context, spec types.FunctionDeployment) (int, error) {
248+
// func (s *Client) deploy(ctx context.Context, method string, spec types.FunctionDeployment) (int, error) {
249+
func (s *Client) Deploy(ctx context.Context, spec types.FunctionDeployment) error {
207250
return s.deploy(ctx, http.MethodPost, spec)
208-
209251
}
210252

211-
func (s *Client) Update(ctx context.Context, spec types.FunctionDeployment) (int, error) {
253+
func (s *Client) Update(ctx context.Context, spec types.FunctionDeployment) error {
212254
return s.deploy(ctx, http.MethodPut, spec)
213255
}
214256

215-
func (s *Client) deploy(ctx context.Context, method string, spec types.FunctionDeployment) (int, error) {
257+
func (s *Client) deploy(ctx context.Context, method string, spec types.FunctionDeployment) error {
216258

217259
bodyBytes, err := json.Marshal(spec)
218260
if err != nil {
219-
return http.StatusBadRequest, err
261+
return createHttpError(err, http.StatusBadRequest)
220262
}
221263

222264
bodyReader := bytes.NewReader(bodyBytes)
@@ -226,18 +268,18 @@ func (s *Client) deploy(ctx context.Context, method string, spec types.FunctionD
226268

227269
req, err := http.NewRequestWithContext(ctx, method, u.String(), bodyReader)
228270
if err != nil {
229-
return http.StatusBadGateway, err
271+
return fmt.Errorf("unable to create request for %s, error: %w", u.String(), err)
230272
}
231273

232274
if s.ClientAuth != nil {
233275
if err := s.ClientAuth.Set(req); err != nil {
234-
return http.StatusInternalServerError, fmt.Errorf("unable to set Authorization header: %w", err)
276+
return fmt.Errorf("unable to set Authorization header: %w", err)
235277
}
236278
}
237279

238280
res, err := s.Client.Do(req)
239281
if err != nil {
240-
return http.StatusBadGateway, err
282+
return fmt.Errorf("unable to make HTTP request to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
241283
}
242284

243285
var body []byte
@@ -248,13 +290,13 @@ func (s *Client) deploy(ctx context.Context, method string, spec types.FunctionD
248290

249291
switch res.StatusCode {
250292
case http.StatusAccepted, http.StatusOK, http.StatusCreated:
251-
return res.StatusCode, nil
293+
return nil
252294

253295
case http.StatusUnauthorized:
254-
return res.StatusCode, fmt.Errorf("unauthorized action, please setup authentication for this server")
296+
return createHttpError(fmt.Errorf("unauthorized action, please setup authentication for this server"), res.StatusCode)
255297

256298
default:
257-
return res.StatusCode, fmt.Errorf("unexpected status code: %d, message: %q", res.StatusCode, string(body))
299+
return createHttpError(fmt.Errorf("unexpected status code: %d, message: %q", res.StatusCode, string(body)), res.StatusCode)
258300
}
259301
}
260302

@@ -280,7 +322,7 @@ func (s *Client) ScaleFunction(ctx context.Context, functionName, namespace stri
280322

281323
req, err := http.NewRequestWithContext(ctx, http.MethodPost, u.String(), bodyReader)
282324
if err != nil {
283-
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", u.String(), err)
325+
return fmt.Errorf("unable to create request for %s, error: %w", u.String(), err)
284326
}
285327

286328
if s.ClientAuth != nil {
@@ -290,7 +332,7 @@ func (s *Client) ScaleFunction(ctx context.Context, functionName, namespace stri
290332
}
291333
res, err := http.DefaultClient.Do(req)
292334
if err != nil {
293-
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
335+
return fmt.Errorf("unable to make HTTP request to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
294336

295337
}
296338

@@ -303,10 +345,10 @@ func (s *Client) ScaleFunction(ctx context.Context, functionName, namespace stri
303345
break
304346

305347
case http.StatusNotFound:
306-
return fmt.Errorf("function %s not found", functionName)
348+
return createHttpError(fmt.Errorf("function %s not found", functionName), res.StatusCode)
307349

308350
case http.StatusUnauthorized:
309-
return fmt.Errorf("unauthorized action, please setup authentication for this server")
351+
return createHttpError(fmt.Errorf("unauthorized action, please setup authentication for this server"), res.StatusCode)
310352

311353
default:
312354
var err error
@@ -315,7 +357,7 @@ func (s *Client) ScaleFunction(ctx context.Context, functionName, namespace stri
315357
return err
316358
}
317359

318-
return fmt.Errorf("server returned unexpected status code %d, message: %q", res.StatusCode, string(bytesOut))
360+
return createHttpError(fmt.Errorf("server returned unexpected status code %d, message: %q", res.StatusCode, string(bytesOut)), res.StatusCode)
319361
}
320362
return nil
321363
}
@@ -338,7 +380,7 @@ func (s *Client) DeleteFunction(ctx context.Context, functionName, namespace str
338380

339381
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, u.String(), bodyReader)
340382
if err != nil {
341-
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", u.String(), err)
383+
return fmt.Errorf("unable to create request for %s, error: %w", u.String(), err)
342384
}
343385

344386
if s.ClientAuth != nil {
@@ -348,7 +390,7 @@ func (s *Client) DeleteFunction(ctx context.Context, functionName, namespace str
348390
}
349391
res, err := http.DefaultClient.Do(req)
350392
if err != nil {
351-
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
393+
return fmt.Errorf("unable to make HTTP request to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
352394

353395
}
354396

@@ -361,10 +403,10 @@ func (s *Client) DeleteFunction(ctx context.Context, functionName, namespace str
361403
break
362404

363405
case http.StatusNotFound:
364-
return fmt.Errorf("function %s not found", functionName)
406+
return createHttpError(fmt.Errorf("function %s not found", functionName), res.StatusCode)
365407

366408
case http.StatusUnauthorized:
367-
return fmt.Errorf("unauthorized action, please setup authentication for this server")
409+
return createHttpError(fmt.Errorf("unauthorized action, please setup authentication for this server"), res.StatusCode)
368410

369411
default:
370412
var err error
@@ -373,7 +415,7 @@ func (s *Client) DeleteFunction(ctx context.Context, functionName, namespace str
373415
return err
374416
}
375417

376-
return fmt.Errorf("server returned unexpected status code %d, message: %q", res.StatusCode, string(bytesOut))
418+
return createHttpError(fmt.Errorf("server returned unexpected status code %d, message: %q", res.StatusCode, string(bytesOut)), res.StatusCode)
377419
}
378420
return nil
379421
}

client_test.go

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func TestSdk_DeployFunction(t *testing.T) {
109109
handler: func(rw http.ResponseWriter, req *http.Request) {
110110
rw.WriteHeader(http.StatusUnauthorized)
111111
},
112-
err: fmt.Errorf("unauthorized action, please setup authentication for this server"),
112+
err: createHttpError(fmt.Errorf("unauthorized action, please setup authentication for this server"), http.StatusUnauthorized),
113113
},
114114
{
115115
name: "unknown error",
@@ -118,7 +118,7 @@ func TestSdk_DeployFunction(t *testing.T) {
118118
handler: func(rw http.ResponseWriter, req *http.Request) {
119119
http.Error(rw, "unknown error", http.StatusInternalServerError)
120120
},
121-
err: fmt.Errorf("unexpected status code: %d, message: %q", http.StatusInternalServerError, "unknown error\n"),
121+
err: createHttpError(fmt.Errorf("unexpected status code: %d, message: %q", http.StatusInternalServerError, "unknown error\n"), http.StatusInternalServerError),
122122
},
123123
}
124124

@@ -130,7 +130,8 @@ func TestSdk_DeployFunction(t *testing.T) {
130130

131131
client := NewClient(sU, nil, http.DefaultClient)
132132

133-
_, err := client.Deploy(context.Background(), types.FunctionDeployment{
133+
// _, err := client.Deploy(context.Background(), types.FunctionDeployment{
134+
err := client.Deploy(context.Background(), types.FunctionDeployment{
134135
Service: funcName,
135136
Image: fmt.Sprintf("docker.io/openfaas/%s:latest", funcName),
136137
Namespace: nsName,
@@ -168,7 +169,7 @@ func TestSdk_DeleteFunction(t *testing.T) {
168169
handler: func(rw http.ResponseWriter, req *http.Request) {
169170
rw.WriteHeader(http.StatusNotFound)
170171
},
171-
err: fmt.Errorf("function %s not found", funcName),
172+
err: createHttpError(fmt.Errorf("function %s not found", funcName), http.StatusNotFound),
172173
},
173174
{
174175
name: "client not authorized",
@@ -177,7 +178,7 @@ func TestSdk_DeleteFunction(t *testing.T) {
177178
handler: func(rw http.ResponseWriter, req *http.Request) {
178179
rw.WriteHeader(http.StatusUnauthorized)
179180
},
180-
err: fmt.Errorf("unauthorized action, please setup authentication for this server"),
181+
err: createHttpError(fmt.Errorf("unauthorized action, please setup authentication for this server"), http.StatusUnauthorized),
181182
},
182183
{
183184
name: "unknown error",
@@ -186,7 +187,7 @@ func TestSdk_DeleteFunction(t *testing.T) {
186187
handler: func(rw http.ResponseWriter, req *http.Request) {
187188
http.Error(rw, "unknown error", http.StatusInternalServerError)
188189
},
189-
err: fmt.Errorf("server returned unexpected status code %d, message: %q", http.StatusInternalServerError, string("unknown error\n")),
190+
err: createHttpError(fmt.Errorf("server returned unexpected status code %d, message: %q", http.StatusInternalServerError, string("unknown error\n")), http.StatusUnauthorized),
190191
},
191192
}
192193

@@ -205,3 +206,71 @@ func TestSdk_DeleteFunction(t *testing.T) {
205206
})
206207
}
207208
}
209+
210+
func TestSdk_ScaleFunction(t *testing.T) {
211+
funcName := "funct1"
212+
nsName := "ns1"
213+
tests := []struct {
214+
name string
215+
functionName string
216+
namespace string
217+
replicas uint64
218+
err error
219+
handler func(rw http.ResponseWriter, req *http.Request)
220+
}{
221+
{
222+
name: "scale request accepted",
223+
functionName: funcName,
224+
namespace: nsName,
225+
replicas: 0,
226+
handler: func(rw http.ResponseWriter, req *http.Request) {
227+
rw.WriteHeader(http.StatusAccepted)
228+
},
229+
},
230+
{
231+
name: "function not found",
232+
functionName: funcName,
233+
namespace: nsName,
234+
replicas: 0,
235+
handler: func(rw http.ResponseWriter, req *http.Request) {
236+
rw.WriteHeader(http.StatusNotFound)
237+
},
238+
err: createHttpError(fmt.Errorf("function %s not found", funcName), http.StatusNotFound),
239+
},
240+
{
241+
name: "client not authorized",
242+
functionName: funcName,
243+
namespace: nsName,
244+
replicas: 0,
245+
handler: func(rw http.ResponseWriter, req *http.Request) {
246+
rw.WriteHeader(http.StatusUnauthorized)
247+
},
248+
err: createHttpError(fmt.Errorf("unauthorized action, please setup authentication for this server"), http.StatusUnauthorized),
249+
},
250+
{
251+
name: "unknown error",
252+
functionName: funcName,
253+
namespace: nsName,
254+
replicas: 0,
255+
handler: func(rw http.ResponseWriter, req *http.Request) {
256+
http.Error(rw, "unknown error", http.StatusInternalServerError)
257+
},
258+
err: createHttpError(fmt.Errorf("server returned unexpected status code %d, message: %q", http.StatusInternalServerError, string("unknown error\n")), http.StatusUnauthorized),
259+
},
260+
}
261+
262+
for _, test := range tests {
263+
t.Run(test.name, func(t *testing.T) {
264+
s := httptest.NewServer(http.HandlerFunc(test.handler))
265+
266+
sU, _ := url.Parse(s.URL)
267+
268+
client := NewClient(sU, nil, http.DefaultClient)
269+
err := client.ScaleFunction(context.Background(), test.functionName, test.namespace, test.replicas)
270+
271+
if !errors.Is(err, test.err) && err.Error() != test.err.Error() {
272+
t.Fatalf("wanted %s, but got: %s", test.err, err)
273+
}
274+
})
275+
}
276+
}

0 commit comments

Comments
 (0)