Repository: knative/client (go)

Issue:
`kn trigger describe foo` panics when Sink uses URI instead of Ref
### Bug report

This is basically a replay of #847.

The relevant code for `trigger describe` assumes that `sink.Ref` is not null and panics when a URI is used. It appears to be identical to the `source describe` code as it was before #848 was merged.

### Expected behavior

I expect that `kn trigger describe` does not have an error when inspecting a Trigger that uses a URI instead of a Ref.

### Steps to reproduce the problem

```
$ kn trigger create example-trigger --filter type=dev.knative.example.com --sink http://example.com/
Trigger 'example-trigger' successfully created in namespace 'default'.

$ kn trigger describe example-trigger
Name:         example-trigger
Namespace:    default
Labels:       eventing.knative.dev/broker=default
Annotations:  eventing.knative.dev/creator=jchester@pivotal.io, eventing.knative.dev/lastModifier ...
Age:          25s
Broker:       default
Filter:
  type:       dev.knative.example.com

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x1f9cd59]

goroutine 1 [running]:
knative.dev/client/pkg/kn/commands/trigger.writeSink(0x24ea4a0, 0xc00060a930, 0xc00047ebb0)
	/home/prow/go/src/knative.dev/client/pkg/kn/commands/trigger/describe.go:100 +0x89
knative.dev/client/pkg/kn/commands/trigger.NewTriggerDescribeCommand.func1(0xc0001dcdc0, 0xc00022a7e0, 0x1, 0x1, 0x0, 0x0)
	/home/prow/go/src/knative.dev/client/pkg/kn/commands/trigger/describe.go:76 +0x230
github.com/spf13/cobra.(*Command).execute(0xc0001dcdc0, 0xc00022a7b0, 0x1, 0x1, 0xc0001dcdc0, 0xc00022a7b0)
	/home/prow/go/src/knative.dev/client/vendor/github.com/spf13/cobra/command.go:832 +0x460
github.com/spf13/cobra.(*Command).ExecuteC(0xc0000dc580, 0x0, 0x0, 0xc00000e048)
	/home/prow/go/src/knative.dev/client/vendor/github.com/spf13/cobra/command.go:920 +0x2fb
github.com/spf13/cobra.(*Command).Execute(...)
	/home/prow/go/src/knative.dev/client/vendor/github.com/spf13/cobra/command.go:870
main.main()
	/home/prow/go/src/knative.dev/client/cmd/kn/main.go:42 +0x158
```

### kn version

<!-- Please paste the output of 'kn version' in the code block below -->

```
Version:      v0.15.1
Build Date:   2020-06-03 16:11:35
Git Revision: 0cac223
Supported APIs:
* Serving
  - serving.knative.dev/v1 (knative-serving v0.15.0)
* Eventing
  - sources.knative.dev/v1alpha2 (knative-eventing v0.15.0)
  - eventing.knative.dev/v1alpha1 (knative-eventing v0.15.0)
```

### Knative (serving/eventing) version

v0.15


Pull request description:
Fix Panic for kn trigger describe with Sink URI
## Description

This pull request moves all `Sink.Ref` properties from being referenced for `kn trigger describe` until after it has been checked if `Sink.Ref` is nil due to using a URI instead of a Ref. 

## Reference

Fixes #899

/lint


Patch:
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index 2d288030..649c2c16 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -18,6 +18,10 @@
 |===
 | | Description | PR
 
+| 🐛
+| Fix Panic for `kn trigger describe` with Sink URI
+| https://github.com/knative/client/pull/900[#900]
+
 | 🎁
 | Group commands in usage output with `kn --help`
 | https://github.com/knative/client/pull/887[#887]
