Skip to content

Commit

Permalink
Export CreateBuildContext function
Browse files Browse the repository at this point in the history
Simplify the signature of createBuildContext and export the function so
that it can be used by other packages.

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
  • Loading branch information
welteki authored and alexellis committed Aug 5, 2024
1 parent 8b55f87 commit 35dc699
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 29 deletions.
62 changes: 41 additions & 21 deletions builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,18 @@ func BuildImage(image string, handler string, functionName string, language stri
return fmt.Errorf("building %s, %s is an invalid path", functionName, handler)
}

tempPath, err := createBuildContext(functionName, handler, language, isLanguageTemplate(language), langTemplate.HandlerFolder, copyExtraPaths)
// To avoid breaking the CLI for custom templates that do not set the language attribute
// we ensure it is always set.
//
// While templates are expected to have the language in `template.yaml` set to the same name as the template folder
// this was never enforced.
langTemplate.Language = language

if isDockerfileTemplate(langTemplate.Language) {
langTemplate = nil
}

tempPath, err := CreateBuildContext(functionName, handler, langTemplate, copyExtraPaths)
if err != nil {
return err
}
Expand Down Expand Up @@ -303,8 +314,17 @@ func isRunningInCI() bool {
return false
}

// createBuildContext creates temporary build folder to perform a Docker build with language template
func createBuildContext(functionName string, handler string, language string, useFunction bool, handlerFolder string, copyExtraPaths []string) (string, error) {
// CreateBuildContext creates a Docker build context using the provided function handler and language template.
//
// Parameters:
// - functionName: the name of the function.
// - handler: path to the function handler folder.
// - template: function language template to use. Set to nil if no template is required (e.g. the handler folder is the build context with Dockerfile).
// - copyExtraPaths: additional path to copy into the function handler folder. Paths should be relative to the current directory.
// Any path outside of this current directory will be skipped.
//
// Returns the path to the new build context. An error is returned if creating the build context fails.
func CreateBuildContext(functionName string, handler string, template *stack.LanguageTemplate, copyExtraPaths []string) (string, error) {
tempPath := fmt.Sprintf("./build/%s/", functionName)

if err := os.RemoveAll(tempPath); err != nil {
Expand All @@ -313,16 +333,19 @@ func createBuildContext(functionName string, handler string, language string, us

functionPath := tempPath

if useFunction {
if handlerFolder == "" {
functionPath = path.Join(functionPath, defaultHandlerFolder)
useTemplate := false
if template != nil {
useTemplate = true
}

if useTemplate {
if len(template.HandlerFolder) > 0 {
functionPath = path.Join(functionPath, template.HandlerFolder)
} else {
functionPath = path.Join(functionPath, handlerFolder)
functionPath = path.Join(functionPath, defaultHandlerFolder)
}
}

// fmt.Printf("Preparing: %s %s\n", handler+"/", functionPath)

if isRunningInCI() {
defaultDirPermissions = 0777
}
Expand All @@ -333,8 +356,8 @@ func createBuildContext(functionName string, handler string, language string, us
return tempPath, mkdirErr
}

if useFunction {
if err := CopyFiles(path.Join("./template/", language), tempPath); err != nil {
if useTemplate {
if err := CopyFiles(path.Join("./template/", template.Language), tempPath); err != nil {
fmt.Printf("Error copying template directory: %s.\n", err.Error())
return tempPath, err
}
Expand All @@ -350,6 +373,7 @@ func createBuildContext(functionName string, handler string, language string, us

for _, info := range infos {
switch info.Name() {
// Ignore the build and template folder.
case "build", "template":
fmt.Printf("Skipping \"%s\" folder\n", info.Name())
continue
Expand All @@ -368,16 +392,12 @@ func createBuildContext(functionName string, handler string, language string, us
if err != nil {
return tempPath, err
}
// Note that if useFunction is false, ie is a `dockerfile` template, then

// Note that if template is nil, i.e. is a `dockerfile` template, then
// functionPath == tempPath, the docker build context, not the `function` handler folder
// inside the docker build context
copyErr := CopyFiles(
extraPathAbs,
filepath.Clean(path.Join(functionPath, extraPath)),
)

if copyErr != nil {
return tempPath, copyErr
if err := CopyFiles(extraPathAbs, filepath.Clean(path.Join(functionPath, extraPath))); err != nil {
return tempPath, err
}
}

Expand Down Expand Up @@ -516,6 +536,6 @@ func deDuplicate(buildOptPackages []string) []string {
return retPackages
}

func isLanguageTemplate(language string) bool {
return strings.ToLower(language) != "dockerfile"
func isDockerfileTemplate(language string) bool {
return strings.ToLower(language) == "dockerfile"
}
13 changes: 6 additions & 7 deletions builder/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,22 @@ import (
"github.com/openfaas/faas-cli/stack"
)

func Test_isLanguageTemplate_Dockerfile(t *testing.T) {
func Test_isDockerfileTemplate_Dockerfile(t *testing.T) {

language := "Dockerfile"

want := false
got := isLanguageTemplate(language)
want := true
got := isDockerfileTemplate(language)
if got != want {
t.Errorf("language: %s got %v, want %v", language, got, want)
}
}

func Test_isLanguageTemplate_Node(t *testing.T) {

func Test_isDockerfileTemplate_Node(t *testing.T) {
language := "node"

want := true
got := isLanguageTemplate(language)
want := false
got := isDockerfileTemplate(language)
if got != want {
t.Errorf("language: %s got %v, want %v", language, got, want)
}
Expand Down
13 changes: 12 additions & 1 deletion builder/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,18 @@ func PublishImage(image string, handler string, functionName string, language st
return fmt.Errorf("building %s, %s is an invalid path", functionName, handler)
}

tempPath, err := createBuildContext(functionName, handler, language, isLanguageTemplate(language), langTemplate.HandlerFolder, copyExtraPaths)
// To avoid breaking the CLI for custom templates that do not set the language attribute
// we ensure it is always set.
//
// While templates are expected to have the language in `template.yaml` set to the same name as the template folder
// this was never enforced.
langTemplate.Language = language

if isDockerfileTemplate(langTemplate.Language) {
langTemplate = nil
}

tempPath, err := CreateBuildContext(functionName, handler, langTemplate, copyExtraPaths)
if err != nil {
return err
}
Expand Down

0 comments on commit 35dc699

Please sign in to comment.