(refactor) address the e2e extract / refactor of issue #763 (#765)

* (refactor) address the e2e extract / refactor of issue #763

* various updates to address reviewers feedback

* renamed lib/test/integration to lib/test and package to test
This commit is contained in:
dr.max 2020-04-01 09:21:18 -07:00 committed by GitHub
parent 521a0b423d
commit df78b8b40c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 815 additions and 703 deletions

View File

@ -17,9 +17,12 @@
[cols="1,10,3", options="header", width="100%"]
|===
| | Description | PR
|===
| 🐣
| Refactor `e2e` common code into `lib/test/integration`
| https://github.com/knative/client/pull/765[#765]
## v0.13.1 (2020-03-25)
[cols="1,10,3", options="header", width="100%"]

1
go.mod
View File

@ -14,6 +14,7 @@ require (
github.com/spf13/viper v1.4.0
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413
gomodules.xyz/jsonpatch/v2 v2.1.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gotest.tools v2.2.0+incompatible
k8s.io/api v0.17.0
k8s.io/apimachinery v0.17.0

2
go.sum
View File

@ -543,6 +543,8 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=

View File

@ -16,7 +16,7 @@
set -o pipefail
source_dirs="cmd pkg test"
source_dirs="cmd pkg test lib"
# Store for later
if [ -z "$1" ]; then

View File

@ -12,153 +12,65 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package e2e
package test
import (
"bytes"
"fmt"
"io"
"os/exec"
"strings"
"testing"
"github.com/pkg/errors"
)
type kn struct {
namespace string
}
const (
seperatorHeavy = "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
seperatorLight = "╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍"
)
// Run the 'kn' CLI with args and opts
func (k kn) Run(args ...string) KnRunResult {
return RunKn(k.namespace, args)
}
// Helper methods for calling out to the test cluster
type kubectl struct {
// Kn type
type Kn struct {
namespace string
}
// Run the 'kubectl' CLI with args and opts
func (k kubectl) Run(args ...string) (string, error) {
// New Kn object
func NewKn() Kn {
return Kn{}
}
// Run the 'kn' CLI with args
func (k Kn) Run(args ...string) KnRunResult {
return RunKn(k.namespace, args)
}
// Namespace that this Kn instance uses
func (k Kn) Namespace() string {
return k.namespace
}
// Kubectl type
type Kubectl struct {
namespace string
}
// New Kubectl object
func NewKubectl(namespace string) Kubectl {
return Kubectl{
namespace: namespace,
}
}
// Run the 'kubectl' CLI with args
func (k Kubectl) Run(args ...string) (string, error) {
return RunKubectl(k.namespace, args...)
}
// Collector for results
type KnRunResultCollector struct {
results []KnRunResult
extraDumps []string
t *testing.T
// Namespace that this Kubectl instance uses
func (k Kubectl) Namespace() string {
return k.namespace
}
func NewKnRunResultCollector(t *testing.T) *KnRunResultCollector {
return &KnRunResultCollector{
results: []KnRunResult{},
t: t,
extraDumps: []string{},
}
}
func (c *KnRunResultCollector) AssertNoError(result KnRunResult) {
c.results = append(c.results, result)
if result.Error != nil {
c.t.Logf("ERROR: %v", result.Stderr)
c.t.FailNow()
}
}
func (c *KnRunResultCollector) AssertError(result KnRunResult) {
c.results = append(c.results, result)
if result.Error == nil {
c.t.Log("ERROR: Error expected but no error happened")
c.t.FailNow()
}
}
// AddDump adds extra dump information to the collector which is printed
// out if an error occurs
func (c *KnRunResultCollector) AddDump(kind string, name string, namespace string) {
dumpInfo := extractDumpInfoWithName(kind, name, namespace)
if dumpInfo != "" {
c.extraDumps = append(c.extraDumps, dumpInfo)
}
}
func (c *KnRunResultCollector) DumpIfFailed() {
if c.t.Failed() {
c.t.Log(c.errorDetails())
}
}
func (c *KnRunResultCollector) errorDetails() string {
var out = bytes.Buffer{}
fmt.Fprintln(&out, "=== FAIL: =======================[[ERROR]]========================")
c.printCommands(&out)
var dumpInfos []string
if len(c.results) > 0 {
dumpInfo := c.results[len(c.results)-1].DumpInfo
if dumpInfo != "" {
dumpInfos = append(dumpInfos, dumpInfo)
}
}
dumpInfos = append(dumpInfos, c.extraDumps...)
for _, d := range dumpInfos {
fmt.Fprintln(&out, "--------------------------[[DUMP]]-------------------------------")
fmt.Fprintf(&out, d)
}
fmt.Fprintln(&out, "=================================================================")
return out.String()
}
func (c *KnRunResultCollector) printCommands(out io.Writer) {
for i, result := range c.results {
c.printCommand(out, result)
if i < len(c.results)-1 {
fmt.Fprintf(out, "┣━%s\n", seperatorHeavy)
}
}
}
func (c *KnRunResultCollector) printCommand(out io.Writer, result KnRunResult) {
fmt.Fprintf(out, "🦆 %s\n", result.CmdLine)
for _, l := range strings.Split(result.Stdout, "\n") {
fmt.Fprintf(out, "┃ %s\n", l)
}
if result.Stderr != "" {
errorPrefix := "🔥"
if result.ErrorExpected {
errorPrefix = "︙"
}
for _, l := range strings.Split(result.Stderr, "\n") {
fmt.Fprintf(out, "%s %s\n", errorPrefix, l)
}
}
}
// ========================================================
// Functions:
// Result of a "kn" call
type KnRunResult struct {
// Command line called
CmdLine string
// Standard output of command
Stdout string
// Standard error of command
Stderr string
// And extra dump informations in case of an unexpected error
DumpInfo string
// Error occurred during execution
Error error
// Was an error expected ?
ErrorExpected bool
}
// Public functions
// RunKn runs "kn" in a given namespace
func RunKn(namespace string, args []string) KnRunResult {
@ -195,6 +107,8 @@ func RunKubectl(namespace string, args ...string) (string, error) {
return stdout, nil
}
// Private
func runCli(cli string, args []string) (string, string, error) {
var stderr bytes.Buffer
var stdout bytes.Buffer

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package e2e
package test
import (
"flag"
@ -23,14 +23,15 @@ import (
// Flags holds the command line flags or defaults for settings in the user's environment.
// See ClientFlags for the list of supported fields.
var Flags = initializeFlags()
var Flags = InitializeFlags()
// ClientFlags define the flags that are needed to run the e2e tests.
type ClientFlags struct {
DockerConfigJSON string
}
func initializeFlags() *ClientFlags {
// InitializeFlags initializes the client's flags
func InitializeFlags() *ClientFlags {
var f ClientFlags
dockerConfigJSON := os.Getenv("DOCKER_CONFIG_JSON")

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package e2e
package test
import (
"fmt"
@ -38,38 +38,59 @@ var serviceMutex sync.Mutex
var serviceCount int
var namespaceCount int
type e2eTest struct {
// KnTest type
type KnTest struct {
namespace string
kn kn
kn Kn
}
func NewE2eTest() (*e2eTest, error) {
ns := nextNamespace()
// NewIntegrationTest creates a new ItegrationTest object
func NewKnTest() (*KnTest, error) {
ns := NextNamespace()
err := createNamespace(ns)
err := CreateNamespace(ns)
if err != nil {
return nil, err
}
err = waitForNamespaceCreated(ns)
err = WaitForNamespaceCreated(ns)
if err != nil {
return nil, err
}
return &e2eTest{
return &KnTest{
namespace: ns,
kn: kn{ns},
kn: Kn{ns},
}, nil
}
func nextNamespace() string {
// Teardown clean up
func (test *KnTest) Teardown() error {
return DeleteNamespace(test.namespace)
}
// Teardown clean up
func (test *KnTest) Kn() Kn {
return test.kn
}
// Namespace used by the test
func (test *KnTest) Namespace() string {
return test.namespace
}
// Public functions
// NextNamespace return the next unique namespace
func NextNamespace() string {
ns := os.Getenv("KN_E2E_NAMESPACE")
if ns == "" {
ns = "kne2etests"
}
return fmt.Sprintf("%s%d", ns, getNextNamespaceId())
return fmt.Sprintf("%s%d", ns, GetNextNamespaceId())
}
func getNextNamespaceId() int {
// GetNextNamespaceId return the next unique ID for the next namespace
func GetNextNamespaceId() int {
nsMutex.Lock()
defer nsMutex.Unlock()
current := namespaceCount
@ -77,7 +98,8 @@ func getNextNamespaceId() int {
return current
}
func getNextServiceName(base string) string {
// GetNextServiceName return the name for the next namespace
func GetNextServiceName(base string) string {
serviceMutex.Lock()
defer serviceMutex.Unlock()
current := serviceCount
@ -85,13 +107,8 @@ func getNextServiceName(base string) string {
return base + strconv.Itoa(current)
}
// Teardown clean up
func (test *e2eTest) Teardown() error {
return deleteNamespace(test.namespace)
}
// createNamespace creates and tests a namesspace creation invoking kubectl
func createNamespace(namespace string) error {
// CreateNamespace creates and tests a namesspace creation invoking kubectl
func CreateNamespace(namespace string) error {
expectedOutputRegexp := fmt.Sprintf("namespace?.+%s.+created", namespace)
out, err := createNamespaceWithRetry(namespace, MaxRetries)
if err != nil {
@ -109,9 +126,9 @@ func createNamespace(namespace string) error {
return nil
}
// createNamespace deletes and tests a namesspace deletion invoking kubectl
func deleteNamespace(namespace string) error {
kubectl := kubectl{namespace}
// DeleteNamespace deletes and tests a namesspace deletion invoking kubectl
func DeleteNamespace(namespace string) error {
kubectl := Kubectl{namespace}
out, err := kubectl.Run("delete", "namespace", namespace)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("Cannot delete namespace %s", namespace))
@ -129,7 +146,7 @@ func deleteNamespace(namespace string) error {
}
// WaitForNamespaceDeleted wait until namespace is deleted
func waitForNamespaceDeleted(namespace string) error {
func WaitForNamespaceDeleted(namespace string) error {
deleted := checkNamespace(namespace, false, MaxRetries)
if !deleted {
return fmt.Errorf("error deleting namespace %s, timed out after %d retries", namespace, MaxRetries)
@ -138,7 +155,7 @@ func waitForNamespaceDeleted(namespace string) error {
}
// WaitForNamespaceCreated wait until namespace is created
func waitForNamespaceCreated(namespace string) error {
func WaitForNamespaceCreated(namespace string) error {
created := checkNamespace(namespace, true, MaxRetries)
if !created {
return fmt.Errorf("error creating namespace %s, timed out after %d retries", namespace, MaxRetries)
@ -146,11 +163,20 @@ func waitForNamespaceCreated(namespace string) error {
return nil
}
func CurrentDir(t *testing.T) string {
dir, err := os.Getwd()
if err != nil {
t.Fatal("Unable to read current dir:", err)
}
return dir
}
// Private functions
func checkNamespace(namespace string, created bool, maxRetries int) bool {
retries := 0
for retries < MaxRetries {
output, _ := kubectl{}.Run("get", "namespace")
output, _ := Kubectl{}.Run("get", "namespace")
// check for namespace deleted
if !created && !strings.Contains(output, namespace) {
@ -177,7 +203,7 @@ func createNamespaceWithRetry(namespace string, maxRetries int) (string, error)
)
for retries < maxRetries {
out, err = kubectl{}.Run("create", "namespace", namespace)
out, err = Kubectl{}.Run("create", "namespace", namespace)
if err == nil {
return out, nil
}
@ -195,11 +221,3 @@ func matchRegexp(matchingRegexp, actual string) (bool, error) {
}
return matched, nil
}
func currentDir(t *testing.T) string {
dir, err := os.Getwd()
if err != nil {
t.Fatal("Unable to read current dir:", err)
}
return dir
}

View File

@ -0,0 +1,137 @@
// Copyright 2020 The Knative Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package test
import (
"bytes"
"fmt"
"io"
"strings"
"testing"
)
// KnRunResult holds command and result artifacts of a "kn" call
type KnRunResult struct {
// Command line called
CmdLine string
// Standard output of command
Stdout string
// Standard error of command
Stderr string
// And extra dump informations in case of an unexpected error
DumpInfo string
// Error occurred during execution
Error error
// Was an error expected ?
ErrorExpected bool
}
// KnRunResultCollector collects Kn run's results
type KnRunResultCollector struct {
results []KnRunResult
extraDumps []string
t *testing.T
}
// NewKnRunResultCollector returns a new KnRunResultCollector
func NewKnRunResultCollector(t *testing.T) *KnRunResultCollector {
return &KnRunResultCollector{
results: []KnRunResult{},
t: t,
extraDumps: []string{},
}
}
// AssertError helper to assert no error on result
func (c *KnRunResultCollector) AssertNoError(result KnRunResult) {
c.results = append(c.results, result)
if result.Error != nil {
c.t.Logf("ERROR: %v", result.Stderr)
c.t.FailNow()
}
}
// AssertError helper to assert error on result
func (c *KnRunResultCollector) AssertError(result KnRunResult) {
c.results = append(c.results, result)
if result.Error == nil {
c.t.Log("ERROR: Error expected but no error happened")
c.t.FailNow()
}
}
// AddDump adds extra dump information to the collector which is printed
// out if an error occurs
func (c *KnRunResultCollector) AddDump(kind string, name string, namespace string) {
dumpInfo := extractDumpInfoWithName(kind, name, namespace)
if dumpInfo != "" {
c.extraDumps = append(c.extraDumps, dumpInfo)
}
}
// DumpIfFailed logs if collector failed
func (c *KnRunResultCollector) DumpIfFailed() {
if c.t.Failed() {
c.t.Log(c.errorDetails())
}
}
// Private
func (c *KnRunResultCollector) errorDetails() string {
var out = bytes.Buffer{}
fmt.Fprintln(&out, "=== FAIL: =======================[[ERROR]]========================")
c.printCommands(&out)
var dumpInfos []string
if len(c.results) > 0 {
dumpInfo := c.results[len(c.results)-1].DumpInfo
if dumpInfo != "" {
dumpInfos = append(dumpInfos, dumpInfo)
}
}
dumpInfos = append(dumpInfos, c.extraDumps...)
for _, d := range dumpInfos {
fmt.Fprintln(&out, "--------------------------[[DUMP]]-------------------------------")
fmt.Fprintf(&out, d)
}
fmt.Fprintln(&out, "=================================================================")
return out.String()
}
func (c *KnRunResultCollector) printCommands(out io.Writer) {
for i, result := range c.results {
c.printCommand(out, result)
if i < len(c.results)-1 {
fmt.Fprintf(out, "┣━%s\n", seperatorHeavy)
}
}
}
func (c *KnRunResultCollector) printCommand(out io.Writer, result KnRunResult) {
fmt.Fprintf(out, "🦆 %s\n", result.CmdLine)
for _, l := range strings.Split(result.Stdout, "\n") {
fmt.Fprintf(out, "┃ %s\n", l)
}
if result.Stderr != "" {
errorPrefix := "🔥"
if result.ErrorExpected {
errorPrefix = "︙"
}
for _, l := range strings.Split(result.Stderr, "\n") {
fmt.Fprintf(out, "%s %s\n", errorPrefix, l)
}
}
}

View File

@ -23,60 +23,61 @@ import (
"gotest.tools/assert"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
)
func TestBasicWorkflow(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
t.Log("returns no service before running tests")
test.serviceListEmpty(t, r)
serviceListEmpty(t, it, r)
t.Log("create hello service and return no error")
test.serviceCreate(t, r, "hello")
serviceCreate(t, it, r, "hello")
t.Log("return valid info about hello service")
test.serviceList(t, r, "hello")
test.serviceDescribe(t, r, "hello")
serviceList(t, it, r, "hello")
serviceDescribe(t, it, r, "hello")
t.Log("update hello service's configuration and return no error")
test.serviceUpdate(t, r, "hello", "--env", "TARGET=kn", "--port", "8888")
serviceUpdate(t, it, r, "hello", "--env", "TARGET=kn", "--port", "8888")
t.Log("create another service and return no error")
test.serviceCreate(t, r, "svc2")
serviceCreate(t, it, r, "svc2")
t.Log("return a list of revisions associated with hello and svc2 services")
test.revisionListForService(t, r, "hello")
test.revisionListForService(t, r, "svc2")
revisionListForService(t, it, r, "hello")
revisionListForService(t, it, r, "svc2")
t.Log("describe revision from hello service")
test.revisionDescribe(t, r, "hello")
revisionDescribe(t, it, r, "hello")
t.Log("delete hello and svc2 services and return no error")
test.serviceDelete(t, r, "hello")
test.serviceDelete(t, r, "svc2")
serviceDelete(t, it, r, "hello")
serviceDelete(t, it, r, "svc2")
t.Log("return no service after completing tests")
test.serviceListEmpty(t, r)
serviceListEmpty(t, it, r)
}
func TestWrongCommand(t *testing.T) {
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
out := kn{}.Run("source", "apiserver", "noverb", "--tag=0.13")
out := test.Kn{}.Run("source", "apiserver", "noverb", "--tag=0.13")
assert.Check(t, util.ContainsAll(out.Stderr, "Error", "unknown subcommand", "noverb"))
r.AssertError(out)
out = kn{}.Run("rev")
out = test.Kn{}.Run("rev")
assert.Check(t, util.ContainsAll(out.Stderr, "Error", "unknown command", "rev"))
r.AssertError(out)
@ -84,48 +85,48 @@ func TestWrongCommand(t *testing.T) {
// ==========================================================================
func (test *e2eTest) serviceListEmpty(t *testing.T, r *KnRunResultCollector) {
out := test.kn.Run("service", "list")
func serviceListEmpty(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector) {
out := it.Kn().Run("service", "list")
r.AssertNoError(out)
assert.Check(t, util.ContainsAll(out.Stdout, "No services found."))
}
func (test *e2eTest) serviceCreate(t *testing.T, r *KnRunResultCollector, serviceName string) {
out := test.kn.Run("service", "create", serviceName, "--image", KnDefaultTestImage)
func serviceCreate(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string) {
out := it.Kn().Run("service", "create", serviceName, "--image", test.KnDefaultTestImage)
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "service", serviceName, "creating", "namespace", test.kn.namespace, "ready"))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "service", serviceName, "creating", "namespace", it.Kn().Namespace(), "ready"))
}
func (test *e2eTest) serviceList(t *testing.T, r *KnRunResultCollector, serviceName string) {
out := test.kn.Run("service", "list", serviceName)
func serviceList(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string) {
out := it.Kn().Run("service", "list", serviceName)
r.AssertNoError(out)
assert.Check(t, util.ContainsAll(out.Stdout, serviceName))
}
func (test *e2eTest) serviceDescribe(t *testing.T, r *KnRunResultCollector, serviceName string) {
out := test.kn.Run("service", "describe", serviceName)
func serviceDescribe(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string) {
out := it.Kn().Run("service", "describe", serviceName)
r.AssertNoError(out)
assert.Assert(t, util.ContainsAll(out.Stdout, serviceName, test.kn.namespace, KnDefaultTestImage))
assert.Assert(t, util.ContainsAll(out.Stdout, serviceName, it.Kn().Namespace(), test.KnDefaultTestImage))
assert.Assert(t, util.ContainsAll(out.Stdout, "Conditions", "ConfigurationsReady", "Ready", "RoutesReady"))
assert.Assert(t, util.ContainsAll(out.Stdout, "Name", "Namespace", "URL", "Age", "Revisions"))
}
func (test *e2eTest) serviceUpdate(t *testing.T, r *KnRunResultCollector, serviceName string, args ...string) {
func serviceUpdate(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string, args ...string) {
fullArgs := append([]string{}, "service", "update", serviceName)
fullArgs = append(fullArgs, args...)
out := test.kn.Run(fullArgs...)
out := it.Kn().Run(fullArgs...)
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "updating", "service", serviceName, "ready"))
}
func (test *e2eTest) serviceDelete(t *testing.T, r *KnRunResultCollector, serviceName string) {
out := test.kn.Run("service", "delete", serviceName)
func serviceDelete(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string) {
out := it.Kn().Run("service", "delete", serviceName)
r.AssertNoError(out)
assert.Check(t, util.ContainsAll(out.Stdout, "Service", serviceName, "successfully deleted in namespace", test.kn.namespace))
assert.Check(t, util.ContainsAll(out.Stdout, "Service", serviceName, "successfully deleted in namespace", it.Kn().Namespace()))
}
func (test *e2eTest) revisionListForService(t *testing.T, r *KnRunResultCollector, serviceName string) {
out := test.kn.Run("revision", "list", "-s", serviceName)
func revisionListForService(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string) {
out := it.Kn().Run("revision", "list", "-s", serviceName)
r.AssertNoError(out)
outputLines := strings.Split(out.Stdout, "\n")
// Ignore the last line because it is an empty string caused by splitting a line break
@ -136,10 +137,10 @@ func (test *e2eTest) revisionListForService(t *testing.T, r *KnRunResultCollecto
}
}
func (test *e2eTest) revisionDescribe(t *testing.T, r *KnRunResultCollector, serviceName string) {
revName := test.findRevision(t, r, serviceName)
func revisionDescribe(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string) {
revName := findRevision(t, it, r, serviceName)
out := test.kn.Run("revision", "describe", revName)
out := it.Kn().Run("revision", "describe", revName)
r.AssertNoError(out)
assert.Check(t, util.ContainsAll(out.Stdout, revName, test.kn.namespace, serviceName, "++ Ready", "TARGET=kn"))
assert.Check(t, util.ContainsAll(out.Stdout, revName, it.Kn().Namespace(), serviceName, "++ Ready", "TARGET=kn"))
}

View File

@ -22,92 +22,93 @@ import (
"gotest.tools/assert"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
)
func TestSourcePing(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
t.Log("Creating a testservice")
test.serviceCreate(t, r, "testsvc0")
serviceCreate(t, it, r, "testsvc0")
t.Log("create Ping sources with a sink to a service")
test.pingSourceCreate(t, r, "testpingsource0", "* * * * */1", "ping", "svc:testsvc0")
pingSourceCreate(t, it, r, "testpingsource0", "* * * * */1", "ping", "svc:testsvc0")
t.Log("delete Ping sources")
test.pingSourceDelete(t, r, "testpingsource0")
pingSourceDelete(t, it, r, "testpingsource0")
t.Log("create Ping source with a missing sink service")
test.pingSourceCreateMissingSink(t, r, "testpingsource1", "* * * * */1", "ping", "svc:unknown")
pingSourceCreateMissingSink(t, it, r, "testpingsource1", "* * * * */1", "ping", "svc:unknown")
t.Log("update Ping source sink service")
test.pingSourceCreate(t, r, "testpingsource2", "* * * * */1", "ping", "svc:testsvc0")
test.serviceCreate(t, r, "testsvc1")
test.pingSourceUpdateSink(t, r, "testpingsource2", "svc:testsvc1")
pingSourceCreate(t, it, r, "testpingsource2", "* * * * */1", "ping", "svc:testsvc0")
serviceCreate(t, it, r, "testsvc1")
pingSourceUpdateSink(t, it, r, "testpingsource2", "svc:testsvc1")
jpSinkRefNameInSpec := "jsonpath={.spec.sink.ref.name}"
out, err := test.getResourceFieldsWithJSONPath("pingsource", "testpingsource2", jpSinkRefNameInSpec)
out, err := getResourceFieldsWithJSONPath(t, it, "pingsource", "testpingsource2", jpSinkRefNameInSpec)
assert.NilError(t, err)
assert.Equal(t, out, "testsvc1")
t.Log("verify Ping source description")
mymsg := "This is a message from Ping."
test.pingSourceCreate(t, r, "testpingsource3", "*/1 * * * *", mymsg, "svc:testsvc1")
test.verifyPingSourceDescribe(t, r, "testpingsource3", "*/1 * * * *", mymsg, "testsvc1")
pingSourceCreate(t, it, r, "testpingsource3", "*/1 * * * *", mymsg, "svc:testsvc1")
verifyPingSourceDescribe(t, it, r, "testpingsource3", "*/1 * * * *", mymsg, "testsvc1")
}
func (test *e2eTest) pingSourceCreate(t *testing.T, r *KnRunResultCollector, sourceName string, schedule string, data string, sink string) {
out := test.kn.Run("source", "ping", "create", sourceName,
func pingSourceCreate(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, sourceName string, schedule string, data string, sink string) {
out := it.Kn().Run("source", "ping", "create", sourceName,
"--schedule", schedule, "--data", data, "--sink", sink)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "ping", "source", sourceName, "created", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "ping", "source", sourceName, "created", "namespace", it.Kn().Namespace()))
r.AssertNoError(out)
}
func (test *e2eTest) pingSourceDelete(t *testing.T, r *KnRunResultCollector, sourceName string) {
out := test.kn.Run("source", "ping", "delete", sourceName)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "ping", "source", sourceName, "deleted", "namespace", test.kn.namespace))
func pingSourceDelete(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, sourceName string) {
out := it.Kn().Run("source", "ping", "delete", sourceName)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "ping", "source", sourceName, "deleted", "namespace", it.Kn().Namespace()))
r.AssertNoError(out)
}
func (test *e2eTest) pingSourceCreateMissingSink(t *testing.T, r *KnRunResultCollector, sourceName string, schedule string, data string, sink string) {
out := test.kn.Run("source", "ping", "create", sourceName,
func pingSourceCreateMissingSink(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, sourceName string, schedule string, data string, sink string) {
out := it.Kn().Run("source", "ping", "create", sourceName,
"--schedule", schedule, "--data", data, "--sink", sink)
assert.Check(t, util.ContainsAll(out.Stderr, "services.serving.knative.dev", "not found"))
r.AssertError(out)
}
func (test *e2eTest) pingSourceUpdateSink(t *testing.T, r *KnRunResultCollector, sourceName string, sink string) {
out := test.kn.Run("source", "ping", "update", sourceName, "--sink", sink)
assert.Check(t, util.ContainsAll(out.Stdout, sourceName, "updated", "namespace", test.kn.namespace))
func pingSourceUpdateSink(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, sourceName string, sink string) {
out := it.Kn().Run("source", "ping", "update", sourceName, "--sink", sink)
assert.Check(t, util.ContainsAll(out.Stdout, sourceName, "updated", "namespace", it.Kn().Namespace()))
r.AssertNoError(out)
}
func (test *e2eTest) pingSourceCreateWithResources(t *testing.T, r *KnRunResultCollector, sourceName string, schedule string, data string, sink string, sa string, requestcpu string, requestmm string, limitcpu string, limitmm string) {
out := test.kn.Run("source", "ping", "create", sourceName,
func pingSourceCreateWithResources(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, sourceName string, schedule string, data string, sink string, sa string, requestcpu string, requestmm string, limitcpu string, limitmm string) {
out := it.Kn().Run("source", "ping", "create", sourceName,
"--schedule", schedule, "--data", data, "--sink", sink, "--service-account", sa,
"--requests-cpu", requestcpu, "--requests-memory", requestmm, "--limits-cpu", limitcpu, "--limits-memory", limitmm)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "ping", "source", sourceName, "created", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "ping", "source", sourceName, "created", "namespace", it.Kn().Namespace()))
r.AssertNoError(out)
}
func (test *e2eTest) pingSourceUpdateResources(t *testing.T, r *KnRunResultCollector, sourceName string, requestcpu string, requestmm string, limitcpu string, limitmm string) {
out := test.kn.Run("source", "ping", "update", sourceName,
func pingSourceUpdateResources(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, sourceName string, requestcpu string, requestmm string, limitcpu string, limitmm string) {
out := it.Kn().Run("source", "ping", "update", sourceName,
"--requests-cpu", requestcpu, "--requests-memory", requestmm, "--limits-cpu", limitcpu, "--limits-memory", limitmm)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, sourceName, "updated", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, sourceName, "updated", "namespace", it.Kn().Namespace()))
r.AssertNoError(out)
}
func (test *e2eTest) verifyPingSourceDescribe(t *testing.T, r *KnRunResultCollector, sourceName string, schedule string, data string, sink string) {
out := test.kn.Run("source", "ping", "describe", sourceName)
func verifyPingSourceDescribe(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, sourceName string, schedule string, data string, sink string) {
out := it.Kn().Run("source", "ping", "describe", sourceName)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, sourceName, schedule, data, sink))
r.AssertNoError(out)
}

View File

@ -25,6 +25,7 @@ import (
"gotest.tools/assert"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
)
@ -95,7 +96,7 @@ func TestPluginWithoutLookup(t *testing.T) {
pc, oldPath := setupPluginTestConfigWithNewPath(t)
defer tearDownWithPath(pc, oldPath)
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
knFlags := []string{fmt.Sprintf("--plugins-dir=%s", pc.knPluginsDir), "--lookup-plugins=false"}
@ -114,7 +115,7 @@ func TestPluginWithoutLookup(t *testing.T) {
func TestPluginWithLookup(t *testing.T) {
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
pc := pluginTestConfig{}
@ -132,7 +133,7 @@ func TestPluginWithLookup(t *testing.T) {
func TestListPluginInPath(t *testing.T) {
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
pc, oldPath := setupPluginTestConfigWithNewPath(t)
defer tearDownWithPath(pc, oldPath)
@ -145,7 +146,7 @@ func TestListPluginInPath(t *testing.T) {
}
func TestExecutePluginInPath(t *testing.T) {
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
pc, oldPath := setupPluginTestConfigWithNewPath(t)
@ -171,21 +172,21 @@ func tearDownWithPath(pc pluginTestConfig, oldPath string) {
// Private
func listPlugin(t *testing.T, r *KnRunResultCollector, knFlags []string, expectedPlugins []string, unexpectedPlugins []string) {
func listPlugin(t *testing.T, r *test.KnRunResultCollector, knFlags []string, expectedPlugins []string, unexpectedPlugins []string) {
knArgs := append(knFlags, "plugin", "list")
out := kn{}.Run(knArgs...)
out := test.Kn{}.Run(knArgs...)
r.AssertNoError(out)
assert.Check(t, util.ContainsAll(out.Stdout, expectedPlugins...))
assert.Check(t, util.ContainsNone(out.Stdout, unexpectedPlugins...))
}
func runPlugin(t *testing.T, r *KnRunResultCollector, knFlags []string, pluginName string, args []string, expectedOutput []string) {
func runPlugin(t *testing.T, r *test.KnRunResultCollector, knFlags []string, pluginName string, args []string, expectedOutput []string) {
knArgs := append([]string{}, knFlags...)
knArgs = append(knArgs, pluginName)
knArgs = append(knArgs, args...)
out := kn{}.Run(knArgs...)
out := test.Kn{}.Run(knArgs...)
r.AssertNoError(out)
for _, output := range expectedOutput {
assert.Check(t, util.ContainsAll(out.Stdout, output))

View File

@ -24,99 +24,101 @@ import (
"testing"
"gotest.tools/assert"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
)
func TestRevision(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
t.Log("create hello service and return no error")
test.serviceCreate(t, r, "hello")
serviceCreate(t, it, r, "hello")
t.Log("describe revision from hello service with print flags")
revName := test.findRevision(t, r, "hello")
test.revisionDescribeWithPrintFlags(t, r, revName)
revName := findRevision(t, it, r, "hello")
revisionDescribeWithPrintFlags(t, it, r, revName)
t.Log("update hello service and increase revision count to 2")
test.serviceUpdate(t, r, "hello", "--env", "TARGET=kn", "--port", "8888")
serviceUpdate(t, it, r, "hello", "--env", "TARGET=kn", "--port", "8888")
t.Log("show a list of revisions sorted by the count of configuration generation")
test.revisionListWithService(t, r, "hello")
revisionListWithService(t, it, r, "hello")
t.Log("update hello service and increase revision count to 3")
test.serviceUpdate(t, r, "hello", "--env", "TARGET=kn", "--port", "8888")
serviceUpdate(t, it, r, "hello", "--env", "TARGET=kn", "--port", "8888")
t.Log("delete three revisions with one revision a nonexistent")
existRevision1 := test.findRevisionByGeneration(t, r, "hello", 1)
existRevision2 := test.findRevisionByGeneration(t, r, "hello", 2)
existRevision1 := findRevisionByGeneration(t, it, r, "hello", 1)
existRevision2 := findRevisionByGeneration(t, it, r, "hello", 2)
nonexistRevision := "hello-nonexist"
test.revisionMultipleDelete(t, r, existRevision1, existRevision2, nonexistRevision)
revisionMultipleDelete(t, it, r, existRevision1, existRevision2, nonexistRevision)
t.Log("delete latest revision from hello service and return no error")
revName = test.findRevision(t, r, "hello")
test.revisionDelete(t, r, revName)
revName = findRevision(t, it, r, "hello")
revisionDelete(t, it, r, revName)
t.Log("delete hello service and return no error")
test.serviceDelete(t, r, "hello")
serviceDelete(t, it, r, "hello")
}
func (test *e2eTest) revisionListWithService(t *testing.T, r *KnRunResultCollector, serviceNames ...string) {
func revisionListWithService(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceNames ...string) {
for _, svcName := range serviceNames {
confGen := test.findConfigurationGeneration(t, r, svcName)
out := test.kn.Run("revision", "list", "-s", svcName)
confGen := findConfigurationGeneration(t, it, r, svcName)
out := it.Kn().Run("revision", "list", "-s", svcName)
r.AssertNoError(out)
outputLines := strings.Split(out.Stdout, "\n")
// Ignore the last line because it is an empty string caused by splitting a line break
// at the end of the output string
for _, line := range outputLines[1 : len(outputLines)-1] {
revName := test.findRevisionByGeneration(t, r, svcName, confGen)
revName := findRevisionByGeneration(t, it, r, svcName, confGen)
assert.Check(t, util.ContainsAll(line, revName, svcName, strconv.Itoa(confGen)))
confGen--
}
if t.Failed() {
r.AddDump("service", svcName, test.namespace)
r.AddDump("service", svcName, it.Kn().Namespace())
}
}
}
func (test *e2eTest) revisionDelete(t *testing.T, r *KnRunResultCollector, revName string) {
out := test.kn.Run("revision", "delete", revName)
assert.Check(t, util.ContainsAll(out.Stdout, "Revision", revName, "deleted", "namespace", test.kn.namespace))
func revisionDelete(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, revName string) {
out := it.Kn().Run("revision", "delete", revName)
assert.Check(t, util.ContainsAll(out.Stdout, "Revision", revName, "deleted", "namespace", it.Kn().Namespace()))
r.AssertNoError(out)
}
func (test *e2eTest) revisionMultipleDelete(t *testing.T, r *KnRunResultCollector, existRevision1, existRevision2, nonexistRevision string) {
out := test.kn.Run("revision", "list")
func revisionMultipleDelete(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, existRevision1, existRevision2, nonexistRevision string) {
out := it.Kn().Run("revision", "list")
r.AssertNoError(out)
assert.Check(t, strings.Contains(out.Stdout, existRevision1), "Required revision1 does not exist")
assert.Check(t, strings.Contains(out.Stdout, existRevision2), "Required revision2 does not exist")
out = test.kn.Run("revision", "delete", existRevision1, existRevision2, nonexistRevision)
out = it.Kn().Run("revision", "delete", existRevision1, existRevision2, nonexistRevision)
r.AssertNoError(out)
assert.Check(t, util.ContainsAll(out.Stdout, "Revision", existRevision1, "deleted", "namespace", test.kn.namespace), "Failed to get 'deleted' first revision message")
assert.Check(t, util.ContainsAll(out.Stdout, "Revision", existRevision2, "deleted", "namespace", test.kn.namespace), "Failed to get 'deleted' second revision message")
assert.Check(t, util.ContainsAll(out.Stdout, "Revision", existRevision1, "deleted", "namespace", it.Kn().Namespace()), "Failed to get 'deleted' first revision message")
assert.Check(t, util.ContainsAll(out.Stdout, "Revision", existRevision2, "deleted", "namespace", it.Kn().Namespace()), "Failed to get 'deleted' second revision message")
assert.Check(t, util.ContainsAll(out.Stdout, "revisions.serving.knative.dev", nonexistRevision, "not found"), "Failed to get 'not found' error")
}
func (test *e2eTest) revisionDescribeWithPrintFlags(t *testing.T, r *KnRunResultCollector, revName string) {
out := test.kn.Run("revision", "describe", revName, "-o=name")
func revisionDescribeWithPrintFlags(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, revName string) {
out := it.Kn().Run("revision", "describe", revName, "-o=name")
r.AssertNoError(out)
expectedName := fmt.Sprintf("revision.serving.knative.dev/%s", revName)
assert.Equal(t, strings.TrimSpace(out.Stdout), expectedName)
}
func (test *e2eTest) findRevision(t *testing.T, r *KnRunResultCollector, serviceName string) string {
out := test.kn.Run("revision", "list", "-s", serviceName, "-o=jsonpath={.items[0].metadata.name}")
func findRevision(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string) string {
out := it.Kn().Run("revision", "list", "-s", serviceName, "-o=jsonpath={.items[0].metadata.name}")
r.AssertNoError(out)
if strings.Contains(out.Stdout, "No resources") {
t.Errorf("Could not find revision name.")
@ -124,9 +126,9 @@ func (test *e2eTest) findRevision(t *testing.T, r *KnRunResultCollector, service
return out.Stdout
}
func (test *e2eTest) findRevisionByGeneration(t *testing.T, r *KnRunResultCollector, serviceName string, generation int) string {
maxGen := test.findConfigurationGeneration(t, r, serviceName)
out := test.kn.Run("revision", "list", "-s", serviceName,
func findRevisionByGeneration(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string, generation int) string {
maxGen := findConfigurationGeneration(t, it, r, serviceName)
out := it.Kn().Run("revision", "list", "-s", serviceName,
fmt.Sprintf("-o=jsonpath={.items[%d].metadata.name}", maxGen-generation))
r.AssertNoError(out)
if strings.Contains(out.Stdout, "No resources found.") {
@ -135,8 +137,8 @@ func (test *e2eTest) findRevisionByGeneration(t *testing.T, r *KnRunResultCollec
return out.Stdout
}
func (test *e2eTest) findConfigurationGeneration(t *testing.T, r *KnRunResultCollector, serviceName string) int {
out := test.kn.Run("revision", "list", "-s", serviceName, "-o=jsonpath={.items[0].metadata.labels.serving\\.knative\\.dev/configurationGeneration}")
func findConfigurationGeneration(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string) int {
out := it.Kn().Run("revision", "list", "-s", serviceName, "-o=jsonpath={.items[0].metadata.labels.serving\\.knative\\.dev/configurationGeneration}")
r.AssertNoError(out)
if out.Stdout == "" {
t.Errorf("Could not find configuration generation.")

View File

@ -23,75 +23,77 @@ import (
"testing"
"gotest.tools/assert"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
)
func TestRoute(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
t.Log("create hello service and return no error")
test.serviceCreate(t, r, "hello")
serviceCreate(t, it, r, "hello")
t.Log("return a list of routes")
test.routeList(t, r)
routeList(t, it, r)
t.Log("return a list of routes associated with hello service")
test.routeListWithArgument(t, r, "hello")
routeListWithArgument(t, it, r, "hello")
t.Log("return a list of routes associated with hello service with print flags")
test.routeListWithPrintFlags(t, r, "hello")
routeListWithPrintFlags(t, it, r, "hello")
t.Log("describe route from hello service")
test.routeDescribe(t, r, "hello")
routeDescribe(t, it, r, "hello")
t.Log("describe route from hello service with print flags")
test.routeDescribeWithPrintFlags(t, r, "hello")
routeDescribeWithPrintFlags(t, it, r, "hello")
t.Log("delete hello service and return no error")
test.serviceDelete(t, r, "hello")
serviceDelete(t, it, r, "hello")
}
func (test *e2eTest) routeList(t *testing.T, r *KnRunResultCollector) {
out := test.kn.Run("route", "list")
func routeList(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector) {
out := it.Kn().Run("route", "list")
expectedHeaders := []string{"NAME", "URL", "READY"}
assert.Check(t, util.ContainsAll(out.Stdout, expectedHeaders...))
r.AssertNoError(out)
}
func (test *e2eTest) routeListWithArgument(t *testing.T, r *KnRunResultCollector, routeName string) {
out := test.kn.Run("route", "list", routeName)
func routeListWithArgument(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, routeName string) {
out := it.Kn().Run("route", "list", routeName)
assert.Check(t, util.ContainsAll(out.Stdout, routeName))
r.AssertNoError(out)
}
func (test *e2eTest) routeDescribe(t *testing.T, r *KnRunResultCollector, routeName string) {
out := test.kn.Run("route", "describe", routeName)
func routeDescribe(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, routeName string) {
out := it.Kn().Run("route", "describe", routeName)
assert.Check(t, util.ContainsAll(out.Stdout,
routeName, test.kn.namespace, "URL", "Service", "Traffic", "Targets", "Conditions"))
routeName, it.Kn().Namespace(), "URL", "Service", "Traffic", "Targets", "Conditions"))
r.AssertNoError(out)
}
func (test *e2eTest) routeDescribeWithPrintFlags(t *testing.T, r *KnRunResultCollector, routeName string) {
out := test.kn.Run("route", "describe", routeName, "-o=name")
func routeDescribeWithPrintFlags(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, routeName string) {
out := it.Kn().Run("route", "describe", routeName, "-o=name")
expectedName := fmt.Sprintf("route.serving.knative.dev/%s", routeName)
assert.Equal(t, strings.TrimSpace(out.Stdout), expectedName)
r.AssertNoError(out)
}
func (test *e2eTest) routeListWithPrintFlags(t *testing.T, r *KnRunResultCollector, names ...string) {
out := test.kn.Run("route", "list", "-o=jsonpath={.items[*].metadata.name}")
func routeListWithPrintFlags(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, names ...string) {
out := it.Kn().Run("route", "list", "-o=jsonpath={.items[*].metadata.name}")
assert.Check(t, util.ContainsAll(out.Stdout, names...))
r.AssertNoError(out)
}

View File

@ -23,12 +23,14 @@ import (
"gotest.tools/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"knative.dev/pkg/ptr"
"sigs.k8s.io/yaml"
"knative.dev/client/lib/test"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
servingv1 "knative.dev/serving/pkg/apis/serving/v1"
)
@ -36,60 +38,64 @@ type expectedServiceOption func(*servingv1.Service)
func TestServiceExportImportApply(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
t.Log("create service with byo revision")
test.serviceCreateWithOptions(t, r, "hello", "--revision-name", "rev1")
serviceCreateWithOptions(t, it, r, "hello", "--revision-name", "rev1")
t.Log("export service and compare")
test.serviceExport(t, r, "hello", getSvc(withName("hello"), withRevisionName("hello-rev1"), withAnnotations()), "-o", "json")
serviceExport(t, it, r, "hello", getSvc(withName("hello"), withRevisionName("hello-rev1"), withAnnotations()), "-o", "json")
t.Log("update service - add env variable")
test.serviceUpdateWithOptions(t, r, "hello", "--env", "key1=val1", "--revision-name", "rev2", "--no-lock-to-digest")
test.serviceExport(t, r, "hello", getSvc(withName("hello"), withRevisionName("hello-rev2"), withEnv("key1", "val1")), "-o", "json")
test.serviceExportWithRevisions(t, r, "hello", getSvcListWithOneRevision(), "--with-revisions", "-o", "yaml")
serviceUpdateWithOptions(t, it, r, "hello", "--env", "key1=val1", "--revision-name", "rev2", "--no-lock-to-digest")
serviceExport(t, it, r, "hello", getSvc(withName("hello"), withRevisionName("hello-rev2"), withEnv("key1", "val1")), "-o", "json")
serviceExportWithRevisions(t, it, r, "hello", getSvcListWithOneRevision(), "--with-revisions", "-o", "yaml")
t.Log("update service with tag and split traffic")
test.serviceUpdateWithOptions(t, r, "hello", "--tag", "hello-rev1=candidate", "--traffic", "candidate=2%,@latest=98%")
test.serviceExportWithRevisions(t, r, "hello", getSvcListWithTags(), "--with-revisions", "-o", "yaml")
serviceUpdateWithOptions(t, it, r, "hello", "--tag", "hello-rev1=candidate", "--traffic", "candidate=2%,@latest=98%")
serviceExportWithRevisions(t, it, r, "hello", getSvcListWithTags(), "--with-revisions", "-o", "yaml")
t.Log("update service - untag, add env variable and traffic split")
test.serviceUpdateWithOptions(t, r, "hello", "--untag", "candidate")
test.serviceUpdateWithOptions(t, r, "hello", "--env", "key2=val2", "--revision-name", "rev3", "--traffic", "hello-rev1=30,hello-rev2=30,hello-rev3=40")
test.serviceExportWithRevisions(t, r, "hello", getSvcListWOTags(), "--with-revisions", "-o", "yaml")
serviceUpdateWithOptions(t, it, r, "hello", "--untag", "candidate")
serviceUpdateWithOptions(t, it, r, "hello", "--env", "key2=val2", "--revision-name", "rev3", "--traffic", "hello-rev1=30,hello-rev2=30,hello-rev3=40")
serviceExportWithRevisions(t, it, r, "hello", getSvcListWOTags(), "--with-revisions", "-o", "yaml")
}
func (test *e2eTest) serviceExport(t *testing.T, r *KnRunResultCollector, serviceName string, expService servingv1.Service, options ...string) {
// Private methods
func serviceExport(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string, expService servingv1.Service, options ...string) {
command := []string{"service", "export", serviceName}
command = append(command, options...)
out := test.kn.Run(command...)
validateExportedService(t, out.Stdout, expService)
out := it.Kn().Run(command...)
validateExportedService(t, it, out.Stdout, expService)
r.AssertNoError(out)
}
func validateExportedService(t *testing.T, out string, expService servingv1.Service) {
func serviceExportWithRevisions(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string, expServiceList servingv1.ServiceList, options ...string) {
command := []string{"service", "export", serviceName}
command = append(command, options...)
out := it.Kn().Run(command...)
validateExportedServiceList(t, it, out.Stdout, expServiceList)
r.AssertNoError(out)
}
// Private functions
func validateExportedService(t *testing.T, it *test.KnTest, out string, expService servingv1.Service) {
actSvcJSON := servingv1.Service{}
err := json.Unmarshal([]byte(out), &actSvcJSON)
assert.NilError(t, err)
assert.DeepEqual(t, &expService, &actSvcJSON)
}
func (test *e2eTest) serviceExportWithRevisions(t *testing.T, r *KnRunResultCollector, serviceName string, expServiceList servingv1.ServiceList, options ...string) {
command := []string{"service", "export", serviceName}
command = append(command, options...)
out := test.kn.Run(command...)
validateExportedServiceList(t, out.Stdout, expServiceList)
r.AssertNoError(out)
}
func validateExportedServiceList(t *testing.T, out string, expServiceList servingv1.ServiceList) {
func validateExportedServiceList(t *testing.T, it *test.KnTest, out string, expServiceList servingv1.ServiceList) {
actYaml := servingv1.ServiceList{}
err := yaml.Unmarshal([]byte(out), &actYaml)
assert.NilError(t, err)
@ -108,7 +114,7 @@ func getSvc(options ...expectedServiceOption) servingv1.Service {
Containers: []corev1.Container{
{
Name: "user-container",
Image: KnDefaultTestImage,
Image: test.KnDefaultTestImage,
Resources: corev1.ResourceRequirements{},
ReadinessProbe: &corev1.Probe{
SuccessThreshold: int32(1),

View File

@ -26,76 +26,79 @@ import (
"testing"
"gotest.tools/assert"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
servingv1 "knative.dev/serving/pkg/apis/serving/v1"
)
func TestServiceOptions(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
t.Log("create and validate service with concurrency options")
defer r.DumpIfFailed()
test.serviceCreateWithOptions(t, r, "svc1", "--concurrency-limit", "250", "--concurrency-target", "300")
test.validateServiceConcurrencyTarget(t, r, "svc1", "300")
test.validateServiceConcurrencyLimit(t, r, "svc1", "250")
serviceCreateWithOptions(t, it, r, "svc1", "--concurrency-limit", "250", "--concurrency-target", "300")
validateServiceConcurrencyTarget(t, it, r, "svc1", "300")
validateServiceConcurrencyLimit(t, it, r, "svc1", "250")
t.Log("update and validate service with concurrency limit")
test.serviceUpdate(t, r, "svc1", "--concurrency-limit", "300")
test.validateServiceConcurrencyLimit(t, r, "svc1", "300")
serviceUpdate(t, it, r, "svc1", "--concurrency-limit", "300")
validateServiceConcurrencyLimit(t, it, r, "svc1", "300")
t.Log("update concurrency options with invalid values for service")
out := test.kn.Run("service", "update", "svc1", "--concurrency-limit", "-1", "--concurrency-target", "0")
out := it.Kn().Run("service", "update", "svc1", "--concurrency-limit", "-1", "--concurrency-target", "0")
r.AssertError(out)
assert.Check(t, util.ContainsAll(out.Stderr, "invalid"))
t.Log("returns steady concurrency options for service")
test.validateServiceConcurrencyLimit(t, r, "svc1", "300")
test.validateServiceConcurrencyTarget(t, r, "svc1", "300")
validateServiceConcurrencyLimit(t, it, r, "svc1", "300")
validateServiceConcurrencyTarget(t, it, r, "svc1", "300")
t.Log("delete service")
test.serviceDelete(t, r, "svc1")
serviceDelete(t, it, r, "svc1")
t.Log("create and validate service with min/max scale options ")
test.serviceCreateWithOptions(t, r, "svc2", "--min-scale", "1", "--max-scale", "3")
test.validateServiceMinScale(t, r, "svc2", "1")
test.validateServiceMaxScale(t, r, "svc2", "3")
serviceCreateWithOptions(t, it, r, "svc2", "--min-scale", "1", "--max-scale", "3")
validateServiceMinScale(t, it, r, "svc2", "1")
validateServiceMaxScale(t, it, r, "svc2", "3")
t.Log("update and validate service with max scale option")
test.serviceUpdate(t, r, "svc2", "--max-scale", "2")
test.validateServiceMaxScale(t, r, "svc2", "2")
serviceUpdate(t, it, r, "svc2", "--max-scale", "2")
validateServiceMaxScale(t, it, r, "svc2", "2")
t.Log("delete service")
test.serviceDelete(t, r, "svc2")
serviceDelete(t, it, r, "svc2")
t.Log("create, update and validate service with annotations")
test.serviceCreateWithOptions(t, r, "svc3", "--annotation", "alpha=wolf", "--annotation", "brave=horse")
test.validateServiceAnnotations(t, r, "svc3", map[string]string{"alpha": "wolf", "brave": "horse"})
test.serviceUpdate(t, r, "svc3", "--annotation", "alpha=direwolf", "--annotation", "brave-")
test.validateServiceAnnotations(t, r, "svc3", map[string]string{"alpha": "direwolf", "brave": ""})
test.serviceDelete(t, r, "svc3")
serviceCreateWithOptions(t, it, r, "svc3", "--annotation", "alpha=wolf", "--annotation", "brave=horse")
validateServiceAnnotations(t, it, r, "svc3", map[string]string{"alpha": "wolf", "brave": "horse"})
serviceUpdate(t, it, r, "svc3", "--annotation", "alpha=direwolf", "--annotation", "brave-")
validateServiceAnnotations(t, it, r, "svc3", map[string]string{"alpha": "direwolf", "brave": ""})
serviceDelete(t, it, r, "svc3")
t.Log("create, update and validate service with autoscale window option")
test.serviceCreateWithOptions(t, r, "svc4", "--autoscale-window", "1m")
test.validateAutoscaleWindow(t, r, "svc4", "1m")
test.serviceUpdate(t, r, "svc4", "--autoscale-window", "15s")
test.validateAutoscaleWindow(t, r, "svc4", "15s")
test.serviceDelete(t, r, "svc4")
serviceCreateWithOptions(t, it, r, "svc4", "--autoscale-window", "1m")
validateAutoscaleWindow(t, it, r, "svc4", "1m")
serviceUpdate(t, it, r, "svc4", "--autoscale-window", "15s")
validateAutoscaleWindow(t, it, r, "svc4", "15s")
serviceDelete(t, it, r, "svc4")
t.Log("create, update and validate service with cmd and arg options")
test.serviceCreateWithOptions(t, r, "svc5", "--cmd", "/go/bin/helloworld")
test.validateContainerField(t, r, "svc5", "command", "[/go/bin/helloworld]")
test.serviceUpdate(t, r, "svc5", "--arg", "myArg1", "--arg", "--myArg2")
test.validateContainerField(t, r, "svc5", "args", "[myArg1 --myArg2]")
test.serviceUpdate(t, r, "svc5", "--arg", "myArg1")
test.validateContainerField(t, r, "svc5", "args", "[myArg1]")
serviceCreateWithOptions(t, it, r, "svc5", "--cmd", "/go/bin/helloworld")
validateContainerField(t, it, r, "svc5", "command", "[/go/bin/helloworld]")
serviceUpdate(t, it, r, "svc5", "--arg", "myArg1", "--arg", "--myArg2")
validateContainerField(t, it, r, "svc5", "args", "[myArg1 --myArg2]")
serviceUpdate(t, it, r, "svc5", "--arg", "myArg1")
validateContainerField(t, it, r, "svc5", "args", "[myArg1]")
t.Log("create, update and validate service with user defined")
var uid int64 = 1000
@ -103,79 +106,79 @@ func TestServiceOptions(t *testing.T) {
uid, err = strconv.ParseInt(uids, 10, 64)
assert.NilError(t, err)
}
test.serviceCreateWithOptions(t, r, "svc6", "--user", strconv.FormatInt(uid, 10))
test.validateUserId(t, r, "svc6", uid)
test.serviceUpdate(t, r, "svc6", "--user", strconv.FormatInt(uid+1, 10))
test.validateUserId(t, r, "svc6", uid+1)
serviceCreateWithOptions(t, it, r, "svc6", "--user", strconv.FormatInt(uid, 10))
validateUserId(t, it, r, "svc6", uid)
serviceUpdate(t, it, r, "svc6", "--user", strconv.FormatInt(uid+1, 10))
validateUserId(t, it, r, "svc6", uid+1)
}
func (test *e2eTest) serviceCreateWithOptions(t *testing.T, r *KnRunResultCollector, serviceName string, options ...string) {
command := []string{"service", "create", serviceName, "--image", KnDefaultTestImage}
func serviceCreateWithOptions(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string, options ...string) {
command := []string{"service", "create", serviceName, "--image", test.KnDefaultTestImage}
command = append(command, options...)
out := test.kn.Run(command...)
assert.Check(t, util.ContainsAll(out.Stdout, "service", serviceName, "Creating", "namespace", test.kn.namespace, "Ready"))
out := it.Kn().Run(command...)
assert.Check(t, util.ContainsAll(out.Stdout, "service", serviceName, "Creating", "namespace", it.Kn().Namespace(), "Ready"))
r.AssertNoError(out)
}
func (test *e2eTest) validateServiceConcurrencyLimit(t *testing.T, r *KnRunResultCollector, serviceName, concurrencyLimit string) {
func validateServiceConcurrencyLimit(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName, concurrencyLimit string) {
jsonpath := "jsonpath={.items[0].spec.template.spec.containerConcurrency}"
out := test.kn.Run("service", "list", serviceName, "-o", jsonpath)
out := it.Kn().Run("service", "list", serviceName, "-o", jsonpath)
assert.Equal(t, out.Stdout, concurrencyLimit)
r.AssertNoError(out)
}
func (test *e2eTest) validateServiceConcurrencyTarget(t *testing.T, r *KnRunResultCollector, serviceName, concurrencyTarget string) {
func validateServiceConcurrencyTarget(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName, concurrencyTarget string) {
jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/target}"
out := test.kn.Run("service", "list", serviceName, "-o", jsonpath)
out := it.Kn().Run("service", "list", serviceName, "-o", jsonpath)
assert.Equal(t, out.Stdout, concurrencyTarget)
r.AssertNoError(out)
}
func (test *e2eTest) validateAutoscaleWindow(t *testing.T, r *KnRunResultCollector, serviceName, window string) {
func validateAutoscaleWindow(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName, window string) {
jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/window}"
out := test.kn.Run("service", "list", serviceName, "-o", jsonpath)
out := it.Kn().Run("service", "list", serviceName, "-o", jsonpath)
assert.Equal(t, out.Stdout, window)
r.AssertNoError(out)
}
func (test *e2eTest) validateServiceMinScale(t *testing.T, r *KnRunResultCollector, serviceName, minScale string) {
func validateServiceMinScale(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName, minScale string) {
jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/minScale}"
out := test.kn.Run("service", "list", serviceName, "-o", jsonpath)
out := it.Kn().Run("service", "list", serviceName, "-o", jsonpath)
assert.Equal(t, out.Stdout, minScale)
r.AssertNoError(out)
}
func (test *e2eTest) validateServiceMaxScale(t *testing.T, r *KnRunResultCollector, serviceName, maxScale string) {
func validateServiceMaxScale(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName, maxScale string) {
jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/maxScale}"
out := test.kn.Run("service", "list", serviceName, "-o", jsonpath)
out := it.Kn().Run("service", "list", serviceName, "-o", jsonpath)
assert.Equal(t, out.Stdout, maxScale)
r.AssertNoError(out)
}
func (test *e2eTest) validateServiceAnnotations(t *testing.T, r *KnRunResultCollector, serviceName string, annotations map[string]string) {
func validateServiceAnnotations(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string, annotations map[string]string) {
metadataAnnotationsJsonpathFormat := "jsonpath={.metadata.annotations.%s}"
templateAnnotationsJsonpathFormat := "jsonpath={.spec.template.metadata.annotations.%s}"
for k, v := range annotations {
out := test.kn.Run("service", "describe", serviceName, "-o", fmt.Sprintf(metadataAnnotationsJsonpathFormat, k))
out := it.Kn().Run("service", "describe", serviceName, "-o", fmt.Sprintf(metadataAnnotationsJsonpathFormat, k))
assert.Equal(t, v, out.Stdout)
r.AssertNoError(out)
out = test.kn.Run("service", "describe", serviceName, "-o", fmt.Sprintf(templateAnnotationsJsonpathFormat, k))
out = it.Kn().Run("service", "describe", serviceName, "-o", fmt.Sprintf(templateAnnotationsJsonpathFormat, k))
assert.Equal(t, v, out.Stdout)
r.AssertNoError(out)
}
}
func (test *e2eTest) validateContainerField(t *testing.T, r *KnRunResultCollector, serviceName, field, expected string) {
func validateContainerField(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName, field, expected string) {
jsonpath := fmt.Sprintf("jsonpath={.items[0].spec.template.spec.containers[0].%s}", field)
out := test.kn.Run("service", "list", serviceName, "-o", jsonpath)
out := it.Kn().Run("service", "list", serviceName, "-o", jsonpath)
assert.Equal(t, out.Stdout, expected)
r.AssertNoError(out)
}
func (test *e2eTest) validateUserId(t *testing.T, r *KnRunResultCollector, serviceName string, uid int64) {
out := test.kn.Run("service", "describe", serviceName, "-ojson")
func validateUserId(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string, uid int64) {
out := it.Kn().Run("service", "describe", serviceName, "-ojson")
data := json.NewDecoder(strings.NewReader(out.Stdout))
data.UseNumber()
var service servingv1.Service

View File

@ -23,110 +23,112 @@ import (
"testing"
"gotest.tools/assert"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
"knative.dev/serving/pkg/apis/serving"
)
func TestService(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
t.Log("create hello service, delete, and try to create duplicate and get service already exists error")
test.serviceCreate(t, r, "hello")
test.serviceCreatePrivate(t, r, "hello-private")
test.serviceCreateDuplicate(t, r, "hello-private")
serviceCreate(t, it, r, "hello")
serviceCreatePrivate(t, it, r, "hello-private")
serviceCreateDuplicate(t, it, r, "hello-private")
t.Log("return valid info about hello service with print flags")
test.serviceDescribeWithPrintFlags(t, r, "hello")
serviceDescribeWithPrintFlags(t, it, r, "hello")
t.Log("delete hello service repeatedly and get an error")
test.serviceDelete(t, r, "hello")
test.serviceDeleteNonexistent(t, r, "hello")
serviceDelete(t, it, r, "hello")
serviceDeleteNonexistent(t, it, r, "hello")
t.Log("delete two services with a service nonexistent")
test.serviceCreate(t, r, "hello")
test.serviceMultipleDelete(t, r, "hello", "bla123")
serviceCreate(t, it, r, "hello")
serviceMultipleDelete(t, it, r, "hello", "bla123")
t.Log("create service private and make public")
test.serviceCreatePrivateUpdatePublic(t, r, "hello-private-public")
serviceCreatePrivateUpdatePublic(t, it, r, "hello-private-public")
}
func (test *e2eTest) serviceCreatePrivate(t *testing.T, r *KnRunResultCollector, serviceName string) {
out := test.kn.Run("service", "create", serviceName,
"--image", KnDefaultTestImage, "--cluster-local")
func serviceCreatePrivate(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string) {
out := it.Kn().Run("service", "create", serviceName,
"--image", test.KnDefaultTestImage, "--cluster-local")
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "service", serviceName, "creating", "namespace", test.kn.namespace, "ready"))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "service", serviceName, "creating", "namespace", it.Kn().Namespace(), "ready"))
out = test.kn.Run("service", "describe", serviceName, "--verbose")
out = it.Kn().Run("service", "describe", serviceName, "--verbose")
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, serving.VisibilityLabelKey, serving.VisibilityClusterLocal))
}
func (test *e2eTest) serviceCreatePrivateUpdatePublic(t *testing.T, r *KnRunResultCollector, serviceName string) {
out := test.kn.Run("service", "create", serviceName,
"--image", KnDefaultTestImage, "--cluster-local")
func serviceCreatePrivateUpdatePublic(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string) {
out := it.Kn().Run("service", "create", serviceName,
"--image", test.KnDefaultTestImage, "--cluster-local")
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "service", serviceName, "creating", "namespace", test.kn.namespace, "ready"))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "service", serviceName, "creating", "namespace", it.Kn().Namespace(), "ready"))
out = test.kn.Run("service", "describe", serviceName, "--verbose")
out = it.Kn().Run("service", "describe", serviceName, "--verbose")
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, serving.VisibilityLabelKey, serving.VisibilityClusterLocal))
out = test.kn.Run("service", "update", serviceName,
"--image", KnDefaultTestImage, "--no-cluster-local")
out = it.Kn().Run("service", "update", serviceName,
"--image", test.KnDefaultTestImage, "--no-cluster-local")
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "service", serviceName, "updated", "namespace", test.kn.namespace, "ready"))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "service", serviceName, "updated", "namespace", it.Kn().Namespace(), "ready"))
out = test.kn.Run("service", "describe", serviceName, "--verbose")
out = it.Kn().Run("service", "describe", serviceName, "--verbose")
r.AssertNoError(out)
assert.Check(t, util.ContainsNone(out.Stdout, serving.VisibilityLabelKey, serving.VisibilityClusterLocal))
}
func (test *e2eTest) serviceCreateDuplicate(t *testing.T, r *KnRunResultCollector, serviceName string) {
out := test.kn.Run("service", "list", serviceName)
func serviceCreateDuplicate(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string) {
out := it.Kn().Run("service", "list", serviceName)
r.AssertNoError(out)
assert.Check(t, strings.Contains(out.Stdout, serviceName), "The service does not exist yet")
out = test.kn.Run("service", "create", serviceName, "--image", KnDefaultTestImage)
out = it.Kn().Run("service", "create", serviceName, "--image", test.KnDefaultTestImage)
r.AssertError(out)
assert.Check(t, util.ContainsAll(out.Stderr, "the service already exists"))
}
func (test *e2eTest) serviceDescribeWithPrintFlags(t *testing.T, r *KnRunResultCollector, serviceName string) {
out := test.kn.Run("service", "describe", serviceName, "-o=name")
func serviceDescribeWithPrintFlags(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string) {
out := it.Kn().Run("service", "describe", serviceName, "-o=name")
r.AssertNoError(out)
expectedName := fmt.Sprintf("service.serving.knative.dev/%s", serviceName)
assert.Equal(t, strings.TrimSpace(out.Stdout), expectedName)
}
func (test *e2eTest) serviceDeleteNonexistent(t *testing.T, r *KnRunResultCollector, serviceName string) {
out := test.kn.Run("service", "list", serviceName)
func serviceDeleteNonexistent(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string) {
out := it.Kn().Run("service", "list", serviceName)
r.AssertNoError(out)
assert.Check(t, !strings.Contains(out.Stdout, serviceName), "The service exists")
out = test.kn.Run("service", "delete", serviceName)
out = it.Kn().Run("service", "delete", serviceName)
r.AssertNoError(out)
assert.Check(t, util.ContainsAll(out.Stdout, "hello", "not found"), "Failed to get 'not found' error")
}
func (test *e2eTest) serviceMultipleDelete(t *testing.T, r *KnRunResultCollector, existService, nonexistService string) {
out := test.kn.Run("service", "list")
func serviceMultipleDelete(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, existService, nonexistService string) {
out := it.Kn().Run("service", "list")
r.AssertNoError(out)
assert.Check(t, strings.Contains(out.Stdout, existService), "The service ", existService, " does not exist (but is expected to exist)")
assert.Check(t, !strings.Contains(out.Stdout, nonexistService), "The service", nonexistService, " exists (but is supposed to be not)")
out = test.kn.Run("service", "delete", existService, nonexistService)
out = it.Kn().Run("service", "delete", existService, nonexistService)
r.AssertNoError(out)
expectedSuccess := fmt.Sprintf(`Service '%s' successfully deleted in namespace '%s'.`, existService, test.kn.namespace)
expectedSuccess := fmt.Sprintf(`Service '%s' successfully deleted in namespace '%s'.`, existService, it.Kn().Namespace())
expectedErr := fmt.Sprintf(`services.serving.knative.dev "%s" not found`, nonexistService)
assert.Check(t, strings.Contains(out.Stdout, expectedSuccess), "Failed to get 'successfully deleted' message")
assert.Check(t, strings.Contains(out.Stdout, expectedErr), "Failed to get 'not found' error")

View File

@ -22,6 +22,8 @@ import (
"testing"
"gotest.tools/assert"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
)
@ -57,13 +59,13 @@ func (tc *sinkprefixTestConfig) teardown() {
func TestSinkPrefixConfig(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
tc := sinkprefixTestConfig{}
@ -71,22 +73,22 @@ func TestSinkPrefixConfig(t *testing.T) {
defer tc.teardown()
t.Log("Creating a testservice")
test.serviceCreate(t, r, "testsvc0")
serviceCreate(t, it, r, "testsvc0")
t.Log("create Ping sources with a sink to hello:testsvc0")
test.pingSourceCreateWithConfig(t, r, "testpingsource0", "* * * * */1", "ping", "hello:testsvc0", tc.knConfigPath)
pingSourceCreateWithConfig(t, it, r, "testpingsource0", "* * * * */1", "ping", "hello:testsvc0", tc.knConfigPath)
jpSinkRefNameInSpec := "jsonpath={.spec.sink.ref.name}"
out, err := test.getResourceFieldsWithJSONPath("pingsource", "testpingsource0", jpSinkRefNameInSpec)
out, err := getResourceFieldsWithJSONPath(t, it, "pingsource", "testpingsource0", jpSinkRefNameInSpec)
assert.NilError(t, err)
assert.Equal(t, out, "testsvc0")
t.Log("delete Ping sources")
test.pingSourceDelete(t, r, "testpingsource0")
pingSourceDelete(t, it, r, "testpingsource0")
}
func (test *e2eTest) pingSourceCreateWithConfig(t *testing.T, r *KnRunResultCollector, sourceName string, schedule string, data string, sink string, config string) {
out := test.kn.Run("source", "ping", "create", sourceName,
func pingSourceCreateWithConfig(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, sourceName string, schedule string, data string, sink string, config string) {
out := it.Kn().Run("source", "ping", "create", sourceName,
"--schedule", schedule, "--data", data, "--sink", sink, "--config", config)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "ping", "source", sourceName, "created", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "ping", "source", sourceName, "created", "namespace", it.Kn().Namespace()))
r.AssertNoError(out)
}

View File

@ -25,6 +25,7 @@ import (
"github.com/pkg/errors"
"gotest.tools/assert"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
)
@ -37,117 +38,116 @@ const (
func TestSourceApiServer(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
err1 := test.tearDownForSourceApiServer()
err2 := test.Teardown()
err1 := tearDownForSourceApiServer(t, it)
err2 := it.Teardown()
assert.NilError(t, err1)
assert.NilError(t, err2)
}()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
test.setupForSourceApiServer(t)
test.serviceCreate(t, r, "testsvc0")
setupForSourceApiServer(t, it)
serviceCreate(t, it, r, "testsvc0")
t.Log("create apiserver sources with a sink to a service")
test.apiServerSourceCreate(t, r, "testapisource0", "Event:v1:true", "testsa", "svc:testsvc0")
test.apiServerSourceCreate(t, r, "testapisource1", "Event:v1", "testsa", "svc:testsvc0")
apiServerSourceCreate(t, it, r, "testapisource0", "Event:v1:true", "testsa", "svc:testsvc0")
apiServerSourceCreate(t, it, r, "testapisource1", "Event:v1", "testsa", "svc:testsvc0")
t.Log("list sources")
output := test.sourceList(t, r)
output := sourceList(t, it, r)
assert.Check(t, util.ContainsAll(output, "NAME", "TYPE", "RESOURCE", "SINK", "READY"))
assert.Check(t, util.ContainsAll(output, "testapisource0", "ApiServerSource", "apiserversources.sources.knative.dev", "svc:testsvc0"))
assert.Check(t, util.ContainsAll(output, "testapisource1", "ApiServerSource", "apiserversources.sources.knative.dev", "svc:testsvc0"))
t.Log("list sources in YAML format")
output = test.sourceList(t, r, "-oyaml")
output = sourceList(t, it, r, "-oyaml")
assert.Check(t, util.ContainsAll(output, "testapisource1", "ApiServerSource", "Service", "testsvc0"))
t.Log("delete apiserver sources")
test.apiServerSourceDelete(t, r, "testapisource0")
test.apiServerSourceDelete(t, r, "testapisource1")
apiServerSourceDelete(t, it, r, "testapisource0")
apiServerSourceDelete(t, it, r, "testapisource1")
t.Log("create apiserver source with a missing sink service")
test.apiServerSourceCreateMissingSink(t, r, "testapisource2", "Event:v1:true", "testsa", "svc:unknown")
apiServerSourceCreateMissingSink(t, it, r, "testapisource2", "Event:v1:true", "testsa", "svc:unknown")
t.Log("update apiserver source sink service")
test.apiServerSourceCreate(t, r, "testapisource3", "Event:v1:true", "testsa", "svc:testsvc0")
test.serviceCreate(t, r, "testsvc1")
test.apiServerSourceUpdateSink(t, r, "testapisource3", "svc:testsvc1")
apiServerSourceCreate(t, it, r, "testapisource3", "Event:v1:true", "testsa", "svc:testsvc0")
serviceCreate(t, it, r, "testsvc1")
apiServerSourceUpdateSink(t, it, r, "testapisource3", "svc:testsvc1")
jpSinkRefNameInSpec := "jsonpath={.spec.sink.ref.name}"
out, err := test.getResourceFieldsWithJSONPath("apiserversource.sources.knative.dev", "testapisource3", jpSinkRefNameInSpec)
out, err := getResourceFieldsWithJSONPath(t, it, "apiserversource.sources.knative.dev", "testapisource3", jpSinkRefNameInSpec)
assert.NilError(t, err)
assert.Equal(t, out, "testsvc1")
// TODO(navidshaikh): Verify the source's status with synchronous create/update
}
func (test *e2eTest) apiServerSourceCreate(t *testing.T, r *KnRunResultCollector, sourceName string, resources string, sa string, sink string) {
out := test.kn.Run("source", "apiserver", "create", sourceName, "--resource", resources, "--service-account", sa, "--sink", sink)
func apiServerSourceCreate(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, sourceName string, resources string, sa string, sink string) {
out := it.Kn().Run("source", "apiserver", "create", sourceName, "--resource", resources, "--service-account", sa, "--sink", sink)
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "apiserver", "source", sourceName, "created", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "apiserver", "source", sourceName, "created", "namespace", it.Kn().Namespace()))
}
func (test *e2eTest) apiServerSourceCreateMissingSink(t *testing.T, r *KnRunResultCollector, sourceName string, resources string, sa string, sink string) {
out := test.kn.Run("source", "apiserver", "create", sourceName, "--resource", resources, "--service-account", sa, "--sink", sink)
func apiServerSourceCreateMissingSink(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, sourceName string, resources string, sa string, sink string) {
out := it.Kn().Run("source", "apiserver", "create", sourceName, "--resource", resources, "--service-account", sa, "--sink", sink)
r.AssertError(out)
assert.Check(t, util.ContainsAll(out.Stderr, "services.serving.knative.dev", "not found"))
}
func (test *e2eTest) apiServerSourceDelete(t *testing.T, r *KnRunResultCollector, sourceName string) {
out := test.kn.Run("source", "apiserver", "delete", sourceName)
func apiServerSourceDelete(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, sourceName string) {
out := it.Kn().Run("source", "apiserver", "delete", sourceName)
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "apiserver", "source", sourceName, "deleted", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "apiserver", "source", sourceName, "deleted", "namespace", it.Kn().Namespace()))
}
func (test *e2eTest) setupForSourceApiServer(t *testing.T) {
_, err := kubectl{test.kn.namespace}.Run("create", "serviceaccount", testServiceAccount)
func setupForSourceApiServer(t *testing.T, it *test.KnTest) {
_, err := test.NewKubectl(it.Kn().Namespace()).Run("create", "serviceaccount", testServiceAccount)
assert.NilError(t, err)
_, err = kubectl{}.Run("create", "clusterrole", clusterRolePrefix+test.kn.namespace, "--verb=get,list,watch", "--resource=events,namespaces")
_, err = test.Kubectl{}.Run("create", "clusterrole", clusterRolePrefix+it.Kn().Namespace(), "--verb=get,list,watch", "--resource=events,namespaces")
assert.NilError(t, err)
_, err = kubectl{}.Run(
_, err = test.Kubectl{}.Run(
"create",
"clusterrolebinding",
clusterRoleBindingPrefix+test.kn.namespace,
"--clusterrole="+clusterRolePrefix+test.kn.namespace,
"--serviceaccount="+test.kn.namespace+":"+testServiceAccount)
clusterRoleBindingPrefix+it.Kn().Namespace(),
"--clusterrole="+clusterRolePrefix+it.Kn().Namespace(),
"--serviceaccount="+it.Kn().Namespace()+":"+testServiceAccount)
assert.NilError(t, err)
}
func (test *e2eTest) tearDownForSourceApiServer() error {
func tearDownForSourceApiServer(t *testing.T, it *test.KnTest) error {
saCmd := []string{"delete", "serviceaccount", testServiceAccount}
_, err := kubectl{test.kn.namespace}.Run(saCmd...)
_, err := test.NewKubectl(it.Kn().Namespace()).Run(saCmd...)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("Error executing '%s'", strings.Join(saCmd, " ")))
}
crCmd := []string{"delete", "clusterrole", clusterRolePrefix + test.kn.namespace}
_, err = kubectl{}.Run(crCmd...)
crCmd := []string{"delete", "clusterrole", clusterRolePrefix + it.Kn().Namespace()}
_, err = test.Kubectl{}.Run(crCmd...)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("Error executing '%s'", strings.Join(saCmd, " ")))
}
crbCmd := []string{"delete", "clusterrolebinding", clusterRoleBindingPrefix + test.kn.namespace}
_, err = kubectl{}.Run(crbCmd...)
crbCmd := []string{"delete", "clusterrolebinding", clusterRoleBindingPrefix + it.Kn().Namespace()}
_, err = test.Kubectl{}.Run(crbCmd...)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("Error executing '%s'", strings.Join(saCmd, " ")))
}
return nil
}
func (test *e2eTest) apiServerSourceUpdateSink(t *testing.T, r *KnRunResultCollector, sourceName string, sink string) {
out := test.kn.Run("source", "apiserver", "update", sourceName, "--sink", sink)
func apiServerSourceUpdateSink(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, sourceName string, sink string) {
out := it.Kn().Run("source", "apiserver", "update", sourceName, "--sink", sink)
r.AssertNoError(out)
assert.Check(t, util.ContainsAll(out.Stdout, sourceName, "updated", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAll(out.Stdout, sourceName, "updated", "namespace", it.Kn().Namespace()))
}
func (test *e2eTest) getResourceFieldsWithJSONPath(resource, name, jsonpath string) (string, error) {
out, err := kubectl{test.kn.namespace}.Run("get", resource, name, "-o", jsonpath, "-n", test.kn.namespace)
func getResourceFieldsWithJSONPath(t *testing.T, it *test.KnTest, resource, name, jsonpath string) (string, error) {
out, err := test.NewKubectl(it.Kn().Namespace()).Run("get", resource, name, "-o", jsonpath, "-n", it.Kn().Namespace())
if err != nil {
return "", err
}

View File

@ -21,52 +21,54 @@ import (
"testing"
"gotest.tools/assert"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
)
func TestSourceBinding(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
test.serviceCreate(t, r, "testsvc0")
serviceCreate(t, it, r, "testsvc0")
t.Log("create source binding")
test.sourceBindingCreate(t, r, "my-binding0", "Deployment:apps/v1:myapp", "svc:testsvc0")
sourceBindingCreate(t, it, r, "my-binding0", "Deployment:apps/v1:myapp", "svc:testsvc0")
t.Log("delete source binding")
test.sourceBindingDelete(t, r, "my-binding0")
sourceBindingDelete(t, it, r, "my-binding0")
t.Log("update source binding")
test.sourceBindingCreate(t, r, "my-binding1", "Deployment:apps/v1:myapp", "svc:testsvc0")
test.serviceCreate(t, r, "testsvc1")
test.sourceBindingUpdate(t, r, "my-binding1", "Deployment:apps/v1:myapp", "svc:testsvc1")
sourceBindingCreate(t, it, r, "my-binding1", "Deployment:apps/v1:myapp", "svc:testsvc0")
serviceCreate(t, it, r, "testsvc1")
sourceBindingUpdate(t, it, r, "my-binding1", "Deployment:apps/v1:myapp", "svc:testsvc1")
jpSinkRefNameInSpec := "jsonpath={.spec.sink.ref.name}"
out, err := test.getResourceFieldsWithJSONPath("sinkbindings.sources.knative.dev", "my-binding1", jpSinkRefNameInSpec)
out, err := getResourceFieldsWithJSONPath(t, it, "sinkbindings.sources.knative.dev", "my-binding1", jpSinkRefNameInSpec)
assert.NilError(t, err)
assert.Equal(t, out, "testsvc1")
}
func (test *e2eTest) sourceBindingCreate(t *testing.T, r *KnRunResultCollector, bindingName string, subject string, sink string) {
out := test.kn.Run("source", "binding", "create", bindingName, "--subject", subject, "--sink", sink)
func sourceBindingCreate(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, bindingName string, subject string, sink string) {
out := it.Kn().Run("source", "binding", "create", bindingName, "--subject", subject, "--sink", sink)
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "Sink", "binding", bindingName, "created", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "Sink", "binding", bindingName, "created", "namespace", it.Kn().Namespace()))
}
func (test *e2eTest) sourceBindingDelete(t *testing.T, r *KnRunResultCollector, bindingName string) {
out := test.kn.Run("source", "binding", "delete", bindingName)
func sourceBindingDelete(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, bindingName string) {
out := it.Kn().Run("source", "binding", "delete", bindingName)
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "Sink", "binding", bindingName, "deleted", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "Sink", "binding", bindingName, "deleted", "namespace", it.Kn().Namespace()))
}
func (test *e2eTest) sourceBindingUpdate(t *testing.T, r *KnRunResultCollector, bindingName string, subject string, sink string) {
out := test.kn.Run("source", "binding", "update", bindingName, "--subject", subject, "--sink", sink)
func sourceBindingUpdate(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, bindingName string, subject string, sink string) {
out := it.Kn().Run("source", "binding", "update", bindingName, "--subject", subject, "--sink", sink)
r.AssertNoError(out)
assert.Check(t, util.ContainsAll(out.Stdout, bindingName, "updated", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAll(out.Stdout, bindingName, "updated", "namespace", it.Kn().Namespace()))
}

View File

@ -22,59 +22,60 @@ import (
"gotest.tools/assert"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
)
func TestSourceListTypes(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
t.Log("List available source types")
output := test.sourceListTypes(t, r)
output := sourceListTypes(t, it, r)
assert.Check(t, util.ContainsAll(output, "TYPE", "NAME", "DESCRIPTION", "Ping", "ApiServer"))
t.Log("List available source types in YAML format")
output = test.sourceListTypes(t, r, "-oyaml")
output = sourceListTypes(t, it, r, "-oyaml")
assert.Check(t, util.ContainsAll(output, "apiextensions.k8s.io/v1beta1", "CustomResourceDefinition", "Ping", "ApiServer"))
}
func TestSourceList(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
t.Log("List sources empty case")
output := test.sourceList(t, r)
output := sourceList(t, it, r)
assert.Check(t, util.ContainsAll(output, "No", "sources", "found", "namespace"))
assert.Check(t, util.ContainsNone(output, "NAME", "TYPE", "RESOURCE", "SINK", "READY"))
// non empty list case is tested in test/e2e/source_apiserver_test.go where source setup is present
// non empty list case is tested in test/e2e/source_apiserver_it.go where source setup is present
}
func (test *e2eTest) sourceListTypes(t *testing.T, r *KnRunResultCollector, args ...string) string {
func sourceListTypes(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, args ...string) string {
cmd := append([]string{"source", "list-types"}, args...)
out := test.kn.Run(cmd...)
out := it.Kn().Run(cmd...)
r.AssertNoError(out)
return out.Stdout
}
func (test *e2eTest) sourceList(t *testing.T, r *KnRunResultCollector, args ...string) string {
func sourceList(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, args ...string) string {
cmd := append([]string{"source", "list"}, args...)
out := test.kn.Run(cmd...)
out := it.Kn().Run(cmd...)
r.AssertNoError(out)
return out.Stdout
}

View File

@ -23,6 +23,8 @@ import (
"gotest.tools/assert"
"k8s.io/apimachinery/pkg/util/wait"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
)
@ -34,19 +36,19 @@ const (
)
func TestTektonPipeline(t *testing.T) {
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
kubectl := kubectl{test.namespace}
basedir := currentDir(t) + "/../resources/tekton"
kubectl := test.NewKubectl(it.Namespace())
basedir := test.CurrentDir(t) + "/../resources/tekton"
// create secret for the kn-deployer-account service account
_, err = kubectl.Run("create", "-n", test.namespace, "secret",
_, err = kubectl.Run("create", "-n", it.Namespace(), "secret",
"generic", "container-registry",
"--from-file=.dockerconfigjson="+Flags.DockerConfigJSON,
"--from-file=.dockerconfigjson="+test.Flags.DockerConfigJSON,
"--type=kubernetes.io/dockerconfigjson")
assert.NilError(t, err)
@ -71,16 +73,16 @@ func TestTektonPipeline(t *testing.T) {
err = waitForPipelineSuccess(kubectl)
assert.NilError(t, err)
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
const serviceName = "hello"
out := test.kn.Run("service", "describe", serviceName)
out := it.Kn().Run("service", "describe", serviceName)
r.AssertNoError(out)
assert.Assert(t, util.ContainsAll(out.Stdout, serviceName, test.kn.namespace))
assert.Assert(t, util.ContainsAll(out.Stdout, serviceName, it.Kn().Namespace()))
assert.Assert(t, util.ContainsAll(out.Stdout, "Conditions", "ConfigurationsReady", "Ready", "RoutesReady"))
}
func waitForPipelineSuccess(k kubectl) error {
func waitForPipelineSuccess(k test.Kubectl) error {
return wait.PollImmediate(Interval, Timeout, func() (bool, error) {
out, err := k.Run("get", "pipelinerun", "-o=jsonpath='{.items[0].status.conditions[?(@.type==\"Succeeded\")].status}'")
return strings.Contains(out, "True"), err

View File

@ -24,6 +24,8 @@ import (
"testing"
"gotest.tools/assert"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
)
@ -59,7 +61,7 @@ func splitTargets(s, separator string, partsCount int) ([]string, error) {
// formatActualTargets takes the traffic targets string received after jsonpath operation and converts
// them into []TargetFields for comparison
func formatActualTargets(t *testing.T, actualTargets []string) (formattedTargets []TargetFields) {
func formatActualTargets(t *testing.T, it *test.KnTest, actualTargets []string) (formattedTargets []TargetFields) {
for _, each := range actualTargets {
each := strings.TrimSuffix(each, targetFieldsSeparator)
fields, err := splitTargets(each, targetFieldsSeparator, targetFieldsLength)
@ -76,324 +78,324 @@ func formatActualTargets(t *testing.T, actualTargets []string) (formattedTargets
// TestTrafficSplitSuite runs different e2e tests for service traffic splitting and verifies the traffic targets from service status
func TestTrafficSplit(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
serviceBase := "echo"
t.Run("50:50",
func(t *testing.T) {
t.Log("tag two revisions as v1 and v2 and give 50-50% share")
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
serviceName := getNextServiceName(serviceBase)
test.serviceCreate(t, r, serviceName)
serviceName := test.GetNextServiceName(serviceBase)
serviceCreate(t, it, r, serviceName)
rev1 := fmt.Sprintf("%s-rev-1", serviceName)
test.serviceUpdateWithOptions(t, r, serviceName, "--env", "TARGET=v1", "--revision-name", rev1)
serviceUpdateWithOptions(t, it, r, serviceName, "--env", "TARGET=v1", "--revision-name", rev1)
rev2 := fmt.Sprintf("%s-rev-2", serviceName)
test.serviceUpdateWithOptions(t, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
serviceUpdateWithOptions(t, it, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
tflags := []string{"--tag", fmt.Sprintf("%s=v1,%s=v2", rev1, rev2),
"--traffic", "v1=50,v2=50"}
test.serviceUpdateWithOptions(t, r, serviceName, tflags...)
serviceUpdateWithOptions(t, it, r, serviceName, tflags...)
// make ordered fields per tflags (tag, revision, percent, latest)
expectedTargets := []TargetFields{newTargetFields("v1", rev1, 50, false), newTargetFields("v2", rev2, 50, false)}
test.verifyTargets(t, r, serviceName, expectedTargets)
test.serviceDelete(t, r, serviceName)
verifyTargets(t, it, r, serviceName, expectedTargets)
serviceDelete(t, it, r, serviceName)
},
)
t.Run("20:80",
func(t *testing.T) {
t.Log("ramp/up down a revision to 20% adjusting other traffic to accommodate")
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
serviceName := getNextServiceName(serviceBase)
test.serviceCreate(t, r, serviceName)
serviceName := test.GetNextServiceName(serviceBase)
serviceCreate(t, it, r, serviceName)
rev1 := fmt.Sprintf("%s-rev-1", serviceName)
test.serviceUpdateWithOptions(t, r, serviceName, "--env", "TARGET=v1", "--revision-name", rev1)
serviceUpdateWithOptions(t, it, r, serviceName, "--env", "TARGET=v1", "--revision-name", rev1)
rev2 := fmt.Sprintf("%s-rev-2", serviceName)
test.serviceUpdateWithOptions(t, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
serviceUpdateWithOptions(t, it, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
test.serviceUpdateWithOptions(t, r, serviceName, "--traffic", fmt.Sprintf("%s=20,%s=80", rev1, rev2))
serviceUpdateWithOptions(t, it, r, serviceName, "--traffic", fmt.Sprintf("%s=20,%s=80", rev1, rev2))
expectedTargets := []TargetFields{newTargetFields("", rev1, 20, false), newTargetFields("", rev2, 80, false)}
test.verifyTargets(t, r, serviceName, expectedTargets)
test.serviceDelete(t, r, serviceName)
verifyTargets(t, it, r, serviceName, expectedTargets)
serviceDelete(t, it, r, serviceName)
},
)
t.Run("TagCandidate",
func(t *testing.T) {
t.Log("tag a revision as candidate, without otherwise changing any traffic split")
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
serviceName := getNextServiceName(serviceBase)
serviceName := test.GetNextServiceName(serviceBase)
rev1 := fmt.Sprintf("%s-rev-1", serviceName)
test.serviceCreateWithOptions(t, r, serviceName, "--revision-name", rev1)
serviceCreateWithOptions(t, it, r, serviceName, "--revision-name", rev1)
rev2 := fmt.Sprintf("%s-rev-2", serviceName)
test.serviceUpdateWithOptions(t, r, serviceName, "--env", "TARGET=v1", "--revision-name", rev2)
serviceUpdateWithOptions(t, it, r, serviceName, "--env", "TARGET=v1", "--revision-name", rev2)
// no traffic, append new target with tag in traffic block
test.serviceUpdateWithOptions(t, r, serviceName, "--tag", fmt.Sprintf("%s=%s", rev1, "candidate"))
serviceUpdateWithOptions(t, it, r, serviceName, "--tag", fmt.Sprintf("%s=%s", rev1, "candidate"))
expectedTargets := []TargetFields{newTargetFields("", rev2, 100, true), newTargetFields("candidate", rev1, 0, false)}
test.verifyTargets(t, r, serviceName, expectedTargets)
test.serviceDelete(t, r, serviceName)
verifyTargets(t, it, r, serviceName, expectedTargets)
serviceDelete(t, it, r, serviceName)
},
)
t.Run("TagCandidate:2:98",
func(t *testing.T) {
t.Log("tag a revision as candidate, set 2% traffic adjusting other traffic to accommodate")
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
serviceName := getNextServiceName(serviceBase)
serviceName := test.GetNextServiceName(serviceBase)
rev1 := fmt.Sprintf("%s-rev-1", serviceName)
test.serviceCreateWithOptions(t, r, serviceName, "--revision-name", rev1)
serviceCreateWithOptions(t, it, r, serviceName, "--revision-name", rev1)
rev2 := fmt.Sprintf("%s-rev-2", serviceName)
test.serviceUpdateWithOptions(t, r, serviceName, "--env", "TARGET=v1", "--revision-name", rev2)
serviceUpdateWithOptions(t, it, r, serviceName, "--env", "TARGET=v1", "--revision-name", rev2)
// traffic by tag name and use % at the end
test.serviceUpdateWithOptions(t, r, serviceName,
serviceUpdateWithOptions(t, it, r, serviceName,
"--tag", fmt.Sprintf("%s=%s", rev1, "candidate"),
"--traffic", "candidate=2%,@latest=98%")
expectedTargets := []TargetFields{newTargetFields("", rev2, 98, true), newTargetFields("candidate", rev1, 2, false)}
test.verifyTargets(t, r, serviceName, expectedTargets)
test.serviceDelete(t, r, serviceName)
verifyTargets(t, it, r, serviceName, expectedTargets)
serviceDelete(t, it, r, serviceName)
},
)
t.Run("TagCurrent",
func(t *testing.T) {
t.Log("update tag for a revision from candidate to current, tag current is present on another revision")
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
serviceName := getNextServiceName(serviceBase)
serviceName := test.GetNextServiceName(serviceBase)
// make available 3 revisions for service first
rev1 := fmt.Sprintf("%s-rev-1", serviceName)
test.serviceCreateWithOptions(t, r, serviceName, "--revision-name", rev1)
serviceCreateWithOptions(t, it, r, serviceName, "--revision-name", rev1)
rev2 := fmt.Sprintf("%s-rev-2", serviceName)
test.serviceUpdateWithOptions(t, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
serviceUpdateWithOptions(t, it, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
rev3 := fmt.Sprintf("%s-rev-3", serviceName)
test.serviceUpdateWithOptions(t, r, serviceName, "--env", "TARGET=v3", "--revision-name", rev3) //note that this gives 100% traffic to latest revision (rev3)
serviceUpdateWithOptions(t, it, r, serviceName, "--env", "TARGET=v3", "--revision-name", rev3) //note that this gives 100% traffic to latest revision (rev3)
// make existing state: tag current and candidate exist in traffic block
test.serviceUpdateWithOptions(t, r, serviceName, "--tag", fmt.Sprintf("%s=current,%s=candidate", rev1, rev2))
serviceUpdateWithOptions(t, it, r, serviceName, "--tag", fmt.Sprintf("%s=current,%s=candidate", rev1, rev2))
// desired state of tags: update tag of revision (rev2) from candidate to current (which is present on rev1)
//untag first to update
test.serviceUpdateWithOptions(t, r, serviceName,
serviceUpdateWithOptions(t, it, r, serviceName,
"--untag", "current,candidate",
"--tag", fmt.Sprintf("%s=current", rev2))
// there will be 2 targets in existing block 1. @latest, 2.for revision $rev2
// target for rev1 is removed as it had no traffic and we untagged it's tag current
expectedTargets := []TargetFields{newTargetFields("", rev3, 100, true), newTargetFields("current", rev2, 0, false)}
test.verifyTargets(t, r, serviceName, expectedTargets)
test.serviceDelete(t, r, serviceName)
verifyTargets(t, it, r, serviceName, expectedTargets)
serviceDelete(t, it, r, serviceName)
},
)
t.Run("TagStagingLatest",
func(t *testing.T) {
t.Log("update tag from testing to staging for @latest revision")
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
serviceName := getNextServiceName(serviceBase)
serviceName := test.GetNextServiceName(serviceBase)
rev1 := fmt.Sprintf("%s-rev-1", serviceName)
test.serviceCreateWithOptions(t, r, serviceName, "--revision-name", rev1)
serviceCreateWithOptions(t, it, r, serviceName, "--revision-name", rev1)
// make existing state: tag @latest as testing
test.serviceUpdateWithOptions(t, r, serviceName, "--tag", "@latest=testing")
serviceUpdateWithOptions(t, it, r, serviceName, "--tag", "@latest=testing")
// desired state: change tag from testing to staging
test.serviceUpdateWithOptions(t, r, serviceName, "--untag", "testing", "--tag", "@latest=staging")
serviceUpdateWithOptions(t, it, r, serviceName, "--untag", "testing", "--tag", "@latest=staging")
expectedTargets := []TargetFields{newTargetFields("staging", rev1, 100, true)}
test.verifyTargets(t, r, serviceName, expectedTargets)
test.serviceDelete(t, r, serviceName)
verifyTargets(t, it, r, serviceName, expectedTargets)
serviceDelete(t, it, r, serviceName)
},
)
t.Run("TagStagingNonLatest",
func(t *testing.T) {
t.Log("update tag from testing to staging for a revision (non @latest)")
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
serviceName := getNextServiceName(serviceBase)
serviceName := test.GetNextServiceName(serviceBase)
rev1 := fmt.Sprintf("%s-rev-1", serviceName)
test.serviceCreateWithOptions(t, r, serviceName, "--revision-name", rev1)
serviceCreateWithOptions(t, it, r, serviceName, "--revision-name", rev1)
rev2 := fmt.Sprintf("%s-rev-2", serviceName)
test.serviceUpdateWithOptions(t, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
serviceUpdateWithOptions(t, it, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
// make existing state: tag a revision as testing
test.serviceUpdateWithOptions(t, r, serviceName, "--tag", fmt.Sprintf("%s=testing", rev1))
serviceUpdateWithOptions(t, it, r, serviceName, "--tag", fmt.Sprintf("%s=testing", rev1))
// desired state: change tag from testing to staging
test.serviceUpdateWithOptions(t, r, serviceName, "--untag", "testing", "--tag", fmt.Sprintf("%s=staging", rev1))
serviceUpdateWithOptions(t, it, r, serviceName, "--untag", "testing", "--tag", fmt.Sprintf("%s=staging", rev1))
expectedTargets := []TargetFields{newTargetFields("", rev2, 100, true),
newTargetFields("staging", rev1, 0, false)}
test.verifyTargets(t, r, serviceName, expectedTargets)
test.serviceDelete(t, r, serviceName)
verifyTargets(t, it, r, serviceName, expectedTargets)
serviceDelete(t, it, r, serviceName)
},
)
// test reducing number of targets from traffic blockdd
t.Run("RemoveTag",
func(t *testing.T) {
t.Log("remove a revision with tag old from traffic block entirely")
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
serviceName := getNextServiceName(serviceBase)
serviceName := test.GetNextServiceName(serviceBase)
rev1 := fmt.Sprintf("%s-rev-1", serviceName)
test.serviceCreateWithOptions(t, r, serviceName, "--revision-name", rev1)
serviceCreateWithOptions(t, it, r, serviceName, "--revision-name", rev1)
rev2 := fmt.Sprintf("%s-rev-2", serviceName)
test.serviceUpdateWithOptions(t, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
serviceUpdateWithOptions(t, it, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
// existing state: traffic block having a revision with tag old and some traffic
test.serviceUpdateWithOptions(t, r, serviceName,
serviceUpdateWithOptions(t, it, r, serviceName,
"--tag", fmt.Sprintf("%s=old", rev1),
"--traffic", "old=2,@latest=98")
// desired state: remove revision with tag old
test.serviceUpdateWithOptions(t, r, serviceName, "--untag", "old", "--traffic", "@latest=100")
serviceUpdateWithOptions(t, it, r, serviceName, "--untag", "old", "--traffic", "@latest=100")
expectedTargets := []TargetFields{newTargetFields("", rev2, 100, true)}
test.verifyTargets(t, r, serviceName, expectedTargets)
test.serviceDelete(t, r, serviceName)
verifyTargets(t, it, r, serviceName, expectedTargets)
serviceDelete(t, it, r, serviceName)
},
)
t.Run("TagStable:50:50",
func(t *testing.T) {
t.Log("tag a revision as stable and current with 50-50% traffic")
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
serviceName := getNextServiceName(serviceBase)
serviceName := test.GetNextServiceName(serviceBase)
rev1 := fmt.Sprintf("%s-rev-1", serviceName)
test.serviceCreateWithOptions(t, r, serviceName, "--revision-name", rev1)
serviceCreateWithOptions(t, it, r, serviceName, "--revision-name", rev1)
// existing state: traffic block having two targets
test.serviceUpdateWithOptions(t, r, serviceName, "--env", "TARGET=v2")
serviceUpdateWithOptions(t, it, r, serviceName, "--env", "TARGET=v2")
// desired state: tag non-@latest revision with two tags and 50-50% traffic each
test.serviceUpdateWithOptions(t, r, serviceName,
serviceUpdateWithOptions(t, it, r, serviceName,
"--tag", fmt.Sprintf("%s=stable,%s=current", rev1, rev1),
"--traffic", "stable=50%,current=50%")
expectedTargets := []TargetFields{newTargetFields("stable", rev1, 50, false), newTargetFields("current", rev1, 50, false)}
test.verifyTargets(t, r, serviceName, expectedTargets)
test.serviceDelete(t, r, serviceName)
verifyTargets(t, it, r, serviceName, expectedTargets)
serviceDelete(t, it, r, serviceName)
},
)
t.Run("RevertToLatest",
func(t *testing.T) {
t.Log("revert all traffic to latest ready revision of service")
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
serviceName := getNextServiceName(serviceBase)
serviceName := test.GetNextServiceName(serviceBase)
rev1 := fmt.Sprintf("%s-rev-1", serviceName)
test.serviceCreateWithOptions(t, r, serviceName, "--revision-name", rev1)
serviceCreateWithOptions(t, it, r, serviceName, "--revision-name", rev1)
rev2 := fmt.Sprintf("%s-rev-2", serviceName)
test.serviceUpdateWithOptions(t, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
serviceUpdateWithOptions(t, it, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
// existing state: latest ready revision not getting any traffic
test.serviceUpdateWithOptions(t, r, serviceName, "--traffic", fmt.Sprintf("%s=100", rev1))
serviceUpdateWithOptions(t, it, r, serviceName, "--traffic", fmt.Sprintf("%s=100", rev1))
// desired state: revert traffic to latest ready revision
test.serviceUpdateWithOptions(t, r, serviceName, "--traffic", "@latest=100")
serviceUpdateWithOptions(t, it, r, serviceName, "--traffic", "@latest=100")
expectedTargets := []TargetFields{newTargetFields("", rev2, 100, true)}
test.verifyTargets(t, r, serviceName, expectedTargets)
test.serviceDelete(t, r, serviceName)
verifyTargets(t, it, r, serviceName, expectedTargets)
serviceDelete(t, it, r, serviceName)
},
)
t.Run("TagLatestAsCurrent",
func(t *testing.T) {
t.Log("tag latest ready revision of service as current")
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
serviceName := getNextServiceName(serviceBase)
serviceName := test.GetNextServiceName(serviceBase)
// existing state: latest revision has no tag
rev1 := fmt.Sprintf("%s-rev-1", serviceName)
test.serviceCreateWithOptions(t, r, serviceName, "--revision-name", rev1)
serviceCreateWithOptions(t, it, r, serviceName, "--revision-name", rev1)
// desired state: tag latest ready revision as 'current'
test.serviceUpdateWithOptions(t, r, serviceName, "--tag", "@latest=current")
serviceUpdateWithOptions(t, it, r, serviceName, "--tag", "@latest=current")
expectedTargets := []TargetFields{newTargetFields("current", rev1, 100, true)}
test.verifyTargets(t, r, serviceName, expectedTargets)
test.serviceDelete(t, r, serviceName)
verifyTargets(t, it, r, serviceName, expectedTargets)
serviceDelete(t, it, r, serviceName)
},
)
t.Run("UpdateTag:100:0",
func(t *testing.T) {
t.Log("update tag for a revision as testing and assign all the traffic to it")
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
serviceName := getNextServiceName(serviceBase)
serviceName := test.GetNextServiceName(serviceBase)
rev1 := fmt.Sprintf("%s-rev-1", serviceName)
test.serviceCreateWithOptions(t, r, serviceName, "--revision-name", rev1)
serviceCreateWithOptions(t, it, r, serviceName, "--revision-name", rev1)
rev2 := fmt.Sprintf("%s-rev-2", serviceName)
test.serviceUpdateWithOptions(t, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
serviceUpdateWithOptions(t, it, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
// existing state: two revision exists with traffic share and
// each revision has tag and traffic portions
test.serviceUpdateWithOptions(t, r, serviceName,
serviceUpdateWithOptions(t, it, r, serviceName,
"--tag", fmt.Sprintf("@latest=current,%s=candidate", rev1),
"--traffic", "current=90,candidate=10")
// desired state: update tag for rev1 as testing (from candidate) with 100% traffic
test.serviceUpdateWithOptions(t, r, serviceName,
serviceUpdateWithOptions(t, it, r, serviceName,
"--untag", "candidate", "--tag", fmt.Sprintf("%s=testing", rev1),
"--traffic", "testing=100")
expectedTargets := []TargetFields{newTargetFields("current", rev2, 0, true),
newTargetFields("testing", rev1, 100, false)}
test.verifyTargets(t, r, serviceName, expectedTargets)
test.serviceDelete(t, r, serviceName)
verifyTargets(t, it, r, serviceName, expectedTargets)
serviceDelete(t, it, r, serviceName)
},
)
t.Run("TagReplace",
func(t *testing.T) {
t.Log("replace latest tag of a revision with old and give latest to another revision")
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
serviceName := getNextServiceName(serviceBase)
serviceName := test.GetNextServiceName(serviceBase)
rev1 := fmt.Sprintf("%s-rev-1", serviceName)
test.serviceCreateWithOptions(t, r, serviceName, "--revision-name", rev1)
serviceCreateWithOptions(t, it, r, serviceName, "--revision-name", rev1)
rev2 := fmt.Sprintf("%s-rev-2", serviceName)
test.serviceUpdateWithOptions(t, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
serviceUpdateWithOptions(t, it, r, serviceName, "--env", "TARGET=v2", "--revision-name", rev2)
// existing state: a revision exist with latest tag
test.serviceUpdateWithOptions(t, r, serviceName, "--tag", fmt.Sprintf("%s=latest", rev1))
serviceUpdateWithOptions(t, it, r, serviceName, "--tag", fmt.Sprintf("%s=latest", rev1))
// desired state of revision tags: rev1=old rev2=latest
test.serviceUpdateWithOptions(t, r, serviceName,
serviceUpdateWithOptions(t, it, r, serviceName,
"--untag", "latest",
"--tag", fmt.Sprintf("%s=old,%s=latest", rev1, rev2))
@ -404,34 +406,34 @@ func TestTrafficSplit(t *testing.T) {
// In spec of traffic block (not status) either latestReadyRevision:true or revisionName can be given per target
newTargetFields("latest", rev2, 0, false)}
test.verifyTargets(t, r, serviceName, expectedTargets)
test.serviceDelete(t, r, serviceName)
verifyTargets(t, it, r, serviceName, expectedTargets)
serviceDelete(t, it, r, serviceName)
},
)
}
func (test *e2eTest) verifyTargets(t *testing.T, r *KnRunResultCollector, serviceName string, expectedTargets []TargetFields) {
out := test.serviceDescribeWithJsonPath(r, serviceName, targetsJsonPath)
func verifyTargets(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string, expectedTargets []TargetFields) {
out := serviceDescribeWithJsonPath(t, it, r, serviceName, targetsJsonPath)
assert.Check(t, out != "")
actualTargets, err := splitTargets(out, targetsSeparator, len(expectedTargets))
assert.NilError(t, err)
formattedActualTargets := formatActualTargets(t, actualTargets)
formattedActualTargets := formatActualTargets(t, it, actualTargets)
assert.DeepEqual(t, expectedTargets, formattedActualTargets)
if t.Failed() {
r.AddDump("service", serviceName, test.namespace)
r.AddDump("service", serviceName, it.Kn().Namespace())
}
}
func (test *e2eTest) serviceDescribeWithJsonPath(r *KnRunResultCollector, serviceName, jsonpath string) string {
out := test.kn.Run("service", "describe", serviceName, "-o", jsonpath)
func serviceDescribeWithJsonPath(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName, jsonpath string) string {
out := it.Kn().Run("service", "describe", serviceName, "-o", jsonpath)
r.AssertNoError(out)
return out.Stdout
}
func (test *e2eTest) serviceUpdateWithOptions(t *testing.T, r *KnRunResultCollector, serviceName string, options ...string) {
func serviceUpdateWithOptions(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName string, options ...string) {
command := []string{"service", "update", serviceName}
command = append(command, options...)
out := test.kn.Run(command...)
out := it.Kn().Run(command...)
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "Service", serviceName, "updating", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "Service", serviceName, "updating", "namespace", it.Kn().Namespace()))
}

View File

@ -21,45 +21,47 @@ import (
"testing"
"gotest.tools/assert"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
)
func TestInjectBrokerTrigger(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
assert.NilError(t, err)
test.serviceCreate(t, r, "sinksvc0")
test.serviceCreate(t, r, "sinksvc1")
serviceCreate(t, it, r, "sinksvc0")
serviceCreate(t, it, r, "sinksvc1")
t.Log("create triggers and list them")
test.triggerCreateWithInject(t, r, "trigger1", "sinksvc0", []string{"a=b"})
test.triggerCreateWithInject(t, r, "trigger2", "sinksvc1", []string{"type=knative.dev.bar", "source=ping"})
test.verifyTriggerList(t, r, "trigger1", "trigger2")
test.triggerDelete(t, r, "trigger1")
test.triggerDelete(t, r, "trigger2")
triggerCreateWithInject(t, it, r, "trigger1", "sinksvc0", []string{"a=b"})
triggerCreateWithInject(t, it, r, "trigger2", "sinksvc1", []string{"type=knative.dev.bar", "source=ping"})
verifyTriggerList(t, it, r, "trigger1", "trigger2")
triggerDelete(t, it, r, "trigger1")
triggerDelete(t, it, r, "trigger2")
t.Log("create trigger with error")
out := test.kn.Run("trigger", "create", "errorTrigger", "--broker", "mybroker", "--inject-broker",
out := it.Kn().Run("trigger", "create", "errorTrigger", "--broker", "mybroker", "--inject-broker",
"--sink", "svc:sinksvc0", "--filter", "a=b")
r.AssertError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stderr, "broker", "name", "'default'", "--inject-broker", "flag"))
}
func (test *e2eTest) triggerCreateWithInject(t *testing.T, r *KnRunResultCollector, name string, sinksvc string, filters []string) {
func triggerCreateWithInject(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, name string, sinksvc string, filters []string) {
args := []string{"trigger", "create", name, "--broker", "default", "--inject-broker", "--sink", "svc:" + sinksvc}
for _, v := range filters {
args = append(args, "--filter", v)
}
out := test.kn.Run(args...)
out := it.Kn().Run(args...)
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "Trigger", name, "created", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "Trigger", name, "created", "namespace", it.Kn().Namespace()))
}

View File

@ -24,74 +24,79 @@ import (
"gotest.tools/assert"
"k8s.io/apimachinery/pkg/util/wait"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
)
func TestBrokerTrigger(t *testing.T) {
t.Parallel()
test, err := NewE2eTest()
it, err := test.NewKnTest()
assert.NilError(t, err)
defer func() {
assert.NilError(t, test.Teardown())
assert.NilError(t, it.Teardown())
}()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
err = test.labelNamespaceForDefaultBroker(t)
err = lableNamespaceForDefaultBroker(t, it)
assert.NilError(t, err)
defer test.unlabelNamespaceForDefaultBroker(t)
defer unlableNamespaceForDefaultBroker(t, it)
test.serviceCreate(t, r, "sinksvc0")
test.serviceCreate(t, r, "sinksvc1")
serviceCreate(t, it, r, "sinksvc0")
serviceCreate(t, it, r, "sinksvc1")
t.Log("create triggers and list them")
test.triggerCreate(t, r, "trigger1", "sinksvc0", nil)
test.triggerCreate(t, r, "trigger2", "sinksvc1", []string{"type=knative.dev.bar", "source=ping"})
test.verifyTriggerList(t, r, "trigger1", "trigger2")
test.triggerDelete(t, r, "trigger1")
test.triggerDelete(t, r, "trigger2")
triggerCreate(t, it, r, "trigger1", "sinksvc0", []string{"a=b"})
triggerCreate(t, it, r, "trigger2", "sinksvc1", []string{"type=knative.dev.bar", "source=ping"})
verifyTriggerList(t, it, r, "trigger1", "trigger2")
triggerDelete(t, it, r, "trigger1")
triggerDelete(t, it, r, "trigger2")
t.Log("create a trigger and delete it")
test.triggerCreate(t, r, "deltrigger", "sinksvc0", []string{"a=b"})
test.triggerDelete(t, r, "deltrigger")
test.verifyTriggerNotfound(t, r, "deltrigger")
triggerCreate(t, it, r, "deltrigger", "sinksvc0", []string{"a=b"})
triggerDelete(t, it, r, "deltrigger")
verifyTriggerNotfound(t, it, r, "deltrigger")
t.Log("create a trigger with filters and remove them one by one")
test.triggerCreate(t, r, "filtertrigger", "sinksvc0", []string{"foo=bar", "source=ping"})
test.verifyTriggerDescribe(t, r, "filtertrigger", "default", "sinksvc0", []string{"foo", "bar", "source", "ping"})
test.triggerUpdate(t, r, "filtertrigger", "foo-", "sinksvc0")
test.verifyTriggerDescribe(t, r, "filtertrigger", "default", "sinksvc0", []string{"source", "ping"})
test.triggerUpdate(t, r, "filtertrigger", "source-", "sinksvc0")
test.verifyTriggerDescribe(t, r, "filtertrigger", "default", "sinksvc0", nil)
test.triggerDelete(t, r, "filtertrigger")
triggerCreate(t, it, r, "filtertrigger", "sinksvc0", []string{"foo=bar", "source=ping"})
verifyTriggerDescribe(t, it, r, "filtertrigger", "default", "sinksvc0", []string{"foo", "bar", "source", "ping"})
triggerUpdate(t, it, r, "filtertrigger", "foo-", "sinksvc0")
verifyTriggerDescribe(t, it, r, "filtertrigger", "default", "sinksvc0", []string{"source", "ping"})
triggerUpdate(t, it, r, "filtertrigger", "source-", "sinksvc0")
verifyTriggerDescribe(t, it, r, "filtertrigger", "default", "sinksvc0", nil)
triggerDelete(t, it, r, "filtertrigger")
t.Log("create a trigger, describe and update it")
test.triggerCreate(t, r, "updtrigger", "sinksvc0", []string{"a=b"})
test.verifyTriggerDescribe(t, r, "updtrigger", "default", "sinksvc0", []string{"a", "b"})
test.triggerUpdate(t, r, "updtrigger", "type=knative.dev.bar", "sinksvc1")
test.verifyTriggerDescribe(t, r, "updtrigger", "default", "sinksvc1", []string{"a", "b", "type", "knative.dev.bar"})
test.triggerDelete(t, r, "updtrigger")
triggerCreate(t, it, r, "updtrigger", "sinksvc0", []string{"a=b"})
verifyTriggerDescribe(t, it, r, "updtrigger", "default", "sinksvc0", []string{"a", "b"})
triggerUpdate(t, it, r, "updtrigger", "type=knative.dev.bar", "sinksvc1")
verifyTriggerDescribe(t, it, r, "updtrigger", "default", "sinksvc1", []string{"a", "b", "type", "knative.dev.bar"})
triggerDelete(t, it, r, "updtrigger")
t.Log("create trigger with error return")
test.triggerCreateMissingSink(t, r, "errtrigger", "notfound")
triggerCreateMissingSink(t, it, r, "errtrigger", "notfound")
}
func (test *e2eTest) unlabelNamespaceForDefaultBroker(t *testing.T) {
_, err := kubectl{}.Run("label", "namespace", test.kn.namespace, "knative-eventing-injection-")
// Private functions
func unlableNamespaceForDefaultBroker(t *testing.T, it *test.KnTest) {
_, err := test.Kubectl{}.Run("label", "namespace", it.Kn().Namespace(), "knative-eventing-injection-")
if err != nil {
t.Fatalf("Error executing 'kubectl label namespace %s knative-eventing-injection-'. Error: %s", test.kn.namespace, err.Error())
t.Fatalf("Error executing 'kubectl label namespace %s knative-eventing-injection-'. Error: %s", it.Kn().Namespace(), err.Error())
}
}
func (test *e2eTest) labelNamespaceForDefaultBroker(t *testing.T) error {
_, err := kubectl{}.Run("label", "namespace", test.kn.namespace, "knative-eventing-injection=enabled")
func lableNamespaceForDefaultBroker(t *testing.T, it *test.KnTest) error {
_, err := test.Kubectl{}.Run("label", "namespace", it.Kn().Namespace(), "knative-eventing-injection=enabled")
if err != nil {
t.Fatalf("Error executing 'kubectl label namespace %s knative-eventing-injection=enabled'. Error: %s", test.kn.namespace, err.Error())
t.Fatalf("Error executing 'kubectl label namespace %s knative-eventing-injection=enabled'. Error: %s", it.Kn().Namespace(), err.Error())
}
return wait.PollImmediate(10*time.Second, 5*time.Minute, func() (bool, error) {
out, err := kubectl{test.kn.namespace}.Run("get", "broker", "-o=jsonpath='{.items[0].status.conditions[?(@.type==\"Ready\")].status}'")
out, err := test.NewKubectl(it.Kn().Namespace()).Run("get", "broker", "-o=jsonpath='{.items[0].status.conditions[?(@.type==\"Ready\")].status}'")
if err != nil {
return false, nil
} else {
@ -100,44 +105,44 @@ func (test *e2eTest) labelNamespaceForDefaultBroker(t *testing.T) error {
})
}
func (test *e2eTest) triggerCreate(t *testing.T, r *KnRunResultCollector, name string, sinksvc string, filters []string) {
func triggerCreate(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, name string, sinksvc string, filters []string) {
args := []string{"trigger", "create", name, "--broker", "default", "--sink", "svc:" + sinksvc}
if len(filters) > 0 {
for _, v := range filters {
args = append(args, "--filter", v)
}
}
out := test.kn.Run(args...)
out := it.Kn().Run(args...)
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "Trigger", name, "created", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "Trigger", name, "created", "namespace", it.Kn().Namespace()))
}
func (test *e2eTest) triggerCreateMissingSink(t *testing.T, r *KnRunResultCollector, name string, sinksvc string) {
out := test.kn.Run("trigger", "create", name, "--broker", "default", "--sink", "svc:"+sinksvc)
func triggerCreateMissingSink(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, name string, sinksvc string) {
out := it.Kn().Run("trigger", "create", name, "--broker", "default", "--sink", "svc:"+sinksvc)
r.AssertError(out)
assert.Check(t, util.ContainsAll(out.Stderr, "services.serving.knative.dev", "not found"))
}
func (test *e2eTest) triggerDelete(t *testing.T, r *KnRunResultCollector, name string) {
out := test.kn.Run("trigger", "delete", name)
func triggerDelete(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, name string) {
out := it.Kn().Run("trigger", "delete", name)
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "Trigger", name, "deleted", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "Trigger", name, "deleted", "namespace", it.Kn().Namespace()))
}
func (test *e2eTest) triggerUpdate(t *testing.T, r *KnRunResultCollector, name string, filter string, sinksvc string) {
out := test.kn.Run("trigger", "update", name, "--filter", filter, "--sink", "svc:"+sinksvc)
func triggerUpdate(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, name string, filter string, sinksvc string) {
out := it.Kn().Run("trigger", "update", name, "--filter", filter, "--sink", "svc:"+sinksvc)
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "Trigger", name, "updated", "namespace", test.kn.namespace))
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "Trigger", name, "updated", "namespace", it.Kn().Namespace()))
}
func (test *e2eTest) verifyTriggerList(t *testing.T, r *KnRunResultCollector, triggers ...string) {
out := test.kn.Run("trigger", "list")
func verifyTriggerList(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, triggers ...string) {
out := it.Kn().Run("trigger", "list")
r.AssertNoError(out)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, triggers...))
}
func (test *e2eTest) verifyTriggerDescribe(t *testing.T, r *KnRunResultCollector, name string, broker string, sink string, filters []string) {
out := test.kn.Run("trigger", "describe", name)
func verifyTriggerDescribe(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, name string, broker string, sink string, filters []string) {
out := it.Kn().Run("trigger", "describe", name)
r.AssertNoError(out)
if len(filters) > 0 {
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, filters...))
@ -147,8 +152,8 @@ func (test *e2eTest) verifyTriggerDescribe(t *testing.T, r *KnRunResultCollector
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, name, broker, sink))
}
func (test *e2eTest) verifyTriggerNotfound(t *testing.T, r *KnRunResultCollector, name string) {
out := test.kn.Run("trigger", "describe", name)
func verifyTriggerNotfound(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, name string) {
out := it.Kn().Run("trigger", "describe", name)
r.AssertError(out)
assert.Check(t, util.ContainsAll(out.Stderr, name, "not found"))
}

View File

@ -20,16 +20,18 @@ import (
"testing"
"gotest.tools/assert"
"knative.dev/client/lib/test"
"knative.dev/client/pkg/util"
)
func TestVersion(t *testing.T) {
t.Parallel()
r := NewKnRunResultCollector(t)
r := test.NewKnRunResultCollector(t)
defer r.DumpIfFailed()
out := kn{}.Run("version")
out := test.Kn{}.Run("version")
r.AssertNoError(out)
assert.Check(t, util.ContainsAll(out.Stdout, "Version"))
}