Skip to content

Commit 7e08ee3

Browse files
nitishkumar71alexellis
authored andcommitted
enable delete function method
Signed-off-by: Nitishkumar Singh <[email protected]>
1 parent 0bbb58b commit 7e08ee3

File tree

2 files changed

+201
-6
lines changed

2 files changed

+201
-6
lines changed

client.go

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package sdk
22

33
import (
44
"bytes"
5-
"context"
65
"encoding/json"
76
"fmt"
87
"io"
@@ -246,15 +245,20 @@ func (s *Client) deploy(method string, spec types.FunctionDeployment) (int, erro
246245
body, _ = io.ReadAll(res.Body)
247246
}
248247

249-
if res.StatusCode != http.StatusAccepted {
250-
return res.StatusCode, fmt.Errorf("unexpected status code: %d, message: %s", res.StatusCode, string(body))
251-
}
248+
switch res.StatusCode {
249+
case http.StatusAccepted, http.StatusOK, http.StatusCreated:
250+
return res.StatusCode, nil
251+
252+
case http.StatusUnauthorized:
253+
return res.StatusCode, fmt.Errorf("unauthorized action, please setup authentication for this server")
252254

253-
return res.StatusCode, nil
255+
default:
256+
return res.StatusCode, fmt.Errorf("unexpected status code: %d, message: %q", res.StatusCode, string(body))
257+
}
254258
}
255259

