Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for --dry-run in Helm Client #2824

Merged
merged 21 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pkg/app/cassandra.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (cas *CassandraInstance) Install(ctx context.Context, namespace string) err
if err != nil {
return err
}
err = cli.Install(ctx, fmt.Sprintf("%s/%s", cas.chart.RepoName, cas.chart.Chart), cas.chart.Version, cas.chart.Release, cas.namespace, cas.chart.Values, true)
_, err = cli.Install(ctx, fmt.Sprintf("%s/%s", cas.chart.RepoName, cas.chart.Chart), cas.chart.Version, cas.chart.Release, cas.namespace, cas.chart.Values, true, false)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/app/cockroachdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (c *CockroachDB) Install(ctx context.Context, namespace string) error { //n
return errors.Wrapf(err, "Failed to install helm repo. app=%s repo=%s", c.name, c.chart.RepoName)
}

err = cli.Install(ctx, fmt.Sprintf("%s/%s", c.chart.RepoName, c.chart.Chart), c.chart.Version, c.chart.Release, c.namespace, c.chart.Values, false)
_, err = cli.Install(ctx, fmt.Sprintf("%s/%s", c.chart.RepoName, c.chart.Chart), c.chart.Version, c.chart.Release, c.namespace, c.chart.Values, false, false)
return errors.Wrapf(err, "Failed to install helm chart. app=%s chart=%s release=%s", c.name, c.chart.Chart, c.chart.Release)
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/app/couchbase.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func (cb *CouchbaseDB) Install(ctx context.Context, ns string) error { //nolint:
}

// Install cb operator, admission controller and cluster
err = cli.Install(ctx, fmt.Sprintf("%s/%s", cb.chart.RepoName, cb.chart.Chart), cb.chart.Version, cb.chart.Release, cb.namespace, cb.chart.Values, true)
_, err = cli.Install(ctx, fmt.Sprintf("%s/%s", cb.chart.RepoName, cb.chart.Chart), cb.chart.Version, cb.chart.Release, cb.namespace, cb.chart.Values, true, false)
return errors.Wrapf(err, "Failed to install helm chart. app=%s chart=%s release=%s", cb.name, cb.chart.Chart, cb.chart.Release)
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/app/elasticsearch.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func (esi *ElasticsearchInstance) Install(ctx context.Context, namespace string)
return err
}

