Skip to content

Commit

Permalink
Implement namespace support using go-sdk
Browse files Browse the repository at this point in the history
Signed-off-by: Nitishkumar Singh <nitishkumarsingh71@gmail.com>
  • Loading branch information
nitishkumar71 committed Sep 20, 2023
1 parent d12888b commit 850bbeb
Show file tree
Hide file tree
Showing 27 changed files with 1,725 additions and 759 deletions.
31 changes: 31 additions & 0 deletions commands/general.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import (
"crypto/tls"
"net"
"net/http"
"net/url"
"os"
"time"

"github.com/openfaas/faas-cli/proxy"
"github.com/openfaas/go-sdk"
)

var (
Expand Down Expand Up @@ -36,3 +41,29 @@ func GetDefaultCLITransport(tlsInsecure bool, timeout *time.Duration) *http.Tran
}
return nil
}

func GetDefaultSDKClient() (*sdk.Client, error) {
gatewayAddress := getGatewayURL(gateway, defaultGateway, "", os.Getenv(openFaaSURLEnvironment))
gatewayURL, err := url.Parse(gatewayAddress)
if err != nil {
return nil, err
}

transport := GetDefaultCLITransport(tlsInsecure, &commandTimeout)

httpClient := &http.Client{}
httpClient.Timeout = commandTimeout

if transport != nil {
httpClient.Transport = transport
}

clientAuth, err := proxy.NewCLIAuth(token, gateway)
if err != nil {
return nil, err
}

client := sdk.NewClient(gatewayURL, clientAuth, http.DefaultClient)

return client, nil
}
24 changes: 24 additions & 0 deletions commands/namespace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) OpenFaaS Author(s) 2023. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package commands

import (
"github.com/spf13/cobra"
)

func init() {
// Setup flags that are used by multiple commands (variables defined in faas.go)
namespaceCmd.PersistentFlags().StringVarP(&gateway, "gateway", "g", defaultGateway, "Gateway URL starting with http(s)://")
namespaceCmd.PersistentFlags().BoolVar(&tlsInsecure, "tls-no-verify", false, "Disable TLS validation")
namespaceCmd.PersistentFlags().StringVarP(&token, "token", "k", "", "Pass a JWT token to use instead of basic auth")

faasCmd.AddCommand(namespaceCmd)
}

var namespaceCmd = &cobra.Command{
Use: `namespace [--gateway GATEWAY_URL] [--tls-no-verify] [--token JWT_TOKEN]`,
Aliases: []string{"ns"},
Short: "Manage OpenFaaS namespace",
Long: "Manage OpenFaaS namespace either on local or remote gateway",
}
87 changes: 87 additions & 0 deletions commands/namespace_create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (c) OpenFaaS Author(s) 2023. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package commands

import (
"context"
"fmt"

"github.com/openfaas/faas-cli/util"
"github.com/openfaas/faas-provider/types"
"github.com/spf13/cobra"
)

// NamespaceCreateFlags holds flags that are to be added to commands.
type NamespaceCreateFlags struct {
labelOpts []string
annotationOpts []string
}

var namespaceCreateFlags NamespaceCreateFlags

var namespaceCreateCmd = &cobra.Command{
Use: `create NAME
[--label LABEL=VALUE ...]
[--annotation ANNOTATION=VALUE ...]`,
Short: "Create a new namespace",
Long: "Create command creates a new namespace",
Example: `faas-cli namespace create NAME
faas-cli namespace create NAME --label demo=true
faas-cli namespace create NAME --annotation demo=true
faas-cli namespace create NAME --label demo=true \
--annotation demo=true`,
RunE: createNamespace,
PreRunE: preCreateNamespace,
}

func init() {
namespaceCreateCmd.Flags().StringArrayVarP(&namespaceCreateFlags.labelOpts, "label", "l", []string{}, "Set one or more label (LABEL=VALUE)")
namespaceCreateCmd.Flags().StringArrayVarP(&namespaceCreateFlags.annotationOpts, "annotation", "", []string{}, "Set one or more annotation (ANNOTATION=VALUE)")

namespaceCmd.AddCommand(namespaceCreateCmd)
}

func preCreateNamespace(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return fmt.Errorf("namespace name required")
}

if len(args) > 1 {
return fmt.Errorf("too many values for namespace name")
}

return nil
}

func createNamespace(cmd *cobra.Command, args []string) error {
client, err := GetDefaultSDKClient()
if err != nil {
return err
}

labels, err := util.ParseMap(namespaceCreateFlags.labelOpts, "labels")
if err != nil {
return err
}

annotations, err := util.ParseMap(namespaceCreateFlags.annotationOpts, "annotations")
if err != nil {
return err
}

req := types.FunctionNamespace{
Name: args[0],
Labels: labels,
Annotations: annotations,
}

fmt.Printf("Creating Namespace: %s\n", req.Name)
if _, err = client.CreateNamespace(context.Background(), req); err != nil {
return err
}

fmt.Printf("Namespace Created: %s\n", req.Name)

return nil
}
34 changes: 34 additions & 0 deletions commands/namespace_create_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package commands

import "testing"

func Test_preCreateNamespace_NoArgs_Fails(t *testing.T) {
res := preCreateNamespace(nil, []string{})

want := "namespace name required"
if res.Error() != want {
t.Errorf("want %q, got %q", want, res.Error())
}
}

