func/pkg/functions/template.go

93 lines
2.6 KiB
Go

package functions
import (
"context"
"path"
"knative.dev/func/pkg/filesystem"
)
// Template is a function project template.
// It can be used to instantiate new function project.
type Template interface {
// Name of this template.
Name() string
// Runtime for which this template applies.
Runtime() string
// Repository within which this template is contained. Value is set to the
// currently effective name of the repository, which may vary. It is user-
// defined when the repository is added, and can be set to "default" when
// the client is loaded in single repo mode. I.e. not canonical.
Repository() string
// Fullname is a calculated field of [repo]/[name] used
// to uniquely reference a template which may share a name
// with one in another repository.
Fullname() string
// Write updates fields of function f and writes project files to path pointed by f.Root.
Write(ctx context.Context, f *Function) error
}
// template default implementation
type template struct {
name string
runtime string
repository string
fs filesystem.Filesystem
config templateConfig
}
func (t template) Name() string {
return t.name
}
func (t template) Runtime() string {
return t.runtime
}
func (t template) Repository() string {
return t.repository
}
func (t template) Fullname() string {
return t.repository + "/" + t.name
}
// Write the template source files
// (all source code except manifest.yaml and scaffolding)
func (t template) Write(ctx context.Context, f *Function) error {
// Apply fields from the template onto the function itself (Denormalize).
// The template is already the denormalized view of repo->runtime->template
// so it's values are treated as defaults.
// TODO: this begs the question: should the Template's manifest.yaml actually
// be a partially-populated func.yaml?
if len(f.Build.BuilderImages) == 0 {
f.Build.BuilderImages = t.config.BuilderImages
}
if len(f.Build.Buildpacks) == 0 {
f.Build.Buildpacks = t.config.Buildpacks
}
if len(f.Build.BuildEnvs) == 0 {
f.Build.BuildEnvs = t.config.BuildEnvs
}
if len(f.Run.Envs) == 0 {
f.Run.Envs = t.config.RunEnvs
}
if f.Deploy.HealthEndpoints.Liveness == "" {
f.Deploy.HealthEndpoints.Liveness = t.config.Liveness
}
if f.Deploy.HealthEndpoints.Readiness == "" {
f.Deploy.HealthEndpoints.Readiness = t.config.Readiness
}
if f.Invoke == "" && t.config.Invoke != "http" {
f.Invoke = t.config.Invoke
}
mask := func(p string) bool {
_, f := path.Split(p)
return f == manifestFile
}
return filesystem.CopyFromFS(".", f.Root, filesystem.NewMaskingFS(mask, t.fs)) // copy everything but manifest.yaml
}