mirror of https://github.com/knative/func.git
feat: Change Invocation.format to Invoke (#1415)
* test1 * d * templates/* manifest remove http * docs fix * migration test a template tests * docs func_run * docs last * misspell * suggested changes * def http * zz * zz * change invocation struct name * zz file
This commit is contained in:
parent
52cf033348
commit
13fde9025d
|
@ -879,7 +879,6 @@ func (c *Client) Invoke(ctx context.Context, root string, target string, m Invok
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// See invoke.go for implementation details
|
// See invoke.go for implementation details
|
||||||
return invoke(ctx, c, f, target, m, c.verbose)
|
return invoke(ctx, c, f, target, m, c.verbose)
|
||||||
}
|
}
|
||||||
|
|
16
function.go
16
function.go
|
@ -59,9 +59,9 @@ type Function struct {
|
||||||
// fully "Created" (aka initialized)
|
// fully "Created" (aka initialized)
|
||||||
Created time.Time `yaml:"created"`
|
Created time.Time `yaml:"created"`
|
||||||
|
|
||||||
// Invocation defines hints for use when invoking this function.
|
// Invoke defines hints for use when invoking this function.
|
||||||
// See Client.Invoke for usage.
|
// See Client.Invoke for usage.
|
||||||
Invocation Invocation `yaml:"invocation,omitempty"`
|
Invoke string `yaml:"invoke,omitempty"`
|
||||||
|
|
||||||
//BuildSpec define the build properties for a function
|
//BuildSpec define the build properties for a function
|
||||||
Build BuildSpec `yaml:"build"`
|
Build BuildSpec `yaml:"build"`
|
||||||
|
@ -137,18 +137,6 @@ type BuildConfig struct {
|
||||||
BuilderImages map[string]string `yaml:"builderImages,omitempty"`
|
BuilderImages map[string]string `yaml:"builderImages,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invocation defines hints on how to accomplish a function invocation.
|
|
||||||
type Invocation struct {
|
|
||||||
// Format indicates the expected format of the invocation. Either 'http'
|
|
||||||
// (a basic HTTP POST of standard form fields) or 'cloudevent'
|
|
||||||
// (a CloudEvents v2 formatted http request).
|
|
||||||
Format string `yaml:"format,omitempty"`
|
|
||||||
|
|
||||||
// Protocol Note:
|
|
||||||
// Protocol is currently always HTTP. Method etc. determined by the single,
|
|
||||||
// simple switch of the Format field.
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFunctionWith defaults as provided.
|
// NewFunctionWith defaults as provided.
|
||||||
func NewFunctionWith(defaults Function) Function {
|
func NewFunctionWith(defaults Function) Function {
|
||||||
if defaults.SpecVersion == "" {
|
if defaults.SpecVersion == "" {
|
||||||
|
|
|
@ -81,6 +81,7 @@ var migrations = []migration{
|
||||||
{"0.23.0", migrateToBuilderImages},
|
{"0.23.0", migrateToBuilderImages},
|
||||||
{"0.25.0", migrateToSpecVersion},
|
{"0.25.0", migrateToSpecVersion},
|
||||||
{"0.34.0", migrateToSpecsStructure},
|
{"0.34.0", migrateToSpecsStructure},
|
||||||
|
{"0.35.0", migrateFromInvokeStructure},
|
||||||
// New Migrations Here.
|
// New Migrations Here.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,6 +283,32 @@ func migrateToSpecsStructure(f1 Function, m migration) (Function, error) {
|
||||||
return f1, nil
|
return f1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// migrateFromInvokeStructure migrates functions prior 0.35.0 via changing
|
||||||
|
// the Invocation.format(string) to new Invoke(string) to minimalize func.yaml
|
||||||
|
// file. When Invoke now holds default value (http) it will not show up in
|
||||||
|
// func.yaml as the default value is implicitly expected. Otherwise if Invoke
|
||||||
|
// is non-default value, it will be written in func.yaml.
|
||||||
|
func migrateFromInvokeStructure(f1 Function, m migration) (Function, error) {
|
||||||
|
// Load the Function using pertinent parts of the previous version's schema:
|
||||||
|
f0Filename := filepath.Join(f1.Root, FunctionFile)
|
||||||
|
bb, err := os.ReadFile(f0Filename)
|
||||||
|
if err != nil {
|
||||||
|
return f1, errors.New("migration 'migrateFromInvokeStructure' error: " + err.Error())
|
||||||
|
}
|
||||||
|
f0 := migrateFromInvokeStructure_previousFunction{}
|
||||||
|
if err = yaml.Unmarshal(bb, &f0); err != nil {
|
||||||
|
return f1, errors.New("migration 'migrateFromInvokeStructure' error: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if f0.Invocation.Format != "" && f0.Invocation.Format != "http" {
|
||||||
|
f1.Invoke = f0.Invocation.Format
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flag f1 as having had the migration applied
|
||||||
|
f1.SpecVersion = m.version
|
||||||
|
return f1, nil
|
||||||
|
}
|
||||||
|
|
||||||
// The pertinent aspects of the Function's schema prior the 1.0.0 version migrations
|
// The pertinent aspects of the Function's schema prior the 1.0.0 version migrations
|
||||||
type migrateToSpecs_previousFunction struct {
|
type migrateToSpecs_previousFunction struct {
|
||||||
|
|
||||||
|
@ -340,3 +367,14 @@ type migrateToSpecVersion_previousFunction struct {
|
||||||
type migrateToBuilderImages_previousFunction struct {
|
type migrateToBuilderImages_previousFunction struct {
|
||||||
Builder string `yaml:"builder"`
|
Builder string `yaml:"builder"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (Defined only for previous versions migration)
|
||||||
|
// Invocation defines hints on how to accomplish a function invocation.
|
||||||
|
type migrateFromInvokeStructure_invocation struct {
|
||||||
|
Format string `yaml:"format,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions prior to 0.35.0 will have Invocation.Format instead of Invoke
|
||||||
|
type migrateFromInvokeStructure_previousFunction struct {
|
||||||
|
Invocation migrateFromInvokeStructure_invocation `yaml:"invocation,omitempty"`
|
||||||
|
}
|
||||||
|
|
|
@ -170,3 +170,30 @@ func TestMigrateToSpecs(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestMigrateFromInvokeStructure tests that migration from f.Invocation.Format to
|
||||||
|
// f.Invoke works
|
||||||
|
func TestMigrateFromInvokeStructure(t *testing.T) {
|
||||||
|
root0 := "testdata/migrations/v0.35.0"
|
||||||
|
expectedInvoke := "" // empty because http is default and not written in yaml file
|
||||||
|
|
||||||
|
f0, err := NewFunction(root0)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
t.Fatal(f0)
|
||||||
|
}
|
||||||
|
if f0.Invoke != expectedInvoke {
|
||||||
|
t.Fatalf("migrated Function expected Invoke '%v', got '%v'", expectedInvoke, f0.Invoke)
|
||||||
|
}
|
||||||
|
|
||||||
|
root1 := "testdata/migrations/v0.35.0-nondefault"
|
||||||
|
expectedInvoke = "cloudevent"
|
||||||
|
f1, err := NewFunction(root1)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
t.Fatal(f1)
|
||||||
|
}
|
||||||
|
if f1.Invoke != expectedInvoke {
|
||||||
|
t.Fatalf("migrated Function expected Invoke '%v', got '%v'", expectedInvoke, f0.Invoke)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
14
invoke.go
14
invoke.go
|
@ -56,9 +56,6 @@ func invoke(ctx context.Context, c *Client, f Function, target string, m InvokeM
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if verbose {
|
|
||||||
fmt.Printf("Invoking '%v' function at %v\n", f.Invocation.Format, route)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format" either 'http' or 'cloudevent'
|
// Format" either 'http' or 'cloudevent'
|
||||||
// TODO: discuss if providing a Format on Message should a) update the
|
// TODO: discuss if providing a Format on Message should a) update the
|
||||||
|
@ -66,15 +63,20 @@ func invoke(ctx context.Context, c *Client, f Function, target string, m InvokeM
|
||||||
// compatibility fix) or b) always update the function, even if it was already
|
// compatibility fix) or b) always update the function, even if it was already
|
||||||
// set. Once decided, codify in a test.
|
// set. Once decided, codify in a test.
|
||||||
format := DefaultInvokeFormat
|
format := DefaultInvokeFormat
|
||||||
if f.Invocation.Format != "" {
|
|
||||||
|
if verbose {
|
||||||
|
fmt.Printf("Invoking '%v' function at %v\n", f.Invoke, route)
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.Invoke != "" {
|
||||||
// Prefer the format set during function creation if defined.
|
// Prefer the format set during function creation if defined.
|
||||||
format = f.Invocation.Format
|
format = f.Invoke
|
||||||
}
|
}
|
||||||
if m.Format != "" {
|
if m.Format != "" {
|
||||||
// Use the override specified on the message if provided
|
// Use the override specified on the message if provided
|
||||||
format = m.Format
|
format = m.Format
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Printf("Invoking '%v' function using '%v' format\n", f.Invocation.Format, m.Format)
|
fmt.Printf("Invoking '%v' function using '%v' format\n", f.Invoke, m.Format)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,9 +96,9 @@ type funcDefaults struct {
|
||||||
// this can be used to parameterize the builders
|
// this can be used to parameterize the builders
|
||||||
BuildEnvs []Env `yaml:"buildEnvs,omitempty"`
|
BuildEnvs []Env `yaml:"buildEnvs,omitempty"`
|
||||||
|
|
||||||
// Invocation defines invocation hints for a functions which is created
|
// Invoke defines invocation hints for a functions which is created
|
||||||
// from this template prior to being materially modified.
|
// from this template prior to being materially modified.
|
||||||
Invocation Invocation `yaml:"invocation,omitempty"`
|
Invoke string `yaml:"invoke,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type repositoryConfig struct {
|
type repositoryConfig struct {
|
||||||
|
@ -145,7 +145,7 @@ func NewRepository(name, uri string) (r Repository, err error) {
|
||||||
Liveness: DefaultLivenessEndpoint,
|
Liveness: DefaultLivenessEndpoint,
|
||||||
Readiness: DefaultReadinessEndpoint,
|
Readiness: DefaultReadinessEndpoint,
|
||||||
},
|
},
|
||||||
Invocation: Invocation{Format: DefaultInvocationFormat},
|
Invoke: DefaultInvocationFormat,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,9 +137,8 @@
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
},
|
},
|
||||||
"invocation": {
|
"invoke": {
|
||||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
"type": "string"
|
||||||
"$ref": "#/definitions/Invocation"
|
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
@ -184,15 +183,6 @@
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"Invocation": {
|
|
||||||
"properties": {
|
|
||||||
"format": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"Label": {
|
"Label": {
|
||||||
"required": [
|
"required": [
|
||||||
"key"
|
"key"
|
||||||
|
|
|
@ -52,8 +52,8 @@ func (t template) Write(ctx context.Context, f *Function) error {
|
||||||
if f.Deploy.HealthEndpoints.Readiness == "" {
|
if f.Deploy.HealthEndpoints.Readiness == "" {
|
||||||
f.Deploy.HealthEndpoints.Readiness = t.config.HealthEndpoints.Readiness
|
f.Deploy.HealthEndpoints.Readiness = t.config.HealthEndpoints.Readiness
|
||||||
}
|
}
|
||||||
if f.Invocation.Format == "" {
|
if f.Invoke == "" && t.config.Invoke != "http" {
|
||||||
f.Invocation.Format = t.config.Invocation.Format
|
f.Invoke = t.config.Invoke
|
||||||
}
|
}
|
||||||
|
|
||||||
isManifest := func(p string) bool {
|
isManifest := func(p string) bool {
|
||||||
|
|
|
@ -2,6 +2,4 @@
|
||||||
# template can be invoked. These settings can be updated on the resultant
|
# template can be invoked. These settings can be updated on the resultant
|
||||||
# Function as development progresses to ensure 'invoke' can always trigger the
|
# Function as development progresses to ensure 'invoke' can always trigger the
|
||||||
# execution of a running Function instance for testing and development.
|
# execution of a running Function instance for testing and development.
|
||||||
invocation:
|
invoke: "cloudevent"
|
||||||
# Invocations of Functions from this template is via basic HTTP CloudEvent
|
|
||||||
format: "cloudevent"
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
# optional. Invocation defines hints for how Functions created using this
|
|
||||||
# template can be invoked. These settings can be updated on the resultant
|
|
||||||
# Function as development progresses to ensure 'invoke' can always trigger the
|
|
||||||
# execution of a running Function instance for testing and development.
|
|
||||||
invocation:
|
|
||||||
# The invocation format for this template is a standard HTTP request, which
|
|
||||||
# by default is an HTTP POST of form fields of the invocation message.
|
|
||||||
format: "http"
|
|
|
@ -2,6 +2,4 @@
|
||||||
# template can be invoked. These settings can be updated on the resultant
|
# template can be invoked. These settings can be updated on the resultant
|
||||||
# Function as development progresses to ensure 'invoke' can always trigger the
|
# Function as development progresses to ensure 'invoke' can always trigger the
|
||||||
# execution of a running Function instance for testing and development.
|
# execution of a running Function instance for testing and development.
|
||||||
invocation:
|
invoke: "cloudevent"
|
||||||
# Invocations of Functions from this template is via basic HTTP CloudEvent
|
|
||||||
format: "cloudevent"
|
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
invocation:
|
invoke: "cloudevent"
|
||||||
format: "cloudevent"
|
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
invocation:
|
invoke: "cloudevent"
|
||||||
format: "cloudevent"
|
|
||||||
|
|
|
@ -2,6 +2,4 @@
|
||||||
# template can be invoked. These settings can be updated on the resultant
|
# template can be invoked. These settings can be updated on the resultant
|
||||||
# Function as development progresses to ensure 'invoke' can always trigger the
|
# Function as development progresses to ensure 'invoke' can always trigger the
|
||||||
# execution of a running Function instance for testing and development.
|
# execution of a running Function instance for testing and development.
|
||||||
invocation:
|
invoke: "cloudevent"
|
||||||
# Invocations of Functions from this template is via basic HTTP CloudEvent
|
|
||||||
format: "cloudevent"
|
|
||||||
|
|
|
@ -2,6 +2,4 @@
|
||||||
# template can be invoked. These settings can be updated on the resultant
|
# template can be invoked. These settings can be updated on the resultant
|
||||||
# Function as development progresses to ensure 'invoke' can always trigger the
|
# Function as development progresses to ensure 'invoke' can always trigger the
|
||||||
# execution of a running Function instance for testing and development.
|
# execution of a running Function instance for testing and development.
|
||||||
invocation:
|
invoke: "cloudevent"
|
||||||
# Invocations of Functions from this template is via basic HTTP CloudEvent
|
|
||||||
format: "cloudevent"
|
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
invocation:
|
invoke: "cloudevent"
|
||||||
format: "cloudevent"
|
|
||||||
|
|
|
@ -530,8 +530,8 @@ func TestTemplates_ManifestInvocationHints(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Invocation.Format != "format" {
|
if f.Invoke != "format" {
|
||||||
t.Fatalf("expected invocation format 'format', got '%v'", f.Invocation.Format)
|
t.Fatalf("expected invoke format 'format', got '%v'", f.Invoke)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,9 +571,10 @@ func TestTemplates_ManifestRemoved(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestTemplates_InvocationDefault ensures that creating a function which
|
// TestTemplates_InvocationDefault ensures that creating a function which
|
||||||
// does not define an invocation hint defaults to the DefaultInvocationFormat
|
// does not define an invocation hint defaults to empty string (since 0.35.0
|
||||||
// (http post)
|
// default value is omitted from func.yaml file for Invoke)
|
||||||
func TestTemplates_InvocationDefault(t *testing.T) {
|
func TestTemplates_InvocationDefault(t *testing.T) {
|
||||||
|
expectedInvoke := ""
|
||||||
root := "testdata/testTemplatesInvocationDefault"
|
root := "testdata/testTemplatesInvocationDefault"
|
||||||
defer Using(t, root)()
|
defer Using(t, root)()
|
||||||
|
|
||||||
|
@ -597,7 +598,7 @@ func TestTemplates_InvocationDefault(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Invocation.Format != fn.DefaultInvocationFormat {
|
if f.Invoke != expectedInvoke {
|
||||||
t.Fatalf("expected '%v' invocation format. Got '%v'", fn.DefaultInvocationFormat, f.Invocation.Format)
|
t.Fatalf("expected '%v' invoke format. Got '%v'", expectedInvoke, f.Invoke)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
specVersion: 0.34.0
|
||||||
|
name: testfunc
|
||||||
|
namespace: ""
|
||||||
|
runtime: go
|
||||||
|
registry: ""
|
||||||
|
image: ""
|
||||||
|
imageDigest: ""
|
||||||
|
builder: ""
|
||||||
|
invocation:
|
||||||
|
format: cloudevent
|
|
@ -0,0 +1,10 @@
|
||||||
|
specVersion: 0.34.0
|
||||||
|
name: testfunc
|
||||||
|
namespace: ""
|
||||||
|
runtime: go
|
||||||
|
registry: ""
|
||||||
|
image: ""
|
||||||
|
imageDigest: ""
|
||||||
|
builder: ""
|
||||||
|
invocation:
|
||||||
|
format: http
|
|
@ -10,12 +10,11 @@ buildEnvs:
|
||||||
- name: "TEST_TEMPLATE_VARIABLE"
|
- name: "TEST_TEMPLATE_VARIABLE"
|
||||||
value: "test-template"
|
value: "test-template"
|
||||||
|
|
||||||
# optional. Invocation defines hints for how Functions created using this
|
# optional. Invoke defines hints for how Functions created using this
|
||||||
# template can be invoked. These settings can be updated on the resultant
|
# template can be invoked. These settings can be updated on the resultant
|
||||||
# Function as development progresses to ensure 'invoke' can always trigger the
|
# Function as development progresses to ensure 'invoke' can always trigger the
|
||||||
# execution of a running Function instance for testing and development.
|
# execution of a running Function instance for testing and development.
|
||||||
invocation:
|
|
||||||
# The default invocation format is 'http': a basic HTTP POST of form values.
|
# The default invocation format is 'http': a basic HTTP POST of form values.
|
||||||
# Formats not understood by the system fall back to this such that there
|
# Formats not understood by the system fall back to this such that there
|
||||||
# is graceful degredation of service when new formats are added.
|
# is graceful degredation of service when new formats are added.
|
||||||
format: "format"
|
invoke: "format"
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue