mirror of https://github.com/knative/func.git
184 lines
6.1 KiB
Go
184 lines
6.1 KiB
Go
//go:build e2e
|
|
|
|
package e2e
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"net"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
"syscall"
|
|
"testing"
|
|
"time"
|
|
|
|
"gotest.tools/v3/assert"
|
|
"knative.dev/func/test/oncluster"
|
|
"knative.dev/func/test/testhttp"
|
|
|
|
common "knative.dev/func/test/common"
|
|
)
|
|
|
|
// TestFunctionExtendedFlow will run a comprehensive path of func commands an end user may perform such as
|
|
// > create > build > run > (curl)+invoke > deploy > describe > list > (curl)+invoke > deploy (new revision) > (curl) > delete > list
|
|
func TestFunctionExtendedFlow(t *testing.T) {
|
|
|
|
var funcName = "extended-test"
|
|
var funcPath = filepath.Join(t.TempDir(), funcName)
|
|
|
|
knFunc := common.NewKnFuncShellCli(t)
|
|
knFunc.ShouldDumpOnSuccess = false
|
|
|
|
// ---------------------------
|
|
// Func Create Test
|
|
// ---------------------------
|
|
knFunc.Exec("create", "--language", "node", funcPath)
|
|
|
|
// From here on, all commands will be executed from the func project path
|
|
knFunc.SourceDir = funcPath
|
|
|
|
// ---------------------------
|
|
// Func Build Test
|
|
// ---------------------------
|
|
knFunc.Exec("build", "--registry", common.GetRegistry())
|
|
|
|
// ---------------------------
|
|
// Func Run Test
|
|
// ---------------------------
|
|
knFuncTerm1 := common.NewKnFuncShellCli(t)
|
|
knFuncTerm1.ShouldDumpOnSuccess = false
|
|
knFuncTerm2 := common.NewKnFuncShellCli(t)
|
|
knFuncTerm2.ShouldDumpOnSuccess = true
|
|
|
|
portChannel := make(chan string)
|
|
go func() {
|
|
t.Log("----Checking for listening port")
|
|
// set the function that will be executed while "kn func run" is executed
|
|
knFuncTerm1.OnWaitCallback = func(stdout *bytes.Buffer) {
|
|
t.Log("-----Executing OnWaitCallback")
|
|
funcPort, attempts := "", 0
|
|
for funcPort == "" && attempts < 10 {
|
|
t.Logf("----Function Output:\n%v\n", stdout.String())
|
|
findPort := func(exp string, msg string) (port string) {
|
|
matches := regexp.MustCompile(exp).FindStringSubmatch(msg)
|
|
if len(matches) > 1 {
|
|
port = matches[1]
|
|
}
|
|
return
|
|
}
|
|
funcPort = findPort("Running on host port (.*)", stdout.String())
|
|
if funcPort == "" {
|
|
funcPort = findPort("Function started on port (.*)", stdout.String())
|
|
}
|
|
attempts++
|
|
if funcPort == "" {
|
|
time.Sleep(200 * time.Millisecond)
|
|
}
|
|
}
|
|
// can proceed
|
|
portChannel <- funcPort
|
|
}
|
|
knFuncTerm1.Exec("run", "--verbose", "--path", funcPath)
|
|
}()
|
|
|
|
knFuncRunCompleted := false
|
|
knFuncRunProcessFinalizer := func() {
|
|
if knFuncRunCompleted == false {
|
|
knFuncTerm1.ExecCmd.Process.Signal(syscall.SIGTERM)
|
|
knFuncRunCompleted = true
|
|
}
|
|
}
|
|
defer knFuncRunProcessFinalizer()
|
|
|
|
// Get running port (usually 8080) from func output. We can use it for test http.
|
|
funcPort := <-portChannel
|
|
assert.Assert(t, funcPort != "", "Unable to retrieve local port allocated for function")
|
|
|
|
// Wait Port to be available
|
|
net.DialTimeout("tcp", ":"+funcPort, 3*time.Second)
|
|
time.Sleep(time.Second)
|
|
|
|
// GET Function HTTP Endpoint
|
|
_, bodyResp := testhttp.TestGet(t, "http://localhost:"+funcPort+"?message=local")
|
|
assert.Assert(t, strings.Contains(bodyResp, `{"message":"local"}`), "function response does not contain expected body.")
|
|
|
|
// ---------------------------
|
|
// Func Invoke Locally Test
|
|
// ---------------------------
|
|
result := knFuncTerm2.Exec("invoke", "--path", funcPath)
|
|
assert.Assert(t, strings.Contains(result.Out, `{"message":"Hello World"}`), "function response does not contain expected body.")
|
|
|
|
// Stop "kn func run" execution
|
|
knFuncRunProcessFinalizer()
|
|
time.Sleep(2 * time.Second)
|
|
|
|
// ---------------------------
|
|
// Func Deploy Test
|
|
// ---------------------------
|
|
knFuncDelete := func(t *testing.T) {
|
|
knFunc.Exec("delete", funcName)
|
|
listResult := knFunc.Exec("list")
|
|
assert.Assert(t, strings.Contains(listResult.Out, funcName) == false, "Function is listed as deployed after delete")
|
|
}
|
|
|
|
result = knFunc.Exec("deploy", "--build=false")
|
|
firstRevisionName, functionUrl := common.WaitForFunctionReady(t, funcName)
|
|
defer knFuncDelete(t)
|
|
|
|
wasDeployed := regexp.MustCompile("✅ Function [a-z]* in namespace .* at URL: \n http.*").MatchString(result.Out)
|
|
assert.Assert(t, wasDeployed, "Function was not deployed")
|
|
|
|
urlFromDeploy := ""
|
|
matches := regexp.MustCompile("URL: \n (http.*)").FindStringSubmatch(result.Out)
|
|
if len(matches) > 1 {
|
|
urlFromDeploy = matches[1]
|
|
}
|
|
assert.Assert(t, urlFromDeploy != "", "URL not returned on deploy output")
|
|
|
|
// ---------------------------
|
|
// Func Describe Test
|
|
// ---------------------------
|
|
urlFromDescribe := ""
|
|
result = knFunc.Exec("describe", "--output", "plain")
|
|
matches = regexp.MustCompile("Route (http.*)").FindStringSubmatch(result.Out)
|
|
if len(matches) > 1 {
|
|
urlFromDescribe = matches[1]
|
|
}
|
|
assert.Assert(t, urlFromDescribe != "", "URL not returned on info output")
|
|
assert.Assert(t, urlFromDescribe == urlFromDeploy, fmt.Sprintf("URL from 'func info' [%s] does not match URL from 'func deploy' [%s]", urlFromDescribe, urlFromDeploy))
|
|
assert.Assert(t, urlFromDescribe == functionUrl, "URL does not match knative service URL")
|
|
|
|
// ---------------------------
|
|
// Func List Test
|
|
// ---------------------------
|
|
result = knFunc.Exec("list")
|
|
assert.Assert(t, strings.Contains(result.Out, funcName), "deployed function is not listed")
|
|
|
|
// ---------------------------
|
|
// Invoke Remote Test
|
|
// ---------------------------
|
|
result = knFunc.Exec("invoke")
|
|
assert.Assert(t, strings.Contains(result.Out, `{"message":"Hello World"}`), "function response does not contain expected body.")
|
|
|
|
// GET Function HTTP Endpoint
|
|
_, bodyResp = testhttp.TestGet(t, functionUrl+"?message=remote")
|
|
assert.Assert(t, strings.Contains(bodyResp, `{"message":"remote"}`), "function response does not contain expected body.")
|
|
|
|
// ---------------------------
|
|
// Deploy new revision
|
|
// ---------------------------
|
|
oncluster.WriteNewSimpleIndexJS(t, funcPath, "NEW_REVISION")
|
|
knFunc.Exec("deploy")
|
|
|
|
common.WaitForNewRevisionReady(t, firstRevisionName, funcName)
|
|
|
|
// ---------------------------
|
|
// Call New Revision
|
|
// ---------------------------
|
|
_, bodyResp = testhttp.TestGet(t, functionUrl)
|
|
assert.Assert(t, strings.Contains(bodyResp, "NEW_REVISION"), "function new revision does not contain expected body.")
|
|
|
|
// Delete Test (on defer)
|
|
}
|