From de7c5e5a381c47da4f6ca8da27163aa473471c8b Mon Sep 17 00:00:00 2001
From: Matt Butcher <technosophos@gmail.com>
Date: Wed, 14 Dec 2016 18:01:04 -0700
Subject: [PATCH] feat(tiller): Add .Release.Revision and .IsUpgrade

New properties are available to template developers.

Closes #1554
---
 docs/chart_template_guide/builtin_objects.md |  2 ++
 docs/charts.md                               |  4 ++++
 pkg/chartutil/values.go                      |  4 ++++
 pkg/chartutil/values_test.go                 | 10 +++++++++-
 pkg/storage/storage.go                       |  1 +
 pkg/tiller/release_server.go                 | 18 +++++++++++++++---
 6 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/docs/chart_template_guide/builtin_objects.md b/docs/chart_template_guide/builtin_objects.md
index 661cf0a26..98f091eb0 100644
--- a/docs/chart_template_guide/builtin_objects.md
+++ b/docs/chart_template_guide/builtin_objects.md
@@ -11,6 +11,8 @@ In the previous section, we use `{{.Release.Name}}` to insert the name of a rele
 	- `Release.Time`: The time of the release
 	- `Release.Namespace`: The namespace to be released into (if the manifest doesn't override)
 	- `Release.Service`: The name of the releasing service (always `Tiller`).
+  - `Release.Revision`: The revision number of this release. It begins at 1 and is incremented for each `helm upgrade`.
+  - `Release.IsUpgrade`: This is set to `true` if the current operation is an upgrade.
 - `Values`: Values passed into the template from the `values.yaml` file and from user-supplied files. By default, `Values` is empty.
 - `Chart`: The contents of the `Chart.yaml` file. Any data in `Chart.yaml` will be accessible here. For example `{{.Chart.Name}}-{{.Chart.Version}}` will print out the `mychart-0.1.0`.
   - The available fields are listed in the [Charts Guide](charts.md)
diff --git a/docs/charts.md b/docs/charts.md
index 1e7b9a79f..dd4a12253 100644
--- a/docs/charts.md
+++ b/docs/charts.md
@@ -292,6 +292,10 @@ sensitive_.
 - `Release.Namespace`: The namespace the chart was released to.
 - `Release.Service`: The service that conducted the release. Usually
   this is `Tiller`.
+- `Release.IsUpgrade`: This is set to true if the current operation is an upgrade.
+  It is false for install.
+- `Release.Revision`: The revision number. It begins at 1, and increments with
+  each `helm upgrade`.
 - `Chart`: The contents of the `Chart.yaml`. Thus, the chart version is
   obtainable as `Chart.Version` and the maintainers are in
   `Chart.Maintainers`.
diff --git a/pkg/chartutil/values.go b/pkg/chartutil/values.go
index c431454a7..7c3cb21fb 100644
--- a/pkg/chartutil/values.go
+++ b/pkg/chartutil/values.go
@@ -304,6 +304,8 @@ type ReleaseOptions struct {
 	Name      string
 	Time      *timestamp.Timestamp
 	Namespace string
+	IsUpgrade bool
+	Revision  int
 }
 
 // ToRenderValues composes the struct from the data coming from the Releases, Charts and Values files
@@ -314,6 +316,8 @@ func ToRenderValues(chrt *chart.Chart, chrtVals *chart.Config, options ReleaseOp
 			"Name":      options.Name,
 			"Time":      options.Time,
 			"Namespace": options.Namespace,
+			"IsUpgrade": options.IsUpgrade,
+			"Revision":  options.Revision,
 			"Service":   "Tiller",
 		},
 		"Chart": chrt.Metadata,
diff --git a/pkg/chartutil/values_test.go b/pkg/chartutil/values_test.go
index b48d4e943..41da8efe7 100644
--- a/pkg/chartutil/values_test.go
+++ b/pkg/chartutil/values_test.go
@@ -104,6 +104,7 @@ where:
 		Name:      "Seven Voyages",
 		Time:      timeconv.Now(),
 		Namespace: "al Basrah",
+		Revision:  5,
 	}
 
 	res, err := ToRenderValues(c, v, o)
