mirror of https://github.com/knative/func.git
refactor!: function signatures implied from trigger
Renames trigger to template, removing it as an unnecessary configuration. This reiterates that a Function implementation can change function sig implemented at any time, and it is not part of the configuration. This sets the stage for renaming 'templates', and the finalization of the use cases enabling extensible templates.
This commit is contained in:
parent
b3a6bdf398
commit
b30e883e67
17
client.go
17
client.go
|
@ -15,7 +15,12 @@ import (
|
|||
const (
|
||||
DefaultRegistry = "docker.io"
|
||||
DefaultRuntime = "node"
|
||||
DefaultTrigger = "http"
|
||||
|
||||
// DefautlTemplate is the default Function signature / environmental context
|
||||
// of the resultant function. All runtimes are expected to have at least
|
||||
// one implementation of each supported funciton sinagure. Currently that
|
||||
// includes an HTTP Handler ("http") and Cloud Events handler ("events")
|
||||
DefaultTemplate = "http"
|
||||
)
|
||||
|
||||
// Client for managing Function instances.
|
||||
|
@ -348,15 +353,15 @@ func (c *Client) Create(cfg Function) (err error) {
|
|||
f.Runtime = DefaultRuntime
|
||||
}
|
||||
|
||||
// Assert trigger was provided, or default.
|
||||
f.Trigger = cfg.Trigger
|
||||
if f.Trigger == "" {
|
||||
f.Trigger = DefaultTrigger
|
||||
// Assert template was provided, or default.
|
||||
f.Template = cfg.Template
|
||||
if f.Template == "" {
|
||||
f.Template = DefaultTemplate
|
||||
}
|
||||
|
||||
// Write out a template.
|
||||
w := templateWriter{templates: c.templates, verbose: c.verbose}
|
||||
if err = w.Write(f.Runtime, f.Trigger, f.Root); err != nil {
|
||||
if err = w.Write(f.Runtime, f.Template, f.Root); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -154,13 +154,6 @@ func TestDefaultRuntime(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestDefaultTemplate ensures that the default template is
|
||||
// applied when not provided.
|
||||
func TestDefaultTrigger(t *testing.T) {
|
||||
// TODO: need to either expose accessor for introspection, or compare
|
||||
// the files written to those in the embedded repisotory?
|
||||
}
|
||||
|
||||
// TestExtensibleTemplates templates. Ensures that templates are extensible
|
||||
// using a custom path to a template repository on disk. Custom repository
|
||||
// location is not defined herein but expected to be provided because, for
|
||||
|
@ -184,7 +177,7 @@ func TestExtensibleTemplates(t *testing.T) {
|
|||
bosonFunc.WithRegistry(TestRegistry))
|
||||
|
||||
// Create a Function specifying a template, 'json' that only exists in the extensible set
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root, Trigger: "boson-experimental/json"}); err != nil {
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root, Template: "boson-experimental/json"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ func init() {
|
|||
createCmd.Flags().BoolP("confirm", "c", false, "Prompt to confirm all configuration options (Env: $FUNC_CONFIRM)")
|
||||
createCmd.Flags().StringP("runtime", "l", bosonFunc.DefaultRuntime, "Function runtime language/framework. Available runtimes: "+utils.RuntimeList()+" (Env: $FUNC_RUNTIME)")
|
||||
createCmd.Flags().StringP("templates", "", filepath.Join(configPath(), "templates"), "Path to additional templates (Env: $FUNC_TEMPLATES)")
|
||||
createCmd.Flags().StringP("trigger", "t", bosonFunc.DefaultTrigger, "Function trigger. Available triggers: 'http' and 'events' (Env: $FUNC_TRIGGER)")
|
||||
createCmd.Flags().StringP("template", "t", bosonFunc.DefaultTemplate, "Function template. For eample 'http' or 'events' (Env: $FUNC_TEMPLATE)")
|
||||
|
||||
if err := createCmd.RegisterFlagCompletionFunc("runtime", CompleteRuntimeList); err != nil {
|
||||
fmt.Println("internal: error while calling RegisterFlagCompletionFunc: ", err)
|
||||
|
@ -43,12 +43,12 @@ kn func create
|
|||
kn func create --runtime quarkus myfunc
|
||||
|
||||
# Create a function project that uses a CloudEvent based function signature
|
||||
kn func create --trigger events myfunc
|
||||
kn func create -t events myfunc
|
||||
`,
|
||||
SuggestFor: []string{"inti", "new"},
|
||||
PreRunE: bindEnv("runtime", "templates", "trigger", "confirm"),
|
||||
PreRunE: bindEnv("runtime", "templates", "template", "confirm"),
|
||||
RunE: runCreate,
|
||||
// TODO: autocomplate Functions for runtime and trigger.
|
||||
// TODO: autocomplate or interactive prompt for runtime and template.
|
||||
}
|
||||
|
||||
func runCreate(cmd *cobra.Command, args []string) error {
|
||||
|
@ -61,10 +61,10 @@ func runCreate(cmd *cobra.Command, args []string) error {
|
|||
config = config.Prompt()
|
||||
|
||||
function := bosonFunc.Function{
|
||||
Name: config.Name,
|
||||
Root: config.Path,
|
||||
Runtime: config.Runtime,
|
||||
Trigger: config.Trigger,
|
||||
Name: config.Name,
|
||||
Root: config.Path,
|
||||
Runtime: config.Runtime,
|
||||
Template: config.Template,
|
||||
}
|
||||
|
||||
client := bosonFunc.New(
|
||||
|
@ -90,11 +90,14 @@ type createConfig struct {
|
|||
// location is $XDG_CONFIG_HOME/templates ($HOME/.config/func/templates)
|
||||
Templates string
|
||||
|
||||
// Trigger is the form of the resultant Function, i.e. the Function signature
|
||||
// and contextually avaialable resources. For example 'http' for a Function
|
||||
// expected to be invoked via straight HTTP requests, or 'events' for a
|
||||
// Function which will be invoked with CloudEvents.
|
||||
Trigger string
|
||||
// Template is the code written into the new Function project, including
|
||||
// an implementation adhering to one of the supported function signatures.
|
||||
// May also include additional configuration settings or examples.
|
||||
// For example, embedded are 'http' for a Function whose funciton signature
|
||||
// is invoked via straight HTTP requests, or 'events' for a Function which
|
||||
// will be invoked with CloudEvents. These embedded templates contain a
|
||||
// minimum implementation of the signature itself and example tests.
|
||||
Template string
|
||||
|
||||
// Verbose output
|
||||
Verbose bool
|
||||
|
@ -118,7 +121,7 @@ func newCreateConfig(args []string) createConfig {
|
|||
Path: derivedPath,
|
||||
Runtime: viper.GetString("runtime"),
|
||||
Templates: viper.GetString("templates"),
|
||||
Trigger: viper.GetString("trigger"),
|
||||
Template: viper.GetString("template"),
|
||||
Confirm: viper.GetBool("confirm"),
|
||||
Verbose: viper.GetBool("verbose"),
|
||||
}
|
||||
|
@ -133,7 +136,7 @@ func (c createConfig) Prompt() createConfig {
|
|||
fmt.Printf("Project path: %v\n", c.Path)
|
||||
fmt.Printf("Function name: %v\n", c.Name)
|
||||
fmt.Printf("Runtime: %v\n", c.Runtime)
|
||||
fmt.Printf("Trigger: %v\n", c.Trigger)
|
||||
fmt.Printf("Template: %v\n", c.Template)
|
||||
return c
|
||||
}
|
||||
|
||||
|
@ -148,10 +151,9 @@ func (c createConfig) Prompt() createConfig {
|
|||
}
|
||||
|
||||
return createConfig{
|
||||
Name: derivedName,
|
||||
Path: derivedPath,
|
||||
Runtime: prompt.ForString("Runtime", c.Runtime),
|
||||
Trigger: prompt.ForString("Trigger", c.Trigger),
|
||||
// Templates intentionally omitted from prompt for being an edge case.
|
||||
Name: derivedName,
|
||||
Path: derivedPath,
|
||||
Runtime: prompt.ForString("Runtime", c.Runtime),
|
||||
Template: prompt.ForString("Template", c.Template),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@ namespace: ""
|
|||
runtime: go
|
||||
image: ""
|
||||
imageDigest: ""
|
||||
trigger: http
|
||||
builder: quay.io/boson/faas-go-builder
|
||||
builderMap:
|
||||
default: quay.io/boson/faas-go-builder
|
||||
|
@ -72,7 +71,6 @@ annotations: {}
|
|||
}
|
||||
f.Close()
|
||||
|
||||
|
||||
oldWD, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
@ -36,7 +36,6 @@ type config struct {
|
|||
Runtime string `yaml:"runtime"`
|
||||
Image string `yaml:"image"`
|
||||
ImageDigest string `yaml:"imageDigest"`
|
||||
Trigger string `yaml:"trigger"`
|
||||
Builder string `yaml:"builder"`
|
||||
BuilderMap map[string]string `yaml:"builderMap"`
|
||||
Volumes Volumes `yaml:"volumes"`
|
||||
|
@ -128,7 +127,6 @@ func fromConfig(c config) (f Function) {
|
|||
Runtime: c.Runtime,
|
||||
Image: c.Image,
|
||||
ImageDigest: c.ImageDigest,
|
||||
Trigger: c.Trigger,
|
||||
Builder: c.Builder,
|
||||
BuilderMap: c.BuilderMap,
|
||||
Volumes: c.Volumes,
|
||||
|
@ -145,7 +143,6 @@ func toConfig(f Function) config {
|
|||
Runtime: f.Runtime,
|
||||
Image: f.Image,
|
||||
ImageDigest: f.ImageDigest,
|
||||
Trigger: f.Trigger,
|
||||
Builder: f.Builder,
|
||||
BuilderMap: f.BuilderMap,
|
||||
Volumes: f.Volumes,
|
||||
|
@ -227,7 +224,7 @@ func ValidateEnvs(envs Envs) (errors []string) {
|
|||
// all key-pair values from secret are set as ENV; {{ secret.secretName }} or {{ configMap.configMapName }}
|
||||
if !regWholeSecret.MatchString(*env.Value) && !regWholeConfigMap.MatchString(*env.Value) {
|
||||
errors = append(errors, fmt.Sprintf("env entry #%d has invalid value field set, it has '%s', but allowed is only '{{ secret.secretName }}' or '{{ configMap.configMapName }}'",
|
||||
i, *env.Value))
|
||||
i, *env.Value))
|
||||
}
|
||||
} else {
|
||||
if strings.HasPrefix(*env.Value, "{{") {
|
||||
|
|
|
@ -2,20 +2,20 @@
|
|||
|
||||
## `create`
|
||||
|
||||
Creates a new Function project at _`path`_. If _`path`_ is unspecified, assumes the current directory. If _`path`_ does not exist, it will be created. The function name is the name of the leaf directory at path. The user can specify the runtime and trigger with flags.
|
||||
Creates a new Function project at _`path`_. If _`path`_ is unspecified, assumes the current directory. If _`path`_ does not exist, it will be created. The function name is the name of the leaf directory at path. The user can specify the runtime and template with flags.
|
||||
|
||||
Function name must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character (e.g. 'my-name', or '123-abc', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?').
|
||||
|
||||
Similar `kn` command: none.
|
||||
|
||||
```console
|
||||
func create <path> [-l <runtime> -t <trigger>]
|
||||
func create <path> [-l <runtime> -t <template>]
|
||||
```
|
||||
|
||||
When run as a `kn` plugin.
|
||||
|
||||
```console
|
||||
kn func create <path> [-l <runtime> -t <trigger>]
|
||||
kn func create <path> [-l <runtime> -t <template>]
|
||||
```
|
||||
|
||||
## `build`
|
||||
|
|
|
@ -87,10 +87,6 @@ The Kubernetes namespace where your function will be deployed.
|
|||
|
||||
The language runtime for your function. For example `python`.
|
||||
|
||||
### `trigger`
|
||||
|
||||
The invocation event that triggers your function. Possible values are `http`
|
||||
for plain HTTP requests, and `events` for CloudEvent triggered functions.
|
||||
|
||||
|
||||
## Local Environment Variables
|
||||
|
|
|
@ -9,7 +9,6 @@ template structure.
|
|||
Project path: /home/developer/projects/fn
|
||||
Function name: fn
|
||||
Runtime: go
|
||||
Trigger: http
|
||||
|
||||
❯ tree
|
||||
fn
|
||||
|
|
|
@ -39,7 +39,6 @@ func main() {
|
|||
// Local implementation is written to the current working directory.
|
||||
funcTest := bosonFunc.Function{
|
||||
Runtime: "go",
|
||||
Trigger: "events",
|
||||
Name: "my-function",
|
||||
Image: "quay.io/alice/my-function",
|
||||
Root: "my-function",
|
||||
|
|
|
@ -9,7 +9,6 @@ template structure.
|
|||
Project path: /home/developer/projects/fn
|
||||
Function name: fn
|
||||
Runtime: node
|
||||
Trigger: http
|
||||
|
||||
❯ tree fn
|
||||
fn
|
||||
|
|
|
@ -9,7 +9,6 @@ template structure.
|
|||
Project path: /home/developer/src/fn
|
||||
Function name: fn
|
||||
Runtime: python
|
||||
Trigger: http
|
||||
|
||||
❯ tree
|
||||
fn
|
||||
|
|
|
@ -9,7 +9,6 @@ template structure.
|
|||
Project path: /home/developer/projects/fn
|
||||
Function name: fn
|
||||
Runtime: quarkus
|
||||
Trigger: http
|
||||
|
||||
❯ tree
|
||||
fn
|
||||
|
|
|
@ -9,7 +9,6 @@ template structure.
|
|||
Project path: /home/developer/projects/fn
|
||||
Function name: fn
|
||||
Runtime: typescript
|
||||
Trigger: http
|
||||
|
||||
❯ tree fn
|
||||
fn
|
||||
|
|
|
@ -23,8 +23,8 @@ type Function struct {
|
|||
// Runtime is the language plus context. nodejs|go|quarkus|rust etc.
|
||||
Runtime string
|
||||
|
||||
// Trigger of the Function. http|events etc.
|
||||
Trigger string
|
||||
// Template for the Function.
|
||||
Template string
|
||||
|
||||
// Registry at which to store interstitial containers, in the form
|
||||
// [registry]/[user]. If omitted, "Image" must be provided.
|
||||
|
@ -55,7 +55,7 @@ type Function struct {
|
|||
// List of volumes to be mounted to the function
|
||||
Volumes Volumes
|
||||
|
||||
// Env variables to be set
|
||||
// Env variables to be set
|
||||
Envs Envs
|
||||
|
||||
// Map containing user-supplied annotations
|
||||
|
|
|
@ -17,11 +17,6 @@ import (
|
|||
"github.com/markbates/pkger"
|
||||
)
|
||||
|
||||
// DefautlTemplate is the default Function signature / environmental context
|
||||
// of the resultant template. All runtimes are expected to have at least
|
||||
// an HTTP Handler ("http") and Cloud Events ("events")
|
||||
const DefaultTemplate = "http"
|
||||
|
||||
// fileAccessor encapsulates methods for accessing template files.
|
||||
type fileAccessor interface {
|
||||
Stat(name string) (os.FileInfo, error)
|
||||
|
|
|
@ -20,7 +20,7 @@ func TestTemplatesEmbeddedFileMode(t *testing.T) {
|
|||
defer os.RemoveAll(path)
|
||||
|
||||
client := New()
|
||||
function := Function{Root: path, Runtime: "quarkus", Trigger: "events"}
|
||||
function := Function{Root: path, Runtime: "quarkus", Template: "events"}
|
||||
if err := client.Create(function); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ func TestTemplatesExtensibleFileMode(t *testing.T) {
|
|||
defer os.RemoveAll(path)
|
||||
|
||||
client := New(WithTemplates(templates))
|
||||
function := Function{Root: path, Runtime: "quarkus", Trigger: template}
|
||||
function := Function{Root: path, Runtime: "quarkus", Template: template}
|
||||
if err := client.Create(function); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ package e2e
|
|||
import "testing"
|
||||
|
||||
// Create runs `func create' command for a given test project with basic validation
|
||||
func Create(t *testing.T, knFunc *TestShellCmdRunner, project FunctionTestProject) {
|
||||
result := knFunc.Exec("create", project.ProjectPath, "--runtime", project.Runtime, "--trigger", project.Trigger)
|
||||
func Create(t *testing.T, knFunc *TestShellCmdRunner, project FunctionTestProject) {
|
||||
result := knFunc.Exec("create", project.ProjectPath, "--runtime", project.Runtime, "--template", project.Template)
|
||||
if result.Error != nil {
|
||||
t.Fatal()
|
||||
}
|
||||
|
|
|
@ -16,21 +16,21 @@ import (
|
|||
// as HTTP response next time it receives another event with source "e2e:check"
|
||||
// A better solution could be evaluated in future.
|
||||
func TestEmitCommand(t *testing.T) {
|
||||
|
||||
|
||||
project := FunctionTestProject{
|
||||
FunctionName: "emit-test-node",
|
||||
ProjectPath: filepath.Join(os.TempDir(), "emit-test-node"),
|
||||
Runtime: "node",
|
||||
Trigger: "events",
|
||||
FunctionName: "emit-test-node",
|
||||
ProjectPath: filepath.Join(os.TempDir(), "emit-test-node"),
|
||||
Runtime: "node",
|
||||
Template: "events",
|
||||
}
|
||||
knFunc := NewKnFuncShellCli(t)
|
||||
|
||||
|
||||
// Create new project
|
||||
Create(t, knFunc, project)
|
||||
defer project.RemoveProjectFolder()
|
||||
|
||||
//knFunc.Exec("build", "-r", GetRegistry(), "-p", project.ProjectPath, "-b", "quay.io/boson/faas-nodejs-builder:v0.7.1")
|
||||
|
||||
|
||||
// Update the project folder with the content of update_templates/node/events/// and deploy it
|
||||
Update(t, knFunc, &project)
|
||||
defer Delete(t, knFunc, &project)
|
||||
|
@ -41,7 +41,7 @@ func TestEmitCommand(t *testing.T) {
|
|||
if result.Error != nil {
|
||||
t.Fatal()
|
||||
}
|
||||
|
||||
|
||||
// Issue another event (in order to capture the event sent by emit)
|
||||
testEvent := SimpleTestEvent{
|
||||
Type: "e2e:check",
|
||||
|
|
|
@ -18,24 +18,23 @@ type FunctionTestProject struct {
|
|||
ProjectPath string
|
||||
// Function Runtime. Example "node"
|
||||
Runtime string
|
||||
// Function Trigger. Example "http"
|
||||
Trigger string
|
||||
// Function Template. Example "http"
|
||||
Template string
|
||||
// Indicates function is already deployed
|
||||
IsDeployed bool
|
||||
// Indicates new revision deployed (custom template)
|
||||
IsNewRevision bool
|
||||
// Function URL
|
||||
FunctionURL string
|
||||
|
||||
}
|
||||
|
||||
// NewFunctionTestProject initiates a project with derived function name an project path
|
||||
func NewFunctionTestProject(runtime string, trigger string) FunctionTestProject {
|
||||
func NewFunctionTestProject(runtime string, template string) FunctionTestProject {
|
||||
project := FunctionTestProject{
|
||||
Runtime: runtime,
|
||||
Trigger: trigger,
|
||||
Runtime: runtime,
|
||||
Template: template,
|
||||
}
|
||||
project.FunctionName = "func-" + runtime + "-" + trigger
|
||||
project.FunctionName = "func-" + runtime + "-" + template
|
||||
project.ProjectPath = filepath.Join(os.TempDir(), project.FunctionName)
|
||||
return project
|
||||
}
|
||||
|
@ -61,7 +60,7 @@ func (f FunctionTestProject) CreateProjectFolder() error {
|
|||
func (f FunctionTestProject) RemoveProjectFolder() error {
|
||||
if f.ProjectPath != "" {
|
||||
err := os.RemoveAll(f.ProjectPath)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("unable to remove project folder: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,15 +9,15 @@ import (
|
|||
)
|
||||
|
||||
type SimpleTestEvent struct {
|
||||
Type string
|
||||
Source string
|
||||
Type string
|
||||
Source string
|
||||
ContentType string
|
||||
Data string
|
||||
Data string
|
||||
}
|
||||
|
||||
func (s SimpleTestEvent) pushTo(url string, t *testing.T) (body string, statusCode int, err error) {
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("POST", url, strings.NewReader(s.Data) )
|
||||
req, err := http.NewRequest("POST", url, strings.NewReader(s.Data))
|
||||
req.Header.Add("Ce-Id", "message-1")
|
||||
req.Header.Add("Ce-Specversion", "1.0")
|
||||
req.Header.Add("Ce-Type", s.Type)
|
||||
|
@ -39,9 +39,9 @@ func (s SimpleTestEvent) pushTo(url string, t *testing.T) (body string, statusCo
|
|||
}
|
||||
|
||||
type FunctionCloudEventsValidatorEntry struct {
|
||||
targetUrl string
|
||||
targetUrl string
|
||||
contentType string
|
||||
data string
|
||||
data string
|
||||
}
|
||||
|
||||
var defaultFunctionsCloudEventsValidators = map[string]FunctionCloudEventsValidatorEntry{
|
||||
|
@ -57,11 +57,10 @@ var defaultFunctionsCloudEventsValidators = map[string]FunctionCloudEventsValida
|
|||
},
|
||||
}
|
||||
|
||||
|
||||
// DefaultFunctionEventsTest executes a common test (applied for all runtimes) against a deployed
|
||||
// functions that responds to CloudEvents
|
||||
func DefaultFunctionEventsTest(t *testing.T, knFunc *TestShellCmdRunner, project FunctionTestProject) {
|
||||
if project.Trigger == "events" && project.IsDeployed {
|
||||
if project.Template == "events" && project.IsDeployed {
|
||||
|
||||
simpleEvent := SimpleTestEvent{
|
||||
Type: "e2e.test",
|
||||
|
|
|
@ -10,9 +10,9 @@ import (
|
|||
|
||||
// HTTP Based Function Test Validator
|
||||
type FunctionHttpResponsivenessValidator struct {
|
||||
runtime string
|
||||
runtime string
|
||||
targetUrl string
|
||||
expects string
|
||||
expects string
|
||||
}
|
||||
|
||||
func (f FunctionHttpResponsivenessValidator) Validate(t *testing.T, project FunctionTestProject) {
|
||||
|
@ -31,32 +31,31 @@ func (f FunctionHttpResponsivenessValidator) Validate(t *testing.T, project Func
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
var defaultFunctionsHttpValidators = []FunctionHttpResponsivenessValidator{
|
||||
{ runtime: "node",
|
||||
{runtime: "node",
|
||||
targetUrl: "%s?message=hello",
|
||||
expects: `{"message":"hello"}`,
|
||||
},
|
||||
{ runtime: "go",
|
||||
{runtime: "go",
|
||||
targetUrl: "%s",
|
||||
expects: `OK`,
|
||||
},
|
||||
{ runtime: "python",
|
||||
{runtime: "python",
|
||||
targetUrl: "%s",
|
||||
expects: `Howdy!`,
|
||||
},
|
||||
{ runtime: "quarkus",
|
||||
{runtime: "quarkus",
|
||||
targetUrl: "%s?message=hello",
|
||||
expects: `{"message":"hello"}`,
|
||||
},
|
||||
{ runtime: "springboot",
|
||||
{runtime: "springboot",
|
||||
targetUrl: "%s/health/readiness",
|
||||
},
|
||||
}
|
||||
|
||||
// DefaultFunctionHttpTest is meant to validate the deployed (default) function is actually responsive
|
||||
func DefaultFunctionHttpTest(t *testing.T, knFunc *TestShellCmdRunner, project FunctionTestProject) {
|
||||
if project.Trigger == "http" {
|
||||
if project.Template == "http" {
|
||||
for _, v := range defaultFunctionsHttpValidators {
|
||||
v.Validate(t, project)
|
||||
}
|
||||
|
@ -64,19 +63,19 @@ func DefaultFunctionHttpTest(t *testing.T, knFunc *TestShellCmdRunner, project F
|
|||
}
|
||||
|
||||
var newRevisionFunctionsHttpValidators = []FunctionHttpResponsivenessValidator{
|
||||
{ runtime: "node",
|
||||
{runtime: "node",
|
||||
targetUrl: "%s",
|
||||
expects: `HELLO NODE FUNCTION`,
|
||||
},
|
||||
{ runtime: "go",
|
||||
{runtime: "go",
|
||||
targetUrl: "%s",
|
||||
expects: `HELLO GO FUNCTION`,
|
||||
},
|
||||
{ runtime: "python",
|
||||
{runtime: "python",
|
||||
targetUrl: "%s",
|
||||
expects: `HELLO PYTHON FUNCTION`,
|
||||
},
|
||||
{ runtime: "quarkus",
|
||||
{runtime: "quarkus",
|
||||
targetUrl: "%s",
|
||||
expects: `HELLO QUARKUS FUNCTION`,
|
||||
},
|
||||
|
@ -84,14 +83,13 @@ var newRevisionFunctionsHttpValidators = []FunctionHttpResponsivenessValidator{
|
|||
|
||||
// NewRevisionFunctionHttpTest is meant to validate the deployed function (new revision from Template) is actually responsive
|
||||
func NewRevisionFunctionHttpTest(t *testing.T, knFunc *TestShellCmdRunner, project FunctionTestProject) {
|
||||
if project.IsNewRevision && project.Trigger == "http" {
|
||||
if project.IsNewRevision && project.Template == "http" {
|
||||
for _, v := range newRevisionFunctionsHttpValidators {
|
||||
v.Validate(t, project)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// HttpGet Convenient wrapper that calls an URL and returns just the
|
||||
// body and status code. It fails in case some error occurs in the call
|
||||
func HttpGet(t *testing.T, url string) (body string, statusCode int) {
|
||||
|
|
|
@ -11,11 +11,11 @@ import (
|
|||
const updateTemplatesFolder = "update_templates"
|
||||
|
||||
// Update replaces the project content (source files) of the existing project in test
|
||||
// by the source stored under 'update_template/<runtime>/<trigger>
|
||||
// by the source stored under 'update_template/<runtime>/<template>
|
||||
// Once sources are update the project is built and re-deployed
|
||||
func Update(t *testing.T, knFunc *TestShellCmdRunner, project *FunctionTestProject) {
|
||||
func Update(t *testing.T, knFunc *TestShellCmdRunner, project *FunctionTestProject) {
|
||||
|
||||
templatePath := filepath.Join(updateTemplatesFolder, project.Runtime, project.Trigger)
|
||||
templatePath := filepath.Join(updateTemplatesFolder, project.Runtime, project.Template)
|
||||
if _, err := os.Stat(templatePath); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// skip update test when there is no template folder
|
||||
|
@ -25,7 +25,7 @@ func Update(t *testing.T, knFunc *TestShellCmdRunner, project *FunctionTestProje
|
|||
}
|
||||
}
|
||||
|
||||
// Template folder exists for given runtime / trigger.
|
||||
// Template folder exists for given runtime / template.
|
||||
// Let's update the project and redeploy
|
||||
err := projectUpdater{}.UpdateFolderContent(templatePath, project)
|
||||
if err != nil {
|
||||
|
@ -42,20 +42,19 @@ func Update(t *testing.T, knFunc *TestShellCmdRunner, project *FunctionTestProje
|
|||
project.IsNewRevision = true
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// projectUpdater offers methods to update the project source content by the
|
||||
// source provided on update_templates folder
|
||||
// The strategy used consists in
|
||||
// 1. Create a temporary project folder with func.yaml (copied from test folder)
|
||||
// 2. Copy recursivelly all files from ./update_template/<runtime>/<trigger>/** to the temporary project folder
|
||||
// 2. Copy recursivelly all files from ./update_template/<runtime>/<template>/** to the temporary project folder
|
||||
// 3. Replace current project folder by the temporary one (rm -rf <project folder> && mv <tmp folder> <project folder>
|
||||
//
|
||||
type projectUpdater struct {}
|
||||
type projectUpdater struct{}
|
||||
|
||||
func (p projectUpdater) UpdateFolderContent(templatePath string, project *FunctionTestProject) error {
|
||||
// Create temp project folder (reuse func.yaml)
|
||||
projectTmp := NewFunctionTestProject(project.Runtime, project.Trigger)
|
||||
projectTmp := NewFunctionTestProject(project.Runtime, project.Template)
|
||||
projectTmp.ProjectPath = projectTmp.ProjectPath + "-tmp"
|
||||
err := projectTmp.CreateProjectFolder()
|
||||
if err != nil {
|
||||
|
@ -118,7 +117,7 @@ func (p projectUpdater) walkThru(dir string, fn func(path string, f os.FileInfo)
|
|||
return err
|
||||
}
|
||||
if file.IsDir() {
|
||||
err := p.walkThru(filepath.Join(dir,file.Name()), fn)
|
||||
err := p.walkThru(filepath.Join(dir, file.Name()), fn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue