Commit 98310a91 authored by Steve Wilkerson's avatar Steve Wilkerson
Browse files

fix(helm): add warnings for missing chart dependencies

When 'helm install', 'helm package', and 'helm upgrade' are run,
Helm will not issue any warnings if any dependencies listed in
a chart's requirements.yaml file are missing.  This change includes
warnings when a chart is found in requirements.yaml but isn't
in charts/.

Closes #1567
parent ed7bb419
main Release add-codeql dependabot/go_modules/github.com/docker/distribution-2.8.2incompatible dependabot/go_modules/github.com/lib/pq-1.10.9 dependabot/go_modules/github.com/rubenv/sql-migrate-1.4.0 dependabot/go_modules/golang.org/x/crypto-0.9.0 dependabot/go_modules/golang.org/x/term-0.8.0 dependabot/go_modules/k8s.io/klog/v2-2.100.1 dev-v2 feat-v3/event-emitter-lua release-2.10 release-2.11 release-2.12 release-2.13 release-2.14 release-2.15 release-2.16 release-2.17 release-2.2 release-2.3 release-2.4 release-2.5 release-2.6 release-2.7 release-2.8 release-2.9 release-3.0 release-3.1 release-3.10 release-3.11 release-3.12 release-3.2 release-3.3 release-3.4 release-3.5 release-3.6 release-3.6.1 release-3.6.2 release-3.7 release-3.8 release-3.9 release-v3.0.0-beta.4 v3.12.0 v3.12.0-rc.1 v3.12.0-dev.1 v3.11.3 v3.11.2 v3.11.1 v3.11.0 v3.11.0-rc.2 v3.11.0-rc.1 v3.10.3 v3.10.2 v3.10.1 v3.10.0 v3.10.0-rc.1 v3.9.4 v3.9.3 v3.9.2 v3.9.1 v3.9.0 v3.9.0-rc.1 v3.8.2 v3.8.1 v3.8.0 v3.8.0-rc.2 v3.8.0-rc.1 v3.7.2 v3.7.1 v3.7.0 v3.7.0-rc.3 v3.7.0-rc.2 v3.7.0-rc.1 v3.6.3 v3.6.2 v3.6.1 v3.6.0 v3.6.0-rc.1 v3.5.4 v3.5.3 v3.5.2 v3.5.1 v3.5.0 v3.5.0-rc.2 v3.5.0-rc.1 v3.4.2 v3.4.1 v3.4.0 v3.4.0-rc.1 v3.3.4 v3.3.3 v3.3.2 v3.3.1 v3.3.0 v3.3.0-rc.2 v3.3.0-rc.1 v3.2.4 v3.2.3 v3.2.2 v3.2.1 v3.2.0 v3.2.0-rc.1 v3.1.3 v3.1.2 v3.1.1 v3.1.0 v3.1.0-rc.3 v3.1.0-rc.2 v3.1.0-rc.1 v3.0.3 v3.0.2 v3.0.1 v3.0.0 v3.0.0-rc.4 v3.0.0-rc.3 v3.0.0-rc.2 v3.0.0-rc.1 v3.0.0-beta.5 v3.0.0-beta.4 v3.0.0-beta.3 v3.0.0-beta.2 v3.0.0-beta.1 v3.0.0-alpha.2 v3.0.0-alpha.1 v2.17.0 v2.17.0-rc.1 v2.16.12 v2.16.11 v2.16.10 v2.16.9 v2.16.8 v2.16.7 v2.16.6 v2.16.5 v2.16.4 v2.16.3 v2.16.2 v2.16.1 v2.16.0 v2.16.0-rc.2 v2.16.0-rc.1 v2.15.2 v2.15.1 v2.15.0 v2.15.0-rc.2 v2.15.0-rc.1 v2.14.3 v2.14.2 v2.14.1 v2.14.0 v2.14.0-rc.2 v2.14.0-rc.1 v2.13.1 v2.13.1-rc.1 v2.13.0 v2.13.0-rc.2 v2.13.0-rc.1 v2.12.3 v2.12.2 v2.12.1 v2.12.0 v2.12.0-rc.2 v2.12.0-rc.1 v2.11.0 v2.11.0-rc.4 v2.11.0-rc.3 v2.11.0-rc.2 v2.11.0-rc.1 v2.10.0 v2.10.0-rc.3 v2.10.0-rc.2 v2.10.0-rc.1 v2.9.1 v2.9.0 v2.9.0-rc5 v2.9.0-rc4 v2.9.0-rc3 v2.9.0-rc2 v2.9.0-rc1 v2.8.2 v2.8.2-rc1 v2.8.1 v2.8.0 v2.8.0-rc.1 v2.7.2 v2.7.1 v2.7.0 v2.7.0-rc1 v2.6.2 v2.6.1 v2.6.0 v2.5.1 v2.5.0 v2.4.2 v2.4.1 v2.4.0 v2.3.1 v2.3.0 v2.2.3 v2.2.2 v2.2.1 v2.2.0
No related merge requests found
Showing with 127 additions and 0 deletions
+127 -0
......@@ -35,8 +35,10 @@ import (
"k8s.io/helm/cmd/helm/downloader"
"k8s.io/helm/cmd/helm/helmpath"
"k8s.io/helm/cmd/helm/strvals"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/helm"
"k8s.io/helm/pkg/kube"
"k8s.io/helm/pkg/proto/hapi/chart"
"k8s.io/helm/pkg/proto/hapi/release"
)
......@@ -199,6 +201,13 @@ func (i *installCmd) run() error {
fmt.Printf("FINAL NAME: %s\n", i.name)
}
// Check chart requirements to make sure all dependencies are present in /charts
if c, err := chartutil.Load(i.chartPath); err == nil {
if req, err := chartutil.LoadRequirements(c); err == nil {
checkDependencies(c, req, i.out)
}
}
res, err := i.client.InstallRelease(
i.chartPath,
i.namespace,
......@@ -388,3 +397,19 @@ func defaultNamespace() string {
}
return "default"
}
func checkDependencies(ch *chart.Chart, reqs *chartutil.Requirements, out io.Writer) {
deps := ch.GetDependencies()
for _, r := range reqs.Dependencies {
found := false
for _, d := range deps {
if d.Metadata.Name == r.Name {
found = true
break
}
}
if !found {
fmt.Fprintf(out, "Warning: %s is in requirements.yaml but not in the charts/ directory!\n", r.Name)
}
}
}
......@@ -132,6 +132,12 @@ func TestInstall(t *testing.T) {
args: []string{"testdata/testcharts/signtest-0.1.0.tgz"},
flags: strings.Split("--verify --keyring testdata/helm-test-key.pub", " "),
},
// Install, chart with missing dependencies in /charts
{
name: "install chart with missing dependencies",
args: []string{"testdata/testcharts/chart-missing-deps"},
expected: "Warning: reqsubchart2 is in requirements.yaml but not in the charts/ directory!",
},
}
runReleaseCases(t, tests, func(c *fakeReleaseClient, out io.Writer) *cobra.Command {
......
......@@ -125,6 +125,10 @@ func (p *packageCmd) run(cmd *cobra.Command, args []string) error {
return fmt.Errorf("directory name (%s) and Chart.yaml name (%s) must match", filepath.Base(path), ch.Metadata.Name)
}
if reqs, err := chartutil.LoadRequirements(ch); err == nil {
checkDependencies(ch, reqs, p.out)
}
// Save to the current working directory.
cwd, err := os.Getwd()
if err != nil {
......
......@@ -101,6 +101,12 @@ func TestPackage(t *testing.T) {
expect: "",
hasfile: "alpine-0.1.0.tgz",
},
{
name: "package testdata/testcharts/chart-missing-deps",
args: []string{"testdata/testcharts/chart-missing-deps"},
expect: "Warning: reqsubchart2 is in requirements.yaml but not in the charts/ directory!\n",
hasfile: "chart-missing-deps-0.1.0.tgz",
},
}
// Because these tests are destructive, we run them in a tempdir.
......
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj
description: A Helm chart for Kubernetes
name: chart-missing-deps
version: 0.1.0
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj
description: A Helm chart for Kubernetes
name: reqsubchart
version: 0.1.0
# Default values for reqsubchart.
# This is a YAML-formatted file.
# Declare name/value pairs to be passed into your templates.
# name: value
dependencies:
- name: reqsubchart
version: 0.1.0
repository: "https://example.com/charts"
- name: reqsubchart2
version: 0.2.0
repository: "https://example.com/charts"
# Default values for reqtest.
# This is a YAML-formatted file.
# Declare name/value pairs to be passed into your templates.
# name: value
......@@ -26,6 +26,7 @@ import (
"github.com/spf13/cobra"
"k8s.io/helm/cmd/helm/strvals"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/helm"
"k8s.io/helm/pkg/storage/driver"
)
......@@ -160,6 +161,13 @@ func (u *upgradeCmd) run() error {
return err
}
// Check chart requirements to make sure all dependencies are present in /charts
if ch, err := chartutil.Load(chartPath); err == nil {
if req, err := chartutil.LoadRequirements(ch); err == nil {
checkDependencies(ch, req, u.out)
}
}
resp, err := u.client.UpdateRelease(
u.release,
chartPath,
......
......@@ -20,6 +20,7 @@ import (
"io"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/spf13/cobra"
......@@ -79,6 +80,14 @@ func TestUpgradeCmd(t *testing.T) {
t.Errorf("Error loading updated chart: %v", err)
}
originalDepsPath := filepath.Join("testdata/testcharts/reqtest")
missingDepsPath := filepath.Join("testdata/testcharts/chart-missing-deps")
var ch3 *chart.Chart
ch3, err = chartutil.Load(originalDepsPath)
if err != nil {
t.Errorf("Error loading chart with missing dependencies: %v", err)
}
tests := []releaseCase{
{
name: "upgrade a release",
......@@ -121,6 +130,12 @@ func TestUpgradeCmd(t *testing.T) {
resp: releaseMock(&releaseOptions{name: "crazy-bunny", version: 2, chart: ch2}),
expected: "Release \"crazy-bunny\" has been upgraded. Happy Helming!\n",
},
{
name: "upgrade a release with missing dependencies",
args: []string{"bonkers-bunny", missingDepsPath},
resp: releaseMock(&releaseOptions{name: "bonkers-bunny", version: 1, chart: ch3}),
expected: "Warning: reqsubchart2 is in requirements.yaml but not in the charts/ directory!",
},
}
cmd := func(c *fakeReleaseClient, out io.Writer) *cobra.Command {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment