Added support for modtime

Signed-off-by: frenchben <me+git@frenchben.com>
pull/10178/head
frenchben 4 years ago
parent 9fafb4ad68
commit fdfb3d1c9f

@ -19,6 +19,7 @@ import (
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
"time"
) )
// APIVersionV1 is the API version number for version 1. // APIVersionV1 is the API version number for version 1.
@ -48,9 +49,13 @@ type Chart struct {
Values map[string]interface{} `json:"values"` Values map[string]interface{} `json:"values"`
// Schema is an optional JSON schema for imposing structure on Values // Schema is an optional JSON schema for imposing structure on Values
Schema []byte `json:"schema"` Schema []byte `json:"schema"`
// SchemaModTime the chart was last modified
SchemaModTime time.Time `json:"schemamodtime,omitempty"`
// Files are miscellaneous files in a chart archive, // Files are miscellaneous files in a chart archive,
// e.g. README, LICENSE, etc. // e.g. README, LICENSE, etc.
Files []*File `json:"files"` Files []*File `json:"files"`
// ModTime the chart was last modified
ModTime time.Time `json:"modtime,omitempty"`
parent *Chart parent *Chart
dependencies []*Chart dependencies []*Chart

@ -15,6 +15,8 @@ limitations under the License.
package chart package chart
import "time"
// File represents a file as a name/value pair. // File represents a file as a name/value pair.
// //
// By convention, name is a relative path within the scope of the chart's // By convention, name is a relative path within the scope of the chart's
@ -24,4 +26,6 @@ type File struct {
Name string `json:"name"` Name string `json:"name"`
// Data is the template as byte data. // Data is the template as byte data.
Data []byte `json:"data"` Data []byte `json:"data"`
// ModTime is the file's mod-time
ModTime time.Time `json:"modtime,omitempty"`
} }

@ -175,7 +175,7 @@ func LoadArchiveFiles(in io.Reader) ([]*BufferedFile, error) {
data := bytes.TrimPrefix(b.Bytes(), utf8bom) data := bytes.TrimPrefix(b.Bytes(), utf8bom)
files = append(files, &BufferedFile{Name: n, Data: data}) files = append(files, &BufferedFile{Name: n, ModTime: hd.FileInfo().ModTime(), Data: data})
b.Reset() b.Reset()
} }

