From 93190c6fd34a6516f108517edc90d4477bc2e5ae Mon Sep 17 00:00:00 2001 From: fibonacci1729 Date: Tue, 23 Aug 2016 12:14:09 -0600 Subject: [PATCH 01/10] chore(pkg/storage): introduce key name convention for storage objects with updated tests --- pkg/storage/driver/cfgmaps.go | 16 +++---- pkg/storage/driver/cfgmaps_test.go | 37 ++++++++------- pkg/storage/driver/driver.go | 4 +- pkg/storage/driver/memory.go | 12 ++--- pkg/storage/driver/memory_test.go | 72 +++++++++++++++++++++++------- pkg/storage/storage.go | 30 ++++++++----- pkg/storage/storage_test.go | 15 ++++--- 7 files changed, 119 insertions(+), 67 deletions(-) diff --git a/pkg/storage/driver/cfgmaps.go b/pkg/storage/driver/cfgmaps.go index afe031bf5..942634674 100644 --- a/pkg/storage/driver/cfgmaps.go +++ b/pkg/storage/driver/cfgmaps.go @@ -114,7 +114,7 @@ func (cfgmaps *ConfigMaps) List(filter func(*rspb.Release) bool) ([]*rspb.Releas // Create creates a new ConfigMap holding the release. If the // ConfigMap already exists, ErrReleaseExists is returned. -func (cfgmaps *ConfigMaps) Create(rls *rspb.Release) error { +func (cfgmaps *ConfigMaps) Create(key string, rls *rspb.Release) error { // set labels for configmaps object meta data var lbs labels @@ -122,9 +122,9 @@ func (cfgmaps *ConfigMaps) Create(rls *rspb.Release) error { lbs.set("CREATED_AT", strconv.Itoa(int(time.Now().Unix()))) // create a new configmap to hold the release - obj, err := newConfigMapsObject(rls, lbs) + obj, err := newConfigMapsObject(key, rls, lbs) if err != nil { - logerrf(err, "create: failed to encode release %q", rls.Name) + logerrf(err, "create: failed to encode release %q", key) return err } // push the configmap object out into the kubiverse @@ -141,7 +141,7 @@ func (cfgmaps *ConfigMaps) Create(rls *rspb.Release) error { // Update updates the ConfigMap holding the release. If not found // the ConfigMap is created to hold the release. -func (cfgmaps *ConfigMaps) Update(rls *rspb.Release) error { +func (cfgmaps *ConfigMaps) Update(key string, rls *rspb.Release) error { // set labels for configmaps object meta data var lbs labels @@ -149,9 +149,9 @@ func (cfgmaps *ConfigMaps) Update(rls *rspb.Release) error { lbs.set("MODIFIED_AT", strconv.Itoa(int(time.Now().Unix()))) // create a new configmap object to hold the release - obj, err := newConfigMapsObject(rls, lbs) + obj, err := newConfigMapsObject(key, rls, lbs) if err != nil { - logerrf(err, "update: failed to encode release %q", rls.Name) + logerrf(err, "update: failed to encode release %q", key) return err } // push the configmap object out into the kubiverse @@ -194,7 +194,7 @@ func (cfgmaps *ConfigMaps) Delete(key string) (rls *rspb.Release, err error) { // "OWNER" - owner of the configmap, currently "TILLER". // "NAME" - name of the release. // -func newConfigMapsObject(rls *rspb.Release, lbs labels) (*api.ConfigMap, error) { +func newConfigMapsObject(objkey string, rls *rspb.Release, lbs labels) (*api.ConfigMap, error) { const owner = "TILLER" // encode the release @@ -216,7 +216,7 @@ func newConfigMapsObject(rls *rspb.Release, lbs labels) (*api.ConfigMap, error) // create and return configmap object return &api.ConfigMap{ ObjectMeta: api.ObjectMeta{ - Name: rls.Name, + Name: objkey, Labels: lbs.toMap(), }, Data: map[string]string{"release": s}, diff --git a/pkg/storage/driver/cfgmaps_test.go b/pkg/storage/driver/cfgmaps_test.go index bf2c3f7da..5f473809e 100644 --- a/pkg/storage/driver/cfgmaps_test.go +++ b/pkg/storage/driver/cfgmaps_test.go @@ -37,8 +37,10 @@ func TestConfigMapName(t *testing.T) { } func TestConfigMapGet(t *testing.T) { - key := "key-1" - rel := newTestRelease(key, 1, rspb.Status_DEPLOYED) + vers := int32(1) + name := "smug-pigeon" + key := testKey(name, vers) + rel := newTestRelease(name, vers, rspb.Status_DEPLOYED) cfgmaps := newTestFixture(t, []*rspb.Release{rel}...) @@ -103,11 +105,13 @@ func TestConfigMapList(t *testing.T) { func TestConfigMapCreate(t *testing.T) { cfgmaps := newTestFixture(t) - key := "key-1" - rel := newTestRelease(key, 1, rspb.Status_DEPLOYED) + vers := int32(1) + name := "smug-pigeon" + key := testKey(name, vers) + rel := newTestRelease(name, vers, rspb.Status_DEPLOYED) // store the release in a configmap - if err := cfgmaps.Create(rel); err != nil { + if err := cfgmaps.Create(key, rel); err != nil { t.Fatalf("Failed to create release with key %q: %s", key, err) } @@ -124,16 +128,18 @@ func TestConfigMapCreate(t *testing.T) { } func TestConfigMapUpdate(t *testing.T) { - key := "key-1" - rel := newTestRelease(key, 1, rspb.Status_DEPLOYED) + vers := int32(1) + name := "smug-pigeon" + key := testKey(name, vers) + rel := newTestRelease(name, vers, rspb.Status_DEPLOYED) cfgmaps := newTestFixture(t, []*rspb.Release{rel}...) - // modify release status code & version - rel = newTestRelease(key, 2, rspb.Status_SUPERSEDED) + // modify release status code + rel.Info.Status.Code = rspb.Status_SUPERSEDED // perform the update - if err := cfgmaps.Update(rel); err != nil { + if err := cfgmaps.Update(key, rel); err != nil { t.Fatalf("Failed to update release: %s", err) } @@ -144,11 +150,8 @@ func TestConfigMapUpdate(t *testing.T) { } // check release has actually been updated by comparing modified fields - switch { - case rel.Info.Status.Code != got.Info.Status.Code: + if rel.Info.Status.Code != got.Info.Status.Code { t.Errorf("Expected status %s, got status %s", rel.Info.Status.Code, got.Info.Status.Code) - case rel.Version != got.Version: - t.Errorf("Expected version %d, got version %d", rel.Version, got.Version) } } @@ -177,11 +180,13 @@ func (mock *MockConfigMapsInterface) Init(t *testing.T, releases ...*rspb.Releas mock.objects = map[string]*api.ConfigMap{} for _, rls := range releases { - cfgmap, err := newConfigMapsObject(rls, nil) + objkey := testKey(rls.Name, rls.Version) + + cfgmap, err := newConfigMapsObject(objkey, rls, nil) if err != nil { t.Fatalf("Failed to create configmap: %s", err) } - mock.objects[rls.Name] = cfgmap + mock.objects[objkey] = cfgmap } } diff --git a/pkg/storage/driver/driver.go b/pkg/storage/driver/driver.go index f3593d278..96a096497 100644 --- a/pkg/storage/driver/driver.go +++ b/pkg/storage/driver/driver.go @@ -34,7 +34,7 @@ var ( // Create stores the release or returns ErrReleaseExists // if an identical release already exists. type Creator interface { - Create(rls *rspb.Release) error + Create(key string, rls *rspb.Release) error } // Updator is the interface that wraps the Update method. @@ -42,7 +42,7 @@ type Creator interface { // Update updates an existing release or returns // ErrReleaseNotFound if the release does not exist. type Updator interface { - Update(rls *rspb.Release) error + Update(key string, rls *rspb.Release) error } // Deletor is the interface that wraps the Delete method. diff --git a/pkg/storage/driver/memory.go b/pkg/storage/driver/memory.go index 76351b1a7..91e295f97 100644 --- a/pkg/storage/driver/memory.go +++ b/pkg/storage/driver/memory.go @@ -65,22 +65,22 @@ func (mem *Memory) List(filter func(*rspb.Release) bool) ([]*rspb.Release, error } // Create creates a new release or returns ErrReleaseExists. -func (mem *Memory) Create(rls *rspb.Release) error { +func (mem *Memory) Create(key string, rls *rspb.Release) error { defer unlock(mem.wlock()) - if _, ok := mem.cache[rls.Name]; ok { + if _, ok := mem.cache[key]; ok { return ErrReleaseExists } - mem.cache[rls.Name] = rls + mem.cache[key] = rls return nil } // Update updates a release or returns ErrReleaseNotFound. -func (mem *Memory) Update(rls *rspb.Release) error { +func (mem *Memory) Update(key string, rls *rspb.Release) error { defer unlock(mem.wlock()) - if _, ok := mem.cache[rls.Name]; ok { - mem.cache[rls.Name] = rls + if _, ok := mem.cache[key]; ok { + mem.cache[key] = rls return nil } return ErrReleaseNotFound diff --git a/pkg/storage/driver/memory_test.go b/pkg/storage/driver/memory_test.go index 2c50fd1a4..bf49b4c19 100644 --- a/pkg/storage/driver/memory_test.go +++ b/pkg/storage/driver/memory_test.go @@ -17,6 +17,7 @@ limitations under the License. package driver // import "k8s.io/helm/pkg/storage/driver" import ( + "fmt" "reflect" "testing" @@ -33,11 +34,14 @@ func TestMemoryName(t *testing.T) { } func TestMemoryGet(t *testing.T) { - key := "test-1" - rls := &rspb.Release{Name: key} + vers := int32(1) + name := "smug-pigeon" + key := testKey(name, vers) + + rls := &rspb.Release{Name: name, Version: vers} mem := NewMemory() - if err := mem.Create(rls); err != nil { + if err := mem.Create(key, rls); err != nil { t.Fatalf("Failed create: %s", err) } @@ -45,46 +49,76 @@ func TestMemoryGet(t *testing.T) { if err != nil { t.Errorf("Could not get %s: %s", key, err) } - if res.Name != key { - t.Errorf("Expected %s, got %s", key, res.Name) + if res.Name != name { + t.Errorf("Expected name %s, got name %s", key, res.Name) + } + if res.Version != vers { + t.Errorf("Expected version %d, got version %d", vers, res.Version) } } func TestMemoryCreate(t *testing.T) { - key := "test-1" - rls := &rspb.Release{Name: key} + vers := int32(1) + name := "smug-pigeon" + key := testKey(name, vers) + + rls := &rspb.Release{Name: name, Version: vers} mem := NewMemory() - if err := mem.Create(rls); err != nil { + if err := mem.Create(key, rls); err != nil { t.Fatalf("Failed created: %s", err) } - if mem.cache[key].Name != key { + if mem.cache[key].Name != name { t.Errorf("Unexpected release name: %s", mem.cache[key].Name) } + if mem.cache[key].Version != vers { + t.Errorf("Unexpected release version: %d", mem.cache[key].Version) + } } func TestMemoryUpdate(t *testing.T) { - key := "test-1" - rls := &rspb.Release{Name: key} + vers := int32(1) + name := "smug-pigeon" + key := testKey(name, vers) + + rls := &rspb.Release{ + Name: name, + Version: vers, + Info: &rspb.Info{Status: &rspb.Status{Code: rspb.Status_DEPLOYED}}, + } mem := NewMemory() - if err := mem.Create(rls); err != nil { + if err := mem.Create(key, rls); err != nil { t.Fatalf("Failed create: %s", err) } - if err := mem.Update(rls); err != nil { + + // make an update to the release + rls.Info.Status.Code = rspb.Status_DELETED + + if err := mem.Update(key, rls); err != nil { t.Fatalf("Failed update: %s", err) } - if mem.cache[key].Name != key { + + if mem.cache[key].Name != name { t.Errorf("Unexpected release name: %s", mem.cache[key].Name) } + if mem.cache[key].Version != vers { + t.Errorf("Unexpected release version: %d", mem.cache[key].Version) + } + if mem.cache[key].Info.Status.Code != rspb.Status_DELETED { + t.Errorf("Unexpected status code: %s", mem.cache[key].Info.Status.Code) + } } func TestMemoryDelete(t *testing.T) { - key := "test-1" - rls := &rspb.Release{Name: key} + vers := int32(1) + name := "smug-pigeon" + key := testKey(name, vers) + + rls := &rspb.Release{Name: key, Version: vers} mem := NewMemory() - if err := mem.Create(rls); err != nil { + if err := mem.Create(key, rls); err != nil { t.Fatalf("Failed create: %s", err) } @@ -99,3 +133,7 @@ func TestMemoryDelete(t *testing.T) { t.Errorf("Expected %s, got %s", rls, res) } } + +func testKey(name string, version int32) string { + return fmt.Sprintf("%s#v%d", name, version) +} diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index 85b204fcc..2b39d2743 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -17,6 +17,7 @@ limitations under the License. package storage // import "k8s.io/helm/pkg/storage" import ( + "fmt" "log" rspb "k8s.io/helm/pkg/proto/hapi/release" @@ -30,34 +31,34 @@ type Storage struct { // Get retrieves the release from storage. An error is returned // if the storage driver failed to fetch the release, or the -// release identified by key does not exist. -func (s *Storage) Get(key string) (*rspb.Release, error) { - log.Printf("Getting release %q from storage\n", key) - return s.Driver.Get(key) +// release identified by the key, version pair does not exist. +func (s *Storage) Get(name string, version int32) (*rspb.Release, error) { + log.Printf("Getting release %q (v%d) from storage\n", name, version) + return s.Driver.Get(makeKey(name, version)) } // Create creates a new storage entry holding the release. An // error is returned if the storage driver failed to store the // release, or a release with identical an key already exists. func (s *Storage) Create(rls *rspb.Release) error { - log.Printf("Create release %q in storage\n", rls.Name) - return s.Driver.Create(rls) + log.Printf("Create release %q (v%d) in storage\n", rls.Name, rls.Version) + return s.Driver.Create(makeKey(rls.Name, rls.Version), rls) } // Update update the release in storage. An error is returned if the // storage backend fails to update the release or if the release // does not exist. func (s *Storage) Update(rls *rspb.Release) error { - log.Printf("Updating %q in storage\n", rls.Name) - return s.Driver.Update(rls) + log.Printf("Updating %q (v%d) in storage\n", rls.Name, rls.Version) + return s.Driver.Update(makeKey(rls.Name, rls.Version), rls) } // Delete deletes the release from storage. An error is returned if // the storage backend fails to delete the release or if the release // does not exist. -func (s *Storage) Delete(key string) (*rspb.Release, error) { - log.Printf("Deleting release %q from storage\n", key) - return s.Driver.Delete(key) +func (s *Storage) Delete(name string, version int32) (*rspb.Release, error) { + log.Printf("Deleting release %q (v%d) from storage\n", name, version) + return s.Driver.Delete(makeKey(name, version)) } // ListReleases returns all releases from storage. An error is returned if the @@ -114,3 +115,10 @@ func Init(d driver.Driver) *Storage { } return &Storage{Driver: d} } + +// makeKey concatenates a release name and version into +// a string with format ```#v```. +// This key is used to uniquely identify storage objects. +func makeKey(rlsname string, version int32) string { + return fmt.Sprintf("%s#v%d", rlsname, version) +} diff --git a/pkg/storage/storage_test.go b/pkg/storage/storage_test.go index 25975bf1b..623c70282 100644 --- a/pkg/storage/storage_test.go +++ b/pkg/storage/storage_test.go @@ -30,11 +30,12 @@ func TestStorageCreate(t *testing.T) { storage := Init(driver.NewMemory()) // create fake release - rls := ReleaseTestData{Name: "angry-beaver"}.ToRelease() + rls := ReleaseTestData{Name: "angry-beaver", Version: 1}.ToRelease() + assertErrNil(t.Fatal, storage.Create(rls), "StoreRelease") // fetch the release - res, err := storage.Get(rls.Name) + res, err := storage.Get(rls.Name, rls.Version) assertErrNil(t.Fatal, err, "QueryRelease") // verify the fetched and created release are the same @@ -48,16 +49,16 @@ func TestStorageUpdate(t *testing.T) { storage := Init(driver.NewMemory()) // create fake release - rls := ReleaseTestData{Name: "angry-beaver"}.ToRelease() + rls := ReleaseTestData{Name: "angry-beaver", Version: 1}.ToRelease() + assertErrNil(t.Fatal, storage.Create(rls), "StoreRelease") // modify the release - rls.Version = 2 rls.Manifest = "new-manifest" assertErrNil(t.Fatal, storage.Update(rls), "UpdateRelease") // retrieve the updated release - res, err := storage.Get(rls.Name) + res, err := storage.Get(rls.Name, rls.Version) assertErrNil(t.Fatal, err, "QueryRelease") // verify updated and fetched releases are the same. @@ -71,11 +72,11 @@ func TestStorageDelete(t *testing.T) { storage := Init(driver.NewMemory()) // create fake release - rls := ReleaseTestData{Name: "angry-beaver"}.ToRelease() + rls := ReleaseTestData{Name: "angry-beaver", Version: 1}.ToRelease() assertErrNil(t.Fatal, storage.Create(rls), "StoreRelease") // delete the release - res, err := storage.Delete(rls.Name) + res, err := storage.Delete(rls.Name, rls.Version) assertErrNil(t.Fatal, err, "DeleteRelease") // verify updated and fetched releases are the same. From ec1315cea604631a1aff3a90c2359313d9249e1c Mon Sep 17 00:00:00 2001 From: fibonacci1729 Date: Tue, 23 Aug 2016 12:43:14 -0600 Subject: [PATCH 02/10] chore(storage-naming): add version field to tiller protos --- _proto/hapi/services/tiller.proto | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/_proto/hapi/services/tiller.proto b/_proto/hapi/services/tiller.proto index ba3252e3c..45060ccbf 100644 --- a/_proto/hapi/services/tiller.proto +++ b/_proto/hapi/services/tiller.proto @@ -129,6 +129,8 @@ message ListReleasesResponse { message GetReleaseStatusRequest { // Name is the name of the release string name = 1; + // Version is the version of the release + int32 version = 2; } // GetReleaseStatusResponse is the response indicating the status of the named release. @@ -144,6 +146,8 @@ message GetReleaseStatusResponse { message GetReleaseContentRequest { // The name of the release string name = 1; + // Version is the version of the release + int32 version = 2; } // GetReleaseContentResponse is a response containing the contents of a release. @@ -165,6 +169,9 @@ message UpdateReleaseRequest { // DisableHooks causes the server to skip running any hooks for the upgrade. bool disable_hooks = 5; + + // Version is the version of the release to be updated + int32 version = 6; } // UpdateReleaseResponse is the response to an update request. From 837d79a32cd58e32b06a9da758636bde23733b8f Mon Sep 17 00:00:00 2001 From: fibonacci1729 Date: Tue, 23 Aug 2016 16:02:44 -0600 Subject: [PATCH 03/10] chore(storage-naming): update to storage api invocations in release_server and environment --- cmd/tiller/environment/environment.go | 3 +-- cmd/tiller/release_server.go | 12 ++++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/cmd/tiller/environment/environment.go b/cmd/tiller/environment/environment.go index 5e0e81216..3b0ca7d99 100644 --- a/cmd/tiller/environment/environment.go +++ b/cmd/tiller/environment/environment.go @@ -31,7 +31,6 @@ import ( "k8s.io/helm/pkg/kube" "k8s.io/helm/pkg/proto/hapi/chart" "k8s.io/helm/pkg/storage" - "k8s.io/helm/pkg/storage/driver" "k8s.io/kubernetes/pkg/client/unversioned" ) @@ -208,7 +207,7 @@ func New() *Environment { return &Environment{ EngineYard: ey, - Releases: storage.Init(driver.NewMemory()), + Releases: storage.Init(nil), KubeClient: kube.New(nil), } } diff --git a/cmd/tiller/release_server.go b/cmd/tiller/release_server.go index 0fe6a192a..122b370d0 100644 --- a/cmd/tiller/release_server.go +++ b/cmd/tiller/release_server.go @@ -158,7 +158,7 @@ func (s *releaseServer) GetReleaseStatus(c ctx.Context, req *services.GetRelease if req.Name == "" { return nil, errMissingRelease } - rel, err := s.env.Releases.Get(req.Name) + rel, err := s.env.Releases.Get(req.Name, req.Version) if err != nil { return nil, err } @@ -183,7 +183,7 @@ func (s *releaseServer) GetReleaseContent(c ctx.Context, req *services.GetReleas if req.Name == "" { return nil, errMissingRelease } - rel, err := s.env.Releases.Get(req.Name) + rel, err := s.env.Releases.Get(req.Name, req.Version) return &services.GetReleaseContentResponse{Release: rel}, err } @@ -250,7 +250,7 @@ func (s *releaseServer) prepareUpdate(req *services.UpdateReleaseRequest) (*rele } // finds the non-deleted release with the given name - currentRelease, err := s.env.Releases.Get(req.Name) + currentRelease, err := s.env.Releases.Get(req.Name, req.Version) if err != nil { return nil, nil, err } @@ -302,7 +302,7 @@ func (s *releaseServer) uniqName(start string, reuse bool) (string, error) { return "", fmt.Errorf("release name %q exceeds max length of %d", start, releaseNameMaxLen) } - if rel, err := s.env.Releases.Get(start); err == driver.ErrReleaseNotFound { + if rel, err := s.env.Releases.Get(start, 0); err == driver.ErrReleaseNotFound { return start, nil } else if st := rel.Info.Status.Code; reuse && (st == release.Status_DELETED || st == release.Status_FAILED) { // Allowe re-use of names if the previous release is marked deleted. @@ -323,7 +323,7 @@ func (s *releaseServer) uniqName(start string, reuse bool) (string, error) { log.Printf("info: Candidate name %q exceeds maximum length %d. Skipping.", name, releaseNameMaxLen) continue } - if _, err := s.env.Releases.Get(name); err == driver.ErrReleaseNotFound { + if _, err := s.env.Releases.Get(name, 0); err == driver.ErrReleaseNotFound { return name, nil } log.Printf("info: Name %q is taken. Searching again.", name) @@ -525,7 +525,7 @@ func (s *releaseServer) UninstallRelease(c ctx.Context, req *services.UninstallR return nil, errMissingRelease } - rel, err := s.env.Releases.Get(req.Name) + rel, err := s.env.Releases.Get(req.Name, 0) if err != nil { log.Printf("uninstall: Release not loaded: %s", req.Name) return nil, err From 4699d985db07237d10b170cce8e92a0decb219df Mon Sep 17 00:00:00 2001 From: fibonacci1729 Date: Tue, 23 Aug 2016 16:03:45 -0600 Subject: [PATCH 04/10] chore(storage-naming): regenerate proto --- pkg/proto/hapi/services/tiller.pb.go | 107 ++++++++++++++------------- 1 file changed, 57 insertions(+), 50 deletions(-) diff --git a/pkg/proto/hapi/services/tiller.pb.go b/pkg/proto/hapi/services/tiller.pb.go index 838e83647..2d00b269e 100644 --- a/pkg/proto/hapi/services/tiller.pb.go +++ b/pkg/proto/hapi/services/tiller.pb.go @@ -160,6 +160,8 @@ func (m *ListReleasesResponse) GetReleases() []*hapi_release3.Release { type GetReleaseStatusRequest struct { // Name is the name of the release Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Version is the version of the release + Version int32 `protobuf:"varint,2,opt,name=version" json:"version,omitempty"` } func (m *GetReleaseStatusRequest) Reset() { *m = GetReleaseStatusRequest{} } @@ -191,6 +193,8 @@ func (m *GetReleaseStatusResponse) GetInfo() *hapi_release2.Info { type GetReleaseContentRequest struct { // The name of the release Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Version is the version of the release + Version int32 `protobuf:"varint,2,opt,name=version" json:"version,omitempty"` } func (m *GetReleaseContentRequest) Reset() { *m = GetReleaseContentRequest{} } @@ -228,6 +232,8 @@ type UpdateReleaseRequest struct { DryRun bool `protobuf:"varint,4,opt,name=dry_run,json=dryRun" json:"dry_run,omitempty"` // DisableHooks causes the server to skip running any hooks for the upgrade. DisableHooks bool `protobuf:"varint,5,opt,name=disable_hooks,json=disableHooks" json:"disable_hooks,omitempty"` + // Version is the version of the release to be updated + Version int32 `protobuf:"varint,6,opt,name=version" json:"version,omitempty"` } func (m *UpdateReleaseRequest) Reset() { *m = UpdateReleaseRequest{} } @@ -626,54 +632,55 @@ var _ReleaseService_serviceDesc = grpc.ServiceDesc{ } var fileDescriptor0 = []byte{ - // 774 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x56, 0xdb, 0x6e, 0xd3, 0x4c, - 0x10, 0xae, 0x93, 0x34, 0x87, 0xe9, 0x41, 0xe9, 0xfe, 0x6d, 0x93, 0xdf, 0xfa, 0x7f, 0x84, 0x8c, - 0x80, 0x52, 0xa8, 0x03, 0xe1, 0x1e, 0x29, 0x6d, 0xa3, 0xb6, 0x6a, 0x48, 0xa5, 0x0d, 0x05, 0x89, - 0x0b, 0x22, 0x37, 0xd9, 0x50, 0x83, 0x6b, 0x07, 0xef, 0xa6, 0xa2, 0x8f, 0xc0, 0x1b, 0x71, 0xc3, - 0xdb, 0xf0, 0x16, 0xdc, 0xb0, 0x07, 0xaf, 0xc9, 0xc1, 0x06, 0xd3, 0x1b, 0x67, 0x77, 0xe7, 0xdb, - 0x6f, 0x66, 0xbe, 0x99, 0x9d, 0x16, 0xcc, 0x4b, 0x67, 0xec, 0x36, 0x28, 0x09, 0xaf, 0xdd, 0x01, - 0xa1, 0x0d, 0xe6, 0x7a, 0x1e, 0x09, 0xed, 0x71, 0x18, 0xb0, 0x00, 0x6d, 0x0a, 0x9b, 0xad, 0x6d, - 0xb6, 0xb2, 0x99, 0xdb, 0xf2, 0xc6, 0xe0, 0xd2, 0x09, 0x99, 0xfa, 0x2a, 0xb4, 0x59, 0x9b, 0x3e, - 0x0f, 0xfc, 0x91, 0xfb, 0x3e, 0x32, 0x28, 0x17, 0x21, 0xf1, 0x88, 0x43, 0x89, 0xfe, 0x9d, 0xb9, - 0xa4, 0x6d, 0xae, 0x3f, 0x0a, 0x94, 0xc1, 0xfa, 0x6e, 0xc0, 0x3f, 0x1d, 0x97, 0x32, 0xac, 0x4c, - 0x14, 0x93, 0x4f, 0x13, 0x42, 0x19, 0xda, 0x84, 0x65, 0xcf, 0xbd, 0x72, 0x59, 0xdd, 0xb8, 0x6b, - 0xec, 0xe4, 0xb1, 0xda, 0xa0, 0x6d, 0x28, 0x06, 0xa3, 0x11, 0x25, 0xac, 0x9e, 0xe3, 0xc7, 0x15, - 0x1c, 0xed, 0xd0, 0x0b, 0x28, 0xd1, 0x20, 0x64, 0xfd, 0x8b, 0x9b, 0x7a, 0x9e, 0x1b, 0xd6, 0x9b, - 0xf7, 0xed, 0xa4, 0x9c, 0x6c, 0xe1, 0xa9, 0xc7, 0x81, 0xb6, 0xf8, 0xec, 0xdf, 0xe0, 0x22, 0x95, - 0xbf, 0x82, 0x77, 0xe4, 0x7a, 0x8c, 0x84, 0xf5, 0x82, 0xe2, 0x55, 0x3b, 0x74, 0x04, 0x20, 0x79, - 0x83, 0x70, 0xc8, 0x6d, 0xcb, 0x92, 0x7a, 0x27, 0x03, 0xf5, 0x99, 0xc0, 0xe3, 0x0a, 0xd5, 0x4b, - 0xeb, 0x1d, 0x94, 0x35, 0xc0, 0x6a, 0x42, 0x51, 0xb9, 0x47, 0x2b, 0x50, 0x3a, 0xef, 0x9e, 0x76, - 0xcf, 0xde, 0x74, 0xab, 0x4b, 0xa8, 0x0c, 0x85, 0x6e, 0xeb, 0x65, 0xbb, 0x6a, 0xa0, 0x0d, 0x58, - 0xeb, 0xb4, 0x7a, 0xaf, 0xfa, 0xb8, 0xdd, 0x69, 0xb7, 0x7a, 0xed, 0xc3, 0x6a, 0xce, 0xba, 0x03, - 0x95, 0x98, 0x17, 0x95, 0x20, 0xdf, 0xea, 0x1d, 0xa8, 0x2b, 0x87, 0x6d, 0xbe, 0x32, 0xac, 0x2f, - 0x06, 0x6c, 0xce, 0xca, 0x48, 0xc7, 0x81, 0x4f, 0x89, 0xd0, 0x71, 0x10, 0x4c, 0xfc, 0x58, 0x47, - 0xb9, 0x41, 0x08, 0x0a, 0x3e, 0xf9, 0xac, 0x55, 0x94, 0x6b, 0x81, 0x64, 0x01, 0x73, 0x3c, 0xa9, - 0x20, 0x47, 0xca, 0x0d, 0x7a, 0x06, 0xe5, 0xa8, 0x6a, 0x94, 0x6b, 0x93, 0xdf, 0x59, 0x69, 0x6e, - 0xa9, 0xfc, 0x75, 0x7d, 0x23, 0x8f, 0x38, 0x86, 0x59, 0x7b, 0x50, 0x3b, 0x22, 0x3a, 0x92, 0x1e, - 0x73, 0xd8, 0x24, 0xae, 0xaa, 0xf0, 0xeb, 0x5c, 0x11, 0x19, 0x8c, 0xf0, 0xcb, 0xd7, 0xd6, 0x6b, - 0xa8, 0x2f, 0xc2, 0xa3, 0xe8, 0x13, 0xf0, 0xe8, 0x01, 0x14, 0x44, 0xff, 0xc8, 0xd8, 0x57, 0x9a, - 0x68, 0x36, 0x9a, 0x13, 0x6e, 0xc1, 0xd2, 0x6e, 0xd9, 0xd3, 0xbc, 0x07, 0x81, 0xcf, 0x88, 0xcf, - 0x7e, 0x17, 0x47, 0x07, 0xfe, 0x4d, 0xc0, 0x47, 0x81, 0x34, 0xa0, 0x14, 0xb9, 0x90, 0x77, 0x52, - 0x55, 0xd0, 0x28, 0xeb, 0x1b, 0x2f, 0xc8, 0xf9, 0x78, 0xe8, 0x30, 0xa2, 0x4d, 0xe9, 0xae, 0xd1, - 0x43, 0x5e, 0x24, 0xf1, 0x9e, 0xa2, 0x9c, 0x36, 0x14, 0xb7, 0x7a, 0x74, 0x07, 0xe2, 0x8b, 0x95, - 0x1d, 0xed, 0x42, 0xf1, 0xda, 0xf1, 0x38, 0x8f, 0x2c, 0x52, 0x9c, 0x7d, 0x84, 0x94, 0x8f, 0x11, - 0x47, 0x08, 0x54, 0x83, 0xd2, 0x30, 0xbc, 0xe9, 0x87, 0x13, 0x5f, 0x36, 0x75, 0x19, 0x17, 0xf9, - 0x16, 0x4f, 0x7c, 0x74, 0x0f, 0xd6, 0x86, 0x2e, 0x75, 0x2e, 0x3c, 0xd2, 0xbf, 0x0c, 0x82, 0x8f, - 0x54, 0xf6, 0x75, 0x19, 0xaf, 0x46, 0x87, 0xc7, 0xe2, 0xcc, 0x3a, 0x86, 0xad, 0xb9, 0xf0, 0x6f, - 0xab, 0xc4, 0x0f, 0x03, 0xb6, 0x4e, 0x7c, 0xca, 0x9b, 0xc9, 0x9b, 0x93, 0x22, 0x4e, 0xdb, 0xc8, - 0x9c, 0x76, 0xee, 0x6f, 0xd2, 0xce, 0xcf, 0xa4, 0xad, 0x85, 0x2f, 0x4c, 0x09, 0x9f, 0x45, 0x0a, - 0xf4, 0x1f, 0x54, 0x04, 0x98, 0x8e, 0x9d, 0x01, 0xa9, 0x17, 0xe5, 0xed, 0x5f, 0x07, 0xe8, 0x7f, - 0x80, 0x90, 0x4c, 0x28, 0xe9, 0x4b, 0xf2, 0x92, 0xbc, 0x5f, 0x91, 0x27, 0x5d, 0xd1, 0x55, 0x27, - 0xb0, 0x3d, 0x9f, 0xfc, 0x6d, 0x85, 0xc4, 0x50, 0x3b, 0xf7, 0xdd, 0x44, 0x25, 0x93, 0x9a, 0x6a, - 0x21, 0xb7, 0x5c, 0x42, 0x99, 0x4f, 0xa1, 0xbe, 0xc8, 0x79, 0xcb, 0x00, 0x9b, 0x5f, 0x97, 0x61, - 0x5d, 0xbf, 0x63, 0x35, 0x1d, 0x91, 0x0b, 0xab, 0xd3, 0x63, 0x09, 0x3d, 0x4a, 0x1f, 0x9e, 0x73, - 0x7f, 0x01, 0xcc, 0xdd, 0x2c, 0x50, 0x15, 0xaa, 0xb5, 0xf4, 0xd4, 0x40, 0x14, 0xaa, 0xf3, 0x73, - 0x04, 0xed, 0x25, 0x73, 0xa4, 0x8c, 0x27, 0xd3, 0xce, 0x0a, 0xd7, 0x6e, 0xd1, 0x35, 0x6c, 0x2c, - 0x0c, 0x0d, 0xf4, 0x47, 0x9a, 0xd9, 0x69, 0x64, 0x36, 0x32, 0xe3, 0x63, 0xbf, 0x1f, 0x60, 0x6d, - 0xe6, 0x79, 0xa2, 0x14, 0xb5, 0x92, 0x46, 0x90, 0xf9, 0x38, 0x13, 0x36, 0xf6, 0x75, 0x05, 0xeb, - 0xb3, 0x2d, 0x8c, 0x52, 0x08, 0x12, 0x5f, 0xb9, 0xf9, 0x24, 0x1b, 0x38, 0x76, 0xc7, 0xeb, 0x38, - 0xdf, 0x92, 0x69, 0x75, 0x4c, 0x79, 0x0e, 0x69, 0x75, 0x4c, 0xeb, 0x74, 0x6b, 0x69, 0x1f, 0xde, - 0x96, 0x35, 0xfa, 0xa2, 0x28, 0xff, 0x33, 0x79, 0xfe, 0x33, 0x00, 0x00, 0xff, 0xff, 0x97, 0xd7, - 0x36, 0xd6, 0x33, 0x09, 0x00, 0x00, + // 792 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x56, 0xdd, 0x6e, 0xd3, 0x4a, + 0x10, 0xae, 0xf3, 0x9f, 0xe9, 0x8f, 0xd2, 0x3d, 0x6d, 0x93, 0x63, 0x9d, 0x73, 0x74, 0x64, 0x04, + 0x94, 0x02, 0x0e, 0x84, 0x7b, 0xa4, 0xb4, 0x8d, 0xda, 0xaa, 0x21, 0x95, 0x36, 0x14, 0x24, 0x2e, + 0x88, 0xdc, 0x64, 0x43, 0x0d, 0xae, 0x1d, 0xbc, 0x9b, 0x88, 0x3e, 0x02, 0x6f, 0xc4, 0x9b, 0xf0, + 0x02, 0xbc, 0x05, 0x37, 0xac, 0x77, 0xbd, 0x26, 0x4e, 0x6c, 0x30, 0xb9, 0x71, 0x76, 0x77, 0xbe, + 0xfd, 0x66, 0xe6, 0x9b, 0x9d, 0x69, 0x41, 0xbf, 0xb6, 0x26, 0x76, 0x93, 0x12, 0x7f, 0x66, 0x0f, + 0x09, 0x6d, 0x32, 0xdb, 0x71, 0x88, 0x6f, 0x4e, 0x7c, 0x8f, 0x79, 0x68, 0x27, 0xb0, 0x99, 0xca, + 0x66, 0x4a, 0x9b, 0xbe, 0x27, 0x6e, 0x0c, 0xaf, 0x2d, 0x9f, 0xc9, 0xaf, 0x44, 0xeb, 0xf5, 0xf9, + 0x73, 0xcf, 0x1d, 0xdb, 0xef, 0x42, 0x83, 0x74, 0xe1, 0x13, 0x87, 0x58, 0x94, 0xa8, 0xdf, 0xd8, + 0x25, 0x65, 0xb3, 0xdd, 0xb1, 0x27, 0x0d, 0xc6, 0x37, 0x0d, 0xfe, 0xea, 0xda, 0x94, 0x61, 0x69, + 0xa2, 0x98, 0x7c, 0x9c, 0x12, 0xca, 0xd0, 0x0e, 0x14, 0x1d, 0xfb, 0xc6, 0x66, 0x0d, 0xed, 0x7f, + 0x6d, 0x3f, 0x8f, 0xe5, 0x06, 0xed, 0x41, 0xc9, 0x1b, 0x8f, 0x29, 0x61, 0x8d, 0x1c, 0x3f, 0xae, + 0xe2, 0x70, 0x87, 0x9e, 0x43, 0x99, 0x7a, 0x3e, 0x1b, 0x5c, 0xdd, 0x36, 0xf2, 0xdc, 0xb0, 0xd5, + 0xba, 0x6b, 0x26, 0xe5, 0x64, 0x06, 0x9e, 0xfa, 0x1c, 0x68, 0x06, 0x9f, 0xc3, 0x5b, 0x5c, 0xa2, + 0xe2, 0x37, 0xe0, 0x1d, 0xdb, 0x0e, 0x23, 0x7e, 0xa3, 0x20, 0x79, 0xe5, 0x0e, 0x9d, 0x00, 0x08, + 0x5e, 0xcf, 0x1f, 0x71, 0x5b, 0x51, 0x50, 0xef, 0x67, 0xa0, 0xbe, 0x08, 0xf0, 0xb8, 0x4a, 0xd5, + 0xd2, 0x78, 0x0b, 0x15, 0x05, 0x30, 0x5a, 0x50, 0x92, 0xee, 0xd1, 0x3a, 0x94, 0x2f, 0x7b, 0xe7, + 0xbd, 0x8b, 0xd7, 0xbd, 0xda, 0x1a, 0xaa, 0x40, 0xa1, 0xd7, 0x7e, 0xd1, 0xa9, 0x69, 0x68, 0x1b, + 0x36, 0xbb, 0xed, 0xfe, 0xcb, 0x01, 0xee, 0x74, 0x3b, 0xed, 0x7e, 0xe7, 0xb8, 0x96, 0x33, 0xfe, + 0x83, 0x6a, 0xc4, 0x8b, 0xca, 0x90, 0x6f, 0xf7, 0x8f, 0xe4, 0x95, 0xe3, 0x0e, 0x5f, 0x69, 0xc6, + 0x67, 0x0d, 0x76, 0xe2, 0x32, 0xd2, 0x89, 0xe7, 0x52, 0x12, 0xe8, 0x38, 0xf4, 0xa6, 0x6e, 0xa4, + 0xa3, 0xd8, 0x20, 0x04, 0x05, 0x97, 0x7c, 0x52, 0x2a, 0x8a, 0x75, 0x80, 0x64, 0x1e, 0xb3, 0x1c, + 0xa1, 0x20, 0x47, 0x8a, 0x0d, 0x7a, 0x0a, 0x95, 0xb0, 0x6a, 0x94, 0x6b, 0x93, 0xdf, 0x5f, 0x6f, + 0xed, 0xca, 0xfc, 0x55, 0x7d, 0x43, 0x8f, 0x38, 0x82, 0x19, 0x27, 0x50, 0x3f, 0x21, 0x2a, 0x92, + 0x3e, 0xb3, 0xd8, 0x34, 0xaa, 0x6a, 0xe0, 0xd7, 0xba, 0x21, 0x22, 0x98, 0xc0, 0x2f, 0x5f, 0xa3, + 0x06, 0x94, 0x67, 0xc4, 0xa7, 0xb6, 0xe7, 0x8a, 0x70, 0x8a, 0x58, 0x6d, 0x8d, 0x57, 0xd0, 0x58, + 0x26, 0x0a, 0xf3, 0x4a, 0x62, 0xba, 0x07, 0x85, 0xe0, 0x65, 0x09, 0x9a, 0xf5, 0x16, 0x8a, 0xc7, + 0x79, 0xc6, 0x2d, 0x58, 0xd8, 0x8d, 0xd3, 0x79, 0xde, 0x23, 0xcf, 0x65, 0xc4, 0x65, 0xab, 0x45, + 0xd8, 0x85, 0xbf, 0x13, 0x98, 0xc2, 0x10, 0x9b, 0x50, 0x0e, 0x9d, 0x0b, 0xb6, 0x54, 0xe5, 0x14, + 0xca, 0xf8, 0xca, 0x8b, 0x78, 0x39, 0x19, 0x59, 0x8c, 0x28, 0xd3, 0x2f, 0x82, 0xba, 0xcf, 0x0b, + 0x1b, 0xf4, 0x60, 0x98, 0xed, 0xb6, 0xe4, 0x96, 0x8d, 0x7a, 0x14, 0x7c, 0xb1, 0xb4, 0xa3, 0x03, + 0x28, 0xcd, 0x2c, 0x87, 0xf3, 0x88, 0xc2, 0x46, 0xba, 0x84, 0x48, 0xd1, 0xc0, 0x38, 0x44, 0xa0, + 0x3a, 0x94, 0x47, 0xfe, 0xed, 0xc0, 0x9f, 0xba, 0xa2, 0x11, 0x2a, 0xb8, 0xc4, 0xb7, 0x78, 0xea, + 0xa2, 0x3b, 0xb0, 0x39, 0xb2, 0xa9, 0x75, 0xe5, 0x90, 0xc1, 0xb5, 0xe7, 0x7d, 0xa0, 0xa2, 0x17, + 0x2a, 0x78, 0x23, 0x3c, 0x3c, 0x0d, 0xce, 0xe6, 0x75, 0x2a, 0xc5, 0x75, 0x3a, 0x85, 0xdd, 0x85, + 0xc4, 0x56, 0xd5, 0xe8, 0xbb, 0x06, 0xbb, 0x67, 0x2e, 0xe5, 0x4f, 0xd3, 0x59, 0x10, 0x29, 0x12, + 0x44, 0xcb, 0x2c, 0x48, 0xee, 0x4f, 0x04, 0xc9, 0xc7, 0x04, 0x51, 0x25, 0x29, 0xcc, 0x95, 0x24, + 0x93, 0x48, 0xff, 0x40, 0x35, 0x00, 0xd3, 0x89, 0x35, 0x24, 0x42, 0xa6, 0x2a, 0xfe, 0x79, 0x80, + 0xfe, 0x05, 0xf0, 0xc9, 0x94, 0x92, 0x81, 0x20, 0x2f, 0x8b, 0xfb, 0x55, 0x71, 0xd2, 0xe3, 0x07, + 0xc6, 0x19, 0xec, 0x2d, 0x26, 0xbf, 0xaa, 0x90, 0x18, 0xea, 0x97, 0xae, 0x9d, 0xa8, 0x64, 0xd2, + 0x73, 0x5b, 0xca, 0x2d, 0xb7, 0x9c, 0x9b, 0x71, 0x0e, 0x8d, 0x65, 0xce, 0x15, 0x03, 0x6c, 0x7d, + 0x29, 0xc2, 0x96, 0xea, 0x7d, 0x39, 0x6b, 0x91, 0x0d, 0x1b, 0xf3, 0x43, 0x0e, 0x3d, 0x48, 0x1f, + 0xc5, 0x0b, 0x7f, 0x4f, 0xf4, 0x83, 0x2c, 0x50, 0x19, 0xaa, 0xb1, 0xf6, 0x44, 0x43, 0x14, 0x6a, + 0x8b, 0xb3, 0x07, 0x3d, 0x4e, 0xe6, 0x48, 0x19, 0x76, 0xba, 0x99, 0x15, 0xae, 0xdc, 0xa2, 0x19, + 0x6c, 0x2f, 0x8d, 0x13, 0xf4, 0x5b, 0x9a, 0xf8, 0x04, 0xd3, 0x9b, 0x99, 0xf1, 0x91, 0xdf, 0xf7, + 0xb0, 0x19, 0x6b, 0x4f, 0x94, 0xa2, 0x56, 0xd2, 0x70, 0xd2, 0x1f, 0x66, 0xc2, 0x46, 0xbe, 0x6e, + 0x60, 0x2b, 0xfe, 0x84, 0x51, 0x0a, 0x41, 0x62, 0x97, 0xeb, 0x8f, 0xb2, 0x81, 0x23, 0x77, 0xbc, + 0x8e, 0x8b, 0x4f, 0x32, 0xad, 0x8e, 0x29, 0xed, 0x90, 0x56, 0xc7, 0xb4, 0x97, 0x6e, 0xac, 0x1d, + 0xc2, 0x9b, 0x8a, 0x42, 0x5f, 0x95, 0xc4, 0xff, 0x39, 0xcf, 0x7e, 0x04, 0x00, 0x00, 0xff, 0xff, + 0x4c, 0x6b, 0x35, 0xf8, 0x81, 0x09, 0x00, 0x00, } From 14f5641905ddea0a306051bf5274786865815b10 Mon Sep 17 00:00:00 2001 From: fibonacci1729 Date: Wed, 24 Aug 2016 09:42:26 -0600 Subject: [PATCH 05/10] chore(storage-naming): cleanup redundant environment test --- cmd/tiller/environment/environment_test.go | 75 ---------------------- 1 file changed, 75 deletions(-) diff --git a/cmd/tiller/environment/environment_test.go b/cmd/tiller/environment/environment_test.go index 236df6a2b..68cc5d63c 100644 --- a/cmd/tiller/environment/environment_test.go +++ b/cmd/tiller/environment/environment_test.go @@ -23,9 +23,6 @@ import ( "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/proto/hapi/chart" - "k8s.io/helm/pkg/proto/hapi/release" - "k8s.io/helm/pkg/storage" - "k8s.io/helm/pkg/storage/driver" unversionedclient "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/client/unversioned/testclient" ) @@ -38,52 +35,6 @@ func (e *mockEngine) Render(chrt *chart.Chart, v chartutil.Values) (map[string]s return e.out, nil } -type mockReleaseStorage struct { - rel *release.Release -} - -var _ driver.Driver = (*mockReleaseStorage)(nil) - -func (r *mockReleaseStorage) Create(v *release.Release) error { - r.rel = v - return nil -} - -func (r *mockReleaseStorage) Name() string { - return "mockReleaseStorage" -} - -func (r *mockReleaseStorage) Get(k string) (*release.Release, error) { - return r.rel, nil -} - -func (r *mockReleaseStorage) Update(v *release.Release) error { - r.rel = v - return nil -} - -func (r *mockReleaseStorage) Delete(k string) (*release.Release, error) { - return r.rel, nil -} - -func (r *mockReleaseStorage) List(func(*release.Release) bool) ([]*release.Release, error) { - return []*release.Release{}, nil -} - -func (r *mockReleaseStorage) Query(labels map[string]string) ([]*release.Release, error) { - return []*release.Release{}, nil -} - -func (r *mockReleaseStorage) History(n string) ([]*release.Release, error) { - res := []*release.Release{} - rel, err := r.Get(n) - if err != nil { - return res, err - } - res = append(res, rel) - return res, nil -} - type mockKubeClient struct { } @@ -126,32 +77,6 @@ func TestEngine(t *testing.T) { } } -func TestReleaseStorage(t *testing.T) { - rs := &mockReleaseStorage{} - env := New() - env.Releases = storage.Init(rs) - - release := &release.Release{Name: "mariner"} - - if err := env.Releases.Create(release); err != nil { - t.Fatalf("failed to store release: %s", err) - } - - if err := env.Releases.Update(release); err != nil { - t.Fatalf("failed to update release: %s", err) - } - - if v, err := env.Releases.Get("albatross"); err != nil { - t.Errorf("Error fetching release: %s", err) - } else if v.Name != "mariner" { - t.Errorf("Expected mariner, got %q", v.Name) - } - - if _, err := env.Releases.Delete("albatross"); err != nil { - t.Fatalf("failed to delete release: %s", err) - } -} - func TestKubeClient(t *testing.T) { kc := &mockKubeClient{} env := New() From bc2826c813bf72494a55c4c4698364a1fce3bc5e Mon Sep 17 00:00:00 2001 From: fibonacci1729 Date: Wed, 24 Aug 2016 09:53:04 -0600 Subject: [PATCH 06/10] chore(storage-naming): introduce optional version flag (--version) to helm {get, status} --- cmd/helm/get.go | 4 ++++ cmd/helm/status.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/cmd/helm/get.go b/cmd/helm/get.go index f1ad5334c..5bc4dc892 100644 --- a/cmd/helm/get.go +++ b/cmd/helm/get.go @@ -48,6 +48,7 @@ type getCmd struct { release string out io.Writer client helm.Interface + version int32 } func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command { @@ -71,6 +72,9 @@ func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command { return get.run() }, } + + cmd.PersistentFlags().Int32Var(&get.version, "version", 0, "version of release") + cmd.AddCommand(newGetValuesCmd(nil, out)) cmd.AddCommand(newGetManifestCmd(nil, out)) cmd.AddCommand(newGetHooksCmd(nil, out)) diff --git a/cmd/helm/status.go b/cmd/helm/status.go index 436445642..88eb14305 100644 --- a/cmd/helm/status.go +++ b/cmd/helm/status.go @@ -34,6 +34,7 @@ type statusCmd struct { release string out io.Writer client helm.Interface + version int32 } func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command { @@ -57,6 +58,9 @@ func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command { return status.run() }, } + + cmd.PersistentFlags().Int32Var(&status.version, "version", 0, "version of release") + return cmd } From caa782e51363375fb8671b3681fb2e88f95a65ec Mon Sep 17 00:00:00 2001 From: fibonacci1729 Date: Wed, 24 Aug 2016 15:09:04 -0600 Subject: [PATCH 07/10] chore(storage-naming): introduce helm option --- pkg/helm/option.go | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/pkg/helm/option.go b/pkg/helm/option.go index 2af4742da..8225456c6 100644 --- a/pkg/helm/option.go +++ b/pkg/helm/option.go @@ -47,6 +47,10 @@ type options struct { instReq rls.InstallReleaseRequest // release update options are applied directly to the update release request updateReq rls.UpdateReleaseRequest + // release get status options are applied directly to the get release status request + statusReq rls.GetReleaseStatusRequest + // release get content options are applied directly to the get release content request + contentReq rls.GetReleaseContentRequest } // Home specifies the location of helm home, (default = "$HOME/.helm"). @@ -178,13 +182,32 @@ func InstallReuseName(reuse bool) InstallOption { } } -// ContentOption -- TODO +// ContentOption allows setting optional attributes when +// performing a GetReleaseContent tiller rpc. type ContentOption func(*options) -// StatusOption -- TODO +// ContentReleaseVersion will instruct Tiller to retrieve the content +// of a paritcular version of a release. +func ContentReleaseVersion(version int32) ContentOption { + return func(opts *options) { + opts.contentReq.Version = version + } +} + +// StatusOption allows setting optional attributes when +// performing a GetReleaseStatus tiller rpc. type StatusOption func(*options) -// DeleteOption -- TODO +// StatusReleaseVersion will instruct Tiller to retrieve the status +// of a paritcular version of a release. +func StatusReleaseVersion(version int32) StatusOption { + return func(opts *options) { + opts.statusReq.Version = version + } +} + +// DeleteOption allows setting optional attributes when +// performing a UninstallRelease tiller rpc. type DeleteOption func(*options) // UpdateOption allows specifying various settings @@ -257,12 +280,18 @@ func (o *options) rpcUpdateRelease(rlsName string, chr *cpb.Chart, rlc rls.Relea // Executes tiller.GetReleaseStatus RPC. func (o *options) rpcGetReleaseStatus(rlsName string, rlc rls.ReleaseServiceClient, opts ...StatusOption) (*rls.GetReleaseStatusResponse, error) { - req := &rls.GetReleaseStatusRequest{Name: rlsName} - return rlc.GetReleaseStatus(context.TODO(), req) + for _, opt := range opts { + opt(o) + } + o.statusReq.Name = rlsName + return rlc.GetReleaseStatus(context.TODO(), &o.statusReq) } // Executes tiller.GetReleaseContent. func (o *options) rpcGetReleaseContent(rlsName string, rlc rls.ReleaseServiceClient, opts ...ContentOption) (*rls.GetReleaseContentResponse, error) { - req := &rls.GetReleaseContentRequest{Name: rlsName} - return rlc.GetReleaseContent(context.TODO(), req) + for _, opt := range opts { + opt(o) + } + o.contentReq.Name = rlsName + return rlc.GetReleaseContent(context.TODO(), &o.contentReq) } From dbbb98bde0dc2c99b79b50eaa1144d3417a0f1d3 Mon Sep 17 00:00:00 2001 From: fibonacci1729 Date: Wed, 24 Aug 2016 15:10:49 -0600 Subject: [PATCH 08/10] chore(storage-naming): apply release version options to integrate optional --version flag --- cmd/helm/get.go | 2 +- cmd/helm/status.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/helm/get.go b/cmd/helm/get.go index 5bc4dc892..3a2fddb8d 100644 --- a/cmd/helm/get.go +++ b/cmd/helm/get.go @@ -100,7 +100,7 @@ MANIFEST: // getCmd is the command that implements 'helm get' func (g *getCmd) run() error { - res, err := g.client.ReleaseContent(g.release) + res, err := g.client.ReleaseContent(g.release, helm.ContentReleaseVersion(g.version)) if err != nil { return prettyError(err) } diff --git a/cmd/helm/status.go b/cmd/helm/status.go index 88eb14305..2ef25c5fa 100644 --- a/cmd/helm/status.go +++ b/cmd/helm/status.go @@ -65,7 +65,7 @@ func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command { } func (s *statusCmd) run() error { - res, err := s.client.ReleaseStatus(s.release) + res, err := s.client.ReleaseStatus(s.release, helm.StatusReleaseVersion(s.version)) if err != nil { return prettyError(err) } From e3626da41db7e9c46fa1e2e248dff6bc8075fb4d Mon Sep 17 00:00:00 2001 From: fibonacci1729 Date: Wed, 24 Aug 2016 15:13:11 -0600 Subject: [PATCH 09/10] chore(storage-naming): update storage to allow querying by labels --- pkg/storage/driver/cfgmaps.go | 37 ++++++++++++++++++++++++++++++ pkg/storage/driver/cfgmaps_test.go | 4 ++++ pkg/storage/driver/driver.go | 5 +++- pkg/storage/driver/memory.go | 6 +++++ pkg/storage/driver/memory_test.go | 2 +- pkg/storage/storage.go | 21 +++++++++++++++-- 6 files changed, 71 insertions(+), 4 deletions(-) diff --git a/pkg/storage/driver/cfgmaps.go b/pkg/storage/driver/cfgmaps.go index 942634674..e99884543 100644 --- a/pkg/storage/driver/cfgmaps.go +++ b/pkg/storage/driver/cfgmaps.go @@ -30,6 +30,7 @@ import ( "k8s.io/kubernetes/pkg/api" kberrs "k8s.io/kubernetes/pkg/api/errors" client "k8s.io/kubernetes/pkg/client/unversioned" + kblabels "k8s.io/kubernetes/pkg/labels" ) // ConfigMapsDriverName is the string name of the driver. @@ -95,6 +96,10 @@ func (cfgmaps *ConfigMaps) List(filter func(*rspb.Release) bool) ([]*rspb.Releas return nil, err } + if len(list.Items) == 0 { + return nil, ErrReleaseNotFound + } + var results []*rspb.Release // iterate over the configmaps object list @@ -112,6 +117,38 @@ func (cfgmaps *ConfigMaps) List(filter func(*rspb.Release) bool) ([]*rspb.Releas return results, nil } +// Query fetches all releases that match the provided map of labels. +// An error is returned if the configmap fails to retrieve the releases. +func (cfgmaps *ConfigMaps) Query(labels map[string]string) ([]*rspb.Release, error) { + ls := kblabels.Set{} + for k, v := range labels { + ls[k] = v + } + + opts := api.ListOptions{LabelSelector: ls.AsSelector()} + + list, err := cfgmaps.impl.List(opts) + if err != nil { + logerrf(err, "query: failed to query with labels") + return nil, err + } + + if len(list.Items) == 0 { + return nil, ErrReleaseNotFound + } + + var results []*rspb.Release + for _, item := range list.Items { + rls, err := decodeRelease(item.Data["release"]) + if err != nil { + logerrf(err, "query: failed to decode release: %s", err) + continue + } + results = append(results, rls) + } + return results, nil +} + // Create creates a new ConfigMap holding the release. If the // ConfigMap already exists, ErrReleaseExists is returned. func (cfgmaps *ConfigMaps) Create(key string, rls *rspb.Release) error { diff --git a/pkg/storage/driver/cfgmaps_test.go b/pkg/storage/driver/cfgmaps_test.go index 5f473809e..70231fad1 100644 --- a/pkg/storage/driver/cfgmaps_test.go +++ b/pkg/storage/driver/cfgmaps_test.go @@ -102,6 +102,10 @@ func TestConfigMapList(t *testing.T) { } } +func TestConfigMapQuery(t *testing.T) { + t.Skip("TestConfigMapQuery") +} + func TestConfigMapCreate(t *testing.T) { cfgmaps := newTestFixture(t) diff --git a/pkg/storage/driver/driver.go b/pkg/storage/driver/driver.go index 96a096497..b51a8394d 100644 --- a/pkg/storage/driver/driver.go +++ b/pkg/storage/driver/driver.go @@ -53,15 +53,18 @@ type Deletor interface { Delete(key string) (*rspb.Release, error) } -// Queryor is the interface that wraps the Get and List methods. +// Queryor is the interface that wraps the Get, List, and Query methods. // // Get returns the release named by key or returns ErrReleaseNotFound // if the release does not exist. // // List returns the set of all releases that satisfy the filter predicate. +// +// Query returns the set of all releases that match the provided set of labels. type Queryor interface { Get(key string) (*rspb.Release, error) List(filter func(*rspb.Release) bool) ([]*rspb.Release, error) + Query(labels map[string]string) ([]*rspb.Release, error) } // Driver is the interface composed of Creator, Updator, Deletor, Queryor diff --git a/pkg/storage/driver/memory.go b/pkg/storage/driver/memory.go index 91e295f97..d25023522 100644 --- a/pkg/storage/driver/memory.go +++ b/pkg/storage/driver/memory.go @@ -17,6 +17,7 @@ limitations under the License. package driver // import "k8s.io/helm/pkg/storage/driver" import ( + "fmt" "sync" rspb "k8s.io/helm/pkg/proto/hapi/release" @@ -64,6 +65,11 @@ func (mem *Memory) List(filter func(*rspb.Release) bool) ([]*rspb.Release, error return releases, nil } +// Query does not apply to in-memory storage. +func (mem *Memory) Query(_ map[string]string) ([]*rspb.Release, error) { + return nil, fmt.Errorf("memory: cannot apply query by labels to in-memory storage") +} + // Create creates a new release or returns ErrReleaseExists. func (mem *Memory) Create(key string, rls *rspb.Release) error { defer unlock(mem.wlock()) diff --git a/pkg/storage/driver/memory_test.go b/pkg/storage/driver/memory_test.go index bf49b4c19..26eddb332 100644 --- a/pkg/storage/driver/memory_test.go +++ b/pkg/storage/driver/memory_test.go @@ -135,5 +135,5 @@ func TestMemoryDelete(t *testing.T) { } func testKey(name string, version int32) string { - return fmt.Sprintf("%s#v%d", name, version) + return fmt.Sprintf("%s.v%d", name, version) } diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index 2b39d2743..d5318b1f4 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -34,6 +34,23 @@ type Storage struct { // release identified by the key, version pair does not exist. func (s *Storage) Get(name string, version int32) (*rspb.Release, error) { log.Printf("Getting release %q (v%d) from storage\n", name, version) + // an unspecified version implies latest so we need to select from the + // set of releases any such that NAME == "name" and STATUS == "DEPLOYED" + if version == 0 { + ls, err := s.Driver.Query(map[string]string{ + "NAME": name, + "STATUS": "DEPLOYED", + }) + switch { + case err != nil: + return nil, err + case len(ls) == 0: + return nil, fmt.Errorf("bad query") + default: + return ls[0], nil + } + } + return s.Driver.Get(makeKey(name, version)) } @@ -117,8 +134,8 @@ func Init(d driver.Driver) *Storage { } // makeKey concatenates a release name and version into -// a string with format ```#v```. +// a string with format ```.v```. // This key is used to uniquely identify storage objects. func makeKey(rlsname string, version int32) string { - return fmt.Sprintf("%s#v%d", rlsname, version) + return fmt.Sprintf("%s.v%d", rlsname, version) } From 8ffba4c0c91c9f1f5ca74e3c15bdede67d855e46 Mon Sep 17 00:00:00 2001 From: fibonacci1729 Date: Wed, 24 Aug 2016 15:16:08 -0600 Subject: [PATCH 10/10] chore(storage-naming): update release server to update old release status to SUPERSEDED on upgrade. Update tests to fail early if error to avoid nil --- cmd/tiller/release_server.go | 7 ++++++- cmd/tiller/release_server_test.go | 19 ++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/cmd/tiller/release_server.go b/cmd/tiller/release_server.go index 122b370d0..69413f9e4 100644 --- a/cmd/tiller/release_server.go +++ b/cmd/tiller/release_server.go @@ -198,7 +198,7 @@ func (s *releaseServer) UpdateRelease(c ctx.Context, req *services.UpdateRelease return nil, err } - if err := s.env.Releases.Update(updatedRelease); err != nil { + if err := s.env.Releases.Create(updatedRelease); err != nil { return nil, err } @@ -234,6 +234,11 @@ func (s *releaseServer) performUpdate(originalRelease, updatedRelease *release.R } } + originalRelease.Info.Status.Code = release.Status_SUPERSEDED + if err := env.Releases.Update(originalRelease); err != nil { + return nil, fmt.Errorf("Update of %s failed: %s", originalRelease.Name, err) + } + updatedRelease.Info.Status.Code = release.Status_DEPLOYED return res, nil diff --git a/cmd/tiller/release_server_test.go b/cmd/tiller/release_server_test.go index dba2fc9db..bd1a643ad 100644 --- a/cmd/tiller/release_server_test.go +++ b/cmd/tiller/release_server_test.go @@ -178,7 +178,7 @@ func TestInstallRelease(t *testing.T) { t.Errorf("Expected release namespace 'spaced', got '%s'.", res.Release.Namespace) } - rel, err := rs.env.Releases.Get(res.Release.Name) + rel, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) if err != nil { t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) } @@ -248,7 +248,7 @@ func TestInstallReleaseDryRun(t *testing.T) { t.Errorf("Should not contain template data for an empty file. %s", res.Release.Manifest) } - if _, err := rs.env.Releases.Get(res.Release.Name); err == nil { + if _, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version); err == nil { t.Errorf("Expected no stored release.") } @@ -317,10 +317,11 @@ func TestUpdateRelease(t *testing.T) { {Name: "hooks", Data: []byte(manifestWithUpgradeHooks)}, }, }, + Version: 1, } res, err := rs.UpdateRelease(c, req) if err != nil { - t.Errorf("Failed updated: %s", err) + t.Fatalf("Failed updated: %s", err) } if res.Release.Name == "" { @@ -335,7 +336,7 @@ func TestUpdateRelease(t *testing.T) { t.Errorf("Expected release namespace '%s', got '%s'.", rel.Namespace, res.Release.Namespace) } - updated, err := rs.env.Releases.Get(res.Release.Name) + updated, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) if err != nil { t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) } @@ -392,7 +393,7 @@ func TestUpdateReleaseNoHooks(t *testing.T) { res, err := rs.UpdateRelease(c, req) if err != nil { - t.Errorf("Failed updated: %s", err) + t.Fatalf("Failed updated: %s", err) } if hl := res.Release.Hooks[0].LastRun; hl != nil { @@ -412,7 +413,7 @@ func TestUninstallRelease(t *testing.T) { res, err := rs.UninstallRelease(c, req) if err != nil { - t.Errorf("Failed uninstall: %s", err) + t.Fatalf("Failed uninstall: %s", err) } if res.Release.Name != "angry-panda" { @@ -451,7 +452,7 @@ func TestUninstallReleaseNoHooks(t *testing.T) { res, err := rs.UninstallRelease(c, req) if err != nil { - t.Errorf("Failed uninstall: %s", err) + t.Fatalf("Failed uninstall: %s", err) } // The default value for a protobuf timestamp is nil. @@ -470,7 +471,7 @@ func TestGetReleaseContent(t *testing.T) { res, err := rs.GetReleaseContent(c, &services.GetReleaseContentRequest{Name: rel.Name}) if err != nil { - t.Errorf("Error getting release content: %s", err) + t.Fatalf("Error getting release content: %s", err) } if res.Release.Chart.Metadata.Name != rel.Chart.Metadata.Name { @@ -488,7 +489,7 @@ func TestGetReleaseStatus(t *testing.T) { res, err := rs.GetReleaseStatus(c, &services.GetReleaseStatusRequest{Name: rel.Name}) if err != nil { - t.Errorf("Error getting release content: %s", err) + t.Fatalf("Error getting release content: %s", err) } if res.Info.Status.Code != release.Status_DEPLOYED {