Skip to content

Commit 63806f7

Browse files
nitishkumar71alexellis
authored andcommitted
include namespace support
Signed-off-by: Nitishkumar Singh <[email protected]>
1 parent d3220ce commit 63806f7

File tree

4 files changed

+498
-0
lines changed

4 files changed

+498
-0
lines changed

.github/workflows/test.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: test
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ master ]
8+
9+
jobs:
10+
build:
11+
env:
12+
GO111MODULE: off
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@master
16+
with:
17+
fetch-depth: 1
18+
- name: Install Go
19+
uses: actions/setup-go@v2
20+
with:
21+
go-version: 1.20.x
22+
23+
- name: test
24+
run: make test

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export GO111MODULE=on
2+
3+
.PHONY: all
4+
all: test
5+
6+
.PHONY: test
7+
test:
8+
CGO_ENABLED=0 go test ./...

client.go

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,221 @@ func (s *Client) GetNamespaces(ctx context.Context) ([]string, error) {
8181
return namespaces, err
8282
}
8383

84+
// GetNamespaces get openfaas namespaces
85+
func (s *Client) GetNamespace(ctx context.Context, namespace string) (types.FunctionNamespace, error) {
86+
u := s.GatewayURL
87+
u.Path = fmt.Sprintf("/system/namespace/%s", namespace)
88+
89+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
90+
if err != nil {
91+
return types.FunctionNamespace{}, fmt.Errorf("unable to create request for %s, error: %w", u.String(), err)
92+
}
93+
94+
if s.ClientAuth != nil {
95+
if err := s.ClientAuth.Set(req); err != nil {
96+
return types.FunctionNamespace{}, fmt.Errorf("unable to set Authorization header: %w", err)
97+
}
98+
}
99+
100+
res, err := s.Client.Do(req)
101+
if err != nil {
102+
return types.FunctionNamespace{}, fmt.Errorf("unable to make HTTP request: %w", err)
103+
}
104+
105+
if res.Body != nil {
106+
defer res.Body.Close()
107+
}
108+
body, _ := io.ReadAll(res.Body)
109+
110+
switch res.StatusCode {
111+
case http.StatusOK:
112+
fnNamespace := types.FunctionNamespace{}
113+
if err := json.Unmarshal(body, &fnNamespace); err != nil {
114+
return types.FunctionNamespace{},
115+
fmt.Errorf("unable to unmarshal value: %q, error: %w", string(body), err)
116+
}
117+
return fnNamespace, err
118+
119+
case http.StatusNotFound:
120+
return types.FunctionNamespace{}, fmt.Errorf("namespace %s not found", namespace)
121+
122+
case http.StatusUnauthorized:
123+
return types.FunctionNamespace{}, fmt.Errorf("unauthorized action, please setup authentication for this server")
124+
125+
default:
126+
return types.FunctionNamespace{}, fmt.Errorf("unexpected status code: %d, message: %q", res.StatusCode, string(body))
127+
}
128+
}
129+
130+
// CreateNamespace creates a namespace
131+
func (s *Client) CreateNamespace(ctx context.Context, spec types.FunctionNamespace) (int, error) {
132+
133+
// set openfaas label
134+
if spec.Labels == nil {
135+
spec.Labels = map[string]string{}
136+
}
137+
spec.Labels["openfaas"] = "1"
138+
139+
bodyBytes, err := json.Marshal(spec)
140+
if err != nil {
141+
return http.StatusBadRequest, err
142+
}
143+
144+
bodyReader := bytes.NewReader(bodyBytes)
145+
146+
u := s.GatewayURL
147+
u.Path = "/system/namespace/"
148+
149+
req, err := http.NewRequestWithContext(ctx, http.MethodPost, u.String(), bodyReader)
150+
if err != nil {
151+
return http.StatusBadGateway, err
152+
}
153+
154+
if s.ClientAuth != nil {
155+
if err := s.ClientAuth.Set(req); err != nil {
156+
return http.StatusInternalServerError, fmt.Errorf("unable to set Authorization header: %w", err)
157+
}
158+
}
159+
160+
res, err := s.Client.Do(req)
161+
if err != nil {
162+
return http.StatusBadGateway, err
163+
}
164+
165+
var body []byte
166+
if res.Body != nil {
167+
defer res.Body.Close()
168+
body, _ = io.ReadAll(res.Body)
169+
}
170+
171+
switch res.StatusCode {
172+
case http.StatusAccepted, http.StatusOK, http.StatusCreated:
173+
return res.StatusCode, nil
174+
175+
case http.StatusUnauthorized:
176+
return res.StatusCode, fmt.Errorf("unauthorized action, please setup authentication for this server")
177+
178+
default:
179+
return res.StatusCode, fmt.Errorf("unexpected status code: %d, message: %q", res.StatusCode, string(body))
180+
}
181+
}
182+
183+
// UpdateNamespace updates a namespace
184+
func (s *Client) UpdateNamespace(ctx context.Context, spec types.FunctionNamespace) (int, error) {
185+
186+
// set openfaas label
187+
if spec.Labels == nil {
188+
spec.Labels = map[string]string{}
189+
}
190+
spec.Labels["openfaas"] = "1"
191+
192+
bodyBytes, err := json.Marshal(spec)
193+
if err != nil {
194+
return http.StatusBadRequest, err
195+
}
196+
197+
bodyReader := bytes.NewReader(bodyBytes)
198+
199+
u := s.GatewayURL
200+
u.Path = fmt.Sprintf("/system/namespace/%s", spec.Name)
201+
202+
req, err := http.NewRequestWithContext(ctx, http.MethodPut, u.String(), bodyReader)
203+
if err != nil {
204+
return http.StatusBadGateway, err
205+
}
206+
207+
if s.ClientAuth != nil {
208+
if err := s.ClientAuth.Set(req); err != nil {
209+
return http.StatusInternalServerError, fmt.Errorf("unable to set Authorization header: %w", err)
210+
}
211+
}
212+
213+
res, err := s.Client.Do(req)
214+
if err != nil {
215+
return http.StatusBadGateway, err
216+
}
217+
218+
var body []byte
219+
if res.Body != nil {
220+
defer res.Body.Close()
221+
body, _ = io.ReadAll(res.Body)
222+
}
223+
224+
switch res.StatusCode {
225+
case http.StatusAccepted, http.StatusOK, http.StatusCreated:
226+
return res.StatusCode, nil
227+
228+
case http.StatusNotFound:
229+
return res.StatusCode, fmt.Errorf("namespace %s not found", spec.Name)
230+
231+
case http.StatusUnauthorized:
232+
return res.StatusCode, fmt.Errorf("unauthorized action, please setup authentication for this server")
233+
234+
default:
235+
return res.StatusCode, fmt.Errorf("unexpected status code: %d, message: %q", res.StatusCode, string(body))
236+
}
237+
}
238+
239+
// DeleteNamespace deletes a namespace
240+
func (s *Client) DeleteNamespace(ctx context.Context, namespace string) error {
241+
242+
delReq := types.FunctionNamespace{
243+
Name: namespace,
244+
Labels: map[string]string{
245+
"openfaas": "1",
246+
},
247+
}
248+
249+
var err error
250+
251+
bodyBytes, _ := json.Marshal(delReq)
252+
bodyReader := bytes.NewReader(bodyBytes)
253+
254+
u := s.GatewayURL
255+
u.Path = fmt.Sprintf("/system/namespace/%s", namespace)
256+
257+
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, u.String(), bodyReader)
258+
if err != nil {
259+
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", u.String(), err)
260+
}
261+
262+
if s.ClientAuth != nil {
263+
if err := s.ClientAuth.Set(req); err != nil {
264+
return fmt.Errorf("unable to set Authorization header: %w", err)
265+
}
266+
}
267+
res, err := http.DefaultClient.Do(req)
268+
if err != nil {
269+
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
270+
271+
}
272+
273+
if res.Body != nil {
274+
defer res.Body.Close()
275+
}
276+
277+
switch res.StatusCode {
278+
case http.StatusAccepted, http.StatusOK, http.StatusCreated:
279+
break
280+
281+
case http.StatusNotFound:
282+
return fmt.Errorf("namespace %s not found", namespace)
283+
284+
case http.StatusUnauthorized:
285+
return fmt.Errorf("unauthorized action, please setup authentication for this server")
286+
287+
default:
288+
var err error
289+
bytesOut, err := io.ReadAll(res.Body)
290+
if err != nil {
291+
return err
292+
}
293+
294+
return fmt.Errorf("unexpected status code: %d, message: %q", res.StatusCode, string(bytesOut))
295+
}
296+
return nil
297+
}
298+
84299
// GetFunctions lists all functions
85300
func (s *Client) GetFunctions(ctx context.Context, namespace string) ([]types.FunctionStatus, error) {
86301
u := s.GatewayURL

0 commit comments

Comments
 (0)