256260
// ScaleFunction scales a function to a number of replicas
257-
func (s *Client) ScaleFunction(ctx context.Context, functionName, namespace string, replicas uint64) error {
261+
func (s *Client) ScaleFunction(functionName, namespace string, replicas uint64) error {
258262

259263
scaleReq := types.ScaleServiceRequest{
260264
ServiceName: functionName,
@@ -314,3 +318,61 @@ func (s *Client) ScaleFunction(ctx context.Context, functionName, namespace stri
314318
}
315319
return nil
316320
}
321+
322+
// DeleteFunction deletes a function
323+
func (s *Client) DeleteFunction(functionName, namespace string) error {
324+
325+
delReq := types.DeleteFunctionRequest{
326+
FunctionName: functionName,
327+
Namespace: namespace,
328+
}
329+
330+
var err error
331+
332+
bodyBytes, _ := json.Marshal(delReq)
333+
bodyReader := bytes.NewReader(bodyBytes)
334+
335+
u := s.GatewayURL
336+
u.Path = "/system/functions"
337+
338+
req, err := http.NewRequest(http.MethodDelete, u.String(), bodyReader)
339+
if err != nil {
340+
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", u.String(), err)
341+
}
342+
343+
if s.ClientAuth != nil {
344+
if err := s.ClientAuth.Set(req); err != nil {
345+
return fmt.Errorf("unable to set Authorization header: %w", err)
346+
}
347+
}
348+
res, err := http.DefaultClient.Do(req)
349+
if err != nil {
350+
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
351+
352+
}
353+
354+
if res.Body != nil {
355+
defer res.Body.Close()
356+
}
357+
358+
switch res.StatusCode {
359+
case http.StatusAccepted, http.StatusOK, http.StatusCreated:
360+
break
361+
362+
case http.StatusNotFound:
363+
return fmt.Errorf("function %s not found", functionName)
364+
365+
case http.StatusUnauthorized:
366+
return fmt.Errorf("unauthorized action, please setup authentication for this server")
367+
368+
default:
369+
var err error
370+
bytesOut, err := io.ReadAll(res.Body)
371+
if err != nil {
372+
return err
373+
}
374+
375+
return fmt.Errorf("server returned unexpected status code %d, message: %q", res.StatusCode, string(bytesOut))
376+
}
377+
return nil
378+
}

client_test.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package sdk
22

33
import (
4+
"errors"
5+
"fmt"
46
"net/http"
57
"net/http/httptest"
68
"net/url"
79
"testing"
10+
11+
"github.com/openfaas/faas-provider/types"
812
)
913

1014
func TestSdk_GetNamespaces_TwoNamespaces(t *testing.T) {
@@ -70,3 +74,132 @@ func TestSdk_GetNamespaces_NoNamespaces(t *testing.T) {
7074
t.Fatalf("want %d namespaces, got: %d", len(wantNS), gotNS)
7175
}
7276
}
77+
78+
func TestSdk_DeployFunction(t *testing.T) {
79+
funcName := "funct1"
80+
nsName := "ns1"
81+
tests := []struct {
82+
name string
83+
functionName string
84+
namespace string
85+
err error
86+
handler func(rw http.ResponseWriter, req *http.Request)
87+
}{
88+
{
89+
name: "function deployed",
90+
functionName: funcName,
91+
namespace: nsName,
92+
handler: func(rw http.ResponseWriter, req *http.Request) {
93+
rw.WriteHeader(http.StatusOK)
94+
},
95+
},
96+
{
97+
name: "function will bedeployed",
98+
functionName: funcName,
99+
namespace: nsName,
100+
handler: func(rw http.ResponseWriter, req *http.Request) {
101+
rw.WriteHeader(http.StatusAccepted)
102+
},
103+
},
104+
{
105+
name: "client not authorized",
106+
functionName: funcName,
107+
namespace: nsName,
108+
handler: func(rw http.ResponseWriter, req *http.Request) {
109+
rw.WriteHeader(http.StatusUnauthorized)
110+
},
111+
err: fmt.Errorf("unauthorized action, please setup authentication for this server"),
112+
},
113+
{
114+
name: "unknown error",
115+
functionName: funcName,
116+
namespace: nsName,
117+
handler: func(rw http.ResponseWriter, req *http.Request) {
118+
http.Error(rw, "unknown error", http.StatusInternalServerError)
119+
},
120+
err: fmt.Errorf("unexpected status code: %d, message: %q", http.StatusInternalServerError, "unknown error\n"),
121+
},
122+
}
123+
124+
for _, test := range tests {
125+
t.Run(test.name, func(t *testing.T) {
126+
s := httptest.NewServer(http.HandlerFunc(test.handler))
127+
128+
sU, _ := url.Parse(s.URL)
129+
130+
client := NewClient(sU, nil, http.DefaultClient)
131+
_, err := client.Deploy(types.FunctionDeployment{
132+
Service: funcName,
133+
Image: fmt.Sprintf("docker.io/openfaas/%s:latest", funcName),
134+
Namespace: nsName,
135+
})
136+
137+
if !errors.Is(err, test.err) && err.Error() != test.err.Error() {
138+
t.Fatalf("wanted %s, but got: %s", test.err, err)
139+
}
140+
})
141+
}
142+
}
143+
144+
func TestSdk_DeleteFunction(t *testing.T) {
145+
funcName := "funct1"
146+
nsName := "ns1"
147+
tests := []struct {
148+
name string
149+
functionName string
150+
namespace string
151+
err error
152+
handler func(rw http.ResponseWriter, req *http.Request)
153+
}{
154+
{
155+
name: "function deleted",
156+
functionName: funcName,
157+
namespace: nsName,
158+
handler: func(rw http.ResponseWriter, req *http.Request) {
159+
rw.WriteHeader(http.StatusAccepted)
160+
},
161+
},
162+
{
163+
name: "function not found",
164+
functionName: funcName,
165+
namespace: nsName,
166+
handler: func(rw http.ResponseWriter, req *http.Request) {
167+
rw.WriteHeader(http.StatusNotFound)
168+
},
169+
err: fmt.Errorf("function %s not found", funcName),
170+
},
171+
{
172+
name: "client not authorized",
173+
functionName: funcName,
174+
namespace: nsName,
175+
handler: func(rw http.ResponseWriter, req *http.Request) {
176+
rw.WriteHeader(http.StatusUnauthorized)
177+
},
178+
err: fmt.Errorf("unauthorized action, please setup authentication for this server"),
179+
},
180+
{
181+
name: "unknown error",
182+
functionName: funcName,
183+
namespace: nsName,
184+
handler: func(rw http.ResponseWriter, req *http.Request) {
185+
http.Error(rw, "unknown error", http.StatusInternalServerError)
186+
},
187+
err: fmt.Errorf("server returned unexpected status code %d, message: %q", http.StatusInternalServerError, string("unknown error\n")),
188+
},
189+
}
190+
191+
for _, test := range tests {
192+
t.Run(test.name, func(t *testing.T) {
193+
s := httptest.NewServer(http.HandlerFunc(test.handler))
194+
195+
sU, _ := url.Parse(s.URL)
196+
197+
client := NewClient(sU, nil, http.DefaultClient)
198+
err := client.DeleteFunction(test.functionName, test.namespace)
199+
200+
if !errors.Is(err, test.err) && err.Error() != test.err.Error() {
201+
t.Fatalf("wanted %s, but got: %s", test.err, err)
202+
}
203+
})
204+
}
205+
}

0 commit comments

Comments
 (0)