mirror of https://github.com/knative/client.git
add trigger list (#558)
This commit is contained in:
parent
8a9d8fcc94
commit
60b88017a9
|
|
@ -30,4 +30,5 @@ kn trigger [flags]
|
|||
* [kn trigger create](kn_trigger_create.md) - Create a trigger
|
||||
* [kn trigger delete](kn_trigger_delete.md) - Delete a trigger.
|
||||
* [kn trigger describe](kn_trigger_describe.md) - Describe a trigger.
|
||||
* [kn trigger list](kn_trigger_list.md) - List available triggers.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
## kn trigger list
|
||||
|
||||
List available triggers.
|
||||
|
||||
### Synopsis
|
||||
|
||||
List available triggers.
|
||||
|
||||
```
|
||||
kn trigger list [name] [flags]
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
|
||||
# List all triggers
|
||||
kn trigger list
|
||||
|
||||
# List all triggers in JSON output format
|
||||
kn trigger list -o json
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-A, --all-namespaces If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.
|
||||
--allow-missing-template-keys If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats. (default true)
|
||||
-h, --help help for list
|
||||
-n, --namespace string Specify the namespace to operate in.
|
||||
--no-headers When using the default output format, don't print headers (default: print headers).
|
||||
-o, --output string Output format. One of: json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-file.
|
||||
--template string Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string kn config file (default is $HOME/.kn/config.yaml)
|
||||
--kubeconfig string kubectl config file (default is $HOME/.kube/config)
|
||||
--log-http log http traffic
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [kn trigger](kn_trigger.md) - Trigger command group
|
||||
|
||||
|
|
@ -16,12 +16,18 @@ package v1alpha1
|
|||
|
||||
import (
|
||||
apis_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
kn_errors "knative.dev/client/pkg/errors"
|
||||
"knative.dev/client/pkg/util"
|
||||
"knative.dev/eventing/pkg/apis/eventing/v1alpha1"
|
||||
"knative.dev/eventing/pkg/client/clientset/versioned/scheme"
|
||||
client_v1alpha1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1alpha1"
|
||||
)
|
||||
|
||||
const (
|
||||
nameFieldKey = "metadata.name"
|
||||
)
|
||||
|
||||
// KnEventingClient to Eventing Sources. All methods are relative to the
|
||||
// namespace specified during construction
|
||||
type KnEventingClient interface {
|
||||
|
|
@ -33,6 +39,8 @@ type KnEventingClient interface {
|
|||
DeleteTrigger(name string) error
|
||||
// GetTrigger is used to get an instance of trigger
|
||||
GetTrigger(name string) (*v1alpha1.Trigger, error)
|
||||
// ListTrigger returns list of trigger CRDs
|
||||
ListTriggers() (*v1alpha1.TriggerList, error)
|
||||
}
|
||||
|
||||
// KnEventingClient is a combination of Sources client interface and namespace
|
||||
|
|
@ -78,7 +86,35 @@ func (c *knEventingClient) GetTrigger(name string) (*v1alpha1.Trigger, error) {
|
|||
return trigger, nil
|
||||
}
|
||||
|
||||
func (c *knEventingClient) ListTriggers() (*v1alpha1.TriggerList, error) {
|
||||
triggerList, err := c.client.Triggers(c.namespace).List(apis_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, kn_errors.GetError(err)
|
||||
}
|
||||
triggerListNew := triggerList.DeepCopy()
|
||||
err = updateTriggerGvk(triggerListNew)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
triggerListNew.Items = make([]v1alpha1.Trigger, len(triggerList.Items))
|
||||
for idx, trigger := range triggerList.Items {
|
||||
triggerClone := trigger.DeepCopy()
|
||||
err := updateTriggerGvk(triggerClone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
triggerListNew.Items[idx] = *triggerClone
|
||||
}
|
||||
return triggerListNew, nil
|
||||
}
|
||||
|
||||
// Return the client's namespace
|
||||
func (c *knEventingClient) Namespace() string {
|
||||
return c.namespace
|
||||
}
|
||||
|
||||
// update with the v1alpha1 group + version
|
||||
func updateTriggerGvk(obj runtime.Object) error {
|
||||
return util.UpdateGroupVersionKindWithScheme(obj, v1alpha1.SchemeGroupVersion, scheme.Scheme)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ func (sr *EventingRecorder) CreateTrigger(trigger interface{}, err error) {
|
|||
sr.r.Add("CreateTrigger", []interface{}{trigger}, []interface{}{trigger, err})
|
||||
}
|
||||
|
||||
// CreateTrigger performs a previously recorded action, failing if non has been registered
|
||||
// CreateTrigger performs a previously recorded action
|
||||
func (c *MockKnEventingClient) CreateTrigger(trigger *v1alpha1.Trigger) (*v1alpha1.Trigger, error) {
|
||||
call := c.recorder.r.VerifyCall("CreateTrigger", trigger)
|
||||
return call.Result[0].(*v1alpha1.Trigger), mock.ErrorOrNil(call.Result[1])
|
||||
|
|
@ -74,7 +74,7 @@ func (sr *EventingRecorder) GetTrigger(name interface{}, trigger *v1alpha1.Trigg
|
|||
sr.r.Add("GetTrigger", []interface{}{name}, []interface{}{trigger, err})
|
||||
}
|
||||
|
||||
// GetTrigger performs a previously recorded action, failing if non has been registered
|
||||
// GetTrigger performs a previously recorded action
|
||||
func (c *MockKnEventingClient) GetTrigger(name string) (*v1alpha1.Trigger, error) {
|
||||
call := c.recorder.r.VerifyCall("GetTrigger", name)
|
||||
return call.Result[0].(*v1alpha1.Trigger), mock.ErrorOrNil(call.Result[1])
|
||||
|
|
@ -91,6 +91,17 @@ func (c *MockKnEventingClient) DeleteTrigger(name string) error {
|
|||
return mock.ErrorOrNil(call.Result[0])
|
||||
}
|
||||
|
||||
// ListTriggers records a call for ListTriggers with the expected result and error (nil if none)
|
||||
func (sr *EventingRecorder) ListTriggers(triggerList *v1alpha1.TriggerList, err error) {
|
||||
sr.r.Add("ListTriggers", nil, []interface{}{triggerList, err})
|
||||
}
|
||||
|
||||
// ListTriggers performs a previously recorded action
|
||||
func (c *MockKnEventingClient) ListTriggers() (*v1alpha1.TriggerList, error) {
|
||||
call := c.recorder.r.VerifyCall("ListTriggers")
|
||||
return call.Result[0].(*v1alpha1.TriggerList), mock.ErrorOrNil(call.Result[1])
|
||||
}
|
||||
|
||||
// Validate validates whether every recorded action has been called
|
||||
func (sr *EventingRecorder) Validate() {
|
||||
sr.r.CheckThatAllRecordedMethodsHaveBeenCalled()
|
||||
|
|
|
|||
|
|
@ -30,11 +30,13 @@ func TestMockKnClient(t *testing.T) {
|
|||
recorder.GetTrigger("hello", nil, nil)
|
||||
recorder.CreateTrigger(&v1alpha1.Trigger{}, nil)
|
||||
recorder.DeleteTrigger("hello", nil)
|
||||
recorder.ListTriggers(nil, nil)
|
||||
|
||||
// Call all service
|
||||
client.GetTrigger("hello")
|
||||
client.CreateTrigger(&v1alpha1.Trigger{})
|
||||
client.DeleteTrigger("hello")
|
||||
client.ListTriggers()
|
||||
|
||||
// Validate
|
||||
recorder.Validate()
|
||||
|
|
|
|||
|
|
@ -107,6 +107,27 @@ func TestGetTrigger(t *testing.T) {
|
|||
assert.ErrorContains(t, err, "errorTrigger")
|
||||
}
|
||||
|
||||
func TestListTrigger(t *testing.T) {
|
||||
serving, client := setup()
|
||||
|
||||
t.Run("list trigger returns a list of triggers", func(t *testing.T) {
|
||||
trigger1 := newTrigger("trigger-1")
|
||||
trigger2 := newTrigger("trigger-2")
|
||||
|
||||
serving.AddReactor("list", "triggers",
|
||||
func(a client_testing.Action) (bool, runtime.Object, error) {
|
||||
assert.Equal(t, testNamespace, a.GetNamespace())
|
||||
return true, &v1alpha1.TriggerList{Items: []v1alpha1.Trigger{*trigger1, *trigger2}}, nil
|
||||
})
|
||||
|
||||
listTriggers, err := client.ListTriggers()
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, len(listTriggers.Items) == 2)
|
||||
assert.Equal(t, listTriggers.Items[0].Name, "trigger-1")
|
||||
assert.Equal(t, listTriggers.Items[1].Name, "trigger-2")
|
||||
})
|
||||
}
|
||||
|
||||
func newTrigger(name string) *v1alpha1.Trigger {
|
||||
obj := &v1alpha1.Trigger{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright © 2019 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 flags
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
"knative.dev/client/pkg/kn/commands"
|
||||
hprinters "knative.dev/client/pkg/printers"
|
||||
)
|
||||
|
||||
// ListFlags composes common printer flag structs
|
||||
// used in the list command.
|
||||
type ListFlags struct {
|
||||
GenericPrintFlags *genericclioptions.PrintFlags
|
||||
HumanReadableFlags *commands.HumanPrintFlags
|
||||
PrinterHandler func(h hprinters.PrintHandler)
|
||||
}
|
||||
|
||||
// AllowedFormats is the list of formats in which data can be displayed
|
||||
func (f *ListFlags) AllowedFormats() []string {
|
||||
formats := f.GenericPrintFlags.AllowedFormats()
|
||||
formats = append(formats, f.HumanReadableFlags.AllowedFormats()...)
|
||||
return formats
|
||||
}
|
||||
|
||||
// ToPrinter attempts to find a composed set of ListTypesFlags suitable for
|
||||
// returning a printer based on current flag values.
|
||||
func (f *ListFlags) ToPrinter() (hprinters.ResourcePrinter, error) {
|
||||
// if there are flags specified for generic printing
|
||||
if f.GenericPrintFlags.OutputFlagSpecified() {
|
||||
p, err := f.GenericPrintFlags.ToPrinter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
p, err := f.HumanReadableFlags.ToPrinter(f.PrinterHandler)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// AddFlags receives a *cobra.Command reference and binds
|
||||
// flags related to humanreadable and template printing.
|
||||
func (f *ListFlags) AddFlags(cmd *cobra.Command) {
|
||||
f.GenericPrintFlags.AddFlags(cmd)
|
||||
f.HumanReadableFlags.AddFlags(cmd)
|
||||
}
|
||||
|
||||
// NewListFlags returns flags associated with humanreadable,
|
||||
// template, and "name" printing, with default values set.
|
||||
func NewListFlags(printer func(h hprinters.PrintHandler)) *ListFlags {
|
||||
return &ListFlags{
|
||||
GenericPrintFlags: genericclioptions.NewPrintFlags(""),
|
||||
HumanReadableFlags: commands.NewHumanPrintFlags(),
|
||||
PrinterHandler: printer,
|
||||
}
|
||||
}
|
||||
|
||||
// EnsureWithNamespace ensures that humanreadable flags return
|
||||
// a printer capable of printing with a "namespace" column.
|
||||
func (f *ListFlags) EnsureWithNamespace() {
|
||||
f.HumanReadableFlags.EnsureWithNamespace()
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright © 2019 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 flags
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"gotest.tools/assert"
|
||||
hprinters "knative.dev/client/pkg/printers"
|
||||
)
|
||||
|
||||
func TestListFlagsFormats(t *testing.T) {
|
||||
flags := NewListFlags(nil)
|
||||
formats := flags.AllowedFormats()
|
||||
expected := []string{"json", "yaml", "name", "go-template", "go-template-file", "template", "templatefile", "jsonpath", "jsonpath-file", "no-headers"}
|
||||
assert.DeepEqual(t, formats, expected)
|
||||
}
|
||||
|
||||
func TestListFlags(t *testing.T) {
|
||||
var cmd *cobra.Command
|
||||
flags := NewListFlags(func(h hprinters.PrintHandler) {})
|
||||
|
||||
cmd = &cobra.Command{}
|
||||
flags.AddFlags(cmd)
|
||||
|
||||
assert.Assert(t, flags != nil)
|
||||
assert.Assert(t, cmd.Flags() != nil)
|
||||
|
||||
allowMissingTemplateKeys, err := cmd.Flags().GetBool("allow-missing-template-keys")
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, allowMissingTemplateKeys == true)
|
||||
|
||||
p, err := flags.ToPrinter()
|
||||
assert.NilError(t, err)
|
||||
_, ok := p.(hprinters.ResourcePrinter)
|
||||
assert.Check(t, ok == true)
|
||||
}
|
||||
|
|
@ -90,5 +90,6 @@ func NewAPIServerCreateCommand(p *commands.KnParams) *cobra.Command {
|
|||
updateFlags.Add(cmd)
|
||||
sinkFlags.Add(cmd)
|
||||
cmd.MarkFlagRequired("resource")
|
||||
cmd.MarkFlagRequired("sink")
|
||||
return cmd
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ func TestCreateApiServerSource(t *testing.T) {
|
|||
servingRecorder.Validate()
|
||||
}
|
||||
|
||||
func TestNoSinkError(t *testing.T) {
|
||||
func TestSinkNotFoundError(t *testing.T) {
|
||||
servingClient := knserving_client.NewMockKnServiceClient(t)
|
||||
apiServerClient := knsources_v1alpha1.NewMockKnAPIServerSourceClient(t)
|
||||
|
||||
|
|
@ -61,3 +61,9 @@ func TestNoSinkError(t *testing.T) {
|
|||
assert.Assert(t, util.ContainsAll(out, errorMsg, "Usage"))
|
||||
servingRecorder.Validate()
|
||||
}
|
||||
|
||||
func TestNoSinkError(t *testing.T) {
|
||||
apiServerClient := knsources_v1alpha1.NewMockKnAPIServerSourceClient(t)
|
||||
_, err := executeAPIServerSourceCommand(apiServerClient, nil, "create", "testsource", "--resource", "Event:v1:false", "--service-account", "testsa", "--mode", "Ref")
|
||||
assert.ErrorContains(t, err, "required flag(s)", "sink", "not set")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ func NewTriggerCreateCommand(p *commands.KnParams) *cobra.Command {
|
|||
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
if len(args) != 1 {
|
||||
return errors.New("'trigger create' requires the name of the trigger as single argument")
|
||||
return errors.New("'trigger create' requires the name of the trigger")
|
||||
}
|
||||
name := args[0]
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ func NewTriggerCreateCommand(p *commands.KnParams) *cobra.Command {
|
|||
commands.AddNamespaceFlags(cmd.Flags(), false)
|
||||
triggerUpdateFlags.Add(cmd)
|
||||
sinkFlags.Add(cmd)
|
||||
cmd.MarkFlagRequired("schedule")
|
||||
cmd.MarkFlagRequired("sink")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,13 +20,10 @@ import (
|
|||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
eventing_client "knative.dev/client/pkg/eventing/v1alpha1"
|
||||
knserving_client "knative.dev/client/pkg/serving/v1alpha1"
|
||||
"knative.dev/client/pkg/util"
|
||||
"knative.dev/eventing/pkg/apis/eventing/v1alpha1"
|
||||
duckv1 "knative.dev/pkg/apis/duck/v1"
|
||||
serving_v1alpha1 "knative.dev/serving/pkg/apis/serving/v1alpha1"
|
||||
)
|
||||
|
||||
|
|
@ -45,7 +42,7 @@ func TestTriggerCreate(t *testing.T) {
|
|||
}, nil)
|
||||
|
||||
eventingRecorder := eventingClient.Recorder()
|
||||
eventingRecorder.CreateTrigger(createTrigger(triggerName, map[string]string{"type": "dev.knative.foo"}, "mybroker", "mysvc"), nil)
|
||||
eventingRecorder.CreateTrigger(createTrigger("default", triggerName, map[string]string{"type": "dev.knative.foo"}, "mybroker", "mysvc"), nil)
|
||||
|
||||
out, err := executeTriggerCommand(eventingClient, servingClient, "create", triggerName, "--broker", "mybroker",
|
||||
"--filter", "type=dev.knative.foo", "--sink", "svc:mysvc")
|
||||
|
|
@ -56,7 +53,7 @@ func TestTriggerCreate(t *testing.T) {
|
|||
servingRecorder.Validate()
|
||||
}
|
||||
|
||||
func TestNoSinkError(t *testing.T) {
|
||||
func TestSinkNotFoundError(t *testing.T) {
|
||||
eventingClient := eventing_client.NewMockKnEventingClient(t)
|
||||
servingClient := knserving_client.NewMockKnServiceClient(t)
|
||||
|
||||
|
|
@ -71,6 +68,13 @@ func TestNoSinkError(t *testing.T) {
|
|||
servingRecorder.Validate()
|
||||
}
|
||||
|
||||
func TestNoSinkError(t *testing.T) {
|
||||
eventingClient := eventing_client.NewMockKnEventingClient(t)
|
||||
_, err := executeTriggerCommand(eventingClient, nil, "create", triggerName, "--broker", "mybroker",
|
||||
"--filter", "type=dev.knative.foo")
|
||||
assert.ErrorContains(t, err, "required flag(s)", "sink", "not set")
|
||||
}
|
||||
|
||||
func TestTriggerCreateMultipleFilter(t *testing.T) {
|
||||
eventingClient := eventing_client.NewMockKnEventingClient(t)
|
||||
servingClient := knserving_client.NewMockKnServiceClient(t)
|
||||
|
|
@ -82,7 +86,7 @@ func TestTriggerCreateMultipleFilter(t *testing.T) {
|
|||
}, nil)
|
||||
|
||||
eventingRecorder := eventingClient.Recorder()
|
||||
eventingRecorder.CreateTrigger(createTrigger(triggerName, map[string]string{"type": "dev.knative.foo", "source": "event.host"}, "mybroker", "mysvc"), nil)
|
||||
eventingRecorder.CreateTrigger(createTrigger("default", triggerName, map[string]string{"type": "dev.knative.foo", "source": "event.host"}, "mybroker", "mysvc"), nil)
|
||||
|
||||
out, err := executeTriggerCommand(eventingClient, servingClient, "create", triggerName, "--broker", "mybroker",
|
||||
"--filter", "type=dev.knative.foo", "--filter", "source=event.host", "--sink", "svc:mysvc")
|
||||
|
|
@ -92,26 +96,3 @@ func TestTriggerCreateMultipleFilter(t *testing.T) {
|
|||
eventingRecorder.Validate()
|
||||
servingRecorder.Validate()
|
||||
}
|
||||
|
||||
func createTrigger(name string, filters map[string]string, broker string, svcname string) *v1alpha1.Trigger {
|
||||
triggerFilterAttributes := v1alpha1.TriggerFilterAttributes(filters)
|
||||
wanted := &v1alpha1.Trigger{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: v1alpha1.TriggerSpec{
|
||||
Broker: broker,
|
||||
Filter: &v1alpha1.TriggerFilter{
|
||||
Attributes: &triggerFilterAttributes,
|
||||
},
|
||||
Subscriber: &duckv1.Destination{
|
||||
Ref: &corev1.ObjectReference{
|
||||
Name: svcname,
|
||||
Kind: "Service",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return wanted
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
package trigger
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
|
|
@ -43,7 +42,7 @@ func TestTriggerDeleteWithError(t *testing.T) {
|
|||
|
||||
eventingClient := eventing_client.NewMockKnEventingClient(t)
|
||||
eventingRecorder := eventingClient.Recorder()
|
||||
eventingRecorder.DeleteTrigger(triggerName, errors.New(fmt.Sprintf("trigger %s not found", triggerName)))
|
||||
eventingRecorder.DeleteTrigger(triggerName, fmt.Errorf("trigger %s not found", triggerName))
|
||||
|
||||
out, err := executeTriggerCommand(eventingClient, nil, "delete", triggerName)
|
||||
assert.ErrorContains(t, err, triggerName)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright © 2019 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 trigger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"knative.dev/client/pkg/kn/commands"
|
||||
"knative.dev/client/pkg/kn/commands/flags"
|
||||
)
|
||||
|
||||
// NewTriggerListCommand represents 'kn trigger list' command
|
||||
func NewTriggerListCommand(p *commands.KnParams) *cobra.Command {
|
||||
triggerListFlags := flags.NewListFlags(TriggerListHandlers)
|
||||
|
||||
triggerListCommand := &cobra.Command{
|
||||
Use: "list [name]",
|
||||
Short: "List available triggers.",
|
||||
Example: `
|
||||
# List all triggers
|
||||
kn trigger list
|
||||
|
||||
# List all triggers in JSON output format
|
||||
kn trigger list -o json`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
namespace, err := p.GetNamespace(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client, err := p.NewEventingClient(namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
triggerList, err := client.ListTriggers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(triggerList.Items) == 0 {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "No triggers found.\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
// empty namespace indicates all-namespaces flag is specified
|
||||
if namespace == "" {
|
||||
triggerListFlags.EnsureWithNamespace()
|
||||
}
|
||||
|
||||
printer, err := triggerListFlags.ToPrinter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = printer.PrintObj(triggerList, cmd.OutOrStdout())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
commands.AddNamespaceFlags(triggerListCommand.Flags(), true)
|
||||
triggerListFlags.AddFlags(triggerListCommand)
|
||||
return triggerListCommand
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
// Copyright © 2019 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 trigger
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"knative.dev/client/pkg/kn/commands"
|
||||
hprinters "knative.dev/client/pkg/printers"
|
||||
eventing "knative.dev/eventing/pkg/apis/eventing/v1alpha1"
|
||||
)
|
||||
|
||||
// TriggerListHandlers handles printing human readable table for `kn source list-types` command's output
|
||||
func TriggerListHandlers(h hprinters.PrintHandler) {
|
||||
sourceTypesColumnDefinitions := []metav1beta1.TableColumnDefinition{
|
||||
{Name: "Namespace", Type: "string", Description: "Namespace of the trigger", Priority: 0},
|
||||
{Name: "Name", Type: "string", Description: "Name of the trigger", Priority: 1},
|
||||
{Name: "Broker", Type: "string", Description: "Name of the broker", Priority: 1},
|
||||
{Name: "Subscriber_URI", Type: "string", Description: "URI of the subscriber", Priority: 1},
|
||||
{Name: "Ready", Type: "string", Description: "Ready condition status of the trigger", Priority: 1},
|
||||
{Name: "Reason", Type: "string", Description: "Reason for non-ready condition of the trigger", Priority: 1},
|
||||
}
|
||||
h.TableHandler(sourceTypesColumnDefinitions, printTrigger)
|
||||
h.TableHandler(sourceTypesColumnDefinitions, printTriggerList)
|
||||
}
|
||||
|
||||
// printKService populates the knative service table rows
|
||||
func printTrigger(trigger *eventing.Trigger, options hprinters.PrintOptions) ([]metav1beta1.TableRow, error) {
|
||||
name := trigger.Name
|
||||
broker := trigger.Spec.Broker
|
||||
uri := trigger.Status.SubscriberURI
|
||||
ready := commands.ReadyCondition(trigger.Status.Conditions)
|
||||
reason := commands.NonReadyConditionReason(trigger.Status.Conditions)
|
||||
|
||||
row := metav1beta1.TableRow{
|
||||
Object: runtime.RawExtension{Object: trigger},
|
||||
}
|
||||
|
||||
if options.AllNamespaces {
|
||||
row.Cells = append(row.Cells, trigger.Namespace)
|
||||
}
|
||||
|
||||
row.Cells = append(row.Cells,
|
||||
name,
|
||||
broker,
|
||||
uri,
|
||||
ready,
|
||||
reason)
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
|
||||
// printTriggerListWithNamespace populates the knative service table rows with namespace column
|
||||
func printTriggerListWithNamespace(triggerList *eventing.TriggerList, options hprinters.PrintOptions) ([]metav1beta1.TableRow, error) {
|
||||
rows := make([]metav1beta1.TableRow, 0, len(triggerList.Items))
|
||||
|
||||
// temporary slice for sorting services in non-default namespace
|
||||
others := []metav1beta1.TableRow{}
|
||||
|
||||
for _, trigger := range triggerList.Items {
|
||||
// Fill in with services in `default` namespace at first
|
||||
if trigger.Namespace == "default" {
|
||||
r, err := printTrigger(&trigger, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rows = append(rows, r...)
|
||||
continue
|
||||
}
|
||||
// put other services in temporary slice
|
||||
r, err := printTrigger(&trigger, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
others = append(others, r...)
|
||||
}
|
||||
|
||||
// sort other services list alphabetically by namespace
|
||||
sort.SliceStable(others, func(i, j int) bool {
|
||||
return others[i].Cells[0].(string) < others[j].Cells[0].(string)
|
||||
})
|
||||
|
||||
return append(rows, others...), nil
|
||||
}
|
||||
|
||||
// printSourceTypesList populates the source types list table rows
|
||||
func printTriggerList(triggerList *eventing.TriggerList, options hprinters.PrintOptions) ([]metav1beta1.TableRow, error) {
|
||||
rows := make([]metav1beta1.TableRow, 0, len(triggerList.Items))
|
||||
|
||||
if options.AllNamespaces {
|
||||
return printTriggerListWithNamespace(triggerList, options)
|
||||
}
|
||||
|
||||
for _, trigger := range triggerList.Items {
|
||||
r, err := printTrigger(&trigger, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rows = append(rows, r...)
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
// Copyright © 2019 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 trigger
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
eventing_client "knative.dev/client/pkg/eventing/v1alpha1"
|
||||
knserving_client "knative.dev/client/pkg/serving/v1alpha1"
|
||||
"knative.dev/client/pkg/util"
|
||||
"knative.dev/eventing/pkg/apis/eventing/v1alpha1"
|
||||
serving_v1alpha1 "knative.dev/serving/pkg/apis/serving/v1alpha1"
|
||||
)
|
||||
|
||||
func TestTriggerList(t *testing.T) {
|
||||
servingClient := knserving_client.NewMockKnServiceClient(t)
|
||||
servingRecorder := servingClient.Recorder()
|
||||
servingRecorder.GetService("mysink", &serving_v1alpha1.Service{
|
||||
TypeMeta: metav1.TypeMeta{Kind: "Service"},
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "mysink"},
|
||||
}, nil)
|
||||
|
||||
eventingClient := eventing_client.NewMockKnEventingClient(t)
|
||||
eventingRecorder := eventingClient.Recorder()
|
||||
|
||||
trigger1 := createTriggerWithStatus("default", "trigger1", map[string]string{"type": "dev.knative.foo"}, "mybroker1", "mysink")
|
||||
trigger2 := createTriggerWithStatus("default", "trigger2", map[string]string{"source": "svc.service.knative"}, "mybroker2", "mysink")
|
||||
trigger3 := createTriggerWithStatus("default", "trigger3", map[string]string{"type": "src.eventing.knative"}, "mybroker3", "mysink")
|
||||
triggerList := &v1alpha1.TriggerList{Items: []v1alpha1.Trigger{*trigger1, *trigger2, *trigger3}}
|
||||
eventingRecorder.ListTriggers(triggerList, nil)
|
||||
|
||||
output, err := executeTriggerCommand(eventingClient, servingClient, "list")
|
||||
assert.NilError(t, err)
|
||||
|
||||
outputLines := strings.Split(output, "\n")
|
||||
assert.Check(t, util.ContainsAll(outputLines[0], "NAME", "BROKER", "SUBSCRIBER_URI", "READY", "REASON"))
|
||||
assert.Check(t, util.ContainsAll(outputLines[1], "trigger1", "mybroker1", "mysink"))
|
||||
assert.Check(t, util.ContainsAll(outputLines[2], "trigger2", "mybroker2", "mysink"))
|
||||
assert.Check(t, util.ContainsAll(outputLines[3], "trigger3", "mybroker3", "mysink"))
|
||||
|
||||
eventingRecorder.Validate()
|
||||
}
|
||||
|
||||
func TestTriggerListEmpty(t *testing.T) {
|
||||
eventingClient := eventing_client.NewMockKnEventingClient(t)
|
||||
eventingRecorder := eventingClient.Recorder()
|
||||
|
||||
eventingRecorder.ListTriggers(&v1alpha1.TriggerList{}, nil)
|
||||
output, err := executeTriggerCommand(eventingClient, nil, "list")
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, util.ContainsAll(output, "No", "triggers", "found"))
|
||||
|
||||
eventingRecorder.Validate()
|
||||
}
|
||||
|
||||
func TestTriggerListAllNamespace(t *testing.T) {
|
||||
servingClient := knserving_client.NewMockKnServiceClient(t)
|
||||
servingRecorder := servingClient.Recorder()
|
||||
servingRecorder.GetService("mysink", &serving_v1alpha1.Service{
|
||||
TypeMeta: metav1.TypeMeta{Kind: "Service"},
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "mysink"},
|
||||
}, nil)
|
||||
|
||||
eventingClient := eventing_client.NewMockKnEventingClient(t)
|
||||
eventingRecorder := eventingClient.Recorder()
|
||||
|
||||
trigger1 := createTriggerWithStatus("default1", "trigger1", map[string]string{"type": "dev.knative.foo"}, "mybroker1", "mysink")
|
||||
trigger2 := createTriggerWithStatus("default2", "trigger2", map[string]string{"source": "svc.service.knative"}, "mybroker2", "mysink")
|
||||
trigger3 := createTriggerWithStatus("default3", "trigger3", map[string]string{"type": "src.eventing.knative"}, "mybroker3", "mysink")
|
||||
triggerList := &v1alpha1.TriggerList{Items: []v1alpha1.Trigger{*trigger1, *trigger2, *trigger3}}
|
||||
eventingRecorder.ListTriggers(triggerList, nil)
|
||||
|
||||
output, err := executeTriggerCommand(eventingClient, servingClient, "list", "--all-namespaces")
|
||||
assert.NilError(t, err)
|
||||
|
||||
outputLines := strings.Split(output, "\n")
|
||||
assert.Check(t, util.ContainsAll(outputLines[0], "NAMESPACE", "NAME", "BROKER", "SUBSCRIBER_URI", "READY", "REASON"))
|
||||
assert.Check(t, util.ContainsAll(outputLines[1], "default1", "trigger1", "mybroker1", "mysink"))
|
||||
assert.Check(t, util.ContainsAll(outputLines[2], "default2", "trigger2", "mybroker2", "mysink"))
|
||||
assert.Check(t, util.ContainsAll(outputLines[3], "default3", "trigger3", "mybroker3", "mysink"))
|
||||
|
||||
eventingRecorder.Validate()
|
||||
}
|
||||
|
|
@ -29,5 +29,6 @@ func NewTriggerCommand(p *commands.KnParams) *cobra.Command {
|
|||
triggerCmd.AddCommand(NewTriggerCreateCommand(p))
|
||||
triggerCmd.AddCommand(NewTriggerDeleteCommand(p))
|
||||
triggerCmd.AddCommand(NewTriggerDescribeCommand(p))
|
||||
triggerCmd.AddCommand(NewTriggerListCommand(p))
|
||||
return triggerCmd
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,11 +17,16 @@ package trigger
|
|||
import (
|
||||
"bytes"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
||||
eventc_v1alpha1 "knative.dev/client/pkg/eventing/v1alpha1"
|
||||
"knative.dev/client/pkg/kn/commands"
|
||||
serving_client_v1alpha1 "knative.dev/client/pkg/serving/v1alpha1"
|
||||
"knative.dev/eventing/pkg/apis/eventing/v1alpha1"
|
||||
"knative.dev/pkg/apis"
|
||||
duckv1 "knative.dev/pkg/apis/duck/v1"
|
||||
)
|
||||
|
||||
// Helper methods
|
||||
|
|
@ -70,3 +75,40 @@ func executeTriggerCommand(triggerClient eventc_v1alpha1.KnEventingClient, servi
|
|||
|
||||
return output.String(), err
|
||||
}
|
||||
|
||||
func createTrigger(namespace string, name string, filters map[string]string, broker string, svcname string) *v1alpha1.Trigger {
|
||||
triggerFilterAttributes := v1alpha1.TriggerFilterAttributes(filters)
|
||||
wanted := &v1alpha1.Trigger{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1alpha1.TriggerSpec{
|
||||
Broker: broker,
|
||||
Filter: &v1alpha1.TriggerFilter{
|
||||
Attributes: &triggerFilterAttributes,
|
||||
},
|
||||
Subscriber: &duckv1.Destination{
|
||||
Ref: &corev1.ObjectReference{
|
||||
Name: svcname,
|
||||
Kind: "Service",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return wanted
|
||||
}
|
||||
|
||||
func createTriggerWithStatus(namespace string, name string, filters map[string]string, broker string, svcname string) *v1alpha1.Trigger {
|
||||
wanted := createTrigger(namespace, name, filters, broker, svcname)
|
||||
wanted.Status = v1alpha1.TriggerStatus{
|
||||
Status: duckv1.Status{
|
||||
Conditions: []apis.Condition{{
|
||||
Type: "Ready",
|
||||
Status: "True",
|
||||
}},
|
||||
},
|
||||
SubscriberURI: apis.HTTP(svcname),
|
||||
}
|
||||
return wanted
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue