|
|
|
@ -19,9 +19,7 @@ package action
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
|
|
|
|
"fmt"
|
|
|
|
|
"path"
|
|
|
|
|
"sort"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
@ -29,12 +27,9 @@ import (
|
|
|
|
|
|
|
|
|
|
"helm.sh/helm/pkg/chart"
|
|
|
|
|
"helm.sh/helm/pkg/chartutil"
|
|
|
|
|
"helm.sh/helm/pkg/engine"
|
|
|
|
|
"helm.sh/helm/pkg/hooks"
|
|
|
|
|
"helm.sh/helm/pkg/kube"
|
|
|
|
|
"helm.sh/helm/pkg/release"
|
|
|
|
|
"helm.sh/helm/pkg/releaseutil"
|
|
|
|
|
"helm.sh/helm/pkg/version"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Upgrade is the action for upgrading releases.
|
|
|
|
@ -164,7 +159,7 @@ func (u *Upgrade) prepareUpgrade(name string, chart *chart.Chart) (*release.Rele
|
|
|
|
|
return nil, nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hooks, manifestDoc, notesTxt, err := u.renderResources(chart, valuesToRender, caps.APIVersions)
|
|
|
|
|
hooks, manifestDoc, notesTxt, err := u.cfg.renderResources(chart, valuesToRender)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, nil, err
|
|
|
|
|
}
|
|
|
|
@ -213,8 +208,8 @@ func (u *Upgrade) performUpgrade(originalRelease, upgradedRelease *release.Relea
|
|
|
|
|
u.cfg.Log("warning: %s", msg)
|
|
|
|
|
upgradedRelease.Info.Status = release.StatusFailed
|
|
|
|
|
upgradedRelease.Info.Description = msg
|
|
|
|
|
u.cfg.recordRelease(originalRelease, true)
|
|
|
|
|
u.cfg.recordRelease(upgradedRelease, true)
|
|
|
|
|
u.cfg.recordRelease(originalRelease)
|
|
|
|
|
u.cfg.recordRelease(upgradedRelease)
|
|
|
|
|
return upgradedRelease, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -226,7 +221,7 @@ func (u *Upgrade) performUpgrade(originalRelease, upgradedRelease *release.Relea
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
originalRelease.Info.Status = release.StatusSuperseded
|
|
|
|
|
u.cfg.recordRelease(originalRelease, true)
|
|
|
|
|
u.cfg.recordRelease(originalRelease)
|
|
|
|
|
|
|
|
|
|
upgradedRelease.Info.Status = release.StatusDeployed
|
|
|
|
|
upgradedRelease.Info.Description = "Upgrade complete"
|
|
|
|
@ -297,73 +292,8 @@ func newCapabilities(dc discovery.DiscoveryInterface) (*chartutil.Capabilities,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *Upgrade) renderResources(ch *chart.Chart, values chartutil.Values, vs chartutil.VersionSet) ([]*release.Hook, *bytes.Buffer, string, error) {
|
|
|
|
|
if ch.Metadata.KubeVersion != "" {
|
|
|
|
|
cap, _ := values["Capabilities"].(*chartutil.Capabilities)
|
|
|
|
|
gitVersion := cap.KubeVersion.String()
|
|
|
|
|
k8sVersion := strings.Split(gitVersion, "+")[0]
|
|
|
|
|
if !version.IsCompatibleRange(ch.Metadata.KubeVersion, k8sVersion) {
|
|
|
|
|
return nil, nil, "", errors.Errorf("chart requires kubernetesVersion: %s which is incompatible with Kubernetes %s", ch.Metadata.KubeVersion, k8sVersion)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u.cfg.Log("rendering %s chart using values", ch.Name())
|
|
|
|
|
files, err := engine.Render(ch, values)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, nil, "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NOTES.txt gets rendered like all the other files, but because it's not a hook nor a resource,
|
|
|
|
|
// pull it out of here into a separate file so that we can actually use the output of the rendered
|
|
|
|
|
// text file. We have to spin through this map because the file contains path information, so we
|
|
|
|
|
// look for terminating NOTES.txt. We also remove it from the files so that we don't have to skip
|
|
|
|
|
// it in the sortHooks.
|
|
|
|
|
notes := ""
|
|
|
|
|
for k, v := range files {
|
|
|
|
|
if strings.HasSuffix(k, notesFileSuffix) {
|
|
|
|
|
// Only apply the notes if it belongs to the parent chart
|
|
|
|
|
// Note: Do not use filePath.Join since it creates a path with \ which is not expected
|
|
|
|
|
if k == path.Join(ch.Name(), "templates", notesFileSuffix) {
|
|
|
|
|
notes = v
|
|
|
|
|
}
|
|
|
|
|
delete(files, k)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sort hooks, manifests, and partials. Only hooks and manifests are returned,
|
|
|
|
|
// as partials are not used after renderer.Render. Empty manifests are also
|
|
|
|
|
// removed here.
|
|
|
|
|
hooks, manifests, err := releaseutil.SortManifests(files, vs, releaseutil.InstallOrder)
|
|
|
|
|
if err != nil {
|
|
|
|
|
// By catching parse errors here, we can prevent bogus releases from going
|
|
|
|
|
// to Kubernetes.
|
|
|
|
|
//
|
|
|
|
|
// We return the files as a big blob of data to help the user debug parser
|
|
|
|
|
// errors.
|
|
|
|
|
b := bytes.NewBuffer(nil)
|
|
|
|
|
for name, content := range files {
|
|
|
|
|
if len(strings.TrimSpace(content)) == 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
b.WriteString("\n---\n# Source: " + name + "\n")
|
|
|
|
|
b.WriteString(content)
|
|
|
|
|
}
|
|
|
|
|
return nil, b, "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Aggregate all valid manifests into one big doc.
|
|
|
|
|
b := bytes.NewBuffer(nil)
|
|
|
|
|
for _, m := range manifests {
|
|
|
|
|
b.WriteString("\n---\n# Source: " + m.Name + "\n")
|
|
|
|
|
b.WriteString(m.Content)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return hooks, b, notes, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func validateManifest(c kube.KubernetesClient, ns string, manifest []byte) error {
|
|
|
|
|
r := bytes.NewReader(manifest)
|
|
|
|
|
_, err := c.BuildUnstructured(ns, r)
|
|
|
|
|
_, err := c.BuildUnstructured(ns, bytes.NewReader(manifest))
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|