Skip to content

Commit

Permalink
include namespace support
Browse files Browse the repository at this point in the history
Signed-off-by: Nitishkumar Singh <[email protected]>
  • Loading branch information
nitishkumar71 authored and alexellis committed Sep 6, 2023
1 parent d3220ce commit 63806f7
Show file tree
Hide file tree
Showing 4 changed files with 498 additions and 0 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: test

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build:
env:
GO111MODULE: off
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
with:
fetch-depth: 1
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.20.x

- name: test
run: make test
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export GO111MODULE=on

.PHONY: all
all: test

.PHONY: test
test:
CGO_ENABLED=0 go test ./...
215 changes: 215 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,221 @@ func (s *Client) GetNamespaces(ctx context.Context) ([]string, error) {
return namespaces, err
}

// GetNamespaces get openfaas namespaces
func (s *Client) GetNamespace(ctx context.Context, namespace string) (types.FunctionNamespace, error) {
u := s.GatewayURL
u.Path = fmt.Sprintf("/system/namespace/%s", namespace)

req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
if err != nil {
return types.FunctionNamespace{}, fmt.Errorf("unable to create request for %s, error: %w", u.String(), err)
}

if s.ClientAuth != nil {
if err := s.ClientAuth.Set(req); err != nil {
return types.FunctionNamespace{}, fmt.Errorf("unable to set Authorization header: %w", err)
}
}

res, err := s.Client.Do(req)
if err != nil {
return types.FunctionNamespace{}, fmt.Errorf("unable to make HTTP request: %w", err)
}

if res.Body != nil {
defer res.Body.Close()
}
body, _ := io.ReadAll(res.Body)

switch res.StatusCode {
case http.StatusOK:
fnNamespace := types.FunctionNamespace{}
if err := json.Unmarshal(body, &fnNamespace); err != nil {
return types.FunctionNamespace{},
fmt.Errorf("unable to unmarshal value: %q, error: %w", string(body), err)
}
return fnNamespace, err

case http.StatusNotFound:
return types.FunctionNamespace{}, fmt.Errorf("namespace %s not found", namespace)

case http.StatusUnauthorized:
return types.FunctionNamespace{}, fmt.Errorf("unauthorized action, please setup authentication for this server")

default:
return types.FunctionNamespace{}, fmt.Errorf("unexpected status code: %d, message: %q", res.StatusCode, string(body))
}
}

// CreateNamespace creates a namespace
func (s *Client) CreateNamespace(ctx context.Context, spec types.FunctionNamespace) (int, error) {

// set openfaas label
if spec.Labels == nil {
spec.Labels = map[string]string{}
}
spec.Labels["openfaas"] = "1"

bodyBytes, err := json.Marshal(spec)
if err != nil {
return http.StatusBadRequest, err
}

bodyReader := bytes.NewReader(bodyBytes)

u := s.GatewayURL
u.Path = "/system/namespace/"

req, err := http.NewRequestWithContext(ctx, http.MethodPost, u.String(), bodyReader)
if err != nil {
return http.StatusBadGateway, err
}

if s.ClientAuth != nil {
if err := s.ClientAuth.Set(req); err != nil {
return http.StatusInternalServerError, fmt.Errorf("unable to set Authorization header: %w", err)
}
}

res, err := s.Client.Do(req)
if err != nil {
return http.StatusBadGateway, err
}

var body []byte
if res.Body != nil {
defer res.Body.Close()
body, _ = io.ReadAll(res.Body)
}

switch res.StatusCode {
case http.StatusAccepted, http.StatusOK, http.StatusCreated:
return res.StatusCode, nil

case http.StatusUnauthorized:
return res.StatusCode, fmt.Errorf("unauthorized action, please setup authentication for this server")

default:
return res.StatusCode, fmt.Errorf("unexpected status code: %d, message: %q", res.StatusCode, string(body))
}
}

// UpdateNamespace updates a namespace
func (s *Client) UpdateNamespace(ctx context.Context, spec types.FunctionNamespace) (int, error) {

// set openfaas label
if spec.Labels == nil {
spec.Labels = map[string]string{}
}
spec.Labels["openfaas"] = "1"

bodyBytes, err := json.Marshal(spec)
if err != nil {
return http.StatusBadRequest, err
}

bodyReader := bytes.NewReader(bodyBytes)

u := s.GatewayURL
u.Path = fmt.Sprintf("/system/namespace/%s", spec.Name)

req, err := http.NewRequestWithContext(ctx, http.MethodPut, u.String(), bodyReader)
if err != nil {
return http.StatusBadGateway, err
}

if s.ClientAuth != nil {
if err := s.ClientAuth.Set(req); err != nil {
return http.StatusInternalServerError, fmt.Errorf("unable to set Authorization header: %w", err)
}
}

res, err := s.Client.Do(req)
if err != nil {
return http.StatusBadGateway, err
}

var body []byte
if res.Body != nil {
defer res.Body.Close()
body, _ = io.ReadAll(res.Body)
}

switch res.StatusCode {
case http.StatusAccepted, http.StatusOK, http.StatusCreated:
return res.StatusCode, nil

case http.StatusNotFound:
return res.StatusCode, fmt.Errorf("namespace %s not found", spec.Name)

case http.StatusUnauthorized:
return res.StatusCode, fmt.Errorf("unauthorized action, please setup authentication for this server")

default:
return res.StatusCode, fmt.Errorf("unexpected status code: %d, message: %q", res.StatusCode, string(body))
}
}

// DeleteNamespace deletes a namespace
func (s *Client) DeleteNamespace(ctx context.Context, namespace string) error {

delReq := types.FunctionNamespace{
Name: namespace,
Labels: map[string]string{
"openfaas": "1",
},
}

var err error

bodyBytes, _ := json.Marshal(delReq)
bodyReader := bytes.NewReader(bodyBytes)

u := s.GatewayURL
u.Path = fmt.Sprintf("/system/namespace/%s", namespace)

req, err := http.NewRequestWithContext(ctx, http.MethodDelete, u.String(), bodyReader)
if err != nil {
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", u.String(), err)
}

if s.ClientAuth != nil {
if err := s.ClientAuth.Set(req); err != nil {
return fmt.Errorf("unable to set Authorization header: %w", err)
}
}
res, err := http.DefaultClient.Do(req)
if err != nil {
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)

}

if res.Body != nil {
defer res.Body.Close()
}

switch res.StatusCode {
case http.StatusAccepted, http.StatusOK, http.StatusCreated:
break

case http.StatusNotFound:
return fmt.Errorf("namespace %s not found", namespace)

case http.StatusUnauthorized:
return fmt.Errorf("unauthorized action, please setup authentication for this server")

default:
var err error
bytesOut, err := io.ReadAll(res.Body)
if err != nil {
return err
}

return fmt.Errorf("unexpected status code: %d, message: %q", res.StatusCode, string(bytesOut))
}
return nil
}

// GetFunctions lists all functions
func (s *Client) GetFunctions(ctx context.Context, namespace string) ([]types.FunctionStatus, error) {
u := s.GatewayURL
Expand Down
Loading

0 comments on commit 63806f7

Please sign in to comment.