Skip to content

Commit

Permalink
Refactor without reflection
Browse files Browse the repository at this point in the history
  • Loading branch information
dsimansk committed Mar 23, 2023
1 parent b22cbc0 commit 0e2e461
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 32 deletions.
75 changes: 44 additions & 31 deletions pkg/kn/commands/trigger/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ package trigger

import (
"errors"
"reflect"

"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"

"knative.dev/client/lib/printing"
"knative.dev/client/pkg/kn/commands"
"knative.dev/client/pkg/printers"
Expand Down Expand Up @@ -136,38 +134,53 @@ func writeTrigger(dw printers.PrefixWriter, trigger *v1beta1.Trigger, printDetai

// writeNestedFilters goes through SubscriptionsAPIFilter and writes its content accordingly
func writeNestedFilters(dw printers.PrefixWriter, filter v1beta1.SubscriptionsAPIFilter) {
v := reflect.ValueOf(filter)
for i := 0; i < v.NumField(); i++ {
field := v.Type().Field(i)
fieldValue := v.Field(i)

// Write if it's non-zero string, fields: CESQL
if fieldValue.Kind() == reflect.String && !fieldValue.IsZero() {
dw.WriteAttribute(field.Name, fieldValue.String())
// All []SubscriptionsAPIFilter
if len(filter.All) > 0 {
// create new indentation after name
subWriter := dw.WriteAttribute("all", "")
for _, nestedFilter := range filter.All {
writeNestedFilters(subWriter, nestedFilter)
}
// Write map[string]string key:value pairs of field: Exact, Prefix, Suffix
if fieldValue.Kind() == reflect.Map && fieldValue.Len() > 0 {
for k, v := range fieldValue.Interface().(map[string]string) {
dw.WriteAttribute(k, v)
}
}
// Any []SubscriptionsAPIFilter
if len(filter.Any) > 0 {
// create new indentation after name
subWriter := dw.WriteAttribute("any", "")
for _, nestedFilter := range filter.Any {
writeNestedFilters(subWriter, nestedFilter)
}

// iterate through []SubscriptionsAPIFilter of fields: All, Any
if fieldValue.Kind() == reflect.Slice {
for j := 0; j < fieldValue.Len(); j++ {
element := fieldValue.Index(j)
// Write filter field name only and create next indentation
dw = dw.WriteAttribute(field.Name, "")
// Call write recursively for struct SubscriptionsAPIFilter
if element.Kind() == reflect.Struct {
writeNestedFilters(dw, element.Interface().(v1beta1.SubscriptionsAPIFilter))
}
}
}
// Not *SubscriptionsAPIFilter
if filter.Not != nil {
subWriter := dw.WriteAttribute("not", "")
writeNestedFilters(subWriter, *filter.Not)
}
// Exact map[string]string
if len(filter.Exact) > 0 {
// create new indentation after name
subWriter := dw.WriteAttribute("exact", "")
for k, v := range filter.Exact {
subWriter.WriteAttribute(k, v)
}

// Call write recursively for struct SubscriptionsAPIFilter of field: Not
if fieldValue.Kind() == reflect.Struct {
writeNestedFilters(dw, fieldValue.Interface().(v1beta1.SubscriptionsAPIFilter))
}
// Prefix map[string]string
if len(filter.Prefix) > 0 {
// create new indentation after name
subWriter := dw.WriteAttribute("prefix", "")
for k, v := range filter.Prefix {
subWriter.WriteAttribute(k, v)
}
}
// Suffix map[string]string
if len(filter.Suffix) > 0 {
// create new indentation after name
subWriter := dw.WriteAttribute("suffix", "")
for k, v := range filter.Suffix {
subWriter.WriteAttribute(k, v)
}
}
// CESQL string
if filter.CESQL != "" {
dw.WriteAttribute("cesql", filter.CESQL)
}
}
157 changes: 156 additions & 1 deletion pkg/kn/commands/trigger/describe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@
package trigger

import (
"bytes"
"encoding/json"
"errors"
"testing"

"knative.dev/client/pkg/printers"

"gotest.tools/v3/assert"
"gotest.tools/v3/assert/cmp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -48,7 +51,7 @@ func TestSimpleDescribe(t *testing.T) {

assert.Assert(t, util.ContainsAll(out, "Broker:", "mybroker"))
assert.Assert(t, util.ContainsAll(out, "Filter:", "type", "foo.type.knative", "source", "src.eventing.knative"))
assert.Assert(t, util.ContainsAll(out, "Filters", "experimental", "CESQL", "LOWER", "type"))
assert.Assert(t, util.ContainsAll(out, "Filters", "experimental", "cesql", "LOWER", "type"))
assert.Assert(t, util.ContainsAll(out, "Sink:", "Service", "myservicenamespace", "mysvc"))
})

Expand Down Expand Up @@ -113,6 +116,158 @@ func TestDescribeTriggerMachineReadable(t *testing.T) {
recorder.Validate()
}

func TestWriteNestedFilters(t *testing.T) {
testCases := []struct {
name string
filter v1beta1.SubscriptionsAPIFilter
expectedOutput string
}{
{
name: "Exact filter",
filter: v1beta1.SubscriptionsAPIFilter{
Exact: map[string]string{
"type": "example"}},
expectedOutput: "exact: \n" +
" type: example\n",
},
{
name: "Prefix filter",
filter: v1beta1.SubscriptionsAPIFilter{
Prefix: map[string]string{
"type": "foo.bar"}},
expectedOutput: "" +
"prefix: \n" +
" type: foo.bar\n",
},
{
name: "Suffix filter",
filter: v1beta1.SubscriptionsAPIFilter{
Suffix: map[string]string{
"type": "foo.bar"}},
expectedOutput: "" +
"suffix: \n" +
" type: foo.bar\n",
},
{
name: "All filter",
filter: v1beta1.SubscriptionsAPIFilter{
All: []v1beta1.SubscriptionsAPIFilter{
{Exact: map[string]string{
"type": "foo.bar"}},
{Prefix: map[string]string{
"source": "foo"}},
{Suffix: map[string]string{
"subject": "test"}}}},
expectedOutput: "" +
"all: \n" +
" exact: \n" +
" type: foo.bar\n" +
" prefix: \n" +
" source: foo\n" +
" suffix: \n" +
" subject: test\n",
},
{
name: "Any filter",
filter: v1beta1.SubscriptionsAPIFilter{
Any: []v1beta1.SubscriptionsAPIFilter{
{Exact: map[string]string{
"type": "foo.bar"}},
{Prefix: map[string]string{
"source": "foo"}},
{Suffix: map[string]string{
"subject": "test"}}},
},
expectedOutput: "" +
"any: \n" +
" exact: \n" +
" type: foo.bar\n" +
" prefix: \n" +
" source: foo\n" +
" suffix: \n" +
" subject: test\n",
},
{
name: "Nested All filter",
filter: v1beta1.SubscriptionsAPIFilter{
All: []v1beta1.SubscriptionsAPIFilter{
{Exact: map[string]string{
"type": "foo.bar"}},
{All: []v1beta1.SubscriptionsAPIFilter{
{Prefix: map[string]string{
"source": "foo"}},
{Suffix: map[string]string{
"subject": "test"}}}}}},
expectedOutput: "" +
"all: \n" +
" exact: \n" +
" type: foo.bar\n" +
" all: \n" +
" prefix: \n" +
" source: foo\n" +
" suffix: \n" +
" subject: test\n",
},
{
name: "Nested Any filter",
filter: v1beta1.SubscriptionsAPIFilter{
Any: []v1beta1.SubscriptionsAPIFilter{
{Exact: map[string]string{
"type": "foo.bar"}},
{Any: []v1beta1.SubscriptionsAPIFilter{
{Prefix: map[string]string{
"source": "foo"}},
{Suffix: map[string]string{
"subject": "test"}}}}}},
expectedOutput: "" +
"any: \n" +
" exact: \n" +
" type: foo.bar\n" +
" any: \n" +
" prefix: \n" +
" source: foo\n" +
" suffix: \n" +
" subject: test\n",
},
{
name: "Nested Not filter",
filter: v1beta1.SubscriptionsAPIFilter{
Not: &v1beta1.SubscriptionsAPIFilter{
Exact: map[string]string{
"type": "foo.bar",
},
Prefix: map[string]string{
"type": "bar",
},
CESQL: "select bar",
Not: &v1beta1.SubscriptionsAPIFilter{
Suffix: map[string]string{
"source": "foo"}}}},
expectedOutput: "" +
"not: \n" +
" not: \n" +
" suffix: \n" +
" source: foo\n" +
" exact: \n" +
" type: foo.bar\n" +
" prefix: \n" +
" type: bar\n" +
" cesql: select bar\n",
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
buf := &bytes.Buffer{}
dw := printers.NewPrefixWriter(buf)
writeNestedFilters(dw, tc.filter)
err := dw.Flush()
assert.NilError(t, err)
assert.Equal(t, tc.expectedOutput, buf.String())
})
}
}

func getTriggerSinkRef() *v1beta1.Trigger {
return &v1beta1.Trigger{
TypeMeta: v1.TypeMeta{
Expand Down

0 comments on commit 0e2e461

Please sign in to comment.