feat(helm): Add Files.Glob method to permit file organization

parent 190dafbc
......@@ -9,6 +9,8 @@ Helm provides access to files through the `.Files` object. Before we get going w
- Files in `templates/` cannot be accessed.
- Charts to not preserve UNIX mode information, so file-level permissions will have no impact on the availability of a file when it comes to the `.Files` object.
## Basic example
With those caveats behind, let's write a template that reads three files into our ConfigMap. To get started, we will add three files to the chart, putting all three directly inside of the `mychart/` directory.
`config1.toml`:
......@@ -65,6 +67,42 @@ data:
message = Goodbye from config 3
```
As your chart grows, you may find you have a greater need to organize your
files more, and so we provide a `Files.Glob(pattern string)` method to assist
in extracting certain files however you need.
For example, imagine the directory structure:
```
foo/:
foo.txt foo.yaml
bar/:
bar.go bar.conf baz.yaml
```
## Glob patterns
You have multiple options with Globs:
```yaml
{{ range $path := .Files.Glob "**.yaml" }}
{{ $path }}: |
{{ .Files.Get $path }}
{{ end }}
```
Or
```yaml
{{ range $path, $bytes := .Files.Glob "foo/*" }}
{{ $path }}: '{{ b64enc $bytes }}'
{{ end }}
```
## Secrets
When working with a Secret resource, you can import a file and have the template base-64 encode it for you:
```yaml
......
hash: 89695daf5f2de706b79fdd8e8b095f9514f418c0fbcf80d7fdca4c208d114d19
updated: 2016-11-29T14:56:31.55726541-07:00
hash: 707ac6d1785d0029397f2f9a3b0bc45f7d8ce819f14f6c246967b0a404627a2c
updated: 2016-12-01T09:07:51.289370422-07:00
imports:
- name: cloud.google.com/go
version: 3b1ae45394a234c385be014e9a488f2bb6eef821
......@@ -103,6 +103,16 @@ imports:
version: 465937c80b3c07a7c7ad20cc934898646a91c1de
- name: github.com/ghodss/yaml
version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee
- name: github.com/gobwas/glob
version: 0354991b92587e2742549d3036f3b5bae5ab03f2
subpackages:
- compiler
- match
- syntax
- syntax/ast
- syntax/lexer
- util/runes
- util/strings
- name: github.com/gogo/protobuf
version: e18d7aa8f8c624c915db340349aad4c49b10d173
subpackages:
......
......@@ -49,3 +49,5 @@ import:
- package: golang.org/x/crypto
subpackages:
- openpgp
- package: github.com/gobwas/glob
version: ^0.2.1
......@@ -16,6 +16,7 @@ limitations under the License.
package chartutil
import (
"github.com/gobwas/glob"
"github.com/golang/protobuf/ptypes/any"
)
......@@ -26,8 +27,10 @@ type Files map[string][]byte
// Given an []*any.Any (the format for files in a chart.Chart), extract a map of files.
func NewFiles(from []*any.Any) Files {
files := map[string][]byte{}
for _, f := range from {
files[f.TypeUrl] = f.Value
if from != nil {
for _, f := range from {
files[f.TypeUrl] = f.Value
}
}
return files
}
......@@ -56,3 +59,26 @@ func (f Files) GetBytes(name string) []byte {
func (f Files) Get(name string) string {
return string(f.GetBytes(name))
}
// Glob takes a glob pattern and returns another files object only containing
// matched files.
//
// This is designed to be called from a template.
// {{ range $name, $content := .Files.Glob("foo/**") }}
// {{ $name }}: |
// {{ .Files.Get($name) | indent 4 }}{{ end }}
func (f Files) Glob(pattern string) Files {
g, err := glob.Compile(pattern, '/')
if err != nil {
g, _ = glob.Compile("**")
}
nf := NewFiles(nil)
for name, contents := range f {
if g.Match(name) {
nf[name] = contents
}
}
return nf
}
......@@ -21,23 +21,25 @@ import (
"github.com/golang/protobuf/ptypes/any"
)
func TestNewFiles(t *testing.T) {
cases := []struct {
path, data string
}{
{"ship/captain.txt", "The Captain"},
{"ship/stowaway.txt", "Legatt"},
{"story/name.txt", "The Secret Sharer"},
{"story/author.txt", "Joseph Conrad"},
}
var cases = []struct {
path, data string
}{
{"ship/captain.txt", "The Captain"},
{"ship/stowaway.txt", "Legatt"},
{"story/name.txt", "The Secret Sharer"},
{"story/author.txt", "Joseph Conrad"},
}
func getTestFiles() []*any.Any {
a := []*any.Any{}
for _, c := range cases {
a = append(a, &any.Any{TypeUrl: c.path, Value: []byte(c.data)})
}
return a
}
files := NewFiles(a)
func TestNewFiles(t *testing.T) {
files := NewFiles(getTestFiles())
if len(files) != len(cases) {
t.Errorf("Expected len() = %d, got %d", len(cases), len(files))
}
......@@ -51,3 +53,18 @@ func TestNewFiles(t *testing.T) {
}
}
}
func TestFileGlob(t *testing.T) {
f := NewFiles(getTestFiles())
matched := f.Glob("story/**")
if len(matched) != 2 {
t.Errorf("Expected two files in glob story/**, got %d", len(matched))
}
m, expect := matched.Get("story/author.txt"), "Joseph Conrad"
if m != expect {
t.Errorf("Wrong globbed file content. Expected %s, got %s", expect, m)
}
}
Markdown is supported
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