diff --git a/pkg/chartutil/create.go b/pkg/chartutil/create.go index 7b7c24e20..6f0b38c05 100644 --- a/pkg/chartutil/create.go +++ b/pkg/chartutil/create.go @@ -35,6 +35,8 @@ const ( ChartfileName = "Chart.yaml" // ValuesfileName is the default values file name. ValuesfileName = "values.yaml" + // SchemafileName is the default values schema file name. + SchemafileName = "values.schema.json" // TemplatesDir is the relative directory name for templates. TemplatesDir = "templates" // ChartsDir is the relative directory name for charts dependencies. diff --git a/pkg/chartutil/save.go b/pkg/chartutil/save.go index 1d90142c1..ca6eeaa19 100644 --- a/pkg/chartutil/save.go +++ b/pkg/chartutil/save.go @@ -19,6 +19,7 @@ package chartutil import ( "archive/tar" "compress/gzip" + "encoding/json" "fmt" "os" "path/filepath" @@ -56,6 +57,14 @@ func SaveDir(c *chart.Chart, dest string) error { } } + // Save values.schema.json if it exists + if c.Schema != nil { + filename := filepath.Join(outdir, SchemafileName) + if err := writeFile(filename, c.Schema); err != nil { + return err + } + } + // Save templates and files for _, o := range [][]*chart.File{c.Templates, c.Files} { for _, f := range o { @@ -124,6 +133,7 @@ func Save(c *chart.Chart, outDir string) (string, error) { if err := writeTarContents(twriter, c, ""); err != nil { rollback = true + return filename, err } return filename, err } @@ -149,6 +159,16 @@ func writeTarContents(out *tar.Writer, c *chart.Chart, prefix string) error { return err } + // Save values.schema.json if it exists + if c.Schema != nil { + if !json.Valid(c.Schema) { + return errors.New("Invalid JSON in " + SchemafileName) + } + if err := writeToTar(out, filepath.Join(base, SchemafileName), c.Schema); err != nil { + return err + } + } + // Save templates for _, f := range c.Templates { n := filepath.Join(base, f.Name) diff --git a/pkg/chartutil/save_test.go b/pkg/chartutil/save_test.go index 377e89dcb..8941d0368 100644 --- a/pkg/chartutil/save_test.go +++ b/pkg/chartutil/save_test.go @@ -17,10 +17,12 @@ limitations under the License. package chartutil import ( + "bytes" "io/ioutil" "os" "path" "path/filepath" + "regexp" "strings" "testing" @@ -46,7 +48,9 @@ func TestSave(t *testing.T) { Files: []*chart.File{ {Name: "scheherazade/shahryar.txt", Data: []byte("1,001 Nights")}, }, + Schema: []byte("{\n \"title\": \"Values\"\n}"), } + chartWithInvalidJSON := withSchema(*c, []byte("{")) where, err := Save(c, dest) if err != nil { @@ -69,10 +73,32 @@ func TestSave(t *testing.T) { if len(c2.Files) != 1 || c2.Files[0].Name != "scheherazade/shahryar.txt" { t.Fatal("Files data did not match") } + + if !bytes.Equal(c.Schema, c2.Schema) { + indentation := 4 + formattedExpected := Indent(indentation, string(c.Schema)) + formattedActual := Indent(indentation, string(c2.Schema)) + t.Fatalf("Schema data did not match.\nExpected:\n%s\nActual:\n%s", formattedExpected, formattedActual) + } + if _, err := Save(&chartWithInvalidJSON, dest); err == nil { + t.Fatalf("Invalid JSON was not caught while saving chart") + } }) } } +// Creates a copy with a different schema; does not modify anything. +func withSchema(chart chart.Chart, schema []byte) chart.Chart { + chart.Schema = schema + return chart +} + +func Indent(n int, text string) string { + startOfLine := regexp.MustCompile(`(?m)^`) + indentation := strings.Repeat(" ", n) + return startOfLine.ReplaceAllLiteralString(text, indentation) +} + func TestSaveDir(t *testing.T) { tmp, err := ioutil.TempDir("", "helm-") if err != nil {