@@ -115,9 +116,16 @@ where:
 	if name := res["Chart"].(*chart.Metadata).Name; name != "test" {
 		t.Errorf("Expected chart name 'test', got %q", name)
 	}
-	if name := res["Release"].(map[string]interface{})["Name"]; fmt.Sprint(name) != "Seven Voyages" {
+	relmap := res["Release"].(map[string]interface{})
+	if name := relmap["Name"]; name.(string) != "Seven Voyages" {
 		t.Errorf("Expected release name 'Seven Voyages', got %q", name)
 	}
+	if rev := relmap["Revision"]; rev.(int) != 5 {
+		t.Errorf("Expected release revision %d, got %q", 5, rev)
+	}
+	if relmap["IsUpgrade"].(bool) {
+		t.Errorf("Expected upgrade to be false.")
+	}
 	if data := res["Files"].(Files)["scheherazade/shahryar.txt"]; string(data) != "1,001 Nights" {
 		t.Errorf("Expected file '1,001 Nights', got %q", string(data))
 	}
diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go
index 88fcd255f..a10f377da 100644
--- a/pkg/storage/storage.go
+++ b/pkg/storage/storage.go
@@ -139,6 +139,7 @@ func (s *Storage) History(name string) ([]*rspb.Release, error) {
 	return l, nil
 }
 
+// Last fetches the last revision of the named release.
 func (s *Storage) Last(name string) (*rspb.Release, error) {
 	h, err := s.History(name)
 	if err != nil {
diff --git a/pkg/tiller/release_server.go b/pkg/tiller/release_server.go
index e5266c509..c3fecc456 100644
--- a/pkg/tiller/release_server.go
+++ b/pkg/tiller/release_server.go
@@ -393,11 +393,17 @@ func (s *ReleaseServer) prepareUpdate(req *services.UpdateReleaseRequest) (*rele
 	// If new values were not supplied in the upgrade, re-use the existing values.
 	s.reuseValues(req, currentRelease)
 
+	// Increment revision count. This is passed to templates, and also stored on
+	// the release object.
+	revision := currentRelease.Version + 1
+
 	ts := timeconv.Now()
 	options := chartutil.ReleaseOptions{
 		Name:      req.Name,
 		Time:      ts,
 		Namespace: currentRelease.Namespace,
+		IsUpgrade: true,
+		Revision:  int(revision),
 	}
 
 	valuesToRender, err := chartutil.ToRenderValues(req.Chart, req.Values, options)
@@ -421,7 +427,7 @@ func (s *ReleaseServer) prepareUpdate(req *services.UpdateReleaseRequest) (*rele
 			LastDeployed:  ts,
 			Status:        &release.Status{Code: release.Status_UNKNOWN},
 		},
-		Version:  currentRelease.Version + 1,
+		Version:  revision,
 		Manifest: manifestDoc.String(),
 		Hooks:    hooks,
 	}
@@ -646,8 +652,14 @@ func (s *ReleaseServer) prepareRelease(req *services.InstallReleaseRequest) (*re
 		return nil, err
 	}
 
+	revision := 1
 	ts := timeconv.Now()
-	options := chartutil.ReleaseOptions{Name: name, Time: ts, Namespace: req.Namespace}
+	options := chartutil.ReleaseOptions{
+		Name:      name,
+		Time:      ts,
+		Namespace: req.Namespace,
+		Revision:  revision,
+	}
 	valuesToRender, err := chartutil.ToRenderValues(req.Chart, req.Values, options)
 	if err != nil {
 		return nil, err
@@ -688,7 +700,7 @@ func (s *ReleaseServer) prepareRelease(req *services.InstallReleaseRequest) (*re
 		},
 		Manifest: manifestDoc.String(),
 		Hooks:    hooks,
-		Version:  1,
+		Version:  int32(revision),
 	}
 	if len(notesTxt) > 0 {
 		rel.Info.Status.Notes = notesTxt
-- 
GitLab