Repository: knative/client (go)

Issue:
[source list] Add custom type for different types of source objects
### Feature request

`kn source list` gives you objects of different types of sources. While printing the JSON/YAML format of list, we'd need 
proper values for `apiVersion` and `kind` fields of the list printed, since the objects list contains are of different types.

Current behavior, sets empty string for `apiVersion` and `List` for `kind`.
This is to track setting these fields to for eg: `apiVersion: client.knative.dev/v1alpha1` 
ref: https://github.com/knative/client/pull/948#discussion_r461362683

There is also a discussion about what `apiVersion` and `kind` values should be if, the source list is of single type source OR `--type` filter is given with single type to `kn source list`, in this scenario, only single type of source objects are printed.

Pull request description:
Set client custom GVK for source list for machine readable output
## Description
 - Source list may contain different source types CO and machine readable output (using -o)
   requires List object to have GVK set, since the list contains different types of source COs,
   we set a custom client GVK on it.

<!-- Please add a short summary about what the pull request is going to bring on the table -->

## Changes
 - Use custom GVK {Group: client.knative.dev, Version: v1alpha1, Kind: SourceList}


## Reference

Fixes #953


/lint



Patch:
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index 7cf0f459..089409be 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -45,6 +45,10 @@
 | 🐛
 | Fix client side volume name generation
 | https://github.com/knative/client/pull/975[#975]
+
+| ✨
+| `kn source list` output now has client custom GVK set as `{Group: client.knative.dev, Version: v1alpha1, Kind: SourceList}`
+| https://github.com/knative/client/pull/980[#980]
 |===
 
 ## v0.16.0 (2020-07-14)
diff --git a/pkg/dynamic/client.go b/pkg/dynamic/client.go
index fb97beaf..78bea88b 100644
--- a/pkg/dynamic/client.go
+++ b/pkg/dynamic/client.go
@@ -34,6 +34,9 @@ const (
 	crdKinds          = "customresourcedefinitions"
 	sourcesLabelKey   = "duck.knative.dev/source"
 	sourcesLabelValue = "true"
+	sourceListGroup   = "client.knative.dev"
+	sourceListVersion = "v1alpha1"
+	sourceListKind    = "SourceList"
 )
 
 // KnDynamicClient to client-go Dynamic client. All methods are relative to the
@@ -111,9 +114,8 @@ func (c knDynamicClient) RawClient() dynamic.Interface {
 // only given types of source objects
 func (c *knDynamicClient) ListSources(types ...WithType) (*unstructured.UnstructuredList, error) {
 	var (
-		sourceList               unstructured.UnstructuredList
-		options                  metav1.ListOptions
-		numberOfSourceTypesFound int
+		sourceList unstructured.UnstructuredList
+		options    metav1.ListOptions
 	)
 	sourceTypes, err := c.ListSourcesTypes()
 	if err != nil {
@@ -151,16 +153,11 @@ func (c *knDynamicClient) ListSources(types ...WithType) (*unstructured.Unstruct
 		}
 
 		if len(sList.Items) > 0 {
-			// keep a track if we found source objects of different types
-			numberOfSourceTypesFound++
 			sourceList.Items = append(sourceList.Items, sList.Items...)
-			sourceList.SetGroupVersionKind(sList.GetObjectKind().GroupVersionKind())
 		}
 	}
-	// Clear the Group and Version for list if there are multiple types of source objects found
-	// Keep the source's GVK if there is only one type of source objects found or requested via --type filter
-	if numberOfSourceTypesFound > 1 {
-		sourceList.SetGroupVersionKind(schema.GroupVersionKind{Group: "", Version: "", Kind: "List"})
+	if len(sourceList.Items) > 0 {
+		sourceList.SetGroupVersionKind(schema.GroupVersionKind{Group: sourceListGroup, Version: sourceListVersion, Kind: sourceListKind})
 	}
 	return &sourceList, nil
 }
@@ -172,9 +169,8 @@ func (c *knDynamicClient) ListSourcesUsingGVKs(gvks *[]schema.GroupVersionKind,
 	}
 
 	var (
-		sourceList               unstructured.UnstructuredList
-		options                  metav1.ListOptions
-		numberOfSourceTypesFound int
+		sourceList unstructured.UnstructuredList
+		options    metav1.ListOptions
 	)
 	namespace := c.Namespace()
 	filters := WithTypes(types).List()
@@ -193,16 +189,11 @@ func (c *knDynamicClient) ListSourcesUsingGVKs(gvks *[]schema.GroupVersionKind,
 		}
 
 		if len(sList.Items) > 0 {
-			// keep a track if we found source objects of different types
-			numberOfSourceTypesFound++
 			sourceList.Items = append(sourceList.Items, sList.Items...)
-			sourceList.SetGroupVersionKind(sList.GetObjectKind().GroupVersionKind())
 		}
 	}
-	// Clear the Group and Version for list if there are multiple types of source objects found
-	// Keep the source's GVK if there is only one type of source objects found or requested via --type filter
-	if numberOfSourceTypesFound > 1 {
-		sourceList.SetGroupVersionKind(schema.GroupVersionKind{Group: "", Version: "", Kind: "List"})
+	if len(sourceList.Items) > 0 {
+		sourceList.SetGroupVersionKind(schema.GroupVersionKind{Group: sourceListGroup, Version: sourceListVersion, Kind: sourceListKind})
 	}
 	return &sourceList, nil
 }


Test patch:
diff --git a/pkg/dynamic/client_test.go b/pkg/dynamic/client_test.go
index aae3df4c..69043d99 100644
--- a/pkg/dynamic/client_test.go
+++ b/pkg/dynamic/client_test.go
@@ -122,6 +122,7 @@ func TestListSources(t *testing.T) {
 		sources, err := client.ListSources(WithTypeFilter("pingsource"), WithTypeFilter("ApiServerSource"))
 		assert.NilError(t, err)
 		assert.Equal(t, len(sources.Items), 2)
+		assert.DeepEqual(t, sources.GroupVersionKind(), schema.GroupVersionKind{sourceListGroup, sourceListVersion, sourceListKind})
 	})
 }
 
@@ -149,12 +150,14 @@ func TestListSourcesUsingGVKs(t *testing.T) {
 		assert.NilError(t, err)
 		assert.Check(t, s != nil)
 		assert.Equal(t, len(s.Items), 2)
+		assert.DeepEqual(t, s.GroupVersionKind(), schema.GroupVersionKind{sourceListGroup, sourceListVersion, sourceListKind})
 
 		// withType
 		s, err = client.ListSourcesUsingGVKs(&gvks, WithTypeFilter("PingSource"))
 		assert.NilError(t, err)
 		assert.Check(t, s != nil)
 		assert.Equal(t, len(s.Items), 1)
+		assert.DeepEqual(t, s.GroupVersionKind(), schema.GroupVersionKind{sourceListGroup, sourceListVersion, sourceListKind})
 	})
 
 }