diff --git a/.appveyor.yml b/.appveyor.yml index d7ba1d9fd..40d02927d 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -6,10 +6,10 @@ environment: install: - ps: iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/fishworks/gofish/master/scripts/install.ps1')) - gofish init - - gofish install dep - - dep ensure -v + - gofish install glide + - glide install --strip-vendor cache: - - vendor -> Gopkg.lock + - vendor -> glide.lock build: "off" deploy: "off" test_script: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7958a9adb..aba3388a6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -178,7 +178,7 @@ contributing to Helm. All issue types follow the same general lifecycle. Differe 1. Submit a pull request. Coding conventions and standards are explained in the official developer docs: -https://github.com/helm/helm/blob/master/docs/developers.md +[Developers Guide](docs/developers.md) The next section contains more information on the workflow followed for PRs diff --git a/cmd/helm/create.go b/cmd/helm/create.go index 7f0f99af8..0d278c8b5 100644 --- a/cmd/helm/create.go +++ b/cmd/helm/create.go @@ -75,6 +75,9 @@ func newCreateCmd(out io.Writer) *cobra.Command { if len(args) == 0 { return errors.New("the name of the new chart is required") } + if len(args) > 1 { + return errors.New("command 'create' doesn't support multiple arguments") + } cc.name = args[0] return cc.run() }, diff --git a/cmd/helm/helm_test.go b/cmd/helm/helm_test.go index 3551eb534..6e915fa7b 100644 --- a/cmd/helm/helm_test.go +++ b/cmd/helm/helm_test.go @@ -29,6 +29,7 @@ import ( "github.com/spf13/cobra" + "k8s.io/client-go/util/homedir" "k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm/environment" "k8s.io/helm/pkg/helm/helmpath" @@ -167,7 +168,7 @@ func TestRootCmd(t *testing.T) { { name: "defaults", args: []string{"home"}, - home: filepath.Join(os.Getenv("HOME"), "/.helm"), + home: filepath.Join(homedir.HomeDir(), ".helm"), }, { name: "with --home set", @@ -236,7 +237,7 @@ func TestTLSFlags(t *testing.T) { homePath := os.Getenv("HELM_HOME") if homePath == "" { - homePath = filepath.Join(os.Getenv("HOME"), ".helm") + homePath = filepath.Join(homedir.HomeDir(), ".helm") } home := helmpath.Home(homePath) diff --git a/cmd/helm/package_test.go b/cmd/helm/package_test.go index 7ed9829a5..d3bd25af7 100644 --- a/cmd/helm/package_test.go +++ b/cmd/helm/package_test.go @@ -17,10 +17,12 @@ package main import ( "bytes" + "fmt" "io/ioutil" "os" "path/filepath" "regexp" + "runtime" "testing" "github.com/spf13/cobra" @@ -53,6 +55,13 @@ func TestSetVersion(t *testing.T) { func TestPackage(t *testing.T) { + statExe := "stat" + statFileMsg := "no such file or directory" + if runtime.GOOS == "windows" { + statExe = "FindFirstFile" + statFileMsg = "The system cannot find the file specified." + } + tests := []struct { name string flags map[string]string @@ -106,7 +115,7 @@ func TestPackage(t *testing.T) { name: "package --destination does-not-exist", args: []string{"testdata/testcharts/alpine"}, flags: map[string]string{"destination": "does-not-exist"}, - expect: "stat does-not-exist: no such file or directory", + expect: fmt.Sprintf("Failed to save: %s does-not-exist: %s", statExe, statFileMsg), err: true, }, { diff --git a/cmd/helm/template_test.go b/cmd/helm/template_test.go index ec989ea67..98044eff0 100644 --- a/cmd/helm/template_test.go +++ b/cmd/helm/template_test.go @@ -75,7 +75,7 @@ func TestTemplateCmd(t *testing.T) { { name: "check_execute_absolute", desc: "verify --execute single template", - args: []string{subchart1ChartPath, "-x", subchart1AbsChartPath + "/" + "templates/service.yaml", "--set", "service.name=apache"}, + args: []string{subchart1ChartPath, "-x", filepath.Join(subchart1AbsChartPath, "templates", "service.yaml"), "--set", "service.name=apache"}, expectKey: "subchart1/templates/service.yaml", expectValue: "protocol: TCP\n name: apache", }, diff --git a/cmd/helm/verify_test.go b/cmd/helm/verify_test.go index 4d683df75..d4a580c23 100644 --- a/cmd/helm/verify_test.go +++ b/cmd/helm/verify_test.go @@ -28,7 +28,7 @@ func TestVerifyCmd(t *testing.T) { statPathMsg := "no such file or directory" statFileMsg := statPathMsg if runtime.GOOS == "windows" { - statExe = "GetFileAttributesEx" + statExe = "FindFirstFile" statPathMsg = "The system cannot find the path specified." statFileMsg = "The system cannot find the file specified." } diff --git a/docs/README.md b/docs/README.md index 4ca93bd1f..ed13cc22a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,6 +24,7 @@ - [Variables](chart_template_guide/variables.md) - [Named Templates (Partials)](chart_template_guide/named_templates.md) - [Accessing Files Inside Templates](chart_template_guide/accessing_files.md) + - [Ignoring unwanted files and folders](chart_template_guide/helm_ignore_file.md) - [Creating a NOTES.txt File](chart_template_guide/notes_files.md) - [Subcharts and Global Values](chart_template_guide/subcharts_and_globals.md) - [Debugging Templates](chart_template_guide/debugging.md) diff --git a/docs/chart_template_guide/helm_ignore_file.md b/docs/chart_template_guide/helm_ignore_file.md new file mode 100644 index 000000000..6793bdfec --- /dev/null +++ b/docs/chart_template_guide/helm_ignore_file.md @@ -0,0 +1,23 @@ +# The .helmignore file + +The `.helmignore` file is used to specify files you don't want to include in your helm chart. + +If this file exists, the `helm package` command will ignore all the files that match the pattern specified in the `.helmignore` file while packaging your application. + +This can help in avoiding unncessary or sensitive files or directories from being added in your helm chart. + +The `.helmignore` file supports Unix shell glob matching, relative path matching, and negation (prefixed with !). Only one pattern per line is considered. + +Here is an example `.helmignore` file: + +``` +# comment +.git +*/temp* +*/*/temp* +temp? +``` + +**We'd love your help** making this document better. To add, correct, or remove +information, [file an issue](https://github.com/helm/helm/issues) or +send us a pull request. diff --git a/docs/charts.md b/docs/charts.md index 2f7605350..5a895fd49 100644 --- a/docs/charts.md +++ b/docs/charts.md @@ -124,7 +124,14 @@ project is: ## Chart LICENSE, README and NOTES Charts can also contain files that describe the installation, configuration, usage and license of a -chart. A README for a chart should be formatted in Markdown (README.md), and should generally +chart. + +A LICENSE is a plain text file containing the [license](https://en.wikipedia.org/wiki/Software_license) +for the chart. The chart can contain a license as it may have programming logic in the templates and +would therefore not be configuration only. There can also be separate license(s) for the application +installed by the chart, if required. + +A README for a chart should be formatted in Markdown (README.md), and should generally contain: - A description of the application or service the chart provides @@ -259,27 +266,27 @@ Tags - The tags field is a YAML list of labels to associate with this chart. In the top parent's values, all charts with tags can be enabled or disabled by specifying the tag and a boolean value. -```` +```yaml # parentchart/requirements.yaml dependencies: - - name: subchart1 - repository: http://localhost:10191 - version: 0.1.0 - condition: subchart1.enabled,global.subchart1.enabled - tags: - - front-end - - subchart1 - - - name: subchart2 - repository: http://localhost:10191 - version: 0.1.0 - condition: subchart2.enabled,global.subchart2.enabled - tags: - - back-end + - name: subchart1 + repository: http://localhost:10191 + version: 0.1.0 + condition: subchart1.enabled,global.subchart1.enabled + tags: + - front-end + - subchart1 + + - name: subchart2 + repository: http://localhost:10191 + version: 0.1.0 + condition: subchart2.enabled,global.subchart2.enabled + tags: + - back-end - subchart2 -```` -```` +``` +```yaml # parentchart/values.yaml subchart1: diff --git a/pkg/chartutil/load.go b/pkg/chartutil/load.go index b3daefac7..9f1c80c85 100644 --- a/pkg/chartutil/load.go +++ b/pkg/chartutil/load.go @@ -43,6 +43,7 @@ import ( // If a .helmignore file is present, the directory loader will skip loading any files // matching it. But .helmignore is not evaluated when reading out of an archive. func Load(name string) (*chart.Chart, error) { + name = filepath.FromSlash(name) fi, err := os.Stat(name) if err != nil { return nil, err diff --git a/pkg/chartutil/requirements_test.go b/pkg/chartutil/requirements_test.go index 0afde17e1..e433f92ea 100644 --- a/pkg/chartutil/requirements_test.go +++ b/pkg/chartutil/requirements_test.go @@ -15,6 +15,8 @@ limitations under the License. package chartutil import ( + "os" + "path/filepath" "sort" "testing" @@ -426,7 +428,12 @@ func TestDependentChartWithSubChartsHelmignore(t *testing.T) { } func TestDependentChartsWithSubChartsSymlink(t *testing.T) { - c, err := Load("testdata/joonix") + joonix := "testdata/joonix" + if err := os.Symlink(filepath.Join("..", "..", "frobnitz"), filepath.Join(joonix, "charts", "frobnitz")); err != nil { + t.Fatal(err) + } + defer os.RemoveAll(filepath.Join(joonix, "charts", "frobnitz")) + c, err := Load(joonix) if err != nil { t.Fatalf("Failed to load testdata: %s", err) } diff --git a/pkg/chartutil/testdata/joonix/charts/.gitkeep b/pkg/chartutil/testdata/joonix/charts/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/pkg/chartutil/testdata/joonix/charts/frobnitz b/pkg/chartutil/testdata/joonix/charts/frobnitz deleted file mode 120000 index fde1b78ac..000000000 --- a/pkg/chartutil/testdata/joonix/charts/frobnitz +++ /dev/null @@ -1 +0,0 @@ -../../frobnitz \ No newline at end of file diff --git a/pkg/getter/plugingetter_test.go b/pkg/getter/plugingetter_test.go index 9bfe6144d..7c0bd6c1e 100644 --- a/pkg/getter/plugingetter_test.go +++ b/pkg/getter/plugingetter_test.go @@ -18,6 +18,7 @@ package getter import ( "os" "path/filepath" + "runtime" "strings" "testing" @@ -67,6 +68,10 @@ func TestCollectPlugins(t *testing.T) { } func TestPluginGetter(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("TODO: refactor this test to work on windows") + } + oldhh := os.Getenv("HELM_HOME") defer os.Setenv("HELM_HOME", oldhh) os.Setenv("HELM_HOME", "") diff --git a/pkg/repo/index.go b/pkg/repo/index.go index 01bf4a8ca..9031463f3 100644 --- a/pkg/repo/index.go +++ b/pkg/repo/index.go @@ -22,6 +22,7 @@ import ( "fmt" "io/ioutil" "os" + "path" "path/filepath" "sort" "strings" @@ -110,7 +111,7 @@ func (i IndexFile) Add(md *chart.Metadata, filename, baseURL, digest string) { _, file := filepath.Split(filename) u, err = urlutil.URLJoin(baseURL, file) if err != nil { - u = filepath.Join(baseURL, file) + u = path.Join(baseURL, file) } } cr := &ChartVersion{ @@ -246,9 +247,11 @@ func IndexDirectory(dir, baseURL string) (*IndexFile, error) { var parentDir string parentDir, fname = filepath.Split(fname) + // filepath.Split appends an extra slash to the end of parentDir. We want to strip that out. + parentDir = strings.TrimSuffix(parentDir, string(os.PathSeparator)) parentURL, err := urlutil.URLJoin(baseURL, parentDir) if err != nil { - parentURL = filepath.Join(baseURL, parentDir) + parentURL = path.Join(baseURL, parentDir) } c, err := chartutil.Load(arch) diff --git a/pkg/repo/index_test.go b/pkg/repo/index_test.go index 2ce817ce3..7c9239b7a 100644 --- a/pkg/repo/index_test.go +++ b/pkg/repo/index_test.go @@ -272,7 +272,7 @@ func verifyLocalIndex(t *testing.T, i *IndexFile) { } func TestIndexDirectory(t *testing.T) { - dir := "testdata/repository" + dir := filepath.Join("testdata", "repository") index, err := IndexDirectory(dir, "http://localhost:8080") if err != nil { t.Fatal(err)