Skip to content

Commit

Permalink
ref(*): add sorter/filter utilties to releaseutil
Browse files Browse the repository at this point in the history
  • Loading branch information
fibonacci1729 committed Oct 12, 2016
1 parent 7a5ee45 commit 24fe864
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 68 deletions.
12 changes: 2 additions & 10 deletions cmd/tiller/release_history.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@ limitations under the License.
package main

import (
"sort"

"golang.org/x/net/context"
rpb "k8s.io/helm/pkg/proto/hapi/release"
tpb "k8s.io/helm/pkg/proto/hapi/services"
relutil "k8s.io/helm/pkg/releaseutil"
)

func (s *releaseServer) GetHistory(ctx context.Context, req *tpb.GetHistoryRequest) (*tpb.GetHistoryResponse, error) {
Expand All @@ -34,7 +32,7 @@ func (s *releaseServer) GetHistory(ctx context.Context, req *tpb.GetHistoryReque
return nil, err
}

sort.Sort(sort.Reverse(byRev(h)))
relutil.Reverse(h, relutil.SortByRevision)

var resp tpb.GetHistoryResponse
for i := 0; i < min(len(h), int(req.Max)); i++ {
Expand All @@ -44,12 +42,6 @@ func (s *releaseServer) GetHistory(ctx context.Context, req *tpb.GetHistoryReque
return &resp, nil
}

type byRev []*rpb.Release

func (s byRev) Len() int { return len(s) }
func (s byRev) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s byRev) Less(i, j int) bool { return s[i].Version < s[j].Version }

func min(x, y int) int {
if x < y {
return x
Expand Down
33 changes: 5 additions & 28 deletions cmd/tiller/release_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"fmt"
"log"
"regexp"
"sort"
"strings"

"google.golang.org/grpc/metadata"
Expand All @@ -36,6 +35,7 @@ import (
"k8s.io/helm/pkg/proto/hapi/chart"
"k8s.io/helm/pkg/proto/hapi/release"
"k8s.io/helm/pkg/proto/hapi/services"
relutil "k8s.io/helm/pkg/releaseutil"
"k8s.io/helm/pkg/storage/driver"
"k8s.io/helm/pkg/timeconv"
"k8s.io/helm/pkg/version"
Expand Down Expand Up @@ -123,9 +123,9 @@ func (s *releaseServer) ListReleases(req *services.ListReleasesRequest, stream s

switch req.SortBy {
case services.ListSort_NAME:
sort.Sort(byName(rels))
relutil.SortByName(rels)
case services.ListSort_LAST_RELEASED:
sort.Sort(byDate(rels))
relutil.SortByDate(rels)
}

if req.SortOrder == services.ListSort_DESC {
Expand Down Expand Up @@ -480,8 +480,8 @@ func (s *releaseServer) prepareRollback(req *services.RollbackReleaseRequest) (*
return nil, nil, errors.New("no revision to rollback")
}

sort.Sort(sort.Reverse(byRev(h)))
crls := h[0]
relutil.SortByRevision(h)
crls := h[len(h)-1]

rbv := req.Version
if req.Version == 0 {
Expand Down Expand Up @@ -878,29 +878,6 @@ func (s *releaseServer) UninstallRelease(c ctx.Context, req *services.UninstallR
return res, nil
}

// byName implements the sort.Interface for []*release.Release.
type byName []*release.Release

func (r byName) Len() int {
return len(r)
}
func (r byName) Swap(p, q int) {
r[p], r[q] = r[q], r[p]
}
func (r byName) Less(i, j int) bool {
return r[i].Name < r[j].Name
}

type byDate []*release.Release

func (r byDate) Len() int { return len(r) }
func (r byDate) Swap(p, q int) {
r[p], r[q] = r[q], r[p]
}
func (r byDate) Less(p, q int) bool {
return r[p].Info.LastDeployed.Seconds < r[q].Info.LastDeployed.Seconds
}

func splitManifests(bigfile string) map[string]string {
// This is not the best way of doing things, but it's how k8s itself does it.
// Basically, we're quickly splitting a stream of YAML documents into an
Expand Down
15 changes: 13 additions & 2 deletions pkg/storage/filter.go → pkg/releaseutil/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package storage // import "k8s.io/helm/pkg/storage"
package releaseutil // import "k8s.io/helm/pkg/releaseutil"

import rspb "k8s.io/helm/pkg/proto/hapi/release"

// FilterFunc returns true if the release object satisfies
// the predicate of the underlying func.
// the predicate of the underlying filter func.
type FilterFunc func(*rspb.Release) bool

// Check applies the FilterFunc to the release object.
Expand All @@ -30,6 +30,17 @@ func (fn FilterFunc) Check(rls *rspb.Release) bool {
return fn(rls)
}

// Filter applies the filter(s) to the list of provided releases
// returning the list that satisfies the filtering predicate.
func (fn FilterFunc) Filter(rels []*rspb.Release) (rets []*rspb.Release) {
for _, rel := range rels {
if fn.Check(rel) {
rets = append(rets, rel)
}
}
return
}

// Any returns a FilterFunc that filters a list of releases
// determined by the predicate 'f0 || f1 || ... || fn'.
func Any(filters ...FilterFunc) FilterFunc {
Expand Down
58 changes: 58 additions & 0 deletions pkg/releaseutil/filter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 releaseutil // import "k8s.io/helm/pkg/releaseutil"

import (
rspb "k8s.io/helm/pkg/proto/hapi/release"
"testing"
)

func TestFilterAny(t *testing.T) {
ls := Any(StatusFilter(rspb.Status_DELETED)).Filter(releases)
if len(ls) != 2 {
t.Fatalf("expected 2 results, got '%d'", len(ls))
}

r0, r1 := ls[0], ls[1]
switch {
case r0.Info.Status.Code != rspb.Status_DELETED:
t.Fatalf("expected DELETED result, got '%s'", r1.Info.Status.Code)
case r1.Info.Status.Code != rspb.Status_DELETED:
t.Fatalf("expected DELETED result, got '%s'", r1.Info.Status.Code)
}
}

func TestFilterAll(t *testing.T) {
fn := FilterFunc(func(rls *rspb.Release) bool {
// true if not deleted and version < 4
v0 := !StatusFilter(rspb.Status_DELETED).Check(rls)
v1 := rls.Version < 4
return v0 && v1
})

ls := All(fn).Filter(releases)
if len(ls) != 1 {
t.Fatalf("expected 1 result, got '%d'", len(ls))
}

switch r0 := ls[0]; {
case r0.Version == 4:
t.Fatal("got release with status revision 4")
case r0.Info.Status.Code == rspb.Status_DELETED:
t.Fatal("got release with status DELTED")
}
}
77 changes: 77 additions & 0 deletions pkg/releaseutil/sorter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 releaseutil // import "k8s.io/helm/pkg/releaseutil"

import (
"sort"

rspb "k8s.io/helm/pkg/proto/hapi/release"
)

type sorter struct {
list []*rspb.Release
less func(int, int) bool
}

func (s *sorter) Len() int { return len(s.list) }
func (s *sorter) Less(i, j int) bool { return s.less(i, j) }
func (s *sorter) Swap(i, j int) { s.list[i], s.list[j] = s.list[j], s.list[i] }

// Reverse reverses the list of releases sorted by the sort func.
func Reverse(list []*rspb.Release, sortFn func([]*rspb.Release)) {
sortFn(list)
for i, j := 0, len(list)-1; i < j; i, j = i+1, j-1 {
list[i], list[j] = list[j], list[i]
}
}

// SortByName returns the list of releases sorted
// in lexicographical order.
func SortByName(list []*rspb.Release) {
s := &sorter{list: list}
s.less = func(i, j int) bool {
ni := s.list[i].Name
nj := s.list[j].Name
return ni < nj
}
sort.Sort(s)
}

// SortByDate returns the list of releases sorted by a
// release's last deployed time (in seconds).
func SortByDate(list []*rspb.Release) {
s := &sorter{list: list}

s.less = func(i, j int) bool {
ti := s.list[i].Info.LastDeployed.Seconds
tj := s.list[j].Info.LastDeployed.Seconds
return ti < tj
}
sort.Sort(s)
}

// SortByRevision returns the list of releases sorted by a
// release's revision number (release.Version).
func SortByRevision(list []*rspb.Release) {
s := &sorter{list: list}
s.less = func(i, j int) bool {
vi := s.list[i].Version
vj := s.list[j].Version
return vi < vj
}
sort.Sort(s)
}
81 changes: 81 additions & 0 deletions pkg/releaseutil/sorter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 releaseutil // import "k8s.io/helm/pkg/releaseutil"

import (
rspb "k8s.io/helm/pkg/proto/hapi/release"
"k8s.io/helm/pkg/timeconv"
"testing"
"time"
)

// note: this test data is shared with filter_test.go.

var releases = []*rspb.Release{
tsRelease("quiet-bear", 2, 2000, rspb.Status_SUPERSEDED),
tsRelease("angry-bird", 4, 3000, rspb.Status_DEPLOYED),
tsRelease("happy-cats", 1, 4000, rspb.Status_DELETED),
tsRelease("vocal-dogs", 3, 6000, rspb.Status_DELETED),
}

func tsRelease(name string, vers int32, dur time.Duration, code rspb.Status_Code) *rspb.Release {
tmsp := timeconv.Timestamp(time.Now().Add(time.Duration(dur)))
info := &rspb.Info{Status: &rspb.Status{Code: code}, LastDeployed: tmsp}
return &rspb.Release{
Name: name,
Version: vers,
Info: info,
}
}

func check(t *testing.T, by string, fn func(int, int) bool) {
for i := len(releases) - 1; i > 0; i-- {
if fn(i, i-1) {
t.Errorf("release at positions '(%d,%d)' not sorted by %s", i-1, i, by)
}
}
}

func TestSortByName(t *testing.T) {
SortByName(releases)

check(t, "ByName", func(i, j int) bool {
ni := releases[i].Name
nj := releases[j].Name
return ni < nj
})
}

func TestSortByDate(t *testing.T) {
SortByDate(releases)

check(t, "ByDate", func(i, j int) bool {
ti := releases[i].Info.LastDeployed.Seconds
tj := releases[j].Info.LastDeployed.Seconds
return ti < tj
})
}

func TestSortByRevision(t *testing.T) {
SortByRevision(releases)

check(t, "ByRevision", func(i, j int) bool {
vi := releases[i].Version
vj := releases[j].Version
return vi < vj
})
}
22 changes: 0 additions & 22 deletions pkg/storage/doc.go

This file was deleted.

Loading

0 comments on commit 24fe864

Please sign in to comment.