mirror of
https://github.com/helm/helm.git
synced 2026-05-28 04:35:48 -04:00
fix(tests): Add namespace support to memory driver
Signed-off-by: Marc Khouzam <marc.khouzam@montreal.ca>
This commit is contained in:
parent
98962dce3f
commit
e6d2d10bad
7 changed files with 190 additions and 55 deletions
|
|
@ -143,6 +143,9 @@ func executeActionCommandC(store *storage.Storage, cmd string) (*cobra.Command,
|
|||
root.SetOutput(buf)
|
||||
root.SetArgs(args)
|
||||
|
||||
if mem, ok := store.Driver.(*driver.Memory); ok {
|
||||
mem.SetNamespace(settings.Namespace())
|
||||
}
|
||||
c, err := root.ExecuteC()
|
||||
|
||||
return c, buf.String(), err
|
||||
|
|
|
|||
|
|
@ -131,6 +131,16 @@ func TestListCmd(t *testing.T) {
|
|||
},
|
||||
Chart: chartInfo,
|
||||
},
|
||||
{
|
||||
Name: "starlord",
|
||||
Version: 2,
|
||||
Namespace: "milano",
|
||||
Info: &release.Info{
|
||||
LastDeployed: timestamp1,
|
||||
Status: release.StatusDeployed,
|
||||
},
|
||||
Chart: chartInfo,
|
||||
},
|
||||
}
|
||||
|
||||
tests := []cmdTestCase{{
|
||||
|
|
@ -203,6 +213,11 @@ func TestListCmd(t *testing.T) {
|
|||
cmd: "list --uninstalling",
|
||||
golden: "output/list-uninstalling.txt",
|
||||
rels: releaseFixture,
|
||||
}, {
|
||||
name: "list releases in another namespace",
|
||||
cmd: "list -n milano",
|
||||
golden: "output/list-namespace.txt",
|
||||
rels: releaseFixture,
|
||||
}}
|
||||
runTestCmd(t, tests)
|
||||
}
|
||||
|
|
|
|||
2
cmd/helm/testdata/output/list-namespace.txt
vendored
Normal file
2
cmd/helm/testdata/output/list-namespace.txt
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
|
||||
starlord milano 2 2016-01-16 00:00:01 +0000 UTC deployed chickadee-1.0.0 0.0.1
|
||||
|
|
@ -241,6 +241,7 @@ func (c *Configuration) Init(getter genericclioptions.RESTClientGetter, namespac
|
|||
store = storage.Init(d)
|
||||
case "memory":
|
||||
d := driver.NewMemory()
|
||||
d.SetNamespace(namespace)
|
||||
store = storage.Init(d)
|
||||
default:
|
||||
// Not sure what to do here.
|
||||
|
|
|
|||
|
|
@ -26,18 +26,33 @@ import (
|
|||
|
||||
var _ Driver = (*Memory)(nil)
|
||||
|
||||
// MemoryDriverName is the string name of this driver.
|
||||
const MemoryDriverName = "Memory"
|
||||
const (
|
||||
// MemoryDriverName is the string name of this driver.
|
||||
MemoryDriverName = "Memory"
|
||||
|
||||
defaultNamespace = "default"
|
||||
)
|
||||
|
||||
// A map of release names to list of release records
|
||||
type memReleases map[string]records
|
||||
|
||||
// Memory is the in-memory storage driver implementation.
|
||||
type Memory struct {
|
||||
sync.RWMutex
|
||||
cache map[string]records
|
||||
namespace string
|
||||
// A map of namespaces to releases
|
||||
cache map[string]memReleases
|
||||
}
|
||||
|
||||
// NewMemory initializes a new memory driver.
|
||||
func NewMemory() *Memory {
|
||||
return &Memory{cache: map[string]records{}}
|
||||
return &Memory{cache: map[string]memReleases{}, namespace: "default"}
|
||||
}
|
||||
|
||||
// SetNamespace sets a specific namespace in which releases will be accessed.
|
||||
// An empty string indicates all namespaces (for the list operation)
|
||||
func (mem *Memory) SetNamespace(ns string) {
|
||||
mem.namespace = ns
|
||||
}
|
||||
|
||||
// Name returns the name of the driver.
|
||||
|
|
@ -56,7 +71,7 @@ func (mem *Memory) Get(key string) (*rspb.Release, error) {
|
|||
if _, err := strconv.Atoi(ver); err != nil {
|
||||
return nil, ErrInvalidKey
|
||||
}
|
||||
if recs, ok := mem.cache[name]; ok {
|
||||
if recs, ok := mem.cache[mem.namespace][name]; ok {
|
||||
if r := recs.Get(key); r != nil {
|
||||
return r.rls, nil
|
||||
}
|
||||
|
|
@ -72,13 +87,23 @@ func (mem *Memory) List(filter func(*rspb.Release) bool) ([]*rspb.Release, error
|
|||
defer unlock(mem.rlock())
|
||||
|
||||
var ls []*rspb.Release
|
||||
for _, recs := range mem.cache {
|
||||
recs.Iter(func(_ int, rec *record) bool {
|
||||
if filter(rec.rls) {
|
||||
ls = append(ls, rec.rls)
|
||||
}
|
||||
return true
|
||||
})
|
||||
for namespace := range mem.cache {
|
||||
if mem.namespace != "" {
|
||||
// Should only list releases of this namespace
|
||||
namespace = mem.namespace
|
||||
}
|
||||
for _, recs := range mem.cache[namespace] {
|
||||
recs.Iter(func(_ int, rec *record) bool {
|
||||
if filter(rec.rls) {
|
||||
ls = append(ls, rec.rls)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
if mem.namespace != "" {
|
||||
// Should only list releases of this namespace
|
||||
break
|
||||
}
|
||||
}
|
||||
return ls, nil
|
||||
}
|
||||
|
|
@ -93,18 +118,28 @@ func (mem *Memory) Query(keyvals map[string]string) ([]*rspb.Release, error) {
|
|||
lbs.fromMap(keyvals)
|
||||
|
||||
var ls []*rspb.Release
|
||||
for _, recs := range mem.cache {
|
||||
recs.Iter(func(_ int, rec *record) bool {
|
||||
// A query for a release name that doesn't exist (has been deleted)
|
||||
// can cause rec to be nil.
|
||||
if rec == nil {
|
||||
return false
|
||||
}
|
||||
if rec.lbs.match(lbs) {
|
||||
ls = append(ls, rec.rls)
|
||||
}
|
||||
return true
|
||||
})
|
||||
for namespace := range mem.cache {
|
||||
if mem.namespace != "" {
|
||||
// Should only query releases of this namespace
|
||||
namespace = mem.namespace
|
||||
}
|
||||
for _, recs := range mem.cache[namespace] {
|
||||
recs.Iter(func(_ int, rec *record) bool {
|
||||
// A query for a release name that doesn't exist (has been deleted)
|
||||
// can cause rec to be nil.
|
||||
if rec == nil {
|
||||
return false
|
||||
}
|
||||
if rec.lbs.match(lbs) {
|
||||
ls = append(ls, rec.rls)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
if mem.namespace != "" {
|
||||
// Should only query releases of this namespace
|
||||
break
|
||||
}
|
||||
}
|
||||
return ls, nil
|
||||
}
|
||||
|
|
@ -113,14 +148,25 @@ func (mem *Memory) Query(keyvals map[string]string) ([]*rspb.Release, error) {
|
|||
func (mem *Memory) Create(key string, rls *rspb.Release) error {
|
||||
defer unlock(mem.wlock())
|
||||
|
||||
if recs, ok := mem.cache[rls.Name]; ok {
|
||||
// For backwards compatibility, we protect against an unset namespace
|
||||
namespace := rls.Namespace
|
||||
if namespace == "" {
|
||||
namespace = defaultNamespace
|
||||
}
|
||||
mem.SetNamespace(namespace)
|
||||
|
||||
if _, ok := mem.cache[namespace]; !ok {
|
||||
mem.cache[namespace] = memReleases{}
|
||||
}
|
||||
|
||||
if recs, ok := mem.cache[namespace][rls.Name]; ok {
|
||||
if err := recs.Add(newRecord(key, rls)); err != nil {
|
||||
return err
|
||||
}
|
||||
mem.cache[rls.Name] = recs
|
||||
mem.cache[namespace][rls.Name] = recs
|
||||
return nil
|
||||
}
|
||||
mem.cache[rls.Name] = records{newRecord(key, rls)}
|
||||
mem.cache[namespace][rls.Name] = records{newRecord(key, rls)}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -128,9 +174,18 @@ func (mem *Memory) Create(key string, rls *rspb.Release) error {
|
|||
func (mem *Memory) Update(key string, rls *rspb.Release) error {
|
||||
defer unlock(mem.wlock())
|
||||
|
||||
if rs, ok := mem.cache[rls.Name]; ok && rs.Exists(key) {
|
||||
rs.Replace(key, newRecord(key, rls))
|
||||
return nil
|
||||
// For backwards compatibility, we protect against an unset namespace
|
||||
namespace := rls.Namespace
|
||||
if namespace == "" {
|
||||
namespace = defaultNamespace
|
||||
}
|
||||
mem.SetNamespace(namespace)
|
||||
|
||||
if _, ok := mem.cache[namespace]; ok {
|
||||
if rs, ok := mem.cache[namespace][rls.Name]; ok && rs.Exists(key) {
|
||||
rs.Replace(key, newRecord(key, rls))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return ErrReleaseNotFound
|
||||
}
|
||||
|
|
@ -150,11 +205,13 @@ func (mem *Memory) Delete(key string) (*rspb.Release, error) {
|
|||
if _, err := strconv.Atoi(ver); err != nil {
|
||||
return nil, ErrInvalidKey
|
||||
}
|
||||
if recs, ok := mem.cache[name]; ok {
|
||||
if r := recs.Remove(key); r != nil {
|
||||
// recs.Remove changes the slice reference, so we have to re-assign it.
|
||||
mem.cache[name] = recs
|
||||
return r.rls, nil
|
||||
if _, ok := mem.cache[mem.namespace]; ok {
|
||||
if recs, ok := mem.cache[mem.namespace][name]; ok {
|
||||
if r := recs.Remove(key); r != nil {
|
||||
// recs.Remove changes the slice reference, so we have to re-assign it.
|
||||
mem.cache[mem.namespace][name] = recs
|
||||
return r.rls, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, ErrReleaseNotFound
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ func TestMemoryCreate(t *testing.T) {
|
|||
err bool
|
||||
}{
|
||||
{
|
||||
"create should success",
|
||||
"create should succeed",
|
||||
releaseStub("rls-c", 1, "default", rspb.StatusDeployed),
|
||||
false,
|
||||
},
|
||||
|
|
@ -46,6 +46,16 @@ func TestMemoryCreate(t *testing.T) {
|
|||
releaseStub("rls-a", 1, "default", rspb.StatusDeployed),
|
||||
true,
|
||||
},
|
||||
{
|
||||
"create in namespace should succeed",
|
||||
releaseStub("rls-a", 1, "mynamespace", rspb.StatusDeployed),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"create in other namespace should fail (release already exists)",
|
||||
releaseStub("rls-c", 1, "mynamespace", rspb.StatusDeployed),
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
ts := tsFixtureMemory(t)
|
||||
|
|
@ -57,26 +67,34 @@ func TestMemoryCreate(t *testing.T) {
|
|||
if !tt.err {
|
||||
t.Fatalf("failed to create %q: %s", tt.desc, err)
|
||||
}
|
||||
} else if tt.err {
|
||||
t.Fatalf("Did not get expected error for %q\n", tt.desc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMemoryGet(t *testing.T) {
|
||||
var tests = []struct {
|
||||
desc string
|
||||
key string
|
||||
err bool
|
||||
desc string
|
||||
key string
|
||||
namespace string
|
||||
err bool
|
||||
}{
|
||||
{"release key should exist", "rls-a.v1", false},
|
||||
{"release key should not exist", "rls-a.v5", true},
|
||||
{"release key should exist", "rls-a.v1", "default", false},
|
||||
{"release key should not exist", "rls-a.v5", "default", true},
|
||||
{"release key in namespace should exist", "rls-c.v1", "mynamespace", false},
|
||||
{"release key in namespace should not exist", "rls-a.v1", "mynamespace", true},
|
||||
}
|
||||
|
||||
ts := tsFixtureMemory(t)
|
||||
for _, tt := range tests {
|
||||
ts.SetNamespace(tt.namespace)
|
||||
if _, err := ts.Get(tt.key); err != nil {
|
||||
if !tt.err {
|
||||
t.Fatalf("Failed %q to get '%s': %q\n", tt.desc, tt.key, err)
|
||||
}
|
||||
} else if tt.err {
|
||||
t.Fatalf("Did not get expected error for %q '%s'\n", tt.desc, tt.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -123,19 +141,28 @@ func TestMemoryList(t *testing.T) {
|
|||
|
||||
func TestMemoryQuery(t *testing.T) {
|
||||
var tests = []struct {
|
||||
desc string
|
||||
xlen int
|
||||
lbs map[string]string
|
||||
desc string
|
||||
xlen int
|
||||
namespace string
|
||||
lbs map[string]string
|
||||
}{
|
||||
{
|
||||
"should be 2 query results",
|
||||
2,
|
||||
"default",
|
||||
map[string]string{"status": "deployed"},
|
||||
},
|
||||
{
|
||||
"should be 1 query result",
|
||||
1,
|
||||
"mynamespace",
|
||||
map[string]string{"status": "deployed"},
|
||||
},
|
||||
}
|
||||
|
||||
ts := tsFixtureMemory(t)
|
||||
for _, tt := range tests {
|
||||
ts.SetNamespace(tt.namespace)
|
||||
l, err := ts.Query(tt.lbs)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to query: %s\n", err)
|
||||
|
|
@ -162,8 +189,20 @@ func TestMemoryUpdate(t *testing.T) {
|
|||
},
|
||||
{
|
||||
"update release does not exist",
|
||||
"rls-z.v1",
|
||||
releaseStub("rls-z", 1, "default", rspb.StatusUninstalled),
|
||||
"rls-c.v1",
|
||||
releaseStub("rls-c", 1, "default", rspb.StatusUninstalled),
|
||||
true,
|
||||
},
|
||||
{
|
||||
"update release status in namespace",
|
||||
"rls-c.v4",
|
||||
releaseStub("rls-c", 4, "mynamespace", rspb.StatusSuperseded),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"update release in namespace does not exist",
|
||||
"rls-a.v1",
|
||||
releaseStub("rls-a", 1, "mynamespace", rspb.StatusUninstalled),
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
|
@ -175,8 +214,11 @@ func TestMemoryUpdate(t *testing.T) {
|
|||
t.Fatalf("Failed %q: %s\n", tt.desc, err)
|
||||
}
|
||||
continue
|
||||
} else if tt.err {
|
||||
t.Fatalf("Did not get expected error for %q '%s'\n", tt.desc, tt.key)
|
||||
}
|
||||
|
||||
ts.SetNamespace(tt.rls.Namespace)
|
||||
r, err := ts.Get(tt.key)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get: %s\n", err)
|
||||
|
|
@ -190,26 +232,35 @@ func TestMemoryUpdate(t *testing.T) {
|
|||
|
||||
func TestMemoryDelete(t *testing.T) {
|
||||
var tests = []struct {
|
||||
desc string
|
||||
key string
|
||||
err bool
|
||||
desc string
|
||||
key string
|
||||
namespace string
|
||||
err bool
|
||||
}{
|
||||
{"release key should exist", "rls-a.v1", false},
|
||||
{"release key should not exist", "rls-a.v5", true},
|
||||
{"release key should exist", "rls-a.v4", "default", false},
|
||||
{"release key should not exist", "rls-a.v5", "default", true},
|
||||
{"release key from other namespace should not exist", "rls-c.v4", "default", true},
|
||||
{"release key from namespace should exist", "rls-c.v4", "mynamespace", false},
|
||||
{"release key from namespace should not exist", "rls-c.v5", "mynamespace", true},
|
||||
{"release key from namespace2 should not exist", "rls-a.v4", "mynamespace", true},
|
||||
}
|
||||
|
||||
ts := tsFixtureMemory(t)
|
||||
start, err := ts.Query(map[string]string{"name": "rls-a"})
|
||||
ts.SetNamespace("")
|
||||
start, err := ts.Query(map[string]string{"status": "deployed"})
|
||||
if err != nil {
|
||||
t.Errorf("Query failed: %s", err)
|
||||
}
|
||||
startLen := len(start)
|
||||
for _, tt := range tests {
|
||||
ts.SetNamespace(tt.namespace)
|
||||
if rel, err := ts.Delete(tt.key); err != nil {
|
||||
if !tt.err {
|
||||
t.Fatalf("Failed %q to get '%s': %q\n", tt.desc, tt.key, err)
|
||||
}
|
||||
continue
|
||||
} else if tt.err {
|
||||
t.Fatalf("Did not get expected error for %q '%s'\n", tt.desc, tt.key)
|
||||
} else if fmt.Sprintf("%s.v%d", rel.Name, rel.Version) != tt.key {
|
||||
t.Fatalf("Asked for delete on %s, but deleted %d", tt.key, rel.Version)
|
||||
}
|
||||
|
|
@ -220,14 +271,15 @@ func TestMemoryDelete(t *testing.T) {
|
|||
}
|
||||
|
||||
// Make sure that the deleted records are gone.
|
||||
end, err := ts.Query(map[string]string{"name": "rls-a"})
|
||||
ts.SetNamespace("")
|
||||
end, err := ts.Query(map[string]string{"status": "deployed"})
|
||||
if err != nil {
|
||||
t.Errorf("Query failed: %s", err)
|
||||
}
|
||||
endLen := len(end)
|
||||
|
||||
if startLen <= endLen {
|
||||
t.Errorf("expected start %d to be less than end %d", startLen, endLen)
|
||||
if startLen-2 != endLen {
|
||||
t.Errorf("expected end to be %d instead of %d", startLen-2, endLen)
|
||||
for _, ee := range end {
|
||||
t.Logf("Name: %s, Version: %d", ee.Name, ee.Version)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,11 @@ func tsFixtureMemory(t *testing.T) *Memory {
|
|||
releaseStub("rls-b", 1, "default", rspb.StatusSuperseded),
|
||||
releaseStub("rls-b", 3, "default", rspb.StatusSuperseded),
|
||||
releaseStub("rls-b", 2, "default", rspb.StatusSuperseded),
|
||||
// rls-c in other namespace
|
||||
releaseStub("rls-c", 4, "mynamespace", rspb.StatusDeployed),
|
||||
releaseStub("rls-c", 1, "mynamespace", rspb.StatusSuperseded),
|
||||
releaseStub("rls-c", 3, "mynamespace", rspb.StatusSuperseded),
|
||||
releaseStub("rls-c", 2, "mynamespace", rspb.StatusSuperseded),
|
||||
}
|
||||
|
||||
mem := NewMemory()
|
||||
|
|
|
|||
Loading…
Reference in a new issue