diff --git a/pkg/kn/commands/trigger/describe.go b/pkg/kn/commands/trigger/describe.go
index 331b7508..4cae159f 100644
--- a/pkg/kn/commands/trigger/describe.go
+++ b/pkg/kn/commands/trigger/describe.go
@@ -98,10 +98,10 @@ func NewTriggerDescribeCommand(p *commands.KnParams) *cobra.Command {
 
 func writeSink(dw printers.PrefixWriter, sink *duckv1.Destination) {
 	subWriter := dw.WriteAttribute("Sink", "")
-	subWriter.WriteAttribute("Name", sink.Ref.Name)
-	subWriter.WriteAttribute("Namespace", sink.Ref.Namespace)
 	ref := sink.Ref
 	if ref != nil {
+		subWriter.WriteAttribute("Name", sink.Ref.Name)
+		subWriter.WriteAttribute("Namespace", sink.Ref.Namespace)
 		subWriter.WriteAttribute("Resource", fmt.Sprintf("%s (%s)", sink.Ref.Kind, sink.Ref.APIVersion))
 	}
 	uri := sink.URI


Test patch:
diff --git a/pkg/kn/commands/trigger/describe_test.go b/pkg/kn/commands/trigger/describe_test.go
index 15285592..6e70afea 100644
--- a/pkg/kn/commands/trigger/describe_test.go
+++ b/pkg/kn/commands/trigger/describe_test.go
@@ -23,6 +23,7 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	v1beta1 "knative.dev/eventing/pkg/apis/eventing/v1beta1"
+	"knative.dev/pkg/apis"
 	duckv1 "knative.dev/pkg/apis/duck/v1"
 
 	clientv1beta1 "knative.dev/client/pkg/eventing/v1beta1"
@@ -33,7 +34,7 @@ func TestSimpleDescribe(t *testing.T) {
 	client := clientv1beta1.NewMockKnEventingClient(t, "mynamespace")
 
 	recorder := client.Recorder()
-	recorder.GetTrigger("testtrigger", getTrigger(), nil)
+	recorder.GetTrigger("testtrigger", getTriggerSinkRef(), nil)
 
 	out, err := executeTriggerCommand(client, nil, "describe", "testtrigger")
 	assert.NilError(t, err)
@@ -60,8 +61,27 @@ func TestDescribeError(t *testing.T) {
 
 	recorder.Validate()
 }
+func TestDescribeTriggerWithSinkURI(t *testing.T) {
+	client := clientv1beta1.NewMockKnEventingClient(t, "mynamespace")
+
+	recorder := client.Recorder()
+	recorder.GetTrigger("testtrigger", getTriggerSinkURI(), nil)
+
+	out, err := executeTriggerCommand(client, nil, "describe", "testtrigger")
+	assert.NilError(t, err)
 
-func getTrigger() *v1beta1.Trigger {
+	assert.Assert(t, cmp.Regexp("Name:\\s+testtrigger", out))
+	assert.Assert(t, cmp.Regexp("Namespace:\\s+default", out))
+
+	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, "Sink:", "URI", "https", "foo"))
+
+	// Validate that all recorded API methods have been called
+	recorder.Validate()
+}
+
+func getTriggerSinkRef() *v1beta1.Trigger {
 	return &v1beta1.Trigger{
 		TypeMeta: v1.TypeMeta{},
 		ObjectMeta: metav1.ObjectMeta{
@@ -87,3 +107,29 @@ func getTrigger() *v1beta1.Trigger {
 		Status: v1beta1.TriggerStatus{},
 	}
 }
+
+func getTriggerSinkURI() *v1beta1.Trigger {
+	return &v1beta1.Trigger{
+		TypeMeta: v1.TypeMeta{},
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "testtrigger",
+			Namespace: "default",
+		},
+		Spec: v1beta1.TriggerSpec{
+			Broker: "mybroker",
+			Filter: &v1beta1.TriggerFilter{
+				Attributes: v1beta1.TriggerFilterAttributes{
+					"type":   "foo.type.knative",
+					"source": "src.eventing.knative",
+				},
+			},
+			Subscriber: duckv1.Destination{
+				URI: &apis.URL{
+					Scheme: "https",
+					Host:   "foo",
+				},
+			},
+		},
+		Status: v1beta1.TriggerStatus{},
+	}
+}