@ -109,7 +109,7 @@ func LoadDir(dir string) (*chart.Chart, error) {
data = bytes.TrimPrefix(data, utf8bom) data = bytes.TrimPrefix(data, utf8bom)
files = append(files, &BufferedFile{Name: n, Data: data}) files = append(files, &BufferedFile{Name: n, ModTime: fi.ModTime(), Data: data})
return nil return nil
} }
if err = sympath.Walk(topdir, walk); err != nil { if err = sympath.Walk(topdir, walk); err != nil {

@ -22,6 +22,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"time"
"github.com/pkg/errors" "github.com/pkg/errors"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
@ -64,8 +65,9 @@ func Load(name string) (*chart.Chart, error) {
// BufferedFile represents an archive file buffered for later processing. // BufferedFile represents an archive file buffered for later processing.
type BufferedFile struct { type BufferedFile struct {
Name string Name string
Data []byte Data []byte
ModTime time.Time
} }
// LoadFiles loads from in-memory files. // LoadFiles loads from in-memory files.
@ -76,7 +78,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) {
// do not rely on assumed ordering of files in the chart and crash // do not rely on assumed ordering of files in the chart and crash
// if Chart.yaml was not coming early enough to initialize metadata // if Chart.yaml was not coming early enough to initialize metadata
for _, f := range files { for _, f := range files {
c.Raw = append(c.Raw, &chart.File{Name: f.Name, Data: f.Data}) c.Raw = append(c.Raw, &chart.File{Name: f.Name, ModTime: f.ModTime, Data: f.Data})
if f.Name == "Chart.yaml" { if f.Name == "Chart.yaml" {
if c.Metadata == nil { if c.Metadata == nil {
c.Metadata = new(chart.Metadata) c.Metadata = new(chart.Metadata)
@ -90,6 +92,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) {
if c.Metadata.APIVersion == "" { if c.Metadata.APIVersion == "" {
c.Metadata.APIVersion = chart.APIVersionV1 c.Metadata.APIVersion = chart.APIVersionV1
} }
c.ModTime = f.ModTime
} }
} }
for _, f := range files { for _, f := range files {
@ -109,6 +112,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) {
} }
case f.Name == "values.schema.json": case f.Name == "values.schema.json":
c.Schema = f.Data c.Schema = f.Data
c.SchemaModTime = f.ModTime
// Deprecated: requirements.yaml is deprecated use Chart.yaml. // Deprecated: requirements.yaml is deprecated use Chart.yaml.
// We will handle it for you because we are nice people // We will handle it for you because we are nice people

@ -217,8 +217,9 @@ func TestLoadFiles_BadCases(t *testing.T) {
name: "These files contain only requirements.lock", name: "These files contain only requirements.lock",
bufferedFiles: []*BufferedFile{ bufferedFiles: []*BufferedFile{
{ {
Name: "requirements.lock", Name: "requirements.lock",
Data: []byte(""), Data: []byte(""),
ModTime: time.Now(),
}, },
}, },
expectError: "validation: chart.metadata.apiVersion is required"}, expectError: "validation: chart.metadata.apiVersion is required"},
@ -255,22 +256,27 @@ sources:
home: http://example.com home: http://example.com
icon: https://example.com/64x64.png icon: https://example.com/64x64.png
`), `),
ModTime: time.Now(),
}, },
{ {
Name: "values.yaml", Name: "values.yaml",
Data: []byte("var: some values"), Data: []byte("var: some values"),
ModTime: time.Now(),
}, },
{ {
Name: "values.schema.json", Name: "values.schema.json",
Data: []byte("type: Values"), Data: []byte("type: Values"),
ModTime: time.Now(),
}, },
{ {
Name: "templates/deployment.yaml", Name: "templates/deployment.yaml",
Data: []byte("some deployment"), Data: []byte("some deployment"),
ModTime: time.Now(),
}, },
{ {
Name: "templates/service.yaml", Name: "templates/service.yaml",
Data: []byte("some service"), Data: []byte("some service"),
ModTime: time.Now(),
}, },
} }
@ -312,21 +318,25 @@ icon: https://example.com/64x64.png
func TestLoadFilesOrder(t *testing.T) { func TestLoadFilesOrder(t *testing.T) {
goodFiles := []*BufferedFile{ goodFiles := []*BufferedFile{
{ {
Name: "requirements.yaml", Name: "requirements.yaml",
Data: []byte("dependencies:"), Data: []byte("dependencies:"),
ModTime: time.Now(),
}, },
{ {
Name: "values.yaml", Name: "values.yaml",
Data: []byte("var: some values"), Data: []byte("var: some values"),
ModTime: time.Now(),
}, },
{ {
Name: "templates/deployment.yaml", Name: "templates/deployment.yaml",
Data: []byte("some deployment"), Data: []byte("some deployment"),
ModTime: time.Now(),
}, },
{ {
Name: "templates/service.yaml", Name: "templates/service.yaml",
Data: []byte("some service"), Data: []byte("some service"),
ModTime: time.Now(),
}, },
{ {
Name: "Chart.yaml", Name: "Chart.yaml",
@ -348,6 +358,7 @@ sources:
home: http://example.com home: http://example.com
icon: https://example.com/64x64.png icon: https://example.com/64x64.png
`), `),
ModTime: time.Now(),
}, },
} }

@ -165,7 +165,7 @@ func writeTarContents(out *tar.Writer, c *chart.Chart, prefix string) error {
if err != nil { if err != nil {
return err return err
} }
if err := writeToTar(out, filepath.Join(base, ChartfileName), cdata); err != nil { if err := writeToTar(out, filepath.Join(base, ChartfileName), cdata, c.ModTime); err != nil {
return err return err
} }
@ -177,7 +177,7 @@ func writeTarContents(out *tar.Writer, c *chart.Chart, prefix string) error {
if err != nil { if err != nil {
return err return err
} }
if err := writeToTar(out, filepath.Join(base, "Chart.lock"), ldata); err != nil { if err := writeToTar(out, filepath.Join(base, "Chart.lock"), ldata, c.Lock.Generated); err != nil {
return err return err
} }
} }
@ -186,7 +186,7 @@ func writeTarContents(out *tar.Writer, c *chart.Chart, prefix string) error {
// Save values.yaml // Save values.yaml
for _, f := range c.Raw { for _, f := range c.Raw {
if f.Name == ValuesfileName { if f.Name == ValuesfileName {
if err := writeToTar(out, filepath.Join(base, ValuesfileName), f.Data); err != nil { if err := writeToTar(out, filepath.Join(base, ValuesfileName), f.Data, f.ModTime); err != nil {
return err return err
} }
} }
@ -197,7 +197,8 @@ func writeTarContents(out *tar.Writer, c *chart.Chart, prefix string) error {
if !json.Valid(c.Schema) { if !json.Valid(c.Schema) {
return errors.New("Invalid JSON in " + SchemafileName) return errors.New("Invalid JSON in " + SchemafileName)
} }
if err := writeToTar(out, filepath.Join(base, SchemafileName), c.Schema); err != nil { // TODO: read the modtime for the values.schema.json
if err := writeToTar(out, filepath.Join(base, SchemafileName), c.Schema, c.SchemaModTime); err != nil {
return err return err
} }
} }
@ -205,7 +206,7 @@ func writeTarContents(out *tar.Writer, c *chart.Chart, prefix string) error {
// Save templates // Save templates
for _, f := range c.Templates { for _, f := range c.Templates {
n := filepath.Join(base, f.Name) n := filepath.Join(base, f.Name)
if err := writeToTar(out, n, f.Data); err != nil { if err := writeToTar(out, n, f.Data, f.ModTime); err != nil {
return err return err
} }
} }
@ -213,7 +214,7 @@ func writeTarContents(out *tar.Writer, c *chart.Chart, prefix string) error {
// Save files // Save files
for _, f := range c.Files { for _, f := range c.Files {
n := filepath.Join(base, f.Name) n := filepath.Join(base, f.Name)
if err := writeToTar(out, n, f.Data); err != nil { if err := writeToTar(out, n, f.Data, f.ModTime); err != nil {
return err return err
} }
} }
@ -228,13 +229,13 @@ func writeTarContents(out *tar.Writer, c *chart.Chart, prefix string) error {
} }
// writeToTar writes a single file to a tar archive. // writeToTar writes a single file to a tar archive.
func writeToTar(out *tar.Writer, name string, body []byte) error { func writeToTar(out *tar.Writer, name string, body []byte, modTime time.Time) error {
// TODO: Do we need to create dummy parent directory names if none exist? // TODO: Do we need to create dummy parent directory names if none exist?
h := &tar.Header{ h := &tar.Header{
Name: filepath.ToSlash(name), Name: filepath.ToSlash(name),
Mode: 0644, Mode: 0644,
Size: int64(len(body)), Size: int64(len(body)),
ModTime: time.Now(), ModTime: modTime,
} }
if err := out.WriteHeader(h); err != nil { if err := out.WriteHeader(h); err != nil {
return err return err

Loading…
Cancel
Save