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:
David Fridrich 2022-11-11 12:20:19 +01:00 committed by GitHub
parent 52cf033348
commit 13fde9025d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 11254 additions and 11229 deletions

View File

@ -879,7 +879,6 @@ func (c *Client) Invoke(ctx context.Context, root string, target string, m Invok
if err != nil {
return
}
// See invoke.go for implementation details
return invoke(ctx, c, f, target, m, c.verbose)
}

View File

@ -59,9 +59,9 @@ type Function struct {
// fully "Created" (aka initialized)
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.
Invocation Invocation `yaml:"invocation,omitempty"`
Invoke string `yaml:"invoke,omitempty"`
//BuildSpec define the build properties for a function
Build BuildSpec `yaml:"build"`
@ -137,18 +137,6 @@ type BuildConfig struct {
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.
func NewFunctionWith(defaults Function) Function {
if defaults.SpecVersion == "" {

View File

@ -81,6 +81,7 @@ var migrations = []migration{
{"0.23.0", migrateToBuilderImages},
{"0.25.0", migrateToSpecVersion},
{"0.34.0", migrateToSpecsStructure},
{"0.35.0", migrateFromInvokeStructure},
// New Migrations Here.
}
@ -282,6 +283,32 @@ func migrateToSpecsStructure(f1 Function, m migration) (Function, error) {
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
type migrateToSpecs_previousFunction struct {
@ -340,3 +367,14 @@ type migrateToSpecVersion_previousFunction struct {
type migrateToBuilderImages_previousFunction struct {
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"`
}

View File

@ -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)
}
}

View File

@ -56,9 +56,6 @@ func invoke(ctx context.Context, c *Client, f Function, target string, m InvokeM
if err != nil {
return
}
if verbose {
fmt.Printf("Invoking '%v' function at %v\n", f.Invocation.Format, route)
}
// Format" either 'http' or 'cloudevent'
// 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
// set. Once decided, codify in a test.
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.
format = f.Invocation.Format
format = f.Invoke
}
if m.Format != "" {
// Use the override specified on the message if provided
format = m.Format
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)
}
}

View File

@ -96,9 +96,9 @@ type funcDefaults struct {
// this can be used to parameterize the builders
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.
Invocation Invocation `yaml:"invocation,omitempty"`
Invoke string `yaml:"invoke,omitempty"`
}
type repositoryConfig struct {
@ -145,7 +145,7 @@ func NewRepository(name, uri string) (r Repository, err error) {
Liveness: DefaultLivenessEndpoint,
Readiness: DefaultReadinessEndpoint,
},
Invocation: Invocation{Format: DefaultInvocationFormat},
Invoke: DefaultInvocationFormat,
},
}

View File

@ -137,9 +137,8 @@
"type": "string",
"format": "date-time"
},
"invocation": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/Invocation"
"invoke": {
"type": "string"
},
"build": {
"$schema": "http://json-schema.org/draft-04/schema#",
@ -184,15 +183,6 @@
"additionalProperties": false,
"type": "object"
},
"Invocation": {
"properties": {
"format": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
},
"Label": {
"required": [
"key"

View File

@ -52,8 +52,8 @@ func (t template) Write(ctx context.Context, f *Function) error {
if f.Deploy.HealthEndpoints.Readiness == "" {
f.Deploy.HealthEndpoints.Readiness = t.config.HealthEndpoints.Readiness
}
if f.Invocation.Format == "" {
f.Invocation.Format = t.config.Invocation.Format
if f.Invoke == "" && t.config.Invoke != "http" {
f.Invoke = t.config.Invoke
}
isManifest := func(p string) bool {

View File

@ -2,6 +2,4 @@
# 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:
# Invocations of Functions from this template is via basic HTTP CloudEvent
format: "cloudevent"
invoke: "cloudevent"

View File

@ -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"

View File

@ -2,6 +2,4 @@
# 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:
# Invocations of Functions from this template is via basic HTTP CloudEvent
format: "cloudevent"
invoke: "cloudevent"

View File

@ -1,2 +1 @@
invocation:
format: "cloudevent"
invoke: "cloudevent"

View File

@ -1,2 +1 @@
invocation:
format: "cloudevent"
invoke: "cloudevent"

View File

@ -2,6 +2,4 @@
# 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:
# Invocations of Functions from this template is via basic HTTP CloudEvent
format: "cloudevent"
invoke: "cloudevent"

View File

@ -2,6 +2,4 @@
# 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:
# Invocations of Functions from this template is via basic HTTP CloudEvent
format: "cloudevent"
invoke: "cloudevent"

View File

@ -1,2 +1 @@
invocation:
format: "cloudevent"
invoke: "cloudevent"

View File

@ -530,8 +530,8 @@ func TestTemplates_ManifestInvocationHints(t *testing.T) {
t.Fatal(err)
}
if f.Invocation.Format != "format" {
t.Fatalf("expected invocation format 'format', got '%v'", f.Invocation.Format)
if f.Invoke != "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
// does not define an invocation hint defaults to the DefaultInvocationFormat
// (http post)
// does not define an invocation hint defaults to empty string (since 0.35.0
// default value is omitted from func.yaml file for Invoke)
func TestTemplates_InvocationDefault(t *testing.T) {
expectedInvoke := ""
root := "testdata/testTemplatesInvocationDefault"
defer Using(t, root)()
@ -597,7 +598,7 @@ func TestTemplates_InvocationDefault(t *testing.T) {
t.Fatal(err)
}
if f.Invocation.Format != fn.DefaultInvocationFormat {
t.Fatalf("expected '%v' invocation format. Got '%v'", fn.DefaultInvocationFormat, f.Invocation.Format)
if f.Invoke != expectedInvoke {
t.Fatalf("expected '%v' invoke format. Got '%v'", expectedInvoke, f.Invoke)
}
}

View File

@ -0,0 +1,10 @@
specVersion: 0.34.0
name: testfunc
namespace: ""
runtime: go
registry: ""
image: ""
imageDigest: ""
builder: ""
invocation:
format: cloudevent

10
testdata/migrations/v0.35.0/func.yaml vendored Normal file
View File

@ -0,0 +1,10 @@
specVersion: 0.34.0
name: testfunc
namespace: ""
runtime: go
registry: ""
image: ""
imageDigest: ""
builder: ""
invocation:
format: http

View File

@ -10,12 +10,11 @@ buildEnvs:
- name: "TEST_TEMPLATE_VARIABLE"
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
# Function as development progresses to ensure 'invoke' can always trigger the
# execution of a running Function instance for testing and development.
invocation:
# 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
# is graceful degredation of service when new formats are added.
format: "format"
invoke: "format"

22292
zz_filesystem_generated.go generated

File diff suppressed because it is too large Load Diff