From 25053e6adabd4d31edd036514b21527a384cea4f Mon Sep 17 00:00:00 2001 From: Matt Butcher Date: Tue, 24 May 2016 17:21:41 -0600 Subject: [PATCH] feat(pkg/chartutil): add chartutil package --- pkg/chartutil/chartfile.go | 26 ++ pkg/chartutil/chartfile_test.go | 69 +++++ pkg/chartutil/doc.go | 28 ++ pkg/chartutil/load.go | 274 ++++++++++++++++++ pkg/chartutil/load_test.go | 81 ++++++ pkg/chartutil/testdata/albatross/Chart.yaml | 4 + pkg/chartutil/testdata/albatross/values.toml | 1 + pkg/chartutil/testdata/chartfiletest.yaml | 15 + pkg/chartutil/testdata/frobnitz-1.2.3.tgz | Bin 0 -> 3491 bytes pkg/chartutil/testdata/frobnitz/Chart.yaml | 15 + pkg/chartutil/testdata/frobnitz/INSTALL.txt | 1 + pkg/chartutil/testdata/frobnitz/LICENSE | 1 + pkg/chartutil/testdata/frobnitz/README.md | 11 + .../frobnitz/charts/alpine/Chart.yaml | 4 + .../testdata/frobnitz/charts/alpine/README.md | 9 + .../charts/alpine/charts/mast1/Chart.yaml | 4 + .../charts/alpine/charts/mast1/values.toml | 4 + .../charts/alpine/charts/mast2-0.1.0.tgz | Bin 0 -> 435 bytes .../charts/alpine/templates/alpine-pod.yaml | 16 + .../frobnitz/charts/alpine/values.toml | 2 + .../frobnitz/charts/mariner-4.3.2.tgz | Bin 0 -> 905 bytes .../testdata/frobnitz/docs/README.md | 1 + pkg/chartutil/testdata/frobnitz/icon.svg | 8 + .../testdata/frobnitz/templates/template.tpl | 1 + pkg/chartutil/testdata/frobnitz/values.toml | 6 + pkg/chartutil/testdata/genfrob.sh | 12 + pkg/chartutil/testdata/mariner/Chart.yaml | 4 + .../mariner/charts/albatross-0.1.0.tgz | Bin 0 -> 321 bytes .../mariner/templates/placeholder.tpl | 1 + pkg/chartutil/testdata/mariner/values.toml | 4 + 30 files changed, 602 insertions(+) create mode 100644 pkg/chartutil/chartfile.go create mode 100644 pkg/chartutil/chartfile_test.go create mode 100644 pkg/chartutil/doc.go create mode 100644 pkg/chartutil/load.go create mode 100644 pkg/chartutil/load_test.go create mode 100644 pkg/chartutil/testdata/albatross/Chart.yaml create mode 100644 pkg/chartutil/testdata/albatross/values.toml create mode 100644 pkg/chartutil/testdata/chartfiletest.yaml create mode 100644 pkg/chartutil/testdata/frobnitz-1.2.3.tgz create mode 100644 pkg/chartutil/testdata/frobnitz/Chart.yaml create mode 100644 pkg/chartutil/testdata/frobnitz/INSTALL.txt create mode 100644 pkg/chartutil/testdata/frobnitz/LICENSE create mode 100644 pkg/chartutil/testdata/frobnitz/README.md create mode 100644 pkg/chartutil/testdata/frobnitz/charts/alpine/Chart.yaml create mode 100644 pkg/chartutil/testdata/frobnitz/charts/alpine/README.md create mode 100644 pkg/chartutil/testdata/frobnitz/charts/alpine/charts/mast1/Chart.yaml create mode 100644 pkg/chartutil/testdata/frobnitz/charts/alpine/charts/mast1/values.toml create mode 100644 pkg/chartutil/testdata/frobnitz/charts/alpine/charts/mast2-0.1.0.tgz create mode 100644 pkg/chartutil/testdata/frobnitz/charts/alpine/templates/alpine-pod.yaml create mode 100644 pkg/chartutil/testdata/frobnitz/charts/alpine/values.toml create mode 100644 pkg/chartutil/testdata/frobnitz/charts/mariner-4.3.2.tgz create mode 100644 pkg/chartutil/testdata/frobnitz/docs/README.md create mode 100644 pkg/chartutil/testdata/frobnitz/icon.svg create mode 100644 pkg/chartutil/testdata/frobnitz/templates/template.tpl create mode 100644 pkg/chartutil/testdata/frobnitz/values.toml create mode 100755 pkg/chartutil/testdata/genfrob.sh create mode 100644 pkg/chartutil/testdata/mariner/Chart.yaml create mode 100644 pkg/chartutil/testdata/mariner/charts/albatross-0.1.0.tgz create mode 100644 pkg/chartutil/testdata/mariner/templates/placeholder.tpl create mode 100644 pkg/chartutil/testdata/mariner/values.toml diff --git a/pkg/chartutil/chartfile.go b/pkg/chartutil/chartfile.go new file mode 100644 index 000000000..cd5efbc7b --- /dev/null +++ b/pkg/chartutil/chartfile.go @@ -0,0 +1,26 @@ +package chartutil + +import ( + "io/ioutil" + + "github.com/ghodss/yaml" + "github.com/kubernetes/helm/pkg/proto/hapi/chart" +) + +func UnmarshalChartfile(data []byte) (*chart.Metadata, error) { + y := &chart.Metadata{} + err := yaml.Unmarshal(data, y) + if err != nil { + return nil, err + } + return y, nil +} + +// LoadChartfile loads a Chart.yaml file into a *chart.Metadata. +func LoadChartfile(filename string) (*chart.Metadata, error) { + b, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + return UnmarshalChartfile(b) +} diff --git a/pkg/chartutil/chartfile_test.go b/pkg/chartutil/chartfile_test.go new file mode 100644 index 000000000..4d6dbf6e1 --- /dev/null +++ b/pkg/chartutil/chartfile_test.go @@ -0,0 +1,69 @@ +package chartutil + +import ( + "testing" + + "github.com/kubernetes/helm/pkg/proto/hapi/chart" +) + +const testfile = "testdata/chartfiletest.yaml" + +func TestLoadChartfile(t *testing.T) { + f, err := LoadChartfile(testfile) + if err != nil { + t.Errorf("Failed to open %s: %s", testfile, err) + return + } + verifyChartfile(t, f) +} + +func verifyChartfile(t *testing.T, f *chart.Metadata) { + + if f.Name != "frobnitz" { + t.Errorf("Expected frobnitz, got %s", f.Name) + } + + if f.Description != "This is a frobnitz." { + t.Errorf("Unexpected description %q", f.Description) + } + + if f.Version != "1.2.3" { + t.Errorf("Unexpected version %q", f.Version) + } + + if len(f.Maintainers) != 2 { + t.Errorf("Expected 2 maintainers, got %d", len(f.Maintainers)) + } + + if f.Maintainers[0].Name != "The Helm Team" { + t.Errorf("Unexpected maintainer name.") + } + + if f.Maintainers[1].Email != "nobody@example.com" { + t.Errorf("Unexpected maintainer email.") + } + + if len(f.Sources) != 1 { + t.Fatalf("Unexpected number of sources") + } + + if f.Sources[0] != "https://example.com/foo/bar" { + t.Errorf("Expected https://example.com/foo/bar, got %s", f.Sources) + } + + if f.Home != "http://example.com" { + t.Error("Unexpected home.") + } + + if len(f.Keywords) != 3 { + t.Error("Unexpected keywords") + } + + kk := []string{"frobnitz", "sprocket", "dodad"} + for i, k := range f.Keywords { + if kk[i] != k { + t.Errorf("Expected %q, got %q", kk[i], k) + } + } + +} diff --git a/pkg/chartutil/doc.go b/pkg/chartutil/doc.go new file mode 100644 index 000000000..0191c3800 --- /dev/null +++ b/pkg/chartutil/doc.go @@ -0,0 +1,28 @@ +/*Package chartutil contains tools for working with charts. + +Charts are described in the protocol buffer definition (pkg/proto/hapi/charts). +This packe provides utilities for serializing and deserializing charts. + +A chart can be represented on the file system in one of two ways: + + - As a directory that contains a Chart.yaml file and other chart things. + - As a tarred gzipped file containing a directory that then contains a + Chart.yaml file. + +This package provides utilitites for working with those file formats. + +The preferred way of loading a chart is using 'chartutil.Load`: + + chart, err := chartutil.Load(filename) + +This will attempt to discover whether the file at 'filename' is a directory or +a chart archive. It will then load accordingly. + +For accepting raw compressed tar file data from an io.Reader, the +'chartutil.LoadArchive()' will read in the data, uncompress it, and unpack it +into a Chart. + +When creating charts in memory, use the 'github.com/kubernetes/helm/pkg/proto/happy/chart' +package directly. +*/ +package chartutil diff --git a/pkg/chartutil/load.go b/pkg/chartutil/load.go new file mode 100644 index 000000000..00ca9489e --- /dev/null +++ b/pkg/chartutil/load.go @@ -0,0 +1,274 @@ +package chartutil + +import ( + "archive/tar" + "bytes" + "compress/gzip" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "github.com/golang/protobuf/ptypes/any" + "github.com/kubernetes/helm/pkg/proto/hapi/chart" +) + +// Load takes a string name, tries to resolve it to a file or directory, and then loads it. +// +// This is the preferred way to load a chart. It will discover the chart encoding +// and hand off to the appropriate chart reader. +func Load(name string) (*chart.Chart, error) { + fi, err := os.Stat(name) + if err != nil { + return nil, err + } + if fi.IsDir() { + return LoadDir(name) + } + return LoadFile(name) +} + +// subchart is an intermediate representation of a dependency. +// +// It is used to temporarily store a dependency while we process the outer +// file. +type subchart []*afile + +func newSubchart() subchart { + return []*afile{} +} + +func (s subchart) add(name string, data []byte, arch bool) subchart { + s = append(s, &afile{name, data, arch}) + return s +} + +// afile represents an archive file buffered for later processing. +type afile struct { + name string + data []byte + archive bool +} + +// LoadArchive loads from a reader containing a compressed tar archive. +func LoadArchive(in io.Reader) (*chart.Chart, error) { + sc := map[string]subchart{} + unzipped, err := gzip.NewReader(in) + if err != nil { + return nil, err + } + defer unzipped.Close() + + c := &chart.Chart{} + b := bytes.NewBuffer(nil) + + tr := tar.NewReader(unzipped) + for { + hd, err := tr.Next() + if err == io.EOF { + // We're done with the reader. Now add subcharts and exit. + e := addSubcharts(c, sc) + return c, e + } + if err != nil { + return c, err + } + + if hd.FileInfo().IsDir() { + // Use this instead of hd.Typeflag because we don't have to do any + // inference chasing. + continue + } + + parts := strings.Split(hd.Name, "/") + n := strings.Join(parts[1:], "/") + + if _, err := io.Copy(b, tr); err != nil { + return c, err + } + + if strings.HasPrefix(n, "charts/") { + // If there are subcharts, we put those into a temporary holding + // array for later processing. + fmt.Printf("Appending %s to chart %s:\n%s\n", n, c.Metadata.Name, b.String()) + appendSubchart(sc, n, b.Bytes()) + b.Reset() + continue + } + + addToChart(c, n, b.Bytes()) + b.Reset() + } + +} + +// LoadFile loads from an archive file. +func LoadFile(name string) (*chart.Chart, error) { + if fi, err := os.Stat(name); err != nil { + return nil, err + } else if fi.IsDir() { + return nil, errors.New("cannot load a directory") + } + + raw, err := os.Open(name) + if err != nil { + return nil, err + } + defer raw.Close() + + return LoadArchive(raw) +} + +// LoadDir loads from a directory. +// +// This loads charts only from directories. +func LoadDir(dir string) (*chart.Chart, error) { + topdir, err := filepath.Abs(dir) + if err != nil { + return nil, err + } + + topdir += string(filepath.Separator) + sc := map[string]subchart{} + c := &chart.Chart{} + err = filepath.Walk(topdir, func(name string, fi os.FileInfo, err error) error { + n := strings.TrimPrefix(name, topdir) + if err != nil { + return err + } + if fi.IsDir() { + return nil + } + + data, err := ioutil.ReadFile(name) + if err != nil { + return fmt.Errorf("error reading %s: %s", n, err) + } + + if strings.HasPrefix(n, "charts/") { + appendSubchart(sc, n, data) + return nil + } + + return addToChart(c, n, data) + }) + if err != nil { + return c, err + } + + // Ensure that we had a Chart.yaml file + if c.Metadata == nil || c.Metadata.Name == "" { + return c, errors.New("chart metadata (Chart.yaml) missing") + } + + err = addSubcharts(c, sc) + return c, err +} + +func addToChart(c *chart.Chart, n string, data []byte) error { + fmt.Printf("--> Scanning %s\n", n) + if n == "Chart.yaml" { + md, err := UnmarshalChartfile(data) + if err != nil { + return err + } + if md.Name == "" { + fmt.Printf("Chart:\n%s\n", string(data)) + } + fmt.Printf("--> Adding %s as Chart.yaml\n", md.Name) + c.Metadata = md + } else if n == "values.toml" { + c.Values = &chart.Config{Raw: string(data)} + fmt.Printf("--> Adding to values:\n%s\n", string(data)) + } else if strings.HasPrefix(n, "charts/") { + // SKIP THESE. These are handled elsewhere, because they need context + // to process. + return nil + } else if strings.HasPrefix(n, "templates/") { + c.Templates = append(c.Templates, &chart.Template{Name: n, Data: data}) + } else { + c.Files = append(c.Files, &any.Any{TypeUrl: n, Value: data}) + } + return nil +} + +func addSubcharts(c *chart.Chart, s map[string]subchart) error { + for n, sc := range s { + fmt.Printf("===> Unpacking %s\n", n) + if err := addSubchart(c, sc); err != nil { + return fmt.Errorf("error adding %q: %s", n, err) + } + } + return nil +} + +// addSubchart transforms a subchart to a new chart, and then embeds it into the given chart. +func addSubchart(c *chart.Chart, sc subchart) error { + nc := &chart.Chart{} + deps := map[string]subchart{} + + // The sc paths are all relative to the sc itself. + for _, sub := range sc { + if sub.archive { + b := bytes.NewBuffer(sub.data) + var err error + nc, err = LoadArchive(b) + if err != nil { + fmt.Printf("Bad data in %s: %q", sub.name, string(sub.data)) + return err + } + break + } else if strings.HasPrefix(sub.name, "charts/") { + appendSubchart(deps, sub.name, sub.data) + } else { + fmt.Printf("Adding %s to subchart in %s\n", sub.name, c.Metadata.Name) + addToChart(nc, sub.name, sub.data) + } + } + + if nc.Metadata == nil || nc.Metadata.Name == "" { + return errors.New("embedded chart is not well-formed") + } + + fmt.Printf("Added dependency: %q\n", nc.Metadata.Name) + c.Dependencies = append(c.Dependencies, nc) + return nil +} + +func appendSubchart(sc map[string]subchart, n string, b []byte) { + fmt.Printf("Append subchart %s\n", n) + // TODO: Do we need to filter out 0 byte files? + // TODO: If this finds a dependency that is a tarball, we need to untar it, + // and express it as a subchart. + parts := strings.SplitN(n, "/", 3) + lp := len(parts) + switch lp { + case 2: + if filepath.Ext(parts[1]) == ".tgz" { + fmt.Printf("--> Adding archive %s\n", n) + // Basically, we delay expanding tar files until the last minute, + // which helps (a little) keep memory usage down. + bn := strings.TrimSuffix(parts[1], ".tgz") + cc := newSubchart() + sc[bn] = cc.add(parts[1], b, true) + return + } else { + // Skip directory entries and non-charts. + return + } + case 3: + if _, ok := sc[parts[1]]; !ok { + sc[parts[1]] = newSubchart() + } + //fmt.Printf("Adding file %q to %s\n", parts[2], parts[1]) + sc[parts[1]] = sc[parts[1]].add(parts[2], b, false) + return + default: + // Skip 1 or 0. + return + } + +} diff --git a/pkg/chartutil/load_test.go b/pkg/chartutil/load_test.go new file mode 100644 index 000000000..dae3ee438 --- /dev/null +++ b/pkg/chartutil/load_test.go @@ -0,0 +1,81 @@ +package chartutil + +import ( + "testing" + + "github.com/kubernetes/helm/pkg/proto/hapi/chart" +) + +func TestLoadDir(t *testing.T) { + c, err := Load("testdata/frobnitz") + if err != nil { + t.Fatalf("Failed to load testdata: %s", err) + } + verifyFrobnitz(t, c) + verifyChart(t, c) +} + +func TestLoadFile(t *testing.T) { + c, err := Load("testdata/frobnitz-1.2.3.tgz") + if err != nil { + t.Fatalf("Failed to load testdata: %s", err) + } + verifyFrobnitz(t, c) + verifyChart(t, c) +} + +func verifyChart(t *testing.T, c *chart.Chart) { + if len(c.Templates) != 1 { + t.Errorf("Expected 1 template, got %d", len(c.Templates)) + } + + if len(c.Files) != 5 { + t.Errorf("Expected 5 extra files, got %d", len(c.Files)) + for _, n := range c.Files { + t.Logf("\t%s", n.TypeUrl) + } + } + + if len(c.Dependencies) != 2 { + t.Errorf("Expected 2 dependencies, got %d (%v)", len(c.Dependencies), c.Dependencies) + for _, d := range c.Dependencies { + t.Logf("\tSubchart: %s\n", d.Metadata.Name) + } + } + + expect := map[string]map[string]string{ + "alpine": map[string]string{ + "version": "0.1.0", + }, + "mariner": map[string]string{ + "version": "4.3.2", + }, + } + + for _, dep := range c.Dependencies { + exp, ok := expect[dep.Metadata.Name] + if !ok { + t.Fatalf("Unknown dependency %s", dep.Metadata.Name) + } + if exp["version"] != dep.Metadata.Version { + t.Errorf("Expected %s version %s, got %s", dep.Metadata.Name, exp["version"], dep.Metadata.Version) + } + } + +} + +func verifyFrobnitz(t *testing.T, c *chart.Chart) { + verifyChartfile(t, c.Metadata) + + if len(c.Templates) != 1 { + t.Fatalf("Expected 1 template, got %d", len(c.Templates)) + } + + if c.Templates[0].Name != "templates/template.tpl" { + t.Errorf("Unexpected template: %s", c.Templates[0].Name) + } + + if len(c.Templates[0].Data) == 0 { + t.Error("No template data.") + } +} diff --git a/pkg/chartutil/testdata/albatross/Chart.yaml b/pkg/chartutil/testdata/albatross/Chart.yaml new file mode 100644 index 000000000..eeef737ff --- /dev/null +++ b/pkg/chartutil/testdata/albatross/Chart.yaml @@ -0,0 +1,4 @@ +name: albatross +description: A Helm chart for Kubernetes +version: 0.1.0 +home: "" diff --git a/pkg/chartutil/testdata/albatross/values.toml b/pkg/chartutil/testdata/albatross/values.toml new file mode 100644 index 000000000..0ef7eb2f9 --- /dev/null +++ b/pkg/chartutil/testdata/albatross/values.toml @@ -0,0 +1 @@ +albatross = "true" diff --git a/pkg/chartutil/testdata/chartfiletest.yaml b/pkg/chartutil/testdata/chartfiletest.yaml new file mode 100644 index 000000000..9f255b9bd --- /dev/null +++ b/pkg/chartutil/testdata/chartfiletest.yaml @@ -0,0 +1,15 @@ +name: frobnitz +description: This is a frobnitz. +version: "1.2.3" +keywords: + - frobnitz + - sprocket + - dodad +maintainers: + - name: The Helm Team + email: helm@example.com + - name: Someone Else + email: nobody@example.com +sources: + - https://example.com/foo/bar +home: http://example.com diff --git a/pkg/chartutil/testdata/frobnitz-1.2.3.tgz b/pkg/chartutil/testdata/frobnitz-1.2.3.tgz new file mode 100644 index 0000000000000000000000000000000000000000..c908b22642d0aac2394809200e6baa2bc7600b21 GIT binary patch literal 3491 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 R1O$W{_&@1@#;gE%004h72QmNv literal 0 HcmV?d00001 diff --git a/pkg/chartutil/testdata/frobnitz/Chart.yaml b/pkg/chartutil/testdata/frobnitz/Chart.yaml new file mode 100644 index 000000000..9f255b9bd --- /dev/null +++ b/pkg/chartutil/testdata/frobnitz/Chart.yaml @@ -0,0 +1,15 @@ +name: frobnitz +description: This is a frobnitz. +version: "1.2.3" +keywords: + - frobnitz + - sprocket + - dodad +maintainers: + - name: The Helm Team + email: helm@example.com + - name: Someone Else + email: nobody@example.com +sources: + - https://example.com/foo/bar +home: http://example.com diff --git a/pkg/chartutil/testdata/frobnitz/INSTALL.txt b/pkg/chartutil/testdata/frobnitz/INSTALL.txt new file mode 100644 index 000000000..2010438c2 --- /dev/null +++ b/pkg/chartutil/testdata/frobnitz/INSTALL.txt @@ -0,0 +1 @@ +This is an install document. The client may display this. diff --git a/pkg/chartutil/testdata/frobnitz/LICENSE b/pkg/chartutil/testdata/frobnitz/LICENSE new file mode 100644 index 000000000..6121943b1 --- /dev/null +++ b/pkg/chartutil/testdata/frobnitz/LICENSE @@ -0,0 +1 @@ +LICENSE placeholder. diff --git a/pkg/chartutil/testdata/frobnitz/README.md b/pkg/chartutil/testdata/frobnitz/README.md new file mode 100644 index 000000000..8cf4cc3d7 --- /dev/null +++ b/pkg/chartutil/testdata/frobnitz/README.md @@ -0,0 +1,11 @@ +# Frobnitz + +This is an example chart. + +## Usage + +This is an example. It has no usage. + +## Development + +For developer info, see the top-level repository. diff --git a/pkg/chartutil/testdata/frobnitz/charts/alpine/Chart.yaml b/pkg/chartutil/testdata/frobnitz/charts/alpine/Chart.yaml new file mode 100644 index 000000000..cab858d0a --- /dev/null +++ b/pkg/chartutil/testdata/frobnitz/charts/alpine/Chart.yaml @@ -0,0 +1,4 @@ +name: alpine +description: Deploy a basic Alpine Linux pod +version: 0.1.0 +home: https://github.com/kubernetes/helm diff --git a/pkg/chartutil/testdata/frobnitz/charts/alpine/README.md b/pkg/chartutil/testdata/frobnitz/charts/alpine/README.md new file mode 100644 index 000000000..a7c84fc41 --- /dev/null +++ b/pkg/chartutil/testdata/frobnitz/charts/alpine/README.md @@ -0,0 +1,9 @@ +This example was generated using the command `helm create alpine`. + +The `templates/` directory contains a very simple pod resource with a +couple of parameters. + +The `values.toml` file contains the default values for the +`alpine-pod.yaml` template. + +You can install this example using `helm install docs/examples/alpine`. diff --git a/pkg/chartutil/testdata/frobnitz/charts/alpine/charts/mast1/Chart.yaml b/pkg/chartutil/testdata/frobnitz/charts/alpine/charts/mast1/Chart.yaml new file mode 100644 index 000000000..171e36156 --- /dev/null +++ b/pkg/chartutil/testdata/frobnitz/charts/alpine/charts/mast1/Chart.yaml @@ -0,0 +1,4 @@ +name: mast1 +description: A Helm chart for Kubernetes +version: 0.1.0 +home: "" diff --git a/pkg/chartutil/testdata/frobnitz/charts/alpine/charts/mast1/values.toml b/pkg/chartutil/testdata/frobnitz/charts/alpine/charts/mast1/values.toml new file mode 100644 index 000000000..f0cab9e08 --- /dev/null +++ b/pkg/chartutil/testdata/frobnitz/charts/alpine/charts/mast1/values.toml @@ -0,0 +1,4 @@ +# Default values for mast1. +# This is a TOML-formatted file. https://github.com/toml-lang/toml +# Declare name/value pairs to be passed into your templates. +# name = "value" diff --git a/pkg/chartutil/testdata/frobnitz/charts/alpine/charts/mast2-0.1.0.tgz b/pkg/chartutil/testdata/frobnitz/charts/alpine/charts/mast2-0.1.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..232322a261bbcfd9e8c2ce7fcc00414081f84e71 GIT binary patch literal 435 zcmV;k0ZjfMiwG0|32ul0|0w_~VMtOiV@ORlOnEsqVl!4SWK%V1T2nbTPgYhoO;>Dc zVQyr3R8em|NM&qo0PL3CYQrED$8(*hIJDPI)W!q~yBOQWU>m#X3)s{)0TY9oLf?LV z&@l#Mlr0%!{sCqsHbDvkYrjADo{nKwFp&Zu!t1F1`d2p(BJTG5X^4vNn%{DKOt)x^`C>F|A~o_>&(bW3V^Tf ze?sX;{V9(3|12!wo*&pK41^r;SG`Y)EM3C3X*Jk~!S?0(X=T54%ox6hLo0X&jWL7X z&{6;Z literal 0 HcmV?d00001 diff --git a/pkg/chartutil/testdata/frobnitz/charts/alpine/templates/alpine-pod.yaml b/pkg/chartutil/testdata/frobnitz/charts/alpine/templates/alpine-pod.yaml new file mode 100644 index 000000000..08cf3c2c1 --- /dev/null +++ b/pkg/chartutil/testdata/frobnitz/charts/alpine/templates/alpine-pod.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: {{.Release.Name}}-{{.Chart.Name}} + labels: + heritage: {{.Release.Service}} + chartName: {{.Chart.Name}} + chartVersion: {{.Chart.Version | quote}} + annotations: + "helm.sh/created": "{{.Release.Time.Seconds}}" +spec: + restartPolicy: {{default "Never" .restart_policy}} + containers: + - name: waiter + image: "alpine:3.3" + command: ["/bin/sleep","9000"] diff --git a/pkg/chartutil/testdata/frobnitz/charts/alpine/values.toml b/pkg/chartutil/testdata/frobnitz/charts/alpine/values.toml new file mode 100644 index 000000000..504e6e1be --- /dev/null +++ b/pkg/chartutil/testdata/frobnitz/charts/alpine/values.toml @@ -0,0 +1,2 @@ +# The pod name +name = "my-alpine" diff --git a/pkg/chartutil/testdata/frobnitz/charts/mariner-4.3.2.tgz b/pkg/chartutil/testdata/frobnitz/charts/mariner-4.3.2.tgz new file mode 100644 index 0000000000000000000000000000000000000000..d4f19e6243532eba705a306a0c7cca462aa41345 GIT binary patch literal 905 zcmV;419to$iwFQDCPr5P1MQYsXcIvg$Ad+YsCc|s@fusN2fLZw>}I7ZQtN%-RgDjd zPSQ!Uy2*y!iFgzg4^S&8Y8B51kJbkdisCIQ)#61_DYZmvM6rrR3TnM-U3b$&>siGn zBF>M%H%Vq^X6OH1KBP*1tlBJb1VShZ0*F{ggM}R5V50z*6FHV;p@ZW9WO-KPEI^3o zp<)Czf>h%uK17HsNZekmes`WR&ExsWI??y|Wd9L-QT;Q$NF~fdhEAVhXugqKgzfK=lc7R52u5u7g)2g=2oQukraPA$N;0U>;rDoGk`}? z!MLCctA0$dW}S~!Ei#E`>&k5pZ{n<$U zw~LV0|3r`qhGP#3$^|mk+Tg4Ac5w{22I63w6kC4e`6%FH2xDo;|Oo8 zJdL#fgRlC3B)bq%6-`Tn49h@<1JKsmzJ*nbC#g#eEjL>^lEXzb*$C-d5hZlN|0QaaDH_9{*)*%#Wss!W}_jg-#oT5!u- zlUKSWzsOm)(toZ>@jiJy0=58hu*!MCf44qX&p}8`26AfllL<}?6Bt-tzYtF z*QkqCyDkg*V12p&`sR{Z9nK{?L-jXn?i6qC@#IQbyZpyHGftP^(wxbQ;k^@YvJX@b zD%w;y;85trz%iZl+GY1g6}$)+o*CWc&8zyMJM~E|0{UTeHN3rQMs?t5PPoOn%d=Ov zeQW%r@2xI9QFi=@ZpoddZ>=~}r(aWhP1bM2s)?^REx6MqE717TmTs?Ym2qjQX6gU8 fWTQ|h6bgkxp-?Ck3WY+UP=1MzGA=TJ04M+ejvmV5 literal 0 HcmV?d00001 diff --git a/pkg/chartutil/testdata/frobnitz/docs/README.md b/pkg/chartutil/testdata/frobnitz/docs/README.md new file mode 100644 index 000000000..d40747caf --- /dev/null +++ b/pkg/chartutil/testdata/frobnitz/docs/README.md @@ -0,0 +1 @@ +This is a placeholder for documentation. diff --git a/pkg/chartutil/testdata/frobnitz/icon.svg b/pkg/chartutil/testdata/frobnitz/icon.svg new file mode 100644 index 000000000..892130606 --- /dev/null +++ b/pkg/chartutil/testdata/frobnitz/icon.svg @@ -0,0 +1,8 @@ + + + Example icon + + + diff --git a/pkg/chartutil/testdata/frobnitz/templates/template.tpl b/pkg/chartutil/testdata/frobnitz/templates/template.tpl new file mode 100644 index 000000000..c651ee6a0 --- /dev/null +++ b/pkg/chartutil/testdata/frobnitz/templates/template.tpl @@ -0,0 +1 @@ +Hello {{.Name | default "world"}} diff --git a/pkg/chartutil/testdata/frobnitz/values.toml b/pkg/chartutil/testdata/frobnitz/values.toml new file mode 100644 index 000000000..6fc24051f --- /dev/null +++ b/pkg/chartutil/testdata/frobnitz/values.toml @@ -0,0 +1,6 @@ +# A values file contains configuration. + +name = "Some Name" + +[section] +name = "Name in a section" diff --git a/pkg/chartutil/testdata/genfrob.sh b/pkg/chartutil/testdata/genfrob.sh new file mode 100755 index 000000000..38fc1b22c --- /dev/null +++ b/pkg/chartutil/testdata/genfrob.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# Pack the albatross chart into the mariner chart. +echo "Packing albatross into mariner" +tar -zcvf mariner/charts/albatross-0.1.0.tgz albatross + +echo "Packing mariner into frobnitz" +tar -zcvf frobnitz/charts/mariner-4.3.2.tgz mariner + +# Pack the frobnitz chart. +echo "Packing frobnitz" +tar -zcvf frobnitz-1.2.3.tgz frobnitz diff --git a/pkg/chartutil/testdata/mariner/Chart.yaml b/pkg/chartutil/testdata/mariner/Chart.yaml new file mode 100644 index 000000000..4d52794c6 --- /dev/null +++ b/pkg/chartutil/testdata/mariner/Chart.yaml @@ -0,0 +1,4 @@ +name: mariner +description: A Helm chart for Kubernetes +version: 4.3.2 +home: "" diff --git a/pkg/chartutil/testdata/mariner/charts/albatross-0.1.0.tgz b/pkg/chartutil/testdata/mariner/charts/albatross-0.1.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..ed3c1aee9d62a5860abd1069ed0d4863047e1ca7 GIT binary patch literal 321 zcmV-H0lxkpiwFQDCPr5P1MSw`YJ)Hs24Ii9iVrWqC268i*umJzU{?`ciUqADiG|($ zQY{Lj`$ZjP?{ks^Lri>=eCoQ;-nP!&MT=pK7 z)N)grbk1uVrqXEdi_Vvou~++rZoAzl<6PD;wl_kL`9D_L`t(&d_1y0W-y@Uq8*#i46I#Vaorc>(02;x3m8Md{zIM*u4Ay%W@%6|JN|)Pxq8~+Zj}F0000000000 T00000fSdIOLB)V`04M+e6EUjz literal 0 HcmV?d00001 diff --git a/pkg/chartutil/testdata/mariner/templates/placeholder.tpl b/pkg/chartutil/testdata/mariner/templates/placeholder.tpl new file mode 100644 index 000000000..29c11843a --- /dev/null +++ b/pkg/chartutil/testdata/mariner/templates/placeholder.tpl @@ -0,0 +1 @@ +# This is a placeholder. diff --git a/pkg/chartutil/testdata/mariner/values.toml b/pkg/chartutil/testdata/mariner/values.toml new file mode 100644 index 000000000..4a7bbf8e4 --- /dev/null +++ b/pkg/chartutil/testdata/mariner/values.toml @@ -0,0 +1,4 @@ +# Default values for mariner. +# This is a TOML-formatted file. https://github.com/toml-lang/toml +# Declare name/value pairs to be passed into your templates. +# name = "value"