mirror of https://github.com/helm/helm
parent
cfaca7ffb5
commit
4fe37ea634
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package chart
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"compress/gzip"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/kubernetes/deployment-manager/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Save creates an archived chart to the given directory.
|
||||||
|
//
|
||||||
|
// This takes an existing chart and a destination directory.
|
||||||
|
//
|
||||||
|
// If the directory is /foo, and the chart is named bar, with version 1.0.0, this
|
||||||
|
// will generate /foo/bar-1.0.0.tgz.
|
||||||
|
//
|
||||||
|
// This returns the absolute path to the chart archive file.
|
||||||
|
func Save(c *Chart, outDir string) (string, error) {
|
||||||
|
// Create archive
|
||||||
|
if fi, err := os.Stat(outDir); err != nil {
|
||||||
|
return "", err
|
||||||
|
} else if !fi.IsDir() {
|
||||||
|
return "", fmt.Errorf("location %s is not a directory", outDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfile := c.Chartfile()
|
||||||
|
dir := c.Dir()
|
||||||
|
basename := filepath.Base(dir)
|
||||||
|
pdir := filepath.Dir(dir)
|
||||||
|
if basename == "." {
|
||||||
|
basename = fname(cfile.Name)
|
||||||
|
}
|
||||||
|
filename := fmt.Sprintf("%s-%s.tgz", fname(cfile.Name), cfile.Version)
|
||||||
|
filename = filepath.Join(outDir, filename)
|
||||||
|
|
||||||
|
// Fail early if the YAML is borked.
|
||||||
|
if err := cfile.Save(filepath.Join(dir, ChartfileName)); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create file.
|
||||||
|
f, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap in gzip writer
|
||||||
|
zipper := gzip.NewWriter(f)
|
||||||
|
zipper.Header.Extra = headerBytes
|
||||||
|
zipper.Header.Comment = "Helm"
|
||||||
|
|
||||||
|
// Wrap in tar writer
|
||||||
|
twriter := tar.NewWriter(zipper)
|
||||||
|
rollback := false
|
||||||
|
defer func() {
|
||||||
|
twriter.Close()
|
||||||
|
zipper.Close()
|
||||||
|
f.Close()
|
||||||
|
if rollback {
|
||||||
|
log.Warn("Removing incomplete archive %s", filename)
|
||||||
|
os.Remove(filename)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
hdr, err := tar.FileInfoHeader(fi, ".")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
relpath, err := filepath.Rel(pdir, path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
hdr.Name = relpath
|
||||||
|
|
||||||
|
twriter.WriteHeader(hdr)
|
||||||
|
|
||||||
|
// Skip directories.
|
||||||
|
if fi.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
in, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = io.Copy(twriter, in)
|
||||||
|
in.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
rollback = true
|
||||||
|
return filename, err
|
||||||
|
}
|
||||||
|
return filename, nil
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package chart
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"compress/gzip"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const sprocketdir = "testdata/sprocket"
|
||||||
|
|
||||||
|
func TestSave(t *testing.T) {
|
||||||
|
|
||||||
|
tmpdir, err := ioutil.TempDir("", "helm-")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Could not create temp directory")
|
||||||
|
}
|
||||||
|
t.Logf("Temp: %s", tmpdir)
|
||||||
|
// Because of the defer, don't call t.Fatal in the remainder of this
|
||||||
|
// function.
|
||||||
|
defer os.RemoveAll(tmpdir)
|
||||||
|
|
||||||
|
c, err := LoadDir(sprocketdir)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to load %s: %s", sprocketdir, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tfile, err := Save(c, tmpdir)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to save %s to %s: %s", c.Chartfile().Name, tmpdir, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b := filepath.Base(tfile)
|
||||||
|
expectname := "sprocket-1.2.3-alpha.1+12345.tgz"
|
||||||
|
if b != expectname {
|
||||||
|
t.Errorf("Expected %q, got %q", expectname, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err := getAllFiles(tfile)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Could not extract files: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Files should come back in order.
|
||||||
|
expect := []string{
|
||||||
|
"sprocket",
|
||||||
|
"sprocket/Chart.yaml",
|
||||||
|
"sprocket/LICENSE",
|
||||||
|
"sprocket/README.md",
|
||||||
|
"sprocket/docs",
|
||||||
|
"sprocket/docs/README.md",
|
||||||
|
"sprocket/hooks",
|
||||||
|
"sprocket/hooks/pre-install.py",
|
||||||
|
"sprocket/icon.svg",
|
||||||
|
"sprocket/templates",
|
||||||
|
"sprocket/templates/placeholder.txt",
|
||||||
|
}
|
||||||
|
if len(expect) != len(files) {
|
||||||
|
t.Errorf("Expected %d files, found %d", len(expect), len(files))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for i := 0; i < len(expect); i++ {
|
||||||
|
if expect[i] != files[i] {
|
||||||
|
t.Errorf("Expected file %q, got %q", expect[i], files[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAllFiles(tfile string) ([]string, error) {
|
||||||
|
f1, err := os.Open(tfile)
|
||||||
|
if err != nil {
|
||||||
|
return []string{}, err
|
||||||
|
}
|
||||||
|
f2, err := gzip.NewReader(f1)
|
||||||
|
if err != nil {
|
||||||
|
f1.Close()
|
||||||
|
return []string{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if f2.Header.Comment != "Helm" {
|
||||||
|
return []string{}, fmt.Errorf("Expected header Helm. Got %s", f2.Header.Comment)
|
||||||
|
}
|
||||||
|
if string(f2.Header.Extra) != string(headerBytes) {
|
||||||
|
return []string{}, fmt.Errorf("Expected header signature. Got %v", f2.Header.Extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
f3 := tar.NewReader(f2)
|
||||||
|
|
||||||
|
files := []string{}
|
||||||
|
var e error
|
||||||
|
var hdr *tar.Header
|
||||||
|
for e == nil {
|
||||||
|
hdr, e = f3.Next()
|
||||||
|
if e == nil {
|
||||||
|
files = append(files, hdr.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f2.Close()
|
||||||
|
f1.Close()
|
||||||
|
return files, nil
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
name: sprocket
|
||||||
|
description: This is a sprocket.
|
||||||
|
version: 1.2.3-alpha.1+12345
|
||||||
|
home: ""
|
@ -0,0 +1 @@
|
|||||||
|
Placeholder for license.
|
@ -0,0 +1,3 @@
|
|||||||
|
# Sprocket
|
||||||
|
|
||||||
|
This is an example chart.
|
@ -0,0 +1 @@
|
|||||||
|
This is a placeholder for documentation.
|
@ -0,0 +1 @@
|
|||||||
|
# Placeholder.
|
After Width: | Height: | Size: 374 B |
@ -0,0 +1 @@
|
|||||||
|
This is a placeholder.
|
Loading…
Reference in new issue