diff --git a/internal/test/test.go b/internal/test/test.go index 319ec1557..480b466ee 100644 --- a/internal/test/test.go +++ b/internal/test/test.go @@ -58,6 +58,17 @@ func AssertGoldenString(t TestingT, actual, filename string) { } } +// AssertGoldenFile assers that the content of the actual file matches the contents of the expected file +func AssertGoldenFile(t TestingT, actualFileName string, expectedFilename string) { + t.Helper() + + actual, err := ioutil.ReadFile(actualFileName) + if err != nil { + t.Fatalf("%v", err) + } + AssertGoldenBytes(t, actual, expectedFilename) +} + func path(filename string) string { if filepath.IsAbs(filename) { return filename diff --git a/pkg/action/action_test.go b/pkg/action/action_test.go index afd9d4b51..1c53e49fc 100644 --- a/pkg/action/action_test.go +++ b/pkg/action/action_test.go @@ -71,6 +71,32 @@ var manifestWithTestHook = `kind: Pod cmd: fake-command ` +var rbacManifests = `apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: schedule-agents +rules: +- apiGroups: [""] + resources: ["pods", "pods/exec", "pods/log"] + verbs: ["*"] + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: schedule-agents + namespace: {{ default .Release.Namespace}} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: schedule-agents +subjects: +- kind: ServiceAccount + name: schedule-agents + namespace: {{ .Release.Namespace }} +` + type chartOptions struct { *chart.Chart } @@ -127,6 +153,15 @@ func withSampleTemplates() chartOption { } } +func withMultipleManifestTemplate() chartOption { + return func(opts *chartOptions) { + sampleTemplates := []*chart.File{ + {Name: "templates/rbac", Data: []byte(rbacManifests)}, + } + opts.Templates = append(opts.Templates, sampleTemplates...) + } +} + func withKube(version string) chartOption { return func(opts *chartOptions) { opts.Metadata.KubeVersion = version diff --git a/pkg/action/install.go b/pkg/action/install.go index 03f90beb4..1d8a89ddb 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -365,22 +365,24 @@ func (c *Configuration) renderResources(ch *chart.Chart, values chartutil.Values } // Aggregate all valid manifests into one big doc. + fileWritten := make(map[string]bool) for _, m := range manifests { if outputDir == "" { fmt.Fprintf(b, "---\n# Source: %s\n%s\n", m.Name, m.Content) } else { - err = writeToFile(outputDir, m.Name, m.Content) + err = writeToFile(outputDir, m.Name, m.Content, fileWritten[m.Name]) if err != nil { return hs, b, "", err } + fileWritten[m.Name] = true } } return hs, b, notes, nil } -// write the to / -func writeToFile(outputDir string, name string, data string) error { +// write the to /. controls if the file is created or content will be appended +func writeToFile(outputDir string, name string, data string, append bool) error { outfileName := strings.Join([]string{outputDir, name}, string(filepath.Separator)) err := ensureDirectoryForFile(outfileName) @@ -388,14 +390,14 @@ func writeToFile(outputDir string, name string, data string) error { return err } - f, err := os.Create(outfileName) + f, err := createOrOpenFile(outfileName, append) if err != nil { return err } defer f.Close() - _, err = f.WriteString(fmt.Sprintf("---\n# Source: %s\n%s", name, data)) + _, err = f.WriteString(fmt.Sprintf("---\n# Source: %s\n%s\n", name, data)) if err != nil { return err @@ -405,6 +407,13 @@ func writeToFile(outputDir string, name string, data string) error { return nil } +func createOrOpenFile(filename string, append bool) (*os.File, error) { + if append { + return os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, 0600) + } + return os.Create(filename) +} + // check if the directory exists to create file. creates if don't exists func ensureDirectoryForFile(file string) error { baseDir := path.Dir(file) diff --git a/pkg/action/install_test.go b/pkg/action/install_test.go index 12f9bb3b2..d92204298 100644 --- a/pkg/action/install_test.go +++ b/pkg/action/install_test.go @@ -28,6 +28,7 @@ import ( "github.com/stretchr/testify/assert" + "helm.sh/helm/internal/test" "helm.sh/helm/pkg/release" ) @@ -372,7 +373,7 @@ func TestInstallReleaseOutputDir(t *testing.T) { instAction.OutputDir = dir - _, err = instAction.Run(buildChart(withSampleTemplates())) + _, err = instAction.Run(buildChart(withSampleTemplates(), withMultipleManifestTemplate())) if err != nil { t.Fatalf("Failed install: %s", err) } @@ -386,6 +387,11 @@ func TestInstallReleaseOutputDir(t *testing.T) { _, err = os.Stat(filepath.Join(dir, "hello/templates/with-partials")) is.NoError(err) + _, err = os.Stat(filepath.Join(dir, "hello/templates/rbac")) + is.NoError(err) + + test.AssertGoldenFile(t, filepath.Join(dir, "hello/templates/rbac"), "rbac.txt") + _, err = os.Stat(filepath.Join(dir, "hello/templates/empty")) is.True(os.IsNotExist(err)) } diff --git a/pkg/action/testdata/rbac.txt b/pkg/action/testdata/rbac.txt new file mode 100644 index 000000000..0cb15b868 --- /dev/null +++ b/pkg/action/testdata/rbac.txt @@ -0,0 +1,25 @@ +--- +# Source: hello/templates/rbac +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: schedule-agents +rules: +- apiGroups: [""] + resources: ["pods", "pods/exec", "pods/log"] + verbs: ["*"] +--- +# Source: hello/templates/rbac +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: schedule-agents + namespace: spaced +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: schedule-agents +subjects: +- kind: ServiceAccount + name: schedule-agents + namespace: spaced