func Test_preCreateNamespace_MoreThan1Arg_Fails(t *testing.T) {
res := preCreateNamespace(nil, []string{
"secret1",
"secret2",
})

want := "too many values for namespace name"
if res.Error() != want {
t.Errorf("want %q, got %q", want, res.Error())
}
}

func Test_preCreateNamespace_ExtactlyOneArgIsFine(t *testing.T) {
res := preCreateNamespace(nil, []string{
"namespace1",
})

if res != nil {
t.Errorf("expected no validation error, but got %q", res.Error())
}
}
54 changes: 54 additions & 0 deletions commands/namespace_delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (c) OpenFaaS Author(s) 2023. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package commands

import (
"context"
"fmt"

"github.com/spf13/cobra"
)

var namespaceDeleteCmd = &cobra.Command{
Use: `delete NAME`,
Short: "Delete existing namespace",
Long: "Delete existing namespace",
Example: `faas-cli namespace delete NAME`,
RunE: deleteNamespace,
PreRunE: preDeleteNamespace,
}

func init() {
namespaceCmd.AddCommand(namespaceDeleteCmd)
}

func preDeleteNamespace(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return fmt.Errorf("namespace name required")
}

if len(args) > 1 {
return fmt.Errorf("too many values for namespace name")
}

return nil
}

func deleteNamespace(cmd *cobra.Command, args []string) error {
client, err := GetDefaultSDKClient()
if err != nil {
return err
}

ns := args[0]

fmt.Printf("Deleting Namespace: %s\n", ns)
if err = client.DeleteNamespace(context.Background(), ns); err != nil {
return err
}

fmt.Printf("Namespace Deleted: %s\n", ns)

return nil
}
34 changes: 34 additions & 0 deletions commands/namespace_delete_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package commands

import "testing"

func Test_preDeleteNamespace_NoArgs_Fails(t *testing.T) {
res := preDeleteNamespace(nil, []string{})

want := "namespace name required"
if res.Error() != want {
t.Errorf("want %q, got %q", want, res.Error())
}
}

func Test_preDeleteNamespace_MoreThan1Arg_Fails(t *testing.T) {
res := preDeleteNamespace(nil, []string{
"secret1",
"secret2",
})

want := "too many values for namespace name"
if res.Error() != want {
t.Errorf("want %q, got %q", want, res.Error())
}
}

func Test_preDeleteNamespace_ExtactlyOneArgIsFine(t *testing.T) {
res := preDeleteNamespace(nil, []string{
"namespace1",
})

if res != nil {
t.Errorf("expected no validation error, but got %q", res.Error())
}
}
78 changes: 78 additions & 0 deletions commands/namespace_get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright (c) OpenFaaS Author(s) 2023. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package commands

import (
"context"
"fmt"
"io"
"text/tabwriter"

"github.com/openfaas/faas-provider/types"
"github.com/spf13/cobra"
)

var namespaceGetCmd = &cobra.Command{
Use: `get NAMESPACE_NAME`,
Short: "Get existing namespace",
Long: "Get existing namespace",
Example: `faas-cli namespace get NAME`,
RunE: get_namespace,
PreRunE: preGetNamespace,
}

func init() {
namespaceCmd.AddCommand(namespaceGetCmd)
}

func preGetNamespace(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return fmt.Errorf("namespace name required")
}

if len(args) > 1 {
return fmt.Errorf("too many values for namespace name")
}

return nil
}

func get_namespace(cmd *cobra.Command, args []string) error {
client, err := GetDefaultSDKClient()
if err != nil {
return err
}

ns := args[0]

res, err := client.GetNamespace(context.Background(), ns)
if err != nil {
return err
}

printNamespaceDetail(cmd.OutOrStdout(), res)

return nil
}

func printNamespaceDetail(dst io.Writer, nsDetail types.FunctionNamespace) {
w := tabwriter.NewWriter(dst, 0, 0, 1, ' ', tabwriter.TabIndent)
defer w.Flush()

out := printer{
w: w,
verbose: verbose,
}
out.Printf("Name:\t%s\n", nsDetail.Name)
if len(nsDetail.Labels) > 1 {
out.Printf("Labels", nsDetail.Labels)
} else {
out.Printf("Labels", map[string]string{})
}
if len(nsDetail.Annotations) > 1 {
out.Printf("Annotations", nsDetail.Annotations)
} else {
out.Printf("Annotations", map[string]string{})
}
}
34 changes: 34 additions & 0 deletions commands/namespace_get_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package commands

import "testing"

func Test_preGetNamespace_NoArgs_Fails(t *testing.T) {
res := preGetNamespace(nil, []string{})

want := "namespace name required"
if res.Error() != want {
t.Errorf("want %q, got %q", want, res.Error())
}
}

func Test_preGetNamespace_MoreThan1Arg_Fails(t *testing.T) {
res := preGetNamespace(nil, []string{
"secret1",
"secret2",
})

want := "too many values for namespace name"
if res.Error() != want {
t.Errorf("want %q, got %q", want, res.Error())
}
}

func Test_preGetNamespace_ExtactlyOneArgIsFine(t *testing.T) {
res := preGetNamespace(nil, []string{
"namespace1",
})

if res != nil {
t.Errorf("expected no validation error, but got %q", res.Error())
}
}
Loading

0 comments on commit 850bbeb

Please sign in to comment.