Refactor Chart to be a struct, with more methods.

This refactors the Chart to be a struct that can have numerous
properties and methods. Now, a chartLoader implements the
loading and closing of charts.
pull/195/head
Matt Butcher 10 years ago
parent 57a562fb2b
commit cfaca7ffb5

@ -36,6 +36,7 @@ const (
preTemplates string = "templates/"
preHooks string = "hooks/"
preDocs string = "docs/"
preIcon string = "icon.svg"
)
// Chart represents a complete chart.
@ -54,47 +55,93 @@ const (
//
// Optionally, a chart might also locate a provenance (.prov) file that it
// can use for cryptographic signing.
type Chart interface {
type Chart struct {
loader chartLoader
}
// Close the chart.
//
// Charts should always be closed when no longer needed.
func (c *Chart) Close() error {
return c.loader.close()
}
// Chartfile gets the Chartfile (Chart.yaml) for this chart.
func (c *Chart) Chartfile() *Chartfile {
return c.loader.chartfile()
}
// Dir() returns the directory where the charts are located.
func (c *Chart) Dir() string {
return c.loader.dir()
}
// DocsDir returns the directory where the chart's documentation is stored.
func (c *Chart) DocsDir() string {
return filepath.Join(c.loader.dir(), preDocs)
}
// HooksDir returns the directory where the hooks are stored.
func (c *Chart) HooksDir() string {
return filepath.Join(c.loader.dir(), preHooks)
}
// TemplatesDir returns the directory where the templates are stored.
func (c *Chart) TemplatesDir() string {
return filepath.Join(c.loader.dir(), preTemplates)
}
// Icon returns the path to the icon.svg file.
//
// If an icon is not found in the chart, this will return an error.
func (c *Chart) Icon() (string, error) {
i := filepath.Join(c.Dir(), preIcon)
_, err := os.Stat(i)
return i, err
}
// chartLoader provides load, close, and save implementations for a chart.
type chartLoader interface {
// Chartfile resturns a *Chartfile for this chart.
Chartfile() *Chartfile
chartfile() *Chartfile
// Dir returns a directory where the chart can be accessed.
Dir() string
dir() string
// Close cleans up a chart.
Close() error
close() error
}
type dirChart struct {
chartfile *Chartfile
dir string
chartyaml *Chartfile
chartdir string
}
func (d *dirChart) Chartfile() *Chartfile {
return d.chartfile
func (d *dirChart) chartfile() *Chartfile {
return d.chartyaml
}
func (d *dirChart) Dir() string {
return "."
func (d *dirChart) dir() string {
return d.chartdir
}
func (d *dirChart) Close() error {
func (d *dirChart) close() error {
return nil
}
type tarChart struct {
chartfile *Chartfile
chartyaml *Chartfile
tmpDir string
}
func (t *tarChart) Chartfile() *Chartfile {
return t.chartfile
func (t *tarChart) chartfile() *Chartfile {
return t.chartyaml
}
func (t *tarChart) Dir() string {
return "."
func (t *tarChart) dir() string {
return t.tmpDir
}
func (t *tarChart) Close() error {
func (t *tarChart) close() error {
// Remove the temp directory.
return os.RemoveAll(t.tmpDir)
}
@ -105,7 +152,7 @@ func (t *tarChart) Close() error {
//
// If you are just reading the Chart.yaml file, it is substantially more
// performant to use LoadChartfile.
func LoadDir(chart string) (Chart, error) {
func LoadDir(chart string) (*Chart, error) {
if fi, err := os.Stat(chart); err != nil {
return nil, err
} else if !fi.IsDir() {
@ -117,19 +164,21 @@ func LoadDir(chart string) (Chart, error) {
return nil, err
}
c := &dirChart{
chartfile: cf,
dir: chart,
cl := &dirChart{
chartyaml: cf,
chartdir: chart,
}
return c, nil
return &Chart{
loader: cl,
}, nil
}
// Load loads a chart from a chart archive.
//
// A chart archive is a gzipped tar archive that follows the Chart format
// specification.
func Load(archive string) (Chart, error) {
func Load(archive string) (*Chart, error) {
if fi, err := os.Stat(archive); err != nil {
return nil, err
} else if fi.IsDir() {
@ -151,15 +200,15 @@ func Load(archive string) (Chart, error) {
untarred := tar.NewReader(unzipped)
c, err := loadTar(untarred)
if err != nil {
return c, err
return nil, err
}
cf, err := LoadChartfile(filepath.Join(c.tmpDir, ChartfileName))
if err != nil {
return c, err
return nil, err
}
c.chartfile = cf
return c, nil
c.chartyaml = cf
return &Chart{loader: c}, nil
}
func loadTar(r *tar.Reader) (*tarChart, error) {
@ -168,7 +217,7 @@ func loadTar(r *tar.Reader) (*tarChart, error) {
return nil, err
}
c := &tarChart{
chartfile: &Chartfile{},
chartyaml: &Chartfile{},
tmpDir: td,
}
@ -221,7 +270,7 @@ func loadTar(r *tar.Reader) (*tarChart, error) {
if err != nil && err != io.EOF {
log.Warn("Unexpected error reading tar: %s", err)
c.Close()
c.close()
return c, err
}
log.Info("Reached end of Tar file")

@ -17,6 +17,7 @@ limitations under the License.
package chart
import (
"path/filepath"
"testing"
"github.com/kubernetes/deployment-manager/log"
@ -30,11 +31,16 @@ const (
testnochart = "testdata/nochart.tgz"
)
// Type canaries. If these fail, they will fail at compile time.
var _ chartLoader = &dirChart{}
var _ chartLoader = &tarChart{}
func init() {
log.IsDebugging = true
}
func TestLoadDir(t *testing.T) {
c, err := LoadDir(testdir)
if err != nil {
t.Errorf("Failed to load chart: %s", err)
@ -51,6 +57,7 @@ func TestLoadDir(t *testing.T) {
}
func TestLoad(t *testing.T) {
c, err := Load(testarchive)
if err != nil {
t.Errorf("Failed to load chart: %s", err)
@ -80,6 +87,11 @@ func TestLoadIll(t *testing.T) {
t.Error("No chartfile was loaded.")
return
}
// Ill does not have an icon.
if i, err := c.Icon(); err == nil {
t.Errorf("Expected icon to be missing. Got %s", i)
}
}
func TestLoadNochart(t *testing.T) {
@ -88,3 +100,42 @@ func TestLoadNochart(t *testing.T) {
t.Error("Nochart should not have loaded at all.")
}
}
func TestChart(t *testing.T) {
c, err := LoadDir(testdir)
if err != nil {
t.Errorf("Failed to load chart: %s", err)
}
defer c.Close()
if c.Dir() != c.loader.dir() {
t.Errorf("Unexpected location for directory: %s", c.Dir())
}
if c.Chartfile().Name != c.loader.chartfile().Name {
t.Errorf("Unexpected chart file name: %s", c.Chartfile().Name)
}
d := c.DocsDir()
if d != filepath.Join(testdir, preDocs) {
t.Errorf("Unexpectedly, docs are in %s", d)
}
d = c.TemplatesDir()
if d != filepath.Join(testdir, preTemplates) {
t.Errorf("Unexpectedly, templates are in %s", d)
}
d = c.HooksDir()
if d != filepath.Join(testdir, preHooks) {
t.Errorf("Unexpectedly, hooks are in %s", d)
}
i, err := c.Icon()
if err != nil {
t.Errorf("No icon found in test chart: %s", err)
}
if i != filepath.Join(testdir, preIcon) {
t.Errorf("Unexpectedly, icon is in %s", i)
}
}

Binary file not shown.

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.0" width="256" height="256" id="test">
<desc>Example icon</desc>
<rect id="first" x="2" y="2" width="40" height="60" fill="navy"/>
<rect id="second" x="15" y="4" width="40" height="60" fill="red"/>
</svg>

After

Width:  |  Height:  |  Size: 374 B

Loading…
Cancel
Save