err = cli.Install(ctx, fmt.Sprintf("%s/%s", esi.chart.RepoName, esi.chart.Chart), esi.chart.Version, esi.chart.Release, esi.namespace, esi.chart.Values, true)
_, err = cli.Install(ctx, fmt.Sprintf("%s/%s", esi.chart.RepoName, esi.chart.Chart), esi.chart.Version, esi.chart.Release, esi.namespace, esi.chart.Values, true, false)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/app/kafka.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func (kc *KafkaCluster) Install(ctx context.Context, namespace string) error {
return errors.Wrapf(err, "Error adding helm repo for app %s.", kc.name)
}
log.Print("Installing kafka operator using helm.", field.M{"app": kc.name})
err = cli.Install(ctx, kc.chart.RepoName+"/"+kc.chart.Chart, kc.chart.Version, kc.chart.Release, kc.namespace, kc.chart.Values, true)
_, err = cli.Install(ctx, kc.chart.RepoName+"/"+kc.chart.Chart, kc.chart.Version, kc.chart.Release, kc.namespace, kc.chart.Values, true, false)
if err != nil {
return errors.Wrapf(err, "Error installing operator %s through helm.", kc.name)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/app/mariadb.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func (m *MariaDB) Install(ctx context.Context, namespace string) error { //nolin
}

log.Print("Installing maria instance using helm.", field.M{"app": m.name})
err = cli.Install(ctx, m.chart.RepoName+"/"+m.chart.Chart, m.chart.Version, m.chart.Release, m.namespace, m.chart.Values, true)
_, err = cli.Install(ctx, m.chart.RepoName+"/"+m.chart.Chart, m.chart.Version, m.chart.Release, m.namespace, m.chart.Values, true, false)
if err != nil {
return errors.Wrapf(err, "Error intalling application %s through helm.", m.name)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/app/mongodb.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func (mongo *MongoDB) Install(ctx context.Context, namespace string) error {
}

log.Print("Installing application using helm.", field.M{"app": mongo.name})
err = cli.Install(ctx, fmt.Sprintf("%s/%s", mongo.chart.RepoName, mongo.chart.Chart), mongo.chart.Version, mongo.chart.Release, mongo.namespace, mongo.chart.Values, true)
_, err = cli.Install(ctx, fmt.Sprintf("%s/%s", mongo.chart.RepoName, mongo.chart.Chart), mongo.chart.Version, mongo.chart.Release, mongo.namespace, mongo.chart.Values, true, false)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/app/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func (mdb *MysqlDB) Install(ctx context.Context, namespace string) error { //nol
}

log.Print("Installing mysql instance using helm.", field.M{"app": mdb.name})
err = cli.Install(ctx, mdb.chart.RepoName+"/"+mdb.chart.Chart, mdb.chart.Version, mdb.chart.Release, mdb.namespace, mdb.chart.Values, true)
_, err = cli.Install(ctx, mdb.chart.RepoName+"/"+mdb.chart.Chart, mdb.chart.Version, mdb.chart.Release, mdb.namespace, mdb.chart.Values, true, false)
if err != nil {
return errors.Wrapf(err, "Error intalling application %s through helm.", mdb.name)
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/app/postgresql.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ func (pdb *PostgresDB) Install(ctx context.Context, ns string) error {
return err
}
// Install helm chart
return cli.Install(ctx, fmt.Sprintf("%s/%s", pdb.chart.RepoName, pdb.chart.Chart), pdb.chart.Version, pdb.chart.Release, pdb.namespace, pdb.chart.Values, true)
_, err = cli.Install(ctx, fmt.Sprintf("%s/%s", pdb.chart.RepoName, pdb.chart.Chart), pdb.chart.Version, pdb.chart.Release, pdb.namespace, pdb.chart.Values, true, false)
return err
}

func (pdb *PostgresDB) IsReady(ctx context.Context) (bool, error) {
Expand Down
29 changes: 20 additions & 9 deletions pkg/helm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func (h CliClient) UpdateRepo(ctx context.Context) error {
}

// Install installs helm chart with given release name
func (h CliClient) Install(ctx context.Context, chart, version, release, namespace string, values map[string]string, wait bool) error {
func (h CliClient) Install(ctx context.Context, chart, version, release, namespace string, values map[string]string, wait, dryRun bool) (string, error) {
mabhi marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func (h CliClient) Install(ctx context.Context, chart, version, release, namespace string, values map[string]string, wait, dryRun bool) (string, error) {
func (h CliClient) Install(
ctx context.Context,
chart,
version,
release,
namespace string,
values map[string]string,
wait,
dryRun bool) (string, error) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking if there should be a type InstallOptions that would have all these fields. But we can do that later as well.

log.Debug().Print("Installing helm chart", field.M{"chart": chart, "version": version, "release": release, "namespace": namespace})
var setVals string
for k, v := range values {
Expand All @@ -140,14 +140,25 @@ func (h CliClient) Install(ctx context.Context, chart, version, release, namespa
if wait {
cmd = append(cmd, "--wait")
}

out, err := RunCmdWithTimeout(ctx, h.helmBin, cmd)
if err != nil {
log.Error().Print("Error installing helm chart", field.M{"output": out})
return err
}
log.Debug().Print("Result", field.M{"output": out})
return nil
if !dryRun {
out, err := RunCmdWithTimeout(ctx, h.helmBin, cmd)
if err != nil {
log.Error().Print("Error installing helm chart", field.M{"output": out})
return "", err
}
log.Debug().Print("Result", field.M{"output": out})
mabhi marked this conversation as resolved.
Show resolved Hide resolved
} else {
cmd = append(cmd, "--dry-run")
log.Info().Print("Helm dry-run. Executing to capture output:")
out, err := RunCmdWithTimeout(ctx, h.helmBin, cmd)
if err != nil {
log.Error().Print("Error capturing output during Helm dry-run", field.M{"output": out, "error": err})
return "", err
}
log.Info().Print("Helm dry-run output:", field.M{"command": h.helmBin, "args": cmd, "output": out})
mabhi marked this conversation as resolved.
Show resolved Hide resolved
return out, nil
}
return "", nil
mabhi marked this conversation as resolved.
Show resolved Hide resolved
}

func (h CliClient) Upgrade(ctx context.Context, chart, version, release, namespace string, values map[string]string) error {
Expand Down
2 changes: 1 addition & 1 deletion pkg/helm/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type Client interface {
RemoveRepo(ctx context.Context, name string) error
// Install installs helm chart with given release name in the namespace
// wait argument enables/disables --wait flag in 'helm install' command
Install(ctx context.Context, chart, version, release, namespace string, values map[string]string, wait bool) error
Install(ctx context.Context, chart, version, release, namespace string, values map[string]string, wait, dryRun bool) (string, error)
// Uninstall deletes helm release from the given namespace
Uninstall(ctx context.Context, release, namespace string) error
// Upgrade upgrades an installed helm release
Expand Down
55 changes: 55 additions & 0 deletions pkg/helm/helm_helpers.go
viveksinghggits marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package helm

import (
"regexp"
"strings"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml"

"github.com/kanisterio/kanister/pkg/field"
"github.com/kanisterio/kanister/pkg/log"
)

type k8sObj struct {
ObjKind string `json:"kind"`
MetaData metav1.ObjectMeta `json:"metadata"`
}

type K8sObjectType string

type Component struct {
k8sType K8sObjectType
name string
}

func ParseReleaseNameFromHelmStatus(helmStatus string) string {
mabhi marked this conversation as resolved.
Show resolved Hide resolved
mabhi marked this conversation as resolved.
Show resolved Hide resolved
re := regexp.MustCompile(`.*NAME:\s+(.*)\n`)
withNameRE := regexp.MustCompile(`^Release\s+"(.*)"\s+`)
tmpRelease := re.FindAllStringSubmatch(helmStatus, -1)
log.Info().Print("Parsed output for generate name install")
if len(tmpRelease) < 1 {
tmpRelease = withNameRE.FindAllStringSubmatch(helmStatus, -1)
log.Info().Print("Parsed output for specified name install/upgrade")
if len(tmpRelease) < 1 {
return ""
}
}
if len(tmpRelease[0]) == 2 {
return tmpRelease[0][1]
}
return ""
}

func ComponentsFromManifest(manifest string) []Component {
mabhi marked this conversation as resolved.
Show resolved Hide resolved
mabhi marked this conversation as resolved.
Show resolved Hide resolved
var ret []Component
for _, objYaml := range strings.Split(manifest, "---") {
tmpK8s := k8sObj{}
mabhi marked this conversation as resolved.
Show resolved Hide resolved
if err := yaml.Unmarshal([]byte(objYaml), &tmpK8s); err != nil {
log.Error().Print("failed to Unmarshal k8s obj", field.M{"Error": err})
continue
}
ret = append(ret, Component{k8sType: K8sObjectType(strings.ToLower(tmpK8s.ObjKind)), name: tmpK8s.MetaData.Name})
}
return ret
}
4 changes: 2 additions & 2 deletions pkg/testing/helm/helm_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ func (h *HelmApp) AddRepo(name, url string) error {
return h.client.AddRepo(context.Background(), name, url)
}

func (h *HelmApp) Install() error {
func (h *HelmApp) Install() (string, error) {
ctx := context.Background()
return h.client.Install(ctx, h.chart, "", h.name, h.namespace, h.helmValues, true)
return h.client.Install(ctx, h.chart, "", h.name, h.namespace, h.helmValues, true, h.dryRun)
}

func (h *HelmApp) Upgrade(chart string, updatedValues map[string]string) error {
Expand Down
4 changes: 2 additions & 2 deletions pkg/testing/helm/helm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ func (h *HelmTestSuite) TestUpgrade(c *C) {

// install released version of kanister
c.Log("Installing kanister release")
err := h.helmApp.Install()
// TODO: Use manifests to test the helm charts
_, err := h.helmApp.Install()
c.Assert(err, IsNil)

// wait for kanister deployment to be ready
err = kube.WaitOnDeploymentReady(ctx, h.kubeClient, h.helmApp.namespace, h.deploymentName)
c.Assert(err, IsNil)
Expand Down