Repository: helm/helm (go)

Issue:
`helm show values` should have a way to specify what values to show
`Helm show values` doesn't have a way to specify which values you want to output. It would be nice to have this because  tools like bash don't have a yaml parser natively so to get a specific value from a chart I have to download a yaml parser. I believe helm should have this integrated because helm seems to be using something like this for `helm install --set` already.

Pull request:
feature(show): support jsonpath output for `helm show value`
**What this PR does / why we need it**:

Closes #7787

**Special notes for your reviewer**:
1. This is a preliminary realization. I will improve the implementation after listening to everyone's advice.
2. Only `helm show values` support the jsonpath format.
3. This is  implemented through Library `k8s.io/cli-runtime` and related document is [here](https://kubernetes.io/docs/reference/kubectl/jsonpath/).

**If applicable**:
- [ ] this PR contains documentation
- [x] this PR contains unit tests
- [ ] this PR has been tested for backwards compatibility


Patch:
diff --git a/Makefile b/Makefile
index f8325480a..524421279 100644
--- a/Makefile
+++ b/Makefile
@@ -183,7 +183,7 @@ clean:
 .PHONY: release-notes
 release-notes:
 		@if [ ! -d "./_dist" ]; then \
-			echo "please run 'make fetch-dist' first" && \
+			echo "please run 'make fetch-release' first" && \
 			exit 1; \
 		fi
 		@if [ -z "${PREVIOUS_RELEASE}" ]; then \
diff --git a/OWNERS b/OWNERS
index e7c953077..d7dac5514 100644
--- a/OWNERS
+++ b/OWNERS
@@ -6,6 +6,7 @@ maintainers:
   - jdolitsky
   - marckhouzam
   - mattfarina
+  - michelleN
   - prydonius
   - SlickNik
   - technosophos
@@ -13,7 +14,6 @@ maintainers:
   - viglesiasce
 emeritus:
   - jascott1
-  - michelleN
   - migmartri
   - nebril
   - seh
diff --git a/cmd/helm/show.go b/cmd/helm/show.go
index c122d8476..fe5eaee26 100644
--- a/cmd/helm/show.go
+++ b/cmd/helm/show.go
@@ -151,6 +151,9 @@ func addShowFlags(subCmd *cobra.Command, client *action.Show) {
 	f := subCmd.Flags()
 
 	f.BoolVar(&client.Devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored")
+	if subCmd.Name() == "values" {
+		f.StringVar(&client.JSONPathTemplate, "jsonpath", "", "supply a JSONPath expression to filter the output")
+	}
 	addChartPathOptionsFlags(f, &client.ChartPathOptions)
 
 	err := subCmd.RegisterFlagCompletionFunc("version", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
diff --git a/internal/version/version.go b/internal/version/version.go
index 2941bb489..712aae640 100644
--- a/internal/version/version.go
+++ b/internal/version/version.go
@@ -29,6 +29,7 @@ var (
 	//
 	// Increment major number for new feature additions and behavioral changes.
 	// Increment minor number for bug fixes and performance enhancements.
+	// Increment patch number for critical fixes to existing releases.
 	version = "v3.3"
 
 	// metadata is extra build time data
diff --git a/pkg/action/action.go b/pkg/action/action.go
index fec86cd42..698ebd23f 100644
--- a/pkg/action/action.go
+++ b/pkg/action/action.go
@@ -60,8 +60,6 @@ var (
 	errInvalidRevision = errors.New("invalid release revision")
 	// errInvalidName indicates that an invalid release name was provided
 	errInvalidName = errors.New("invalid release name, must match regex ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])+$ and the length must not longer than 53")
-	// errPending indicates that another instance of Helm is already applying an operation on a release.
-	errPending = errors.New("another operation (install/upgrade/rollback) is in progress")
 )
 
 // ValidName is a regular expression for resource names.
diff --git a/pkg/action/show.go b/pkg/action/show.go
index 9baa9cf43..4eab2b4fd 100644
--- a/pkg/action/show.go
+++ b/pkg/action/show.go
@@ -20,6 +20,8 @@ import (
 	"fmt"
 	"strings"
 
+	"github.com/pkg/errors"
+	"k8s.io/cli-runtime/pkg/printers"
 	"sigs.k8s.io/yaml"
 
 	"helm.sh/helm/v3/pkg/chart"
@@ -52,9 +54,10 @@ func (o ShowOutputFormat) String() string {
 // It provides the implementation of 'helm show' and its respective subcommands.
 type Show struct {
 	ChartPathOptions
-	Devel        bool
-	OutputFormat ShowOutputFormat
-	chart        *chart.Chart // for testing
+	Devel            bool
+	OutputFormat     ShowOutputFormat
+	JSONPathTemplate string
+	chart            *chart.Chart // for testing
 }
 
 // NewShow creates a new Show object with the given configuration.
@@ -87,9 +90,17 @@ func (s *Show) Run(chartpath string) (string, error) {
 		if s.OutputFormat == ShowAll {
 			fmt.Fprintln(&out, "---")
 		}
-		for _, f := range s.chart.Raw {
-			if f.Name == chartutil.ValuesfileName {
-				fmt.Fprintln(&out, string(f.Data))
+		if s.JSONPathTemplate != "" {
+			printer, err := printers.NewJSONPathPrinter(s.JSONPathTemplate)
+			if err != nil {
+				return "", errors.Wrapf(err, "error parsing jsonpath %s", s.JSONPathTemplate)
+			}
+			printer.Execute(&out, s.chart.Values)
+		} else {
+			for _, f := range s.chart.Raw {
+				if f.Name == chartutil.ValuesfileName {
+					fmt.Fprintln(&out, string(f.Data))
+				}
 			}
 		}
 	}
diff --git a/pkg/action/upgrade.go b/pkg/action/upgrade.go
index 949aebcae..921a0eba5 100644
--- a/pkg/action/upgrade.go
+++ b/pkg/action/upgrade.go
@@ -170,11 +170,6 @@ func (u *Upgrade) prepareUpgrade(name string, chart *chart.Chart, vals map[strin
 		return nil, nil, err
 	}
 
-	// Concurrent `helm upgrade`s will either fail here with `errPending` or when creating the release with "already exists". This should act as a pessimistic lock.
-	if lastRelease.Info.Status.IsPending() {
-		return nil, nil, errPending
-	}
-
 	var currentRelease *release.Release
 	if lastRelease.Info.Status == release.StatusDeployed {
 		// no need to retrieve the last deployed release from storage as the last release is deployed
diff --git a/pkg/kube/client.go b/pkg/kube/client.go
index 62e1b104b..f908611db 100644
--- a/pkg/kube/client.go
+++ b/pkg/kube/client.go
@@ -542,14 +542,14 @@ func (c *Client) waitForPodSuccess(obj runtime.Object, name string) (bool, error
 
 	switch o.Status.Phase {
 	case v1.PodSucceeded:
-		c.Log("Pod %s succeeded", o.Name)
+		fmt.Printf("Pod %s succeeded\n", o.Name)
 		return true, nil
 	case v1.PodFailed:
 		return true, errors.Errorf("pod %s failed", o.Name)
 	case v1.PodPending:
-		c.Log("Pod %s pending", o.Name)
+		fmt.Printf("Pod %s pending\n", o.Name)
 	case v1.PodRunning:
-		c.Log("Pod %s running", o.Name)
+		fmt.Printf("Pod %s running\n", o.Name)
 	}
 
 	return false, nil
diff --git a/pkg/release/status.go b/pkg/release/status.go
index e0e3ed62a..49b0f1544 100644
--- a/pkg/release/status.go
+++ b/pkg/release/status.go
@@ -42,8 +42,3 @@ const (
 )
 
 func (x Status) String() string { return string(x) }
-
-// IsPending determines if this status is a state or a transition.
-func (x Status) IsPending() bool {
-	return x == StatusPendingInstall || x == StatusPendingUpgrade || x == StatusPendingRollback
-}


Test patch:
diff --git a/cmd/helm/testdata/output/upgrade-with-pending-install.txt b/cmd/helm/testdata/output/upgrade-with-pending-install.txt
deleted file mode 100644
index 57a8e7873..000000000
--- a/cmd/helm/testdata/output/upgrade-with-pending-install.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-Error: UPGRADE FAILED: another operation (install/upgrade/rollback) is in progress
diff --git a/cmd/helm/upgrade_test.go b/cmd/helm/upgrade_test.go
index 64daf2934..7e88bc0df 100644
--- a/cmd/helm/upgrade_test.go
+++ b/cmd/helm/upgrade_test.go
@@ -158,7 +158,7 @@ func TestUpgradeCmd(t *testing.T) {
 		{
 			name:      "upgrade a pending install release",
 			cmd:       fmt.Sprintf("upgrade funny-bunny '%s'", chartPath),
-			golden:    "output/upgrade-with-pending-install.txt",
+			golden:    "output/upgrade-with-bad-or-missing-existing-release.txt",
 			wantError: true,
 			rels:      []*release.Release{relWithStatusMock("funny-bunny", 2, ch, release.StatusPendingInstall)},
 		},
diff --git a/pkg/action/show_test.go b/pkg/action/show_test.go
index 7be9daaa5..a2efdc8ac 100644
--- a/pkg/action/show_test.go
+++ b/pkg/action/show_test.go
@@ -69,3 +69,17 @@ func TestShowNoValues(t *testing.T) {
 		t.Errorf("expected empty values buffer, got %s", output)
 	}
 }
+
+func TestShowValuesByJsonPathFormat(t *testing.T) {
+	client := NewShow(ShowValues)
+	client.JSONPathTemplate = "{$.nestedKey.simpleKey}"
+	client.chart = buildChart(withSampleValues())
+	output, err := client.Run("")
+	if err != nil {
+		t.Fatal(err)
+	}
+	expect := "simpleValue"
+	if output != expect {
+		t.Errorf("Expected\n%q\nGot\n%q\n", expect, output)
+	}
+}
diff --git a/pkg/action/upgrade_test.go b/pkg/action/upgrade_test.go
index f16de6479..f25d115c4 100644
--- a/pkg/action/upgrade_test.go
+++ b/pkg/action/upgrade_test.go
@@ -253,23 +253,3 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) {
 		is.Equal(expectedValues, updatedRes.Config)
 	})
 }
-
-func TestUpgradeRelease_Pending(t *testing.T) {
-	req := require.New(t)
-
-	upAction := upgradeAction(t)
-	rel := releaseStub()
-	rel.Name = "come-fail-away"
-	rel.Info.Status = release.StatusDeployed
-	upAction.cfg.Releases.Create(rel)
-	rel2 := releaseStub()
-	rel2.Name = "come-fail-away"
-	rel2.Info.Status = release.StatusPendingUpgrade
-	rel2.Version = 2
-	upAction.cfg.Releases.Create(rel2)
-
-	vals := map[string]interface{}{}
-
-	_, err := upAction.Run(rel.Name, buildChart(), vals)
-	req.Contains(err.Error(), "progress", err)
-}
diff --git a/pkg/chartutil/capabilities_test.go b/pkg/chartutil/capabilities_test.go
index 66eeee755..ae9624bca 100644
--- a/pkg/chartutil/capabilities_test.go
+++ b/pkg/chartutil/capabilities_test.go
@@ -55,7 +55,7 @@ func TestDefaultCapabilities(t *testing.T) {
 		t.Errorf("Expected default KubeVersion.Major to be 1, got %q", kv.Major)
 	}
 	if kv.Minor != "18" {
-		t.Errorf("Expected default KubeVersion.Minor to be 18, got %q", kv.Minor)
+		t.Errorf("Expected default KubeVersion.Minor to be 16, got %q", kv.Minor)
 	}
 }
 
@@ -63,6 +63,6 @@ func TestDefaultCapabilitiesHelmVersion(t *testing.T) {
 	hv := DefaultCapabilities.HelmVersion
 
 	if hv.Version != "v3.3" {
-		t.Errorf("Expected default HelmVersion to be v3.3, got %q", hv.Version)
+		t.Errorf("Expected default HelmVerison to be v3.3, got %q", hv.Version)
 	}
 }