Skip to content

Commit

Permalink
template pull - address issues from thread openfaas#201
Browse files Browse the repository at this point in the history
1) Moves code that merges zip file contents into template/ dir into
expandTemplatesFromZip() function. Removes hard-coded constant.
2) Sort list of languages found with 'faas-cli new --list' before
printing
3) Fixes for typos, more descriptive comments, and remove incorrect
license attribution

Signed-off-by: Eric Stoekl <ems5311@gmail.com>
  • Loading branch information
ericstoekl committed Nov 7, 2017
1 parent 1e80b83 commit 886f720
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 31 deletions.
6 changes: 5 additions & 1 deletion commands/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func runDeploy(cmd *cobra.Command, args []string) {
}

// Get FProcess to use from the ./template/template.yml, if a template is being used
if function.Language != "" && function.Language != "Dockerfile" && function.Language != "dockerfile" {
if languageExistsNotDockerfile(function.Language) {
pathToTemplateYAML := "./template/" + function.Language + "/template.yml"
if _, err := os.Stat(pathToTemplateYAML); os.IsNotExist(err) {
log.Fatalln(err.Error())
Expand Down Expand Up @@ -299,3 +299,7 @@ func compileEnvironment(envvarOpts []string, yamlEnvironment map[string]string,
functionAndStack := mergeMap(yamlEnvironment, fileEnvironment)
return mergeMap(functionAndStack, envvarArguments), nil
}

func languageExistsNotDockerfile(language string) bool {
return len(language) > 0 && strings.ToLower(language) != "dockerfile"
}
68 changes: 43 additions & 25 deletions commands/fetch_templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -40,34 +38,63 @@ 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 {
// Process only directories inside "template" at root
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/*

Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 5 additions & 1 deletion commands/fetch_templates_test.go
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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) {
Expand All @@ -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
Expand Down
9 changes: 9 additions & 0 deletions commands/new_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"io/ioutil"
"os"
"sort"
"strings"

"github.com/morikuni/aec"
Expand All @@ -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(&functionName, "name", "", "Name for your function")
newFunctionCmd.Flags().StringVar(&lang, "lang", "", "Language or template to use")
Expand Down Expand Up @@ -143,6 +151,7 @@ functions:

func printAvailableTemplates(availableTemplates []string) string {
var result string
sort.Sort(StrSort(availableTemplates))
for _, template := range availableTemplates {
result += fmt.Sprintf("- %s\n", template)
}
Expand Down
2 changes: 1 addition & 1 deletion commands/template_pull.go
Original file line number Diff line number Diff line change
@@ -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

Expand Down
2 changes: 1 addition & 1 deletion commands/template_pull_test.go
Original file line number Diff line number Diff line change
@@ -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

Expand Down
3 changes: 1 addition & 2 deletions stack/language_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions stack/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down

0 comments on commit 886f720

Please sign in to comment.