Skip to content

Commit 203b0f2

Browse files
authored
Merge pull request #1 from matejvasek/tests-for-del-cmd
add tests for delete cmd
2 parents cf9ce0b + 5a3d385 commit 203b0f2

File tree

2 files changed

+182
-55
lines changed

2 files changed

+182
-55
lines changed

cmd/delete.go

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

33
import (
44
"fmt"
5-
65
"github.com/ory/viper"
76
"github.com/spf13/cobra"
87

@@ -13,80 +12,89 @@ import (
1312

1413
func init() {
1514
root.AddCommand(deleteCmd)
16-
deleteCmd.Flags().BoolP("confirm", "c", false, "Prompt to confirm all configuration options (Env: $FUNC_CONFIRM)")
17-
deleteCmd.Flags().StringP("path", "p", cwd(), "Path to the function project that should be undeployed (Env: $FUNC_PATH)")
18-
deleteCmd.Flags().StringP("namespace", "n", "", "Namespace of the function to undeploy. By default, the namespace in func.yaml is used or the actual active namespace if not set in the configuration. (Env: $FUNC_NAMESPACE)")
1915
}
2016

21-
var deleteCmd = &cobra.Command{
22-
Use: "delete [NAME]",
23-
Short: "Undeploy a function",
24-
Long: `Undeploy a function
17+
func NewDeleteCmd(newRemover func(ns string, verbose bool) (fn.Remover, error)) *cobra.Command {
18+
delCmd := &cobra.Command{
19+
Use: "delete [NAME]",
20+
Short: "Undeploy a function",
21+
Long: `Undeploy a function
2522
2623
This command undeploys a function from the cluster. By default the function from
2724
the project in the current directory is undeployed. Alternatively either the name
2825
of the function can be given as argument or the project path provided with --path.
2926
3027
No local files are deleted.
3128
`,
32-
Example: `
29+
Example: `
3330
# Undeploy the function defined in the local directory
3431
kn func delete
3532
3633
# Undeploy the function 'myfunc' in namespace 'apps'
3734
kn func delete -n apps myfunc
3835
`,
39-
SuggestFor: []string{"remove", "rm", "del"},
40-
ValidArgsFunction: CompleteFunctionList,
41-
PreRunE: bindEnv("path", "confirm", "namespace"),
42-
RunE: runDelete,
43-
}
44-
45-
46-
func runDelete(cmd *cobra.Command, args []string) (err error) {
47-
config := newDeleteConfig(args).Prompt()
48-
49-
var function fn.Function
50-
51-
// Initialize func with explicit name (when provided)
52-
if len(args) > 0 && args[0] != "" {
53-
pathChanged := cmd.Flags().Changed("path")
54-
if pathChanged {
55-
return fmt.Errorf("Only one of --path and [NAME] should be provided")
56-
}
57-
function = fn.Function{
58-
Name: args[0],
59-
}
60-
} else {
61-
function, err = fn.NewFunction(config.Path)
62-
if err != nil {
63-
return
64-
}
65-
66-
// Check if the Function has been initialized
67-
if !function.Initialized() {
68-
return fmt.Errorf("the given path '%v' does not contain an initialized function", config.Path)
69-
}
36+
SuggestFor: []string{"remove", "rm", "del"},
37+
ValidArgsFunction: CompleteFunctionList,
38+
PreRunE: bindEnv("path", "confirm", "namespace"),
39+
RunE: func(cmd *cobra.Command, args []string) (err error) {
40+
config := newDeleteConfig(args).Prompt()
41+
42+
var function fn.Function
43+
44+
// Initialize func with explicit name (when provided)
45+
if len(args) > 0 && args[0] != "" {
46+
pathChanged := cmd.Flags().Changed("path")
47+
if pathChanged {
48+
return fmt.Errorf("Only one of --path and [NAME] should be provided")
49+
}
50+
function = fn.Function{
51+
Name: args[0],
52+
}
53+
} else {
54+
function, err = fn.NewFunction(config.Path)
55+
if err != nil {
56+
return
57+
}
58+
59+
// Check if the Function has been initialized
60+
if !function.Initialized() {
61+
return fmt.Errorf("the given path '%v' does not contain an initialized function", config.Path)
62+
}
63+
}
64+
65+
ns := config.Namespace
66+
if ns == "" {
67+
ns = function.Namespace
68+
}
69+
70+
remover, err := newRemover(ns, config.Verbose)
71+
if err != nil {
72+
return
73+
}
74+
75+
client := fn.New(
76+
fn.WithVerbose(config.Verbose),
77+
fn.WithRemover(remover))
78+
79+
return client.Remove(cmd.Context(), function)
80+
},
7081
}
7182

72-
ns := config.Namespace
73-
if ns == "" {
74-
ns = function.Namespace
75-
}
83+
delCmd.Flags().BoolP("confirm", "c", false, "Prompt to confirm all configuration options (Env: $FUNC_CONFIRM)")
84+
delCmd.Flags().StringP("path", "p", cwd(), "Path to the function project that should be undeployed (Env: $FUNC_PATH)")
85+
delCmd.Flags().StringP("namespace", "n", "", "Namespace of the function to undeploy. By default, the namespace in func.yaml is used or the actual active namespace if not set in the configuration. (Env: $FUNC_NAMESPACE)")
7686

77-
remover, err := knative.NewRemover(ns)
87+
return delCmd
88+
}
89+
90+
var deleteCmd = NewDeleteCmd(func(ns string, verbose bool) (fn.Remover, error) {
91+
r, err := knative.NewRemover(ns)
7892
if err != nil {
79-
return
93+
return nil, err
8094
}
81-
82-
remover.Verbose = config.Verbose
83-
84-
client := fn.New(
85-
fn.WithVerbose(config.Verbose),
86-
fn.WithRemover(remover))
87-
88-
return client.Remove(cmd.Context(), function)
89-
}
95+
r.Verbose = verbose
96+
return r, nil
97+
})
9098

9199
type deleteConfig struct {
92100
Name string

cmd/delete_test.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
fn "github.com/boson-project/func"
6+
"io/ioutil"
7+
"os"
8+
"path/filepath"
9+
"testing"
10+
)
11+
12+
type testRemover struct {
13+
invokedWith *string
14+
}
15+
16+
func (t *testRemover) Remove(ctx context.Context, name string) error {
17+
t.invokedWith = &name
18+
return nil
19+
}
20+
21+
// test delete outside project just using function name
22+
func TestDeleteCmdWithoutProject(t *testing.T) {
23+
tr := &testRemover{}
24+
cmd := NewDeleteCmd(func(ns string, verbose bool) (fn.Remover, error) {
25+
return tr, nil
26+
})
27+
28+
cmd.SetArgs([]string{"foo"})
29+
err := cmd.Execute()
30+
if err != nil {
31+
t.Fatal(err)
32+
}
33+
34+
if tr.invokedWith == nil {
35+
t.Fatal("fn.Remover has not been invoked")
36+
}
37+
38+
if *tr.invokedWith != "foo" {
39+
t.Fatalf("expected fn.Remover to be called with 'foo', but was called with '%s'", *tr.invokedWith)
40+
}
41+
}
42+
43+
// test delete from inside project directory (reading func name from func.yaml)
44+
func TestDeleteCmdWithProject(t *testing.T) {
45+
funcYaml := `name: bar
46+
namespace: ""
47+
runtime: go
48+
image: ""
49+
imageDigest: ""
50+
trigger: http
51+
builder: quay.io/boson/faas-go-builder
52+
builderMap:
53+
default: quay.io/boson/faas-go-builder
54+
env: {}
55+
annotations: {}
56+
`
57+
tmpDir, err := ioutil.TempDir("", "bar")
58+
if err != nil {
59+
t.Fatal(err)
60+
}
61+
defer os.RemoveAll(tmpDir)
62+
63+
f, err := os.Create(filepath.Join(tmpDir, "func.yaml"))
64+
if err != nil {
65+
t.Fatal(err)
66+
}
67+
defer f.Close()
68+
69+
f.WriteString(funcYaml)
70+
f.Close()
71+
72+
73+
oldWD, err := os.Getwd()
74+
if err != nil {
75+
t.Fatal(err)
76+
}
77+
defer os.Chdir(oldWD)
78+
err = os.Chdir(tmpDir)
79+
if err != nil {
80+
t.Fatal(err)
81+
}
82+
83+
tr := &testRemover{}
84+
cmd := NewDeleteCmd(func(ns string, verbose bool) (fn.Remover, error) {
85+
return tr, nil
86+
})
87+
88+
cmd.SetArgs([]string{"-p", "."})
89+
err = cmd.Execute()
90+
if err != nil {
91+
t.Fatal(err)
92+
}
93+
94+
if tr.invokedWith == nil {
95+
t.Fatal("fn.Remover has not been invoked")
96+
}
97+
98+
if *tr.invokedWith != "bar" {
99+
t.Fatalf("expected fn.Remover to be called with 'bar', but was called with '%s'", *tr.invokedWith)
100+
}
101+
}
102+
103+
// test where both name and path are provided
104+
func TestDeleteCmdWithBothPathAndName(t *testing.T) {
105+
tr := &testRemover{}
106+
cmd := NewDeleteCmd(func(ns string, verbose bool) (fn.Remover, error) {
107+
return tr, nil
108+
})
109+
110+
cmd.SetArgs([]string{"foo", "-p", "/adir/"})
111+
err := cmd.Execute()
112+
if err == nil {
113+
t.Fatal("error was expected as both name an path cannot be used together")
114+
}
115+
116+
if tr.invokedWith != nil {
117+
t.Fatal("fn.Remove was call when it shouldn't have been")
118+
}
119+
}

0 commit comments

Comments
 (0)