rename language to runtime

This commit is contained in:
Luke K 2020-07-02 13:06:54 +00:00
parent a36841ed07
commit f23e81538f
No known key found for this signature in database
GPG Key ID: 4896F75BAF2E1966
13 changed files with 102 additions and 100 deletions

View File

@ -26,7 +26,7 @@ func NewBuilder(registry, namespace string) *Builder {
}
// Build an image from the function source at path.
func (n *Builder) Build(name, language, path string) (image string, err error) {
func (n *Builder) Build(name, runtime, path string) (image string, err error) {
// Check for the appsody binary explicitly so that we can return
// an extra-friendly error message.
_, err = exec.LookPath("appsody")

View File

@ -30,8 +30,8 @@ func NewInitializer() *Initializer {
return &Initializer{}
}
// Initialize a new function of the given name, of the given language, at the given path.
func (n *Initializer) Initialize(name, language, path string) error {
// Initialize a new function of the given name, of the given runtime, at the given path.
func (n *Initializer) Initialize(name, runtime, path string) error {
// Check for the appsody binary explicitly so that we can return
// an extra-friendly error message.
_, err := exec.LookPath("appsody")
@ -49,14 +49,14 @@ func (n *Initializer) Initialize(name, language, path string) error {
}
// Dereference stack short name. ex. "go" -> "go-ce-functions"
stackName, ok := StackShortNames[language]
stackName, ok := StackShortNames[runtime]
if !ok {
languages := []string{}
runtime := []string{}
for k, _ := range StackShortNames {
languages = append(languages, k)
runtimes = append(runtimes, k)
}
return errors.New(fmt.Sprintf("Unrecognized lanugage '%v'. Please choose one: %v.", language, strings.Join(languages, ", ")))
return errors.New(fmt.Sprintf("Unrecognized runtime '%v'. Please choose one: %v.", runtime, strings.Join(runtimes, ", ")))
}
// set up the command, specifying a sanitized project name and connecting

View File

@ -5,10 +5,11 @@ import (
"context"
"errors"
"fmt"
"github.com/buildpacks/pack"
"github.com/buildpacks/pack/logging"
"io"
"os"
"github.com/buildpacks/pack"
"github.com/buildpacks/pack/logging"
)
type Builder struct {
@ -26,13 +27,13 @@ var lang2pack = map[string]string{
"js": "quay.io/boson/faas-nodejs-builder",
}
func (builder *Builder) Build(name, language, path string) (image string, err error) {
func (builder *Builder) Build(name, runtime, path string) (image string, err error) {
registry := fmt.Sprintf("%s/%s", builder.registry, builder.namespace)
image = fmt.Sprintf("%s/%s", registry, name)
packBuilder, ok := lang2pack[language]
packBuilder, ok := lang2pack[runtime]
if !ok {
err = errors.New(fmt.Sprint("unsupported language: ", language))
err = errors.New(fmt.Sprint("unsupported runtime: ", runtime))
return
}

View File

@ -32,14 +32,14 @@ type Client struct {
type Initializer interface {
// Initialize a Service Function of the given name, context configuration `
// (expected signature) using a context template.
Initialize(language, context, path string) error
Initialize(runtime, context, path string) error
}
// Builder of function source to runnable image.
type Builder interface {
// Build a service function of the given name with source located at path.
// returns the image name built.
Build(name, language, path string) (image string, err error)
Build(name, runtime, path string) (image string, err error)
}
// Pusher of function image to a registry.
@ -255,11 +255,11 @@ func WithDomainSearchLimit(limit int) Option {
}
}
// Create a service function of the given language.
// Create a service function of the given runtime.
// Name and Root are optional:
// Name is derived from root if possible.
// Root is defaulted to the current working directory.
func (c *Client) Create(language, context, name, root string) (err error) {
func (c *Client) Create(runtime, context, name, root string) (err error) {
c.progressListener.SetTotal(5)
c.progressListener.Increment("Initializing")
defer c.progressListener.Done()
@ -276,14 +276,14 @@ func (c *Client) Create(language, context, name, root string) (err error) {
// optional name the other passes root path). This could easily cause
// confusion and thus we may want to rename Initalizer to the more specific
// task it performs: ContextTemplateWriter or similar.
err = f.Initialize(language, context, name, c.domainSearchLimit, c.initializer)
err = f.Initialize(runtime, context, name, c.domainSearchLimit, c.initializer)
if err != nil {
return
}
// Build the now-initialized service function
c.progressListener.Increment("Building")
image, err := c.builder.Build(f.name, language, f.root)
image, err := c.builder.Build(f.name, runtime, f.root)
if err != nil {
return
}
@ -347,7 +347,7 @@ func (c *Client) Update(root string) (err error) {
}
// Build an image from the current state of the service function's implementation.
image, err := c.builder.Build(f.name, f.language, f.root)
image, err := c.builder.Build(f.name, f.runtime, f.root)
if err != nil {
return
}
@ -434,14 +434,14 @@ func (c *Client) Remove(name, root string) error {
type noopInitializer struct{ output io.Writer }
func (n *noopInitializer) Initialize(language, context, root string) error {
func (n *noopInitializer) Initialize(runtime, context, root string) error {
fmt.Fprintln(n.output, "skipping initialize: client not initialized WithInitializer")
return nil
}
type noopBuilder struct{ output io.Writer }
func (n *noopBuilder) Build(name, language, path string) (image string, err error) {
func (n *noopBuilder) Build(name, runtime, path string) (image string, err error) {
fmt.Fprintln(n.output, "skipping build: client not initialized WithBuilder")
return "", nil
}

View File

@ -32,11 +32,11 @@ func TestNewWithInterferingFiles(t *testing.T) {
// TODO
}
// TestCreate ensures that creation of a supported language succeeds with all
// TestCreate ensures that creation of a supported runtime succeeds with all
// defaults (base case).
func TestCreate(t *testing.T) {
// Client with all defaults other than an initializer that verifies the
// specified language.
// specified runtime.
client, err := faas.New(
faas.WithInitializer(mock.NewInitializer()))
if err != nil {
@ -81,34 +81,34 @@ func TestCreateUnderivableName(t *testing.T) {
}
// TestCreateMissingLanguage ensures that instantiation fails if the required
// language parameter is not passed to Create.
func TestCreateMissingLanguage(t *testing.T) {
// TestCreateMissingRuntime ensures that instantiation fails if the required
// runtime parameter is not passed to Create.
func TestCreateMissingRuntime(t *testing.T) {
client, err := faas.New(
faas.WithInitializer(mock.NewInitializer()))
if err != nil {
t.Fatal(err)
}
// create a Service Function call missing language should error
// create a Service Function call missing runtime should error
if err := client.Create("", "", "", ""); err == nil {
t.Fatal("missing language did not generate error")
t.Fatal("missing runtime did not generate error")
}
}
// TestCreateUnsupportedLanguage ensures that instantiation fails if the required
// language parameter is of an unsupported language.
func TestCreateUnsupportedLanguage(t *testing.T) {
// TestCreateUnsupportedRuntime ensures that instantiation fails if the required
// runtime parameter is of an unsupported runtime.
func TestCreateUnsupportedRuntime(t *testing.T) {
client, err := faas.New(
faas.WithInitializer(mock.NewInitializer())) // validtes language passed
faas.WithInitializer(mock.NewInitializer())) // validtes runtime passed
if err != nil {
t.Fatal(err)
}
// create a Service Function call witn an unsupported language should bubble
// create a Service Function call witn an unsupported runtime should bubble
// the error generated by the underlying initializer.
if err := client.Create("cobol", "", "", ""); err == nil {
t.Fatal("unsupported language did not generate error")
t.Fatal("unsupported runtime did not generate error")
}
}
@ -144,10 +144,10 @@ func TestCreateDelegates(t *testing.T) {
// -------------
// The initializer should receive the name expected from the path,
// the passed language, and an absolute path to the funciton soruce.
initializer.InitializeFn = func(language, context, path string) error {
if language != "go" {
t.Fatalf("initializer expected language 'go', got '%v'", language)
// the passed runtime, and an absolute path to the funciton soruce.
initializer.InitializeFn = func(runtime, context, path string) error {
if runtime != "go" {
t.Fatalf("initializer expected runtime 'go', got '%v'", runtime)
}
if context != "" {
t.Fatalf("initializer expected empty context template name, got '%v'", name)
@ -560,7 +560,7 @@ func TestWithName(t *testing.T) {
}
// Ensure that initializing receives the specified path.
initializer.InitializeFn = func(language, context, path2 string) error {
initializer.InitializeFn = func(runtime, context, path2 string) error {
expectedPath, err := filepath.Abs(path)
if err != nil {
t.Fatal(err)

View File

@ -2,13 +2,14 @@ package cmd
import (
"encoding/json"
"os"
"os/user"
"path"
"github.com/boson-project/faas"
"github.com/boson-project/faas/appsody"
"github.com/boson-project/faas/knative"
"github.com/spf13/cobra"
"os"
"os/user"
"path"
)
func CompleteFunctionList(cmd *cobra.Command, args []string, toComplete string) (strings []string, directive cobra.ShellCompDirective) {
@ -26,7 +27,7 @@ func CompleteFunctionList(cmd *cobra.Command, args []string, toComplete string)
directive = cobra.ShellCompDirectiveDefault
return
}
func CompleteLanguageList(cmd *cobra.Command, args []string, toComplete string) (strings []string, directive cobra.ShellCompDirective) {
func CompleteRuntimeList(cmd *cobra.Command, args []string, toComplete string) (strings []string, directive cobra.ShellCompDirective) {
strings = make([]string, 0, len(appsody.StackShortNames))
for lang, _ := range appsody.StackShortNames {
strings = append(strings, lang)
@ -66,4 +67,4 @@ func CompleteRegistryList(cmd *cobra.Command, args []string, toComplete string)
}
directive = cobra.ShellCompDirectiveDefault
return
}
}

View File

@ -37,10 +37,10 @@ func init() {
// functional, deployed service function with a noop implementation. It
// can be optionally created only locally (no deploy) using --local.
var createCmd = &cobra.Command{
Use: "create <language>",
Use: "create <runtime>",
Short: "Create a Service Function",
SuggestFor: []string{"init", "new"},
ValidArgsFunction: CompleteLanguageList,
ValidArgsFunction: CompleteRuntimeList,
Args: cobra.ExactArgs(1),
RunE: create,
PreRun: func(cmd *cobra.Command, args []string) {
@ -93,9 +93,9 @@ type createConfig struct {
// location is $XDG_CONFIG_HOME/templates ($HOME/.config/faas/templates)
Templates string
// Language is the first argument, and specifies the resultant Function
// implementation language.
Language string
// Runtime is the first argument, and specifies the resultant Function
// implementation runtime.
Runtime string
// Path of the Function implementation on local disk. Defaults to current
// working directory of the process.
@ -104,9 +104,9 @@ type createConfig struct {
// create a new service function using the client about config.
func create(cmd *cobra.Command, args []string) (err error) {
// Assert a language parameter was provided
// Assert a runtime parameter was provided
if len(args) == 0 {
return errors.New("'faas create' requires a language argument.")
return errors.New("'faas create' requires a runtime argument.")
}
// Create a deafult configuration populated first with environment variables,
@ -120,7 +120,7 @@ func create(cmd *cobra.Command, args []string) (err error) {
Namespace: viper.GetString("namespace"),
Template: viper.GetString("template"), // to use
Templates: viper.GetString("templates"), // extendex repos
Language: args[0],
Runtime: args[0],
Path: ".", // will be expanded to current working dir.
}
@ -185,7 +185,7 @@ func create(cmd *cobra.Command, args []string) (err error) {
// Returns the final address.
// Name can be empty string (path-dervation will be attempted)
// Path can be empty, defaulting to current working directory.
return client.Create(config.Language, config.Template, config.Name, config.Path)
return client.Create(config.Runtime, config.Template, config.Name, config.Path)
}
func gatherFromUser(config createConfig) (c createConfig, err error) {
@ -198,7 +198,7 @@ func gatherFromUser(config createConfig) (c createConfig, err error) {
config.Internal = prompt.ForBool("Internal; no public route", config.Internal)
config.Registry = prompt.ForString("Image registry", config.Registry)
config.Namespace = prompt.ForString("Namespace at registry", config.Namespace)
config.Language = prompt.ForString("Language of source", config.Language)
config.Runtime = prompt.ForString("Runtime of source", config.Runtime)
config.Template = prompt.ForString("Function Template", config.Template)
return config, nil
}

View File

@ -20,8 +20,8 @@ type Config struct {
// not over the Option WithName, if provided.
Name string `yaml:"name"`
// Language of the implementation.
Language string `yaml:"language"`
// Runtime of the implementation.
Runtime string `yaml:"runtime"`
// Add new values to the applyConfig function as necessary.
}
@ -31,8 +31,8 @@ type Config struct {
// post-instantiation.
func newConfig(f *Function) Config {
return Config{
Name: f.name,
Language: f.language,
Name: f.name,
Runtime: f.runtime,
}
}
@ -79,7 +79,7 @@ func applyConfig(f *Function, root string) error {
// Apply the config to the client object, which effectiely writes back the default
// if it was not defined in the yaml.
f.name = cfg.Name
f.language = cfg.Language
f.runtime = cfg.Runtime
// NOTE: cleverness < clarity

View File

@ -17,7 +17,7 @@ import (
// updates in the binary for access by pkger.
// DefautlTemplate is the default function signature / environmental context
// of the resultant template. All languages are expected to have at least
// of the resultant template. All runtimes are expected to have at least
// an HTTP Handler ("http") and Cloud Events ("events")
const DefaultTemplate = "events"
@ -53,7 +53,7 @@ func NewInitializer(templates string) *Initializer {
return &Initializer{templates: templates}
}
func (n *Initializer) Initialize(language, template string, dest string) error {
func (n *Initializer) Initialize(runtime, template string, dest string) error {
if template == "" {
template = DefaultTemplate
}
@ -62,24 +62,24 @@ func (n *Initializer) Initialize(language, template string, dest string) error {
// step of the create process but future calls directly to initialize would
// be better off being made safe.
if isEmbedded(language, template) {
return copyEmbedded(language, template, dest)
if isEmbedded(runtime, template) {
return copyEmbedded(runtime, template, dest)
}
if n.templates != "" {
return copyFilesystem(n.templates, language, template, dest)
return copyFilesystem(n.templates, runtime, template, dest)
}
return errors.New(fmt.Sprintf("A template for language '%v' template '%v' was not found internally and no extended repository path was defined.", language, template))
return errors.New(fmt.Sprintf("A template for runtime '%v' template '%v' was not found internally and no extended repository path was defined.", runtime, template))
}
func copyEmbedded(language, template, dest string) error {
func copyEmbedded(runtime, template, dest string) error {
// Copy files to the destination
// Example embedded path:
// /templates/go/http
src := filepath.Join("/templates", language, template)
src := filepath.Join("/templates", runtime, template)
return copy(src, dest, embeddedAccessor{})
}
func copyFilesystem(templatesPath, language, templateFullName, dest string) error {
func copyFilesystem(templatesPath, runtime, templateFullName, dest string) error {
// ensure that the templateFullName is of the format "repoName/templateName"
cc := strings.Split(templateFullName, "/")
if len(cc) != 2 {
@ -90,12 +90,12 @@ func copyFilesystem(templatesPath, language, templateFullName, dest string) erro
// Example FileSystem path:
// /home/alice/.config/faas/templates/boson-experimental/go/json
src := filepath.Join(templatesPath, repo, language, template)
src := filepath.Join(templatesPath, repo, runtime, template)
return copy(src, dest, filesystemAccessor{})
}
func isEmbedded(language, template string) bool {
_, err := pkger.Stat(filepath.Join("/templates", language, template))
func isEmbedded(runtime, template string) bool {
_, err := pkger.Stat(filepath.Join("/templates", runtime, template))
return err == nil
}

View File

@ -6,7 +6,7 @@ import (
"testing"
)
// TestInitialize ensures that on initialization of a the reference language
// TestInitialize ensures that on initialization of a the reference runtime
// (Go), the template is written.
func TestInitialize(t *testing.T) {
var (
@ -67,10 +67,10 @@ func TestCustom(t *testing.T) {
os.MkdirAll(path, 0744)
defer os.RemoveAll(path)
// Unrecognized language/template should error
// Unrecognized runtime/template should error
err := NewInitializer("").Initialize("go", template, path)
if err == nil {
t.Fatal("An unrecognized language/template should generate an error")
t.Fatal("An unrecognized runtime/template should generate an error")
}
// Recognized external (non-embedded) path should succeed

View File

@ -12,9 +12,9 @@ import (
)
type Function struct {
root string
language string // will be empty unless initialized/until initialized
name string // will be empty unless initialized/until initialized.
root string
runtime string // will be empty unless initialized/until initialized
name string // will be empty unless initialized/until initialized.
initializer Initializer
}
@ -43,10 +43,10 @@ func (f *Function) DerivedName(searchLimit int) string {
return pathToDomain(f.root, searchLimit)
}
func (f *Function) Initialize(language, context, name string, domainSearchLimit int, initializer Initializer) (err error) {
// Assert language is provided
if language == "" {
err = errors.New("language not specified")
func (f *Function) Initialize(runtime, context, name string, domainSearchLimit int, initializer Initializer) (err error) {
// Assert runtime is provided
if runtime == "" {
err = errors.New("runtime not specified")
return
}
@ -77,12 +77,12 @@ func (f *Function) Initialize(language, context, name string, domainSearchLimit
}
f.name = name
// Write the template implementation in the appropriate language
if err = initializer.Initialize(language, context, f.root); err != nil {
// Write the template implementation in the appropriate runtime
if err = initializer.Initialize(runtime, context, f.root); err != nil {
return
}
// language was validated
f.language = language
// runtime was validated
f.runtime = runtime
// Write out the state as a config file and return.
return writeConfig(f)
@ -91,7 +91,7 @@ func (f *Function) Initialize(language, context, name string, domainSearchLimit
func (f *Function) Initialized() bool {
// TODO: this should probably be more robust than checking what amounts to a
// side-effect of the initialization process.
return (f.language != "" && f.name != "")
return (f.runtime != "" && f.name != "")
}
// contentiousFiles are files which, if extant, preclude the creation of a

View File

@ -11,7 +11,7 @@ func NewBuilder() *Builder {
}
}
func (i *Builder) Build(name, language, path string) (string, error) {
func (i *Builder) Build(name, runtime, path string) (string, error) {
i.BuildInvoked = true
return i.BuildFn(name, path)
}

View File

@ -7,30 +7,30 @@ import (
)
type Initializer struct {
SupportedLanguages []string
InitializeInvoked bool
InitializeFn func(name, language, path string) error
SupportedRuntimes []string
InitializeInvoked bool
InitializeFn func(name, runtime, path string) error
}
func NewInitializer() *Initializer {
return &Initializer{
SupportedLanguages: []string{"go"},
InitializeFn: func(string, string, string) error { return nil },
SupportedRuntimes: []string{"go"},
InitializeFn: func(string, string, string) error { return nil },
}
}
func (i *Initializer) Initialize(name, language, path string) error {
fmt.Printf("Validating language supported: %v\n", language)
func (i *Initializer) Initialize(name, runtime, path string) error {
fmt.Printf("Validating runtime supported: %v\n", runtime)
i.InitializeInvoked = true
if !i.supportsLanguage(language) {
return errors.New(fmt.Sprintf("unsupported language '%v'", language))
if !i.supportsRuntime(runtime) {
return errors.New(fmt.Sprintf("unsupported runtime '%v'", runtime))
}
return i.InitializeFn(name, language, path)
return i.InitializeFn(name, runtime, path)
}
func (i *Initializer) supportsLanguage(language string) bool {
for _, supported := range i.SupportedLanguages {
if strings.ToLower(language) == supported {
func (i *Initializer) supportsRuntime(runtime string) bool {
for _, supported := range i.SupportedRuntimes {
if strings.ToLower(runtime) == supported {
return true
}
}