Skip to content

Commit

Permalink
refactor(service): Add listRoutes() to client + generic way for list …
Browse files Browse the repository at this point in the history
…options
  • Loading branch information
rhuss committed Jul 2, 2019
1 parent 347b87f commit f264ae6
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 41 deletions.
3 changes: 2 additions & 1 deletion pkg/kn/commands/revision/revision_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/spf13/cobra"

"github.com/knative/client/pkg/kn/commands"
v1alpha12 "github.com/knative/client/pkg/serving/v1alpha1"
)

// NewRevisionListCommand represents 'kn revision list' command
Expand Down Expand Up @@ -55,7 +56,7 @@ func NewRevisionListCommand(p *commands.KnParams) *cobra.Command {
if err != nil {
return err
}
revisionList, err = client.ListRevisionsForService(serviceName)
revisionList, err = client.ListRevisions(v1alpha12.WithService(serviceName))
if err != nil {
return err
}
Expand Down
28 changes: 12 additions & 16 deletions pkg/kn/commands/route/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import (
"fmt"

"github.com/knative/client/pkg/kn/commands"
v1alpha12 "github.com/knative/client/pkg/serving/v1alpha1"

"github.com/knative/serving/pkg/apis/serving/v1alpha1"
"github.com/spf13/cobra"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/runtime/schema"
)

// NewrouteListCommand represents 'kn route list' command
Expand All @@ -40,41 +40,37 @@ func NewRouteListCommand(p *commands.KnParams) *cobra.Command {
# List all routes in yaml format
kn route list -o yaml`,
RunE: func(cmd *cobra.Command, args []string) error {
client, err := p.ServingFactory()

namespace, err := p.GetNamespace(cmd)
if err != nil {
return err
}
namespace, err := p.GetNamespace(cmd)
client, err := p.NewClient(namespace)
if err != nil {
return err
}
var listOptions v1.ListOptions

var routeList *v1alpha1.RouteList
switch len(args) {
case 0:
listOptions = v1.ListOptions{}
routeList, err = client.ListRoutes()
case 1:
listOptions.FieldSelector = fields.Set(map[string]string{"metadata.name": args[0]}).String()
routeList, err = client.ListRoutes(v1alpha12.WithName(args[0]))
default:
return fmt.Errorf("'kn route list' accepts maximum 1 argument.")
}
route, err := client.Routes(namespace).List(listOptions)
if err != nil {
return err
}
if len(route.Items) == 0 {
if len(routeList.Items) == 0 {
fmt.Fprintf(cmd.OutOrStdout(), "No resources found.\n")
return nil
}
route.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{
Group: "knative.dev",
Version: "v1alpha1",
Kind: "route",
})
printer, err := routeListFlags.ToPrinter()
if err != nil {
return err
}
err = printer.PrintObj(route, cmd.OutOrStdout())
err = printer.PrintObj(routeList, cmd.OutOrStdout())
if err != nil {
return err
}
Expand Down
102 changes: 82 additions & 20 deletions pkg/serving/v1alpha1/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"time"

"github.com/knative/pkg/apis"
"k8s.io/apimachinery/pkg/fields"

"github.com/knative/client/pkg/serving"
"github.com/knative/client/pkg/wait"
Expand All @@ -39,8 +40,8 @@ type KnClient interface {
// Get a service by its unique name
GetService(name string) (*v1alpha1.Service, error)

// List all services
ListServices() (*v1alpha1.ServiceList, error)
// List services
ListServices(opts ...ListConfig) (*v1alpha1.ServiceList, error)

// Create a new service
CreateService(service *v1alpha1.Service) error
Expand All @@ -57,14 +58,57 @@ type KnClient interface {
// Get a revision by name
GetRevision(name string) (*v1alpha1.Revision, error)

// List all revisions
ListRevisions() (*v1alpha1.RevisionList, error)

// Get all revisions for a specific service
ListRevisionsForService(serviceName string) (*v1alpha1.RevisionList, error)
// List revisions
ListRevisions(opts ...ListConfig) (*v1alpha1.RevisionList, error)

// Delete a revision
DeleteRevision(name string) error

// List routes
ListRoutes(opts ...ListConfig) (*v1alpha1.RouteList, error)
}

type listConfig struct {
// Labels to filter on
Labels labels.Set

// Labels to filter on
Fields fields.Set
}

// Config function for builder pattern
type ListConfig func(config *listConfig)

type ListConfigs []ListConfig

// add selectors to a list options
func (opts ListConfigs) toListOptions() v1.ListOptions {
listConfig := listConfig{labels.Set{}, fields.Set{}}
for _, f := range opts {
f(&listConfig)
}
options := v1.ListOptions{}
if len(listConfig.Fields) > 0 {
options.FieldSelector = listConfig.Fields.String()
}
if len(listConfig.Labels) > 0 {
options.LabelSelector = listConfig.Labels.String()
}
return options
}

// Filter list on the provided name
func WithName(name string) ListConfig {
return func(lo *listConfig) {
lo.Fields["metadata.name"] = name
}
}

// Filter on the service name
func WithService(service string) ListConfig {
return func(lo *listConfig) {
lo.Labels[api_serving.ServiceLabelKey] = service
}
}

type knClient struct {
Expand Down Expand Up @@ -93,9 +137,9 @@ func (cl *knClient) GetService(name string) (*v1alpha1.Service, error) {
return service, nil
}

// List all services
func (cl *knClient) ListServices() (*v1alpha1.ServiceList, error) {
serviceList, err := cl.client.Services(cl.namespace).List(v1.ListOptions{})
// List services
func (cl *knClient) ListServices(config ...ListConfig) (*v1alpha1.ServiceList, error) {
serviceList, err := cl.client.Services(cl.namespace).List(ListConfigs(config).toListOptions())
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -167,25 +211,22 @@ func (cl *knClient) DeleteRevision(name string) error {
return cl.client.Revisions(cl.namespace).Delete(name, &v1.DeleteOptions{})
}

// List all revisions
func (cl *knClient) ListRevisions() (*v1alpha1.RevisionList, error) {
revisionList, err := cl.client.Revisions(cl.namespace).List(v1.ListOptions{})
// List revisions
func (cl *knClient) ListRevisions(config ...ListConfig) (*v1alpha1.RevisionList, error) {
revisionList, err := cl.client.Revisions(cl.namespace).List(ListConfigs(config).toListOptions())
if err != nil {
return nil, err
}
return updateServingGvkForRevisionList(revisionList)
}

func (cl *knClient) ListRevisionsForService(serviceName string) (*v1alpha1.RevisionList, error) {
listOptions := v1.ListOptions{}
listOptions.LabelSelector = labels.Set(
map[string]string{api_serving.ServiceLabelKey: serviceName}).String()

revisionList, err := cl.client.Revisions(cl.namespace).List(listOptions)
// List routes
func (cl *knClient) ListRoutes(config ...ListConfig) (*v1alpha1.RouteList, error) {
routeList, err := cl.client.Routes(cl.namespace).List(ListConfigs(config).toListOptions())
if err != nil {
return nil, err
}
return updateServingGvkForRevisionList(revisionList)
return updateServingGvkForRouteList(routeList)
}

// update all the list + all items contained in the list with
Expand All @@ -209,6 +250,27 @@ func updateServingGvkForRevisionList(revisionList *v1alpha1.RevisionList) (*v1al
return revisionListNew, nil
}

// update all the list + all items contained in the list with
// the proper GroupVersionKind specific to Knative serving
func updateServingGvkForRouteList(routeList *v1alpha1.RouteList) (*v1alpha1.RouteList, error) {
routeListNew := routeList.DeepCopy()
err := updateServingGvk(routeListNew)
if err != nil {
return nil, err
}

routeListNew.Items = make([]v1alpha1.Route, len(routeList.Items))
for idx := range routeList.Items {
revision := routeList.Items[idx].DeepCopy()
err := updateServingGvk(revision)
if err != nil {
return nil, err
}
routeListNew.Items[idx] = *revision
}
return routeListNew, nil
}

// update with the v1alpha1 group + version
func updateServingGvk(obj runtime.Object) error {
return serving.UpdateGroupVersionKind(obj, v1alpha1.SchemeGroupVersion)
Expand Down
54 changes: 53 additions & 1 deletion pkg/serving/v1alpha1/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

"gotest.tools/assert"
"gotest.tools/assert/cmp"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/watch"

serving_api "github.com/knative/serving/pkg/apis/serving"
Expand Down Expand Up @@ -274,7 +275,7 @@ func TestListRevisionForService(t *testing.T) {

t.Run("list revisions for a service returns a list of revisions associated with this this service and no error",
func(t *testing.T) {
revisions, err := client.ListRevisionsForService(serviceName)
revisions, err := client.ListRevisions(WithService(serviceName))
assert.NilError(t, err)

assert.Assert(t, cmp.Len(revisions.Items, 1))
Expand All @@ -285,6 +286,53 @@ func TestListRevisionForService(t *testing.T) {
})
}

func TestListRoutes(t *testing.T) {
serving, client := setup()

singleRouteName := "route-2"
singleRoute := *newRoute(singleRouteName)
routes := []v1alpha1.Route{*newRoute("route-1"), singleRoute, *newRoute("route-3")}
serving.AddReactor("list", "routes",
func(a client_testing.Action) (bool, runtime.Object, error) {
assert.Equal(t, testNamespace, a.GetNamespace())
lAction := a.(client_testing.ListAction)
restrictions := lAction.GetListRestrictions()
assert.Assert(t, restrictions.Labels.Empty())
if !restrictions.Fields.Empty() {
nameField := fields.Set{"metadata.name": singleRouteName}
assert.Check(t, restrictions.Labels.Matches(nameField))
return true, &v1alpha1.RouteList{Items: []v1alpha1.Route{singleRoute}}, nil
}
return true, &v1alpha1.RouteList{Items: routes}, nil
})

t.Run("list routes returns a list of routes and no error", func(t *testing.T) {

routes, err := client.ListRoutes()
assert.NilError(t, err)

assert.Assert(t, len(routes.Items) == 3)
assert.Equal(t, routes.Items[0].Name, "route-1")
assert.Equal(t, routes.Items[1].Name, singleRouteName)
assert.Equal(t, routes.Items[2].Name, "route-3")
validateGroupVersionKind(t, routes)
for i := 0; i < len(routes.Items); i++ {
validateGroupVersionKind(t, &routes.Items[i])
}
})

t.Run("list routes with a name filter a list with one route and no error", func(t *testing.T) {

routes, err := client.ListRoutes(WithName(singleRouteName))
assert.NilError(t, err)

assert.Assert(t, len(routes.Items) == 1)
assert.Equal(t, routes.Items[0].Name, singleRouteName)
validateGroupVersionKind(t, routes)
validateGroupVersionKind(t, &routes.Items[0])
})
}

func TestWaitForService(t *testing.T) {
serving, client := setup()

Expand Down Expand Up @@ -338,6 +386,10 @@ func newRevision(name string, labels ...string) *v1alpha1.Revision {
return rev
}

func newRoute(name string) *v1alpha1.Route {
return &v1alpha1.Route{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: testNamespace}}
}

func getServiceEvents(name string) []watch.Event {
return []watch.Event{
{watch.Added, wait.CreateTestServiceWithConditions(name, corev1.ConditionUnknown, corev1.ConditionUnknown, "")},
Expand Down
4 changes: 1 addition & 3 deletions vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,13 @@ k8s.io/apimachinery/pkg/apis/meta/v1
k8s.io/apimachinery/pkg/util/duration
k8s.io/apimachinery/pkg/apis/meta/v1beta1
k8s.io/apimachinery/pkg/runtime
k8s.io/apimachinery/pkg/runtime/schema
k8s.io/apimachinery/pkg/fields
k8s.io/apimachinery/pkg/api/errors
k8s.io/apimachinery/pkg/api/resource
k8s.io/apimachinery/pkg/api/meta
k8s.io/apimachinery/pkg/util/runtime
k8s.io/apimachinery/pkg/runtime/schema
k8s.io/apimachinery/pkg/labels
k8s.io/apimachinery/pkg/fields
k8s.io/apimachinery/pkg/labels
k8s.io/apimachinery/pkg/watch
k8s.io/apimachinery/pkg/api/equality
k8s.io/apimachinery/pkg/api/validation
Expand Down

0 comments on commit f264ae6

Please sign in to comment.