Skip to content

Commit

Permalink
adding --no-deps features
Browse files Browse the repository at this point in the history
  • Loading branch information
Franck Kambiwa committed Sep 25, 2020
1 parent b159ca8 commit 31c75e8
Show file tree
Hide file tree
Showing 95 changed files with 726 additions and 10,450 deletions.
28 changes: 15 additions & 13 deletions cmd/helmpack/pack.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,21 @@ func NewPackCmd(args []string, out io.Writer) *cobra.Command {
if _, err := os.Stat(args[i]); err != nil {
return err
}
if !client.NoDeps {
if client.DependencyUpdate {
downloadManager := &downloader.Manager{
Out: ioutil.Discard,
ChartPath: path,
Keyring: client.Keyring,
Getters: p,
Debug: settings.Debug,
RepositoryConfig: settings.RepositoryConfig,
RepositoryCache: settings.RepositoryCache,
}

if client.DependencyUpdate {
downloadManager := &downloader.Manager{
Out: ioutil.Discard,
ChartPath: path,
Keyring: client.Keyring,
Getters: p,
Debug: settings.Debug,
RepositoryConfig: settings.RepositoryConfig,
RepositoryCache: settings.RepositoryCache,
}

if err := downloadManager.Update(); err != nil {
return err
if err := downloadManager.Update(); err != nil {
return err
}
}
}
p, err := client.Run(path, vals)
Expand All @@ -90,6 +91,7 @@ func NewPackCmd(args []string, out io.Writer) *cobra.Command {
f.StringVar(&client.AppVersion, "app-version", "", "set the appVersion on the chart to this version")
f.StringVarP(&client.Destination, "destination", "d", ".", "location to write the chart.")
f.BoolVarP(&client.DependencyUpdate, "dependency-update", "u", false, `update dependencies from "Chart.yaml" to dir "charts/" before packaging`)
f.BoolVarP(&client.NoDeps, "no-deps", "n", false, `disables the dependencies from "Chart.yaml" before packaging`)
f.StringArrayVar(&valueOpts.Values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.Parse(args)
return cmd
Expand Down
68 changes: 68 additions & 0 deletions cmd/helmpack/pack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,71 @@ func TestPackWithDependencies(t *testing.T) {
t.Error("property deployment.version not modified")
}
}

func TestPackWithNoDependencies(t *testing.T) {
abs, _ := filepath.Abs("../../testitems/samplenodeps")
if _, err := os.Stat(abs + "/charts"); err == nil {
os.Remove(abs + "/charts")
}
os.Args = []string{"pack", abs, "--set", "deployment.version=myvalue123", "--destination", abs, "--no-deps"}
cmd := NewPackCmd(os.Args[1:], os.Stdout)
if err := cmd.Execute(); err != nil {
t.Errorf("test package failed: %v", err)
}
tarfile, errOpen := os.Open(abs + "/samplenodeps-0.1.0.tgz")
if errOpen != nil {
t.Errorf("opening tar file failed: %v", errOpen)
}
uncompressed, errStream := gzip.NewReader(tarfile)
if errStream != nil {
t.Errorf("error when uncompressign file: %v", errStream)
}
defer tarfile.Close()
tr := tar.NewReader(uncompressed)
testNoDepsOk := true
testvalueOk := false
for {
hdr, errHdr := tr.Next()
if errHdr == io.EOF {
break
}
if errHdr != nil {
t.Errorf("error when reading tar content: %v", errHdr)
}
//test if dependencies has been loaded
if strings.Contains(hdr.Name, "charts") {
testNoDepsOk = false
}
//if the values has been modified
if strings.Contains(hdr.Name, "values.yaml") {
bs, _ := ioutil.ReadAll(tr)
values := map[string]interface{}{}
if errUnmarshal := yaml.Unmarshal(bs, &values); errUnmarshal != nil {
t.Errorf("failed reading values file: %v", errUnmarshal)
}
deploymentValues, ok := values["deployment"].(map[string]interface{})
if !ok {
t.Error("deployment key not found")
}
version, okVersion := deploymentValues["version"].(string)
if !okVersion {
t.Error("version key not found")
}
if version == "myvalue123" {
testvalueOk = true
} else {
t.Errorf("got %s expected %s", version, "myvalue123")
}
}

if testNoDepsOk && testvalueOk {
break
}
}
if !testNoDepsOk {
t.Error("charts dependency should not be present in the archive")
}
if !testvalueOk {
t.Error("property deployment.version not modified")
}
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ require (
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.0.0
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
gopkg.in/yaml.v2 v2.2.8
helm.sh/helm/v3 v3.3.4
k8s.io/client-go v0.18.8
k8s.io/helm v2.16.12+incompatible
sigs.k8s.io/yaml v1.2.0
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,8 @@ k8s.io/component-base v0.18.8 h1:BW5CORobxb6q5mb+YvdwQlyXXS6NVH5fDXWbU7tf2L8=
k8s.io/component-base v0.18.8/go.mod h1:00frPRDas29rx58pPCxNkhUfPbwajlyyvu8ruNgSErU=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/helm v2.16.12+incompatible h1:K2zhF8+B85Ya1n7n3eH34xwwp5qNUM42TBFENDZJT7w=
k8s.io/helm v2.16.12+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
Expand Down
97 changes: 97 additions & 0 deletions manager/directory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package manager

import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"

"github.com/pkg/errors"
"k8s.io/helm/pkg/ignore"
"k8s.io/helm/pkg/sympath"

"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader"
)

var utf8bom = []byte{0xEF, 0xBB, 0xBF}

// LoadDir loads from a directory.
//
// This loads charts only from directories.
func LoadDir(dir string, p *Package) (*chart.Chart, error) {
topdir, err := filepath.Abs(dir)
if err != nil {
return nil, err
}

// Just used for errors.
c := &chart.Chart{}

rules := ignore.Empty()
ifile := filepath.Join(topdir, ignore.HelmIgnore)
if _, err := os.Stat(ifile); err == nil {
r, err := ignore.ParseFile(ifile)
if err != nil {
return c, err
}
rules = r
}
rules.AddDefaults()

files := []*loader.BufferedFile{}
topdir += string(filepath.Separator)

walk := func(name string, fi os.FileInfo, err error) error {
n := strings.TrimPrefix(name, topdir)
if n == "" {
// No need to process top level. Avoid bug with helmignore .* matching
// empty names. See issue 1779.
return nil
}

// Normalize to / since it will also work on Windows
n = filepath.ToSlash(n)

if err != nil {
return err
}
if fi.IsDir() {
// Directory-based ignore rules should involve skipping the entire
// contents of that directory.
if rules.Ignore(n, fi) {
return filepath.SkipDir
}
return nil
}

// If a .helmignore file matches, skip this file.
if rules.Ignore(n, fi) {
return nil
}

// Irregular files include devices, sockets, and other uses of files that
// are not regular files. In Go they have a file mode type bit set.
// See https://golang.org/pkg/os/#FileMode for examples.
if !fi.Mode().IsRegular() {
return fmt.Errorf("cannot load irregular file %s as it has file mode type bits set", name)
}

data, err := ioutil.ReadFile(name)
if err != nil {
return errors.Wrapf(err, "error reading %s", n)
}

data = bytes.TrimPrefix(data, utf8bom)

files = append(files, &loader.BufferedFile{Name: n, Data: data})
return nil
}
if err = sympath.Walk(topdir, walk); err != nil {
return c, err
}

return LoadFiles(files, p)
}
131 changes: 131 additions & 0 deletions manager/load.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package manager

import (
"bytes"
"log"
"path/filepath"
"strings"

"github.com/pkg/errors"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader"
"sigs.k8s.io/yaml"
)

// LoadFiles loads from in-memory files.
func LoadFiles(files []*loader.BufferedFile, p *Package) (*chart.Chart, error) {
c := new(chart.Chart)
subcharts := make(map[string][]*loader.BufferedFile)

for _, f := range files {
c.Raw = append(c.Raw, &chart.File{Name: f.Name, Data: f.Data})
switch {
case f.Name == "Chart.yaml":
if c.Metadata == nil {
c.Metadata = new(chart.Metadata)
}
if err := yaml.Unmarshal(f.Data, c.Metadata); err != nil {
return c, errors.Wrap(err, "cannot load Chart.yaml")
}
// NOTE(bacongobbler): while the chart specification says that APIVersion must be set,
// Helm 2 accepted charts that did not provide an APIVersion in their chart metadata.
// Because of that, if APIVersion is unset, we should assume we're loading a v1 chart.
if c.Metadata.APIVersion == "" {
c.Metadata.APIVersion = chart.APIVersionV1
}
case f.Name == "Chart.lock":
c.Lock = new(chart.Lock)
if err := yaml.Unmarshal(f.Data, &c.Lock); err != nil {
return c, errors.Wrap(err, "cannot load Chart.lock")
}
case f.Name == "values.yaml":
c.Values = make(map[string]interface{})
if err := yaml.Unmarshal(f.Data, &c.Values); err != nil {
return c, errors.Wrap(err, "cannot load values.yaml")
}
case f.Name == "values.schema.json":
c.Schema = f.Data

// Deprecated: requirements.yaml is deprecated use Chart.yaml.
// We will handle it for you because we are nice people
case f.Name == "requirements.yaml":
if c.Metadata == nil {
c.Metadata = new(chart.Metadata)
}
if c.Metadata.APIVersion != chart.APIVersionV1 {
log.Printf("Warning: Dependencies are handled in Chart.yaml since apiVersion \"v2\". We recommend migrating dependencies to Chart.yaml.")
}
if err := yaml.Unmarshal(f.Data, c.Metadata); err != nil {
return c, errors.Wrap(err, "cannot load requirements.yaml")
}
if c.Metadata.APIVersion == chart.APIVersionV1 {
c.Files = append(c.Files, &chart.File{Name: f.Name, Data: f.Data})
}
// Deprecated: requirements.lock is deprecated use Chart.lock.
case f.Name == "requirements.lock":
c.Lock = new(chart.Lock)
if err := yaml.Unmarshal(f.Data, &c.Lock); err != nil {
return c, errors.Wrap(err, "cannot load requirements.lock")
}
if c.Metadata.APIVersion == chart.APIVersionV1 {
c.Files = append(c.Files, &chart.File{Name: f.Name, Data: f.Data})
}

case strings.HasPrefix(f.Name, "templates/"):
c.Templates = append(c.Templates, &chart.File{Name: f.Name, Data: f.Data})
case strings.HasPrefix(f.Name, "charts/"):
if !p.NoDeps {
if filepath.Ext(f.Name) == ".prov" {
c.Files = append(c.Files, &chart.File{Name: f.Name, Data: f.Data})
continue
}
fname := strings.TrimPrefix(f.Name, "charts/")
cname := strings.SplitN(fname, "/", 2)[0]
subcharts[cname] = append(subcharts[cname], &loader.BufferedFile{Name: fname, Data: f.Data})
}

default:
c.Files = append(c.Files, &chart.File{Name: f.Name, Data: f.Data})
}
}

if err := c.Validate(); err != nil {
return c, err
}

for n, files := range subcharts {
var sc *chart.Chart
var err error
switch {
case strings.IndexAny(n, "_.") == 0:
continue
case filepath.Ext(n) == ".tgz":
file := files[0]
if file.Name != n {
return c, errors.Errorf("error unpacking tar in %s: expected %s, got %s", c.Name(), n, file.Name)
}
// Untar the chart and add to c.Dependencies
sc, err = loader.LoadArchive(bytes.NewBuffer(file.Data))
default:
// We have to trim the prefix off of every file, and ignore any file
// that is in charts/, but isn't actually a chart.
buff := make([]*loader.BufferedFile, 0, len(files))
for _, f := range files {
parts := strings.SplitN(f.Name, "/", 2)
if len(parts) < 2 {
continue
}
f.Name = parts[1]
buff = append(buff, f)
}
sc, err = LoadFiles(buff, p)
}

if err != nil {
return c, errors.Wrapf(err, "error unpacking %s in %s", n, c.Name())
}
c.AddDependency(sc)
}

return c, nil
}
Loading

0 comments on commit 31c75e8

Please sign in to comment.