func (h *Helm3Client) LastReleaseStatus(releaseName string) (revision string, status string, err error) {
	stdout, stderr, err := h.cmd("history", releaseName, "--max", "1", "--output", "yaml")
	if err != nil {
		errLine := strings.Split(stderr, "\n")[0]
		if strings.Contains(errLine, "Error:") && strings.Contains(errLine, "not found") {
			err = fmt.Errorf("release '%s' not found\n%v %v", releaseName, stdout, stderr)
			revision = "0"
			return
		}
		err = fmt.Errorf("cannot get history for release '%s'\n%v %v", releaseName, stdout, stderr)
		return
	}
	var historyInfo []map[string]string
	err = k8syaml.Unmarshal([]byte(stdout), &historyInfo)
	if err != nil {
		return "", "", fmt.Errorf("helm history returns invalid json: %v", err)
	}
	if len(historyInfo) == 0 {
		return "", "", fmt.Errorf("helm history is empty: '%s'", stdout)
	}
	status, has := historyInfo[0]["status"]
	if !has {
		return "", "", fmt.Errorf("helm history has no 'status' field: '%s'", stdout)
	}
	revision, has = historyInfo[0]["revision"]
	if !has {
		return "", "", fmt.Errorf("helm history has no 'revision' field: '%s'", stdout)
	}
	return
}
LastReleaseStatus returns last known revision for release and its status
Example helm history output:
REVISION	UPDATED                 	STATUS    	CHART                 	DESCRIPTION
1        Fri Jul 14 18:25:00 2017	SUPERSEDED	symfony-demo-0.1.0    	Install complete
package helm3
import (
	"bytes"
	"context"
	"fmt"
	"os"
	"os/exec"
	"sort"
	"strings"
	"time"
	klient "github.com/flant/kube-client/client"
	log "github.com/sirupsen/logrus"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	kblabels "k8s.io/apimachinery/pkg/labels"
	k8syaml "sigs.k8s.io/yaml"
	"github.com/flant/addon-operator/pkg/app"
	"github.com/flant/addon-operator/pkg/helm/client"
	"github.com/flant/addon-operator/pkg/utils"
	"github.com/flant/shell-operator/pkg/executor"
)
var Helm3Path = "helm"
type Helm3Options struct {
	Namespace  string
	HistoryMax int32
	Timeout    time.Duration
	KubeClient klient.Client
}
var Options *Helm3Options
func Init(options *Helm3Options) error {
	hc := &Helm3Client{
		LogEntry: log.WithField("operator.component", "helm"),
	}
	err := hc.initAndVersion()
	if err != nil {
		return err
	}
	Options = options
	return nil
}
type Helm3Client struct {
	KubeClient klient.Client
	LogEntry   *log.Entry
	Namespace  string
}
var _ client.HelmClient = &Helm3Client{}
func NewClient(logLabels ...map[string]string) client.HelmClient {
	logEntry := log.WithField("operator.component", "helm")
	if len(logLabels) > 0 {
		logEntry = logEntry.WithFields(utils.LabelsToLogFields(logLabels[0]))
	}
	return &Helm3Client{
		LogEntry:   logEntry,
		KubeClient: Options.KubeClient,
		Namespace:  Options.Namespace,
	}
}
func (h *Helm3Client) WithKubeClient(client klient.Client) {
	h.KubeClient = client
}
func (h *Helm3Client) CommandEnv() []string {
	res := make([]string, 0)
	return res
}
func (h *Helm3Client) cmd(args ...string) (stdout string, stderr string, err error) {
	cmd := exec.Command(Helm3Path, args...)
	cmd.Env = append(os.Environ(), h.CommandEnv()...)
	var stdoutBuf bytes.Buffer
	cmd.Stdout = &stdoutBuf
	var stderrBuf bytes.Buffer
	cmd.Stderr = &stderrBuf
	err = executor.Run(cmd)
	stdout = strings.TrimSpace(stdoutBuf.String())
	stderr = strings.TrimSpace(stderrBuf.String())
	return
}
func (h *Helm3Client) initAndVersion() error {
	stdout, stderr, err := h.cmd("version", "--short")
	if err != nil {
		return fmt.Errorf("unable to get helm version: %v\n%v %v", err, stdout, stderr)
	}
	stdout = strings.Join([]string{stdout, stderr}, "\n")
	stdout = strings.ReplaceAll(stdout, "\n", " ")
	log.Infof("Helm 3 version: %s", stdout)
	return nil
}
func (h *Helm3Client) DeleteSingleFailedRevision(releaseName string) error {
	return nil
}
func (h *Helm3Client) DeleteOldFailedRevisions(releaseName string) error {
	return nil
}