mirror of https://github.com/helm/helm
While we removed Tiller, we left the internal client/server architecture mostly intact. This replaces that architecture with the `pkg/action` package. This implements the action package for list, but nothing else. Signed-off-by: Matt Butcher <matt.butcher@microsoft.com>pull/5077/head
parent
d07b95d0ae
commit
2016109616
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The Helm Authors.
|
|
||||||
|
|
||||||
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 main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"k8s.io/helm/pkg/hapi/release"
|
|
||||||
"k8s.io/helm/pkg/helm"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestListCmd(t *testing.T) {
|
|
||||||
tests := []cmdTestCase{{
|
|
||||||
name: "with a release",
|
|
||||||
cmd: "list",
|
|
||||||
rels: []*release.Release{
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide"}),
|
|
||||||
},
|
|
||||||
golden: "output/list-with-release.txt",
|
|
||||||
}, {
|
|
||||||
name: "list",
|
|
||||||
cmd: "list",
|
|
||||||
rels: []*release.Release{
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas"}),
|
|
||||||
},
|
|
||||||
golden: "output/list.txt",
|
|
||||||
}, {
|
|
||||||
name: "list, one deployed, one failed",
|
|
||||||
cmd: "list -q",
|
|
||||||
rels: []*release.Release{
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", Status: release.StatusFailed}),
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide", Status: release.StatusDeployed}),
|
|
||||||
},
|
|
||||||
golden: "output/list-with-failed.txt",
|
|
||||||
}, {
|
|
||||||
name: "with a release, multiple flags",
|
|
||||||
cmd: "list --uninstalled --deployed --failed -q",
|
|
||||||
rels: []*release.Release{
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", Status: release.StatusUninstalled}),
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide", Status: release.StatusDeployed}),
|
|
||||||
},
|
|
||||||
// Note: We're really only testing that the flags parsed correctly. Which results are returned
|
|
||||||
// depends on the backend. And until pkg/helm is done, we can't mock this.
|
|
||||||
golden: "output/list-with-mulitple-flags.txt",
|
|
||||||
}, {
|
|
||||||
name: "with a release, multiple flags",
|
|
||||||
cmd: "list --all -q",
|
|
||||||
rels: []*release.Release{
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", Status: release.StatusUninstalled}),
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide", Status: release.StatusDeployed}),
|
|
||||||
},
|
|
||||||
// See note on previous test.
|
|
||||||
golden: "output/list-with-mulitple-flags2.txt",
|
|
||||||
}, {
|
|
||||||
name: "with a release, multiple flags, deleting",
|
|
||||||
cmd: "list --all -q",
|
|
||||||
rels: []*release.Release{
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", Status: release.StatusUninstalling}),
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide", Status: release.StatusDeployed}),
|
|
||||||
},
|
|
||||||
// See note on previous test.
|
|
||||||
golden: "output/list-with-mulitple-flags-deleting.txt",
|
|
||||||
}, {
|
|
||||||
name: "namespace defined, multiple flags",
|
|
||||||
cmd: "list --all -q --namespace test123",
|
|
||||||
rels: []*release.Release{
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", Namespace: "test123"}),
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide", Namespace: "test321"}),
|
|
||||||
},
|
|
||||||
// See note on previous test.
|
|
||||||
golden: "output/list-with-mulitple-flags-namespaced.txt",
|
|
||||||
}, {
|
|
||||||
name: "with a pending release, multiple flags",
|
|
||||||
cmd: "list --all -q",
|
|
||||||
rels: []*release.Release{
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", Status: release.StatusPendingInstall}),
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide", Status: release.StatusDeployed}),
|
|
||||||
},
|
|
||||||
golden: "output/list-with-mulitple-flags-pending.txt",
|
|
||||||
}, {
|
|
||||||
name: "with a pending release, pending flag",
|
|
||||||
cmd: "list --pending -q",
|
|
||||||
rels: []*release.Release{
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", Status: release.StatusPendingInstall}),
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "wild-idea", Status: release.StatusPendingUpgrade}),
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "crazy-maps", Status: release.StatusPendingRollback}),
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide", Status: release.StatusDeployed}),
|
|
||||||
},
|
|
||||||
golden: "output/list-with-pending.txt",
|
|
||||||
}, {
|
|
||||||
name: "with old releases",
|
|
||||||
cmd: "list",
|
|
||||||
rels: []*release.Release{
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide"}),
|
|
||||||
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", Status: release.StatusFailed}),
|
|
||||||
},
|
|
||||||
golden: "output/list-with-old-releases.txt",
|
|
||||||
}}
|
|
||||||
|
|
||||||
runTestCmd(t, tests)
|
|
||||||
}
|
|
@ -1,2 +1,2 @@
|
|||||||
thomas-guide
|
|
||||||
atlas-guide
|
atlas-guide
|
||||||
|
thomas-guide
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
thomas-guide
|
|
||||||
atlas-guide
|
atlas-guide
|
||||||
|
thomas-guide
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
thomas-guide
|
|
||||||
atlas-guide
|
atlas-guide
|
||||||
|
thomas-guide
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
thomas-guide
|
|
||||||
atlas-guide
|
atlas-guide
|
||||||
|
thomas-guide
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
thomas-guide
|
|
||||||
atlas-guide
|
atlas-guide
|
||||||
|
thomas-guide
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
thomas-guide
|
|
||||||
atlas-guide
|
atlas-guide
|
||||||
|
thomas-guide
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
NAME REVISION UPDATED STATUS CHART NAMESPACE
|
NAME REVISION UPDATED STATUS CHART NAMESPACE
|
||||||
thomas-guide 1 1977-09-02 22:04:05 +0000 UTC deployed foo-0.1.0-beta.1 default
|
thomas-guide 1 1977-09-02 22:04:05 +0000 UTC deployed foo-0.1.0-beta.1 default
|
||||||
thomas-guide 1 1977-09-02 22:04:05 +0000 UTC failed foo-0.1.0-beta.1 default
|
thomas-guide 2 1977-09-02 22:04:05 +0000 UTC failed foo-0.1.0-beta.1 default
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
Copyright The Helm Authors.
|
||||||
|
|
||||||
|
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 action
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestListStates(t *testing.T) {
|
||||||
|
for input, expect := range map[string]ListStates{
|
||||||
|
"deployed": ListDeployed,
|
||||||
|
"uninstalled": ListUninstalled,
|
||||||
|
"uninstalling": ListUninstalling,
|
||||||
|
"superseded": ListSuperseded,
|
||||||
|
"failed": ListFailed,
|
||||||
|
"pending-install": ListPendingInstall,
|
||||||
|
"pending-rollback": ListPendingRollback,
|
||||||
|
"pending-upgrade": ListPendingUpgrade,
|
||||||
|
"unknown": ListUnknown,
|
||||||
|
"totally made up key": ListUnknown,
|
||||||
|
} {
|
||||||
|
if expect != expect.FromName(input) {
|
||||||
|
t.Errorf("Expected %d for %s", expect, input)
|
||||||
|
}
|
||||||
|
// This is a cheap way to verify that ListAll actually allows everything but Unknown
|
||||||
|
if got := expect.FromName(input); got != ListUnknown && got&ListAll == 0 {
|
||||||
|
t.Errorf("Expected %s to match the ListAll filter", input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filter := ListDeployed | ListPendingRollback
|
||||||
|
if status := filter.FromName("deployed"); filter&status == 0 {
|
||||||
|
t.Errorf("Expected %d to match mask %d", status, filter)
|
||||||
|
}
|
||||||
|
if status := filter.FromName("failed"); filter&status != 0 {
|
||||||
|
t.Errorf("Expected %d to fail to match mask %d", status, filter)
|
||||||
|
}
|
||||||
|
}
|
@ -1,83 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The Helm Authors.
|
|
||||||
|
|
||||||
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 tiller
|
|
||||||
|
|
||||||
import (
|
|
||||||
"regexp"
|
|
||||||
|
|
||||||
"k8s.io/helm/pkg/hapi"
|
|
||||||
"k8s.io/helm/pkg/hapi/release"
|
|
||||||
relutil "k8s.io/helm/pkg/releaseutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListReleases lists the releases found by the server.
|
|
||||||
func (s *ReleaseServer) ListReleases(req *hapi.ListReleasesRequest) ([]*release.Release, error) {
|
|
||||||
if len(req.StatusCodes) == 0 {
|
|
||||||
req.StatusCodes = []release.ReleaseStatus{release.StatusDeployed}
|
|
||||||
}
|
|
||||||
|
|
||||||
rels, err := s.Releases.ListFilterAll(func(r *release.Release) bool {
|
|
||||||
for _, sc := range req.StatusCodes {
|
|
||||||
if sc == r.Info.Status {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(req.Filter) != 0 {
|
|
||||||
rels, err = filterReleases(req.Filter, rels)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch req.SortBy {
|
|
||||||
case hapi.SortByName:
|
|
||||||
relutil.SortByName(rels)
|
|
||||||
case hapi.SortByLastReleased:
|
|
||||||
relutil.SortByDate(rels)
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.SortOrder == hapi.SortDesc {
|
|
||||||
ll := len(rels)
|
|
||||||
rr := make([]*release.Release, ll)
|
|
||||||
for i, item := range rels {
|
|
||||||
rr[ll-i-1] = item
|
|
||||||
}
|
|
||||||
rels = rr
|
|
||||||
}
|
|
||||||
|
|
||||||
return rels, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func filterReleases(filter string, rels []*release.Release) ([]*release.Release, error) {
|
|
||||||
preg, err := regexp.Compile(filter)
|
|
||||||
if err != nil {
|
|
||||||
return rels, err
|
|
||||||
}
|
|
||||||
matches := []*release.Release{}
|
|
||||||
for _, r := range rels {
|
|
||||||
if preg.MatchString(r.Name) {
|
|
||||||
matches = append(matches, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return matches, nil
|
|
||||||
}
|
|
@ -1,191 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The Helm Authors.
|
|
||||||
|
|
||||||
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 tiller
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"k8s.io/helm/pkg/hapi"
|
|
||||||
"k8s.io/helm/pkg/hapi/release"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestListReleases(t *testing.T) {
|
|
||||||
rs := rsFixture(t)
|
|
||||||
num := 7
|
|
||||||
for i := 0; i < num; i++ {
|
|
||||||
rel := releaseStub()
|
|
||||||
rel.Name = fmt.Sprintf("rel-%d", i)
|
|
||||||
if err := rs.Releases.Create(rel); err != nil {
|
|
||||||
t.Fatalf("Could not store mock release: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rels, err := rs.ListReleases(&hapi.ListReleasesRequest{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed listing: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rels) != num {
|
|
||||||
t.Errorf("Expected %d releases, got %d", num, len(rels))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListReleasesByStatus(t *testing.T) {
|
|
||||||
rs := rsFixture(t)
|
|
||||||
stubs := []*release.Release{
|
|
||||||
namedReleaseStub("kamal", release.StatusDeployed),
|
|
||||||
namedReleaseStub("astrolabe", release.StatusUninstalled),
|
|
||||||
namedReleaseStub("octant", release.StatusFailed),
|
|
||||||
namedReleaseStub("sextant", release.StatusUnknown),
|
|
||||||
}
|
|
||||||
for _, stub := range stubs {
|
|
||||||
if err := rs.Releases.Create(stub); err != nil {
|
|
||||||
t.Fatalf("Could not create stub: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
statusCodes []release.ReleaseStatus
|
|
||||||
names []string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
names: []string{"kamal"},
|
|
||||||
statusCodes: []release.ReleaseStatus{release.StatusDeployed},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
names: []string{"astrolabe"},
|
|
||||||
statusCodes: []release.ReleaseStatus{release.StatusUninstalled},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
names: []string{"kamal", "octant"},
|
|
||||||
statusCodes: []release.ReleaseStatus{release.StatusDeployed, release.StatusFailed},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
names: []string{"kamal", "astrolabe", "octant", "sextant"},
|
|
||||||
statusCodes: []release.ReleaseStatus{
|
|
||||||
release.StatusDeployed,
|
|
||||||
release.StatusUninstalled,
|
|
||||||
release.StatusFailed,
|
|
||||||
release.StatusUnknown,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, tt := range tests {
|
|
||||||
rels, err := rs.ListReleases(&hapi.ListReleasesRequest{StatusCodes: tt.statusCodes, Offset: "", Limit: 64})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed listing %d: %s", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(tt.names) != len(rels) {
|
|
||||||
t.Fatalf("Expected %d releases, got %d", len(tt.names), len(rels))
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, name := range tt.names {
|
|
||||||
found := false
|
|
||||||
for _, rel := range rels {
|
|
||||||
if rel.Name == name {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
t.Errorf("%d: Did not find name %q", i, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListReleasesSort(t *testing.T) {
|
|
||||||
rs := rsFixture(t)
|
|
||||||
|
|
||||||
// Put them in by reverse order so that the mock doesn't "accidentally"
|
|
||||||
// sort.
|
|
||||||
num := 7
|
|
||||||
for i := num; i > 0; i-- {
|
|
||||||
rel := releaseStub()
|
|
||||||
rel.Name = fmt.Sprintf("rel-%d", i)
|
|
||||||
if err := rs.Releases.Create(rel); err != nil {
|
|
||||||
t.Fatalf("Could not store mock release: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
limit := 6
|
|
||||||
req := &hapi.ListReleasesRequest{
|
|
||||||
Offset: "",
|
|
||||||
Limit: int64(limit),
|
|
||||||
SortBy: hapi.SortByName,
|
|
||||||
}
|
|
||||||
rels, err := rs.ListReleases(req)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed listing: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// if len(rels) != limit {
|
|
||||||
// t.Errorf("Expected %d releases, got %d", limit, len(rels))
|
|
||||||
// }
|
|
||||||
|
|
||||||
for i := 0; i < limit; i++ {
|
|
||||||
n := fmt.Sprintf("rel-%d", i+1)
|
|
||||||
if rels[i].Name != n {
|
|
||||||
t.Errorf("Expected %q, got %q", n, rels[i].Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListReleasesFilter(t *testing.T) {
|
|
||||||
rs := rsFixture(t)
|
|
||||||
names := []string{
|
|
||||||
"axon",
|
|
||||||
"dendrite",
|
|
||||||
"neuron",
|
|
||||||
"neuroglia",
|
|
||||||
"synapse",
|
|
||||||
"nucleus",
|
|
||||||
"organelles",
|
|
||||||
}
|
|
||||||
num := 7
|
|
||||||
for i := 0; i < num; i++ {
|
|
||||||
rel := releaseStub()
|
|
||||||
rel.Name = names[i]
|
|
||||||
if err := rs.Releases.Create(rel); err != nil {
|
|
||||||
t.Fatalf("Could not store mock release: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &hapi.ListReleasesRequest{
|
|
||||||
Offset: "",
|
|
||||||
Limit: 64,
|
|
||||||
Filter: "neuro[a-z]+",
|
|
||||||
SortBy: hapi.SortByName,
|
|
||||||
}
|
|
||||||
rels, err := rs.ListReleases(req)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed listing: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rels) != 2 {
|
|
||||||
t.Errorf("Expected 2 releases, got %d", len(rels))
|
|
||||||
}
|
|
||||||
|
|
||||||
if rels[0].Name != "neuroglia" {
|
|
||||||
t.Errorf("Unexpected sort order: %v.", rels)
|
|
||||||
}
|
|
||||||
if rels[1].Name != "neuron" {
|
|
||||||
t.Errorf("Unexpected sort order: %v.", rels)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in new issue