diff --git a/commands/deploy.go b/commands/deploy.go index 92fc33724..ac6ddb065 100644 --- a/commands/deploy.go +++ b/commands/deploy.go @@ -171,6 +171,7 @@ func runDeploy(cmd *cobra.Command, args []string) { function.FProcess, fprocessErr = deriveFprocess(function) if fprocessErr != nil { log.Fatalln(fprocessErr) + } } @@ -292,6 +293,7 @@ func compileEnvironment(envvarOpts []string, yamlEnvironment map[string]string, return mergeMap(functionAndStack, envvarArguments), nil } +<<<<<<< HEAD func deriveFprocess(function stack.Function) (string, error) { var fprocess string @@ -314,4 +316,8 @@ func deriveFprocess(function stack.Function) (string, error) { } return fprocess, nil +======= +func languageExistsNotDockerfile(language string) bool { + return len(language) > 0 && strings.ToLower(language) != "dockerfile" +>>>>>>> template pull - address issues from thread #201 } diff --git a/commands/fetch_templates.go b/commands/fetch_templates.go index 6aab71f99..2c5b2ebe5 100644 --- a/commands/fetch_templates.go +++ b/commands/fetch_templates.go @@ -22,13 +22,11 @@ import ( const ( defaultTemplateRepository = "https://github.com/openfaas/faas-cli" templateDirectory = "./template/" + rootLanguageDirSplitCount = 3 ) // fetchTemplates fetch code templates from GitHub master zip file. func fetchTemplates(templateURL string, overwrite bool) error { - var existingLanguages []string - availableLanguages := make(map[string]bool) - var fetchedTemplates []string if len(templateURL) == 0 { templateURL = defaultTemplateRepository @@ -40,15 +38,41 @@ func fetchTemplates(templateURL string, overwrite bool) error { return err } - zipFile, err := zip.OpenReader(archive) + log.Printf("Attempting to expand templates from %s\n", archive) + + preExistingLanguages, fetchedLanguages, err := expandTemplatesFromZip(archive, overwrite) if err != nil { return err } - log.Printf("Attempting to expand templates from %s\n", archive) + if len(preExistingLanguages) > 0 { + log.Printf("Cannot overwrite the following %d directories: %v\n", len(preExistingLanguages), preExistingLanguages) + } + + log.Printf("Fetched %d template(s) : %v from %s\n", len(fetchedLanguages), fetchedLanguages, templateURL) + + err = removeArchive(archive) + + return err +} + +// expandTemplatesFromZip() takes a path to an archive, and whether or not +// we are allowed to overwrite pre-existing language templates. It returns +// a list of languages that already exist (could not be overwritten), and +// a list of languages that are newly downloaded. +func expandTemplatesFromZip(archive string, overwrite bool) ([]string, []string, error) { + var existingLanguages []string + var fetchedLanguages []string + availableLanguages := make(map[string]bool) + + zipFile, err := zip.OpenReader(archive) + if err != nil { + return nil, nil, err + } for _, z := range zipFile.File { var rc io.ReadCloser + var isDirectory bool relativePath := z.Name[strings.Index(z.Name, "/")+1:] if strings.Index(relativePath, "template/") != 0 { @@ -56,18 +80,21 @@ func fetchTemplates(templateURL string, overwrite bool) error { continue } - var language string - if languageSplit := strings.Split(relativePath, "/"); len(languageSplit) > 2 { - language = languageSplit[1] + if pathSplit := strings.Split(relativePath, "/"); len(pathSplit) > 2 { + language := pathSplit[1] + + // We know that this path is a directory if the last character is a "/" + isDirectory = relativePath[len(relativePath)-1:] == "/" - if len(languageSplit) == 3 && relativePath[len(relativePath)-1:] == "/" { + // Check if this is the root directory for a language (at ./template/lang) + if len(pathSplit) == rootLanguageDirSplitCount && isDirectory { // template/language/ if !canWriteLanguage(&availableLanguages, language, overwrite) { existingLanguages = append(existingLanguages, language) continue } - fetchedTemplates = append(fetchedTemplates, language) + fetchedLanguages = append(fetchedLanguages, language) } else { // template/language/* @@ -89,24 +116,15 @@ func fetchTemplates(templateURL string, overwrite bool) error { } // If relativePath is just a directory, then skip expanding it. - if len(relativePath) > 1 && relativePath[len(relativePath)-1:] != "/" { + if len(relativePath) > 1 && !isDirectory { if err = writeFile(rc, z.UncompressedSize64, relativePath, z.Mode()); err != nil { - break + return nil, nil, err } } } - if len(existingLanguages) > 0 { - log.Printf("Cannot overwrite the following %d directories: %v\n", len(existingLanguages), existingLanguages) - } - zipFile.Close() - - log.Printf("Fetched %d template(s) : %v from %s\n", len(fetchedTemplates), fetchedTemplates, templateURL) - - err = removeArchive(archive) - - return err + return existingLanguages, fetchedLanguages, nil } // removeArchive removes the given file @@ -187,13 +205,13 @@ func createPath(relativePath string, perms os.FileMode) error { return err } -// Tells whether the language can be expanded from the zip or not +// canWriteLanguage() tells whether the language can be expanded from the zip or not. // availableLanguages map keeps track of which languages we know to be okay to copy. // overwrite flag will allow to force copy the language template func canWriteLanguage(availableLanguages *map[string]bool, language string, overwrite bool) bool { canWrite := false - if len(language) > 0 { - if _, ok := (*availableLanguages)[language]; ok { + if availableLanguages != nil && len(language) > 0 { + if _, found := (*availableLanguages)[language]; found { return (*availableLanguages)[language] } canWrite = checkLanguage(language, overwrite) diff --git a/commands/fetch_templates_test.go b/commands/fetch_templates_test.go index 077eaf45a..44a93f257 100644 --- a/commands/fetch_templates_test.go +++ b/commands/fetch_templates_test.go @@ -1,4 +1,4 @@ -// Copyright (c) Alex Ellis, Eric Stoekl 2017. All rights reserved. +// Copyright (c) Alex Ellis 2017. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. package commands @@ -22,6 +22,8 @@ func Test_PullTemplates(t *testing.T) { if err != nil { t.Error(err) } + + tearDown_fetch_templates(t) } func Test_fetchTemplates(t *testing.T) { @@ -37,6 +39,8 @@ func Test_fetchTemplates(t *testing.T) { if err != nil { t.Error(err) } + + tearDown_fetch_templates(t) } // tearDown_fetch_templates_test cleans all files and directories created by the test diff --git a/commands/new_function.go b/commands/new_function.go index 641585a6b..a9f9a4e41 100644 --- a/commands/new_function.go +++ b/commands/new_function.go @@ -7,6 +7,7 @@ import ( "fmt" "io/ioutil" "os" + "sort" "strings" "github.com/morikuni/aec" @@ -20,6 +21,13 @@ var ( list bool ) +// Implement interface for sorting array of strings +type StrSort []string + +func (a StrSort) Len() int { return len(a) } +func (a StrSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a StrSort) Less(i, j int) bool { return a[i] < a[j] } + func init() { newFunctionCmd.Flags().StringVar(&lang, "lang", "", "Language or template to use") newFunctionCmd.Flags().StringVarP(&gateway, "gateway", "g", defaultGateway, "Gateway URL to store in YAML stack file") @@ -145,6 +153,7 @@ functions: func printAvailableTemplates(availableTemplates []string) string { var result string + sort.Sort(StrSort(availableTemplates)) for _, template := range availableTemplates { result += fmt.Sprintf("- %s\n", template) } diff --git a/commands/template_pull.go b/commands/template_pull.go index 64870675f..0cf5ce8b0 100644 --- a/commands/template_pull.go +++ b/commands/template_pull.go @@ -1,4 +1,4 @@ -// Copyright (c) Alex Ellis, Eric Stoekl 2017. All rights reserved. +// Copyright (c) Alex Ellis 2017. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. package commands diff --git a/commands/template_pull_test.go b/commands/template_pull_test.go index d2be68660..86c0a178f 100644 --- a/commands/template_pull_test.go +++ b/commands/template_pull_test.go @@ -1,4 +1,4 @@ -// Copyright (c) Alex Ellis, Eric Stoekl 2017. All rights reserved. +// Copyright (c) Alex Ellis 2017. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. package commands diff --git a/stack/language_template.go b/stack/language_template.go index d612807f8..8f2240b6a 100644 --- a/stack/language_template.go +++ b/stack/language_template.go @@ -34,8 +34,7 @@ func ParseYAMLForLanguageTemplate(file string) (*LanguageTemplate, error) { return ParseYAMLDataForLanguageTemplate(fileData) } -// iParseYAMLDataForLanguageTemplate parses YAML data into language template -// Use the alias ParseYAMLDataForLanguageTemplate +// ParseYAMLDataForLanguageTemplate parses YAML data into language template func ParseYAMLDataForLanguageTemplate(fileData []byte) (*LanguageTemplate, error) { var langTemplate LanguageTemplate var err error diff --git a/stack/schema.go b/stack/schema.go index e243c48b2..8828413f5 100644 --- a/stack/schema.go +++ b/stack/schema.go @@ -48,6 +48,7 @@ type Services struct { Provider Provider `yaml:"provider,omitempty"` } +// LanguageTemplate read from template.yml within root of a language template folder type LanguageTemplate struct { Language string `yaml:"language"` FProcess string `yaml:"fprocess"`