diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..b6901d5e7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "commands/testdata/templates"] + path = commands/testdata/templates + url = https://github.com/openfaas/templates.git diff --git a/commands/fetch_templates.go b/commands/fetch_templates.go index 5caa50671..523e9575a 100644 --- a/commands/fetch_templates.go +++ b/commands/fetch_templates.go @@ -36,7 +36,7 @@ func fetchTemplates(templateURL string, overwrite bool) error { log.Printf("Attempting to expand templates from %s\n", templateURL) pullDebugPrint(fmt.Sprintf("Temp files in %s", dir)) args := map[string]string{"dir": dir, "repo": templateURL} - if err := versioncontrol.GitClone.Invoke(args); err != nil { + if err := versioncontrol.GitClone.Invoke(".", args); err != nil { return err } diff --git a/commands/fetch_templates_test.go b/commands/fetch_templates_test.go index 93dff9144..9d924343d 100644 --- a/commands/fetch_templates_test.go +++ b/commands/fetch_templates_test.go @@ -5,8 +5,10 @@ package commands import ( "io/ioutil" "os" + "path/filepath" "testing" + "github.com/openfaas/faas-cli/builder" "github.com/openfaas/faas-cli/versioncontrol" ) @@ -41,12 +43,13 @@ func setupLocalTemplateRepo(t *testing.T) string { t.Error(err) } - args := map[string]string{ - "dir": dir, - "repo": defaultTemplateRepository, - } - if err := versioncontrol.GitClone.Invoke(args); err != nil { - t.Error(err) + // Copy the submodule to temp directory to avoid altering it during tests + testRepoGit := filepath.Join("testdata", "templates") + builder.CopyFiles(testRepoGit, dir) + // Remove submodule .git file + os.Remove(filepath.Join(dir, ".git")) + if err := versioncontrol.GitInitRepo.Invoke(dir, map[string]string{"dir": "."}); err != nil { + t.Fatal(err) } return dir diff --git a/commands/new_function.go b/commands/new_function.go index c52b01645..789e8945c 100644 --- a/commands/new_function.go +++ b/commands/new_function.go @@ -7,8 +7,8 @@ import ( "fmt" "io/ioutil" "os" + "path/filepath" "sort" - "strings" "github.com/openfaas/faas-cli/builder" "github.com/openfaas/faas-cli/stack" @@ -20,7 +20,6 @@ var ( list bool ) -// Implement interface for sorting array of strings type StrSort []string func (a StrSort) Len() int { return len(a) } @@ -62,12 +61,8 @@ func runNewFunction(cmd *cobra.Command, args []string) error { } } - fmt.Printf(`Languages available as templates: -` + printAvailableTemplates(availableTemplates) + ` + fmt.Printf("Languages available as templates:\n%s\n", printAvailableTemplates(availableTemplates)) -Or alternatively create a folder containing a Dockerfile, then pick -the "Dockerfile" lang type in your YAML file. -`) return nil } @@ -90,36 +85,19 @@ the "Dockerfile" lang type in your YAML file. return fmt.Errorf("folder: %s already exists", functionName) } - if err := os.Mkdir("./"+functionName, 0700); err == nil { + if err := os.Mkdir(functionName, 0700); err == nil { fmt.Printf("Folder: %s created.\n", functionName) + } else { + return fmt.Errorf("folder: could not create %s : %s", functionName, err) } if err := updateGitignore(); err != nil { return fmt.Errorf("got unexpected error while updating .gitignore file: %s", err) } - // Only "template" language templates - Dockerfile must be custom, so start with empty directory. - if strings.ToLower(lang) != "dockerfile" { - builder.CopyFiles("./template/"+lang+"/function/", "./"+functionName+"/") - } else { - ioutil.WriteFile("./"+functionName+"/Dockerfile", []byte(`FROM alpine:3.6 -# Use any image as your base image, or "scratch" -# Add fwatchdog binary via https://github.com/openfaas/faas/releases/ -# Then set fprocess to the process you want to invoke per request - i.e. "cat" or "my_binary" - -ADD https://github.com/openfaas/faas/releases/download/0.6.9/fwatchdog /usr/bin -# COPY ./fwatchdog /usr/bin/ -RUN chmod +x /usr/bin/fwatchdog - -# Populate example here - i.e. "cat", "sha512sum" or "node index.js" -ENV fprocess="wc -l" + builder.CopyFiles(filepath.Join("template", lang, "function"), functionName) -HEALTHCHECK --interval=5s CMD [ -e /tmp/.lock ] || exit 1 -CMD ["fwatchdog"] -`), 0600) - } - - stack := `provider: + stackYaml := `provider: name: faas gateway: ` + gateway + ` @@ -134,7 +112,7 @@ functions: fmt.Println() fmt.Printf("Function created in folder: %s\n", functionName) - stackWriteErr := ioutil.WriteFile("./"+functionName+".yml", []byte(stack), 0600) + stackWriteErr := ioutil.WriteFile("./"+functionName+".yml", []byte(stackYaml), 0600) if stackWriteErr != nil { return fmt.Errorf("error writing stack file %s", stackWriteErr) } @@ -148,7 +126,6 @@ func printAvailableTemplates(availableTemplates []string) string { sort.Sort(StrSort(availableTemplates)) for _, template := range availableTemplates { result += fmt.Sprintf("- %s\n", template) - } return result } diff --git a/commands/new_function_test.go b/commands/new_function_test.go index 193bb245e..75df2a99d 100644 --- a/commands/new_function_test.go +++ b/commands/new_function_test.go @@ -6,7 +6,6 @@ package commands import ( "fmt" "os" - "path/filepath" "reflect" "regexp" "strings" @@ -21,6 +20,7 @@ const InvalidYAMLMsg = `is not valid YAML` const InvalidYAMLMap = `map is empty` const ListOptionOutput = `Languages available as templates: - csharp +- dockerfile - go - go-armhf - node @@ -123,29 +123,23 @@ func runNewFunctionTest(t *testing.T, nft NewFunctionTest) { } func Test_newFunctionTests(t *testing.T) { - - homeDir, _ := filepath.Abs(".") - if err := os.Chdir("testdata/new_function"); err != nil { - t.Fatalf("Error on cd to testdata dir: %v", err) - } - - for _, test := range NewFunctionTests { - t.Run(test.title, func(t *testing.T) { - runNewFunctionTest(t, test) + // Download templates + templatePullLocalTemplateRepo(t) + defer tearDownFetchTemplates(t) + defer tearDownNewFunction(t) + + for _, testcase := range NewFunctionTests { + t.Run(testcase.title, func(t *testing.T) { + runNewFunctionTest(t, testcase) }) } - - if err := os.Chdir(homeDir); err != nil { - t.Fatalf("Error on cd back to commands/ directory: %v", err) - } } func Test_newFunctionListCmds(t *testing.T) { - - homeDir, _ := filepath.Abs(".") - if err := os.Chdir("testdata/new_function"); err != nil { - t.Fatalf("Error on cd to testdata dir: %v", err) - } + // Download templates + templatePullLocalTemplateRepo(t) + defer tearDownFetchTemplates(t) + defer tearDownNewFunction(t) cmdParameters := []string{ "new", @@ -161,18 +155,13 @@ func Test_newFunctionListCmds(t *testing.T) { if !strings.HasPrefix(stdOut, ListOptionOutput) { t.Fatalf("Output is not as expected: %s\n", stdOut) } - - if err := os.Chdir(homeDir); err != nil { - t.Fatalf("Error on cd back to commands/ directory: %v", err) - } } func Test_languageNotExists(t *testing.T) { - - homeDir, _ := filepath.Abs(".") - if err := os.Chdir("testdata/new_function"); err != nil { - t.Fatalf("Error on cd to testdata dir: %v", err) - } + // Download templates + templatePullLocalTemplateRepo(t) + defer tearDownFetchTemplates(t) + defer tearDownNewFunction(t) // Attempt to create a function with a non-existing language cmdParameters := []string{ @@ -190,8 +179,14 @@ func Test_languageNotExists(t *testing.T) { if found, err := regexp.MatchString(LangNotExistsOutput, stdOut); err != nil || !found { t.Fatalf("Output is not as expected: %s\n", stdOut) } +} - if err := os.Chdir(homeDir); err != nil { - t.Fatalf("Error on cd back to commands/ directory: %v", err) +func tearDownNewFunction(t *testing.T) { + // Remove existing archive file if it exists + if _, err := os.Stat(".gitignore"); err == nil { + err := os.Remove(".gitignore") + if err != nil { + t.Log(err) + } } } diff --git a/commands/template_pull_test.go b/commands/template_pull_test.go index e828e7d5a..4baed3962 100644 --- a/commands/template_pull_test.go +++ b/commands/template_pull_test.go @@ -124,3 +124,12 @@ func Test_repositoryUrlRemoteRegExp(t *testing.T) { }) } } + +// templatePullLocalTemplateRepo executes `template pull` on a local repository to get templates +func templatePullLocalTemplateRepo(t *testing.T) { + localTemplateRepository := setupLocalTemplateRepo(t) + defer os.RemoveAll(localTemplateRepository) + + faasCmd.SetArgs([]string{"template", "pull", localTemplateRepository}) + faasCmd.Execute() +} diff --git a/commands/testdata/master_test.zip b/commands/testdata/master_test.zip deleted file mode 100755 index 42b74f209..000000000 Binary files a/commands/testdata/master_test.zip and /dev/null differ diff --git a/commands/testdata/new_function/.gitignore b/commands/testdata/new_function/.gitignore deleted file mode 100644 index 942d901bd..000000000 --- a/commands/testdata/new_function/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -template -build diff --git a/commands/testdata/new_function/template/csharp/function/.gitignore b/commands/testdata/new_function/template/csharp/function/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/commands/testdata/new_function/template/csharp/template.yml b/commands/testdata/new_function/template/csharp/template.yml deleted file mode 100644 index 45caa67ed..000000000 --- a/commands/testdata/new_function/template/csharp/template.yml +++ /dev/null @@ -1,2 +0,0 @@ -language: csharp -fprocess: dotnet ./root.dll diff --git a/commands/testdata/new_function/template/go-armhf/template.yml b/commands/testdata/new_function/template/go-armhf/template.yml deleted file mode 100644 index 234cf4400..000000000 --- a/commands/testdata/new_function/template/go-armhf/template.yml +++ /dev/null @@ -1,2 +0,0 @@ -language: go-armhf -fprocess: ./handler diff --git a/commands/testdata/new_function/template/go/function/.gitignore b/commands/testdata/new_function/template/go/function/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/commands/testdata/new_function/template/go/template.yml b/commands/testdata/new_function/template/go/template.yml deleted file mode 100644 index 5d341d5d3..000000000 --- a/commands/testdata/new_function/template/go/template.yml +++ /dev/null @@ -1,2 +0,0 @@ -language: go -fprocess: ./handler diff --git a/commands/testdata/new_function/template/node-arm64/function/.gitignore b/commands/testdata/new_function/template/node-arm64/function/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/commands/testdata/new_function/template/node-arm64/template.yml b/commands/testdata/new_function/template/node-arm64/template.yml deleted file mode 100644 index 97e25c5f9..000000000 --- a/commands/testdata/new_function/template/node-arm64/template.yml +++ /dev/null @@ -1,2 +0,0 @@ -language: node-arm64 -fprocess: node index.js diff --git a/commands/testdata/new_function/template/node-armhf/template.yml b/commands/testdata/new_function/template/node-armhf/template.yml deleted file mode 100644 index c2313ae67..000000000 --- a/commands/testdata/new_function/template/node-armhf/template.yml +++ /dev/null @@ -1,2 +0,0 @@ -language: node-armhf -fprocess: node index.js diff --git a/commands/testdata/new_function/template/node/function/.gitignore b/commands/testdata/new_function/template/node/function/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/commands/testdata/new_function/template/node/template.yml b/commands/testdata/new_function/template/node/template.yml deleted file mode 100644 index 1117efa75..000000000 --- a/commands/testdata/new_function/template/node/template.yml +++ /dev/null @@ -1,2 +0,0 @@ -language: node -fprocess: node index.js diff --git a/commands/testdata/new_function/template/python-armhf/template.yml b/commands/testdata/new_function/template/python-armhf/template.yml deleted file mode 100644 index ff8986785..000000000 --- a/commands/testdata/new_function/template/python-armhf/template.yml +++ /dev/null @@ -1,2 +0,0 @@ -language: python-armhf -fprocess: python index.py diff --git a/commands/testdata/new_function/template/python/function/.gitignore b/commands/testdata/new_function/template/python/function/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/commands/testdata/new_function/template/python/template.yml b/commands/testdata/new_function/template/python/template.yml deleted file mode 100644 index 5487218c4..000000000 --- a/commands/testdata/new_function/template/python/template.yml +++ /dev/null @@ -1,2 +0,0 @@ -language: python -fprocess: python index.py diff --git a/commands/testdata/new_function/template/python3/function/.gitignore b/commands/testdata/new_function/template/python3/function/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/commands/testdata/new_function/template/python3/template.yml b/commands/testdata/new_function/template/python3/template.yml deleted file mode 100644 index ea405e8b6..000000000 --- a/commands/testdata/new_function/template/python3/template.yml +++ /dev/null @@ -1,2 +0,0 @@ -language: python3 -fprocess: python3 index.py diff --git a/commands/testdata/new_function/template/ruby/function/.gitignore b/commands/testdata/new_function/template/ruby/function/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/commands/testdata/new_function/template/ruby/template.yml b/commands/testdata/new_function/template/ruby/template.yml deleted file mode 100644 index 417bd6133..000000000 --- a/commands/testdata/new_function/template/ruby/template.yml +++ /dev/null @@ -1,2 +0,0 @@ -language: ruby -fprocess: ruby index.rb diff --git a/commands/testdata/templates b/commands/testdata/templates new file mode 160000 index 000000000..9c4570f2e --- /dev/null +++ b/commands/testdata/templates @@ -0,0 +1 @@ +Subproject commit 9c4570f2e052ac86dfb5d70cc285cabc80d34775 diff --git a/guide/TEMPLATE.md b/guide/TEMPLATE.md index e391489f6..92b83f165 100644 --- a/guide/TEMPLATE.md +++ b/guide/TEMPLATE.md @@ -12,6 +12,9 @@ template ├── csharp │   ├── Dockerfile │   └── template.yml +├── dockerfile +│   ├── Dockerfile +│   └── template.yml ├── node │   ├── Dockerfile │   └── template.yml diff --git a/stack/language_template.go b/stack/language_template.go index e8c035d2c..a4d58aa56 100644 --- a/stack/language_template.go +++ b/stack/language_template.go @@ -50,13 +50,17 @@ func ParseYAMLDataForLanguageTemplate(fileData []byte) (*LanguageTemplate, error func IsValidTemplate(lang string) bool { var found bool + + // TODO harmonise to lowercase when fetching template & parsing yaml + // Ensure that `lang` is lowercase in case of Dockerfile if strings.ToLower(lang) == "dockerfile" { - found = true - } else if _, err := os.Stat("./template/" + lang); err == nil { + lang = strings.ToLower(lang) + } + + if _, err := os.Stat("./template/" + lang); err == nil { templateYAMLPath := "./template/" + lang + "/template.yml" - _, err := ParseYAMLForLanguageTemplate(templateYAMLPath) - if err == nil { + if _, err := ParseYAMLForLanguageTemplate(templateYAMLPath); err == nil { found = true } } diff --git a/stack/language_template_test.go b/stack/language_template_test.go index 13f21b341..07f6a6d97 100644 --- a/stack/language_template_test.go +++ b/stack/language_template_test.go @@ -59,10 +59,6 @@ fprocess: python index.py } func Test_IsValidTemplate(t *testing.T) { - if !IsValidTemplate("Dockerfile") || !IsValidTemplate("dockerfile") { - t.Fatalf("Dockerfile and dockerfile must be valid") - } - if IsValidTemplate("unknown-language") { t.Fatalf("unknown-language must be invalid") } diff --git a/versioncontrol/core.go b/versioncontrol/core.go index 198e3aeff..216de1666 100644 --- a/versioncontrol/core.go +++ b/versioncontrol/core.go @@ -25,10 +25,9 @@ type vcsCmd struct { // Invoke executes the vcsCmd replacing varibables in the cmds with the keyval // variables passed. -func (v *vcsCmd) Invoke(args map[string]string) error { - +func (v *vcsCmd) Invoke(dir string, args map[string]string) error { for _, cmd := range v.cmds { - if _, err := v.run(".", cmd, args, true); err != nil { + if _, err := v.run(dir, cmd, args, true); err != nil { return err } } diff --git a/versioncontrol/git.go b/versioncontrol/git.go index b18839309..2873058c2 100644 --- a/versioncontrol/git.go +++ b/versioncontrol/git.go @@ -7,3 +7,17 @@ var GitClone = &vcsCmd{ cmds: []string{"clone {repo} {dir} --depth=1"}, scheme: []string{"git", "https", "http", "git+ssh", "ssh"}, } + +// GitInitRepo initializes the working directory add commit all files & directories +var GitInitRepo = &vcsCmd{ + name: "Git", + cmd: "git", + cmds: []string{ + "init {dir}", + "config user.email \"contact@openfaas.com\"", + "config user.name \"OpenFaaS\"", + "add {dir}", + "commit -m \"Test-commit\"", + }, + scheme: []string{"git", "https", "http", "git+ssh", "ssh"}, +}