Commit f8193c25 authored by jackgr's avatar jackgr
Browse files

Prepare to download charts

parent 54abaf7e
main Release add-codeql dependabot/go_modules/github.com/docker/distribution-2.8.2incompatible dependabot/go_modules/github.com/lib/pq-1.10.9 dependabot/go_modules/github.com/rubenv/sql-migrate-1.4.0 dependabot/go_modules/golang.org/x/crypto-0.9.0 dependabot/go_modules/golang.org/x/term-0.8.0 dependabot/go_modules/k8s.io/klog/v2-2.100.1 dev-v2 feat-v3/event-emitter-lua kube-update-test release-2.0 release-2.1 release-2.10 release-2.11 release-2.12 release-2.13 release-2.14 release-2.15 release-2.16 release-2.17 release-2.2 release-2.3 release-2.4 release-2.5 release-2.6 release-2.7 release-2.8 release-2.9 release-3.0 release-3.1 release-3.10 release-3.11 release-3.12 release-3.2 release-3.3 release-3.4 release-3.5 release-3.6 release-3.6.1 release-3.6.2 release-3.7 release-3.8 release-3.9 release-v3.0.0-beta.4 1.999.0 v3.12.0 v3.12.0-rc.1 v3.12.0-dev.1 v3.11.3 v3.11.2 v3.11.1 v3.11.0 v3.11.0-rc.2 v3.11.0-rc.1 v3.10.3 v3.10.2 v3.10.1 v3.10.0 v3.10.0-rc.1 v3.9.4 v3.9.3 v3.9.2 v3.9.1 v3.9.0 v3.9.0-rc.1 v3.8.2 v3.8.1 v3.8.0 v3.8.0-rc.2 v3.8.0-rc.1 v3.7.2 v3.7.1 v3.7.0 v3.7.0-rc.3 v3.7.0-rc.2 v3.7.0-rc.1 v3.6.3 v3.6.2 v3.6.1 v3.6.0 v3.6.0-rc.1 v3.5.4 v3.5.3 v3.5.2 v3.5.1 v3.5.0 v3.5.0-rc.2 v3.5.0-rc.1 v3.4.2 v3.4.1 v3.4.0 v3.4.0-rc.1 v3.3.4 v3.3.3 v3.3.2 v3.3.1 v3.3.0 v3.3.0-rc.2 v3.3.0-rc.1 v3.2.4 v3.2.3 v3.2.2 v3.2.1 v3.2.0 v3.2.0-rc.1 v3.1.3 v3.1.2 v3.1.1 v3.1.0 v3.1.0-rc.3 v3.1.0-rc.2 v3.1.0-rc.1 v3.0.3 v3.0.2 v3.0.1 v3.0.0 v3.0.0-rc.4 v3.0.0-rc.3 v3.0.0-rc.2 v3.0.0-rc.1 v3.0.0-beta.5 v3.0.0-beta.4 v3.0.0-beta.3 v3.0.0-beta.2 v3.0.0-beta.1 v3.0.0-alpha.2 v3.0.0-alpha.1 v2.17.0 v2.17.0-rc.1 v2.16.12 v2.16.11 v2.16.10 v2.16.9 v2.16.8 v2.16.7 v2.16.6 v2.16.5 v2.16.4 v2.16.3 v2.16.2 v2.16.1 v2.16.0 v2.16.0-rc.2 v2.16.0-rc.1 v2.15.2 v2.15.1 v2.15.0 v2.15.0-rc.2 v2.15.0-rc.1 v2.14.3 v2.14.2 v2.14.1 v2.14.0 v2.14.0-rc.2 v2.14.0-rc.1 v2.13.1 v2.13.1-rc.1 v2.13.0 v2.13.0-rc.2 v2.13.0-rc.1 v2.12.3 v2.12.2 v2.12.1 v2.12.0 v2.12.0-rc.2 v2.12.0-rc.1 v2.11.0 v2.11.0-rc.4 v2.11.0-rc.3 v2.11.0-rc.2 v2.11.0-rc.1 v2.10.0 v2.10.0-rc.3 v2.10.0-rc.2 v2.10.0-rc.1 v2.9.1 v2.9.0 v2.9.0-rc5 v2.9.0-rc4 v2.9.0-rc3 v2.9.0-rc2 v2.9.0-rc1 v2.8.2 v2.8.2-rc1 v2.8.1 v2.8.0 v2.8.0-rc.1 v2.7.2 v2.7.1 v2.7.0 v2.7.0-rc1 v2.6.2 v2.6.1 v2.6.0 v2.5.1 v2.5.0 v2.4.2 v2.4.1 v2.4.0 v2.3.1 v2.3.0 v2.2.3 v2.2.2 v2.2.1 v2.2.0 v2.1.3 v2.1.2 v2.1.1 v2.1.0 v2.0.2 v2.0.1 v2.0.0 v2.0.0-rc.2 v2.0.0-rc.1 v2.0.0-beta.2 v2.0.0-beta.1 v2.0.0-alpha.5 v2.0.0-alpha.4 v2.0.0-alpha.3 v2.0.0-alpha.2 v2.0.0-alpha.1
No related merge requests found
Showing with 192 additions and 42 deletions
+192 -42
......@@ -20,6 +20,7 @@ import (
"archive/tar"
"bytes"
"compress/gzip"
"encoding/base64"
"errors"
"fmt"
"io"
......@@ -243,25 +244,7 @@ func LoadDir(chart string) (*Chart, error) {
// LoadData loads a chart from data, where data is a []byte containing a gzipped tar file.
func LoadData(data []byte) (*Chart, error) {
b := bytes.NewBuffer(data)
unzipped, err := gzip.NewReader(b)
if err != nil {
return nil, err
}
defer unzipped.Close()
untarred := tar.NewReader(unzipped)
c, err := loadTar(untarred)
if err != nil {
return nil, err
}
cf, err := LoadChartfile(filepath.Join(c.tmpDir, ChartfileName))
if err != nil {
return nil, err
}
c.chartyaml = cf
return &Chart{loader: c}, nil
return LoadDataFromReader(bytes.NewBuffer(data))
}
// Load loads a chart from a chart archive.
......@@ -281,7 +264,11 @@ func Load(archive string) (*Chart, error) {
}
defer raw.Close()
unzipped, err := gzip.NewReader(raw)
return LoadDataFromReader(raw)
}
func LoadDataFromReader(r io.Reader) (*Chart, error) {
unzipped, err := gzip.NewReader(r)
if err != nil {
return nil, err
}
......@@ -367,3 +354,65 @@ func loadTar(r *tar.Reader) (*tarChart, error) {
return c, nil
}
// ChartMember is a file in a chart.
type ChartMember struct {
Path string `json:"path"` // Path from the root of the chart.
Content []byte `json:"content"` // Base64 encoded content.
}
// LoadTemplates loads the members of TemplatesDir().
func (c *Chart) LoadTemplates() ([]*ChartMember, error) {
dir := c.TemplatesDir()
return c.loadDirectory(dir)
}
// loadDirectory loads the members of a directory.
func (c *Chart) loadDirectory(dir string) ([]*ChartMember, error) {
files, err := ioutil.ReadDir(dir)
if err != nil {
return nil, err
}
members := []*ChartMember{}
for _, file := range files {
filename := filepath.Join(dir, file.Name())
member, err := c.loadMember(filename)
if err != nil {
return nil, err
}
members = append(members, member)
}
return members, nil
}
// path is from the root of the chart.
func (c *Chart) LoadMember(path string) (*ChartMember, error) {
filename := filepath.Join(c.loader.dir(), path)
return c.loadMember(filename)
}
// loadMember loads and base 64 encodes a file.
func (c *Chart) loadMember(filename string) (*ChartMember, error) {
dir := c.Dir()
if !strings.HasPrefix(filename, dir) {
err := fmt.Errorf("File %s is outside chart directory %s", filename, dir)
return nil, err
}
b, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
path := strings.TrimPrefix(filename, dir)
content := base64.StdEncoding.EncodeToString(b)
result := &ChartMember{
Path: path,
Content: []byte(content),
}
return result, nil
}
......@@ -17,6 +17,8 @@ limitations under the License.
package chart
import (
"encoding/base64"
"fmt"
"io/ioutil"
"path/filepath"
"testing"
......@@ -30,6 +32,7 @@ const (
testarchive = "testdata/frobnitz-0.0.1.tgz"
testill = "testdata/ill-1.2.3.tgz"
testnochart = "testdata/nochart.tgz"
testmember = "templates/wordpress.jinja"
)
// Type canaries. If these fail, they will fail at compile time.
......@@ -160,3 +163,91 @@ func TestChart(t *testing.T) {
t.Errorf("Unexpectedly, icon is in %s", i)
}
}
func TestLoadTemplates(t *testing.T) {
c, err := LoadDir(testdir)
if err != nil {
t.Errorf("Failed to load chart: %s", err)
}
members, err := c.LoadTemplates()
if members == nil {
t.Fatalf("Cannot load templates: unknown error")
}
if err != nil {
t.Fatalf("Cannot load templates: %s", err)
}
dir := c.TemplatesDir()
files, err := ioutil.ReadDir(dir)
if err != nil {
t.Fatalf("Cannot read template directory: %s", err)
}
if len(members) != len(files) {
t.Fatalf("Expected %s templates, got %d", len(files), len(members))
}
root := c.loader.dir()
for _, file := range files {
path := filepath.Join(preTemplates, file.Name())
if err := findMember(root, path, members); err != nil {
t.Fatal(err)
}
}
}
func findMember(root, path string, members []*ChartMember) error {
for _, member := range members {
if member.Path == path {
filename := filepath.Join(root, path)
if err := compareContent(filename, string(member.Content)); err != nil {
return err
}
return nil
}
}
return fmt.Errorf("Template not found: %s", path)
}
func TestLoadMember(t *testing.T) {
c, err := LoadDir(testdir)
if err != nil {
t.Errorf("Failed to load chart: %s", err)
}
member, err := c.LoadMember(testmember)
if member == nil {
t.Fatalf("Cannot load member %s: unknown error", testmember)
}
if err != nil {
t.Fatalf("Cannot load member %s: %s", testmember, err)
}
if member.Path != testmember {
t.Errorf("Expected member path %s, got %s", testmember, member.Path)
}
filename := filepath.Join(c.loader.dir(), testmember)
if err := compareContent(filename, string(member.Content)); err != nil {
t.Fatal(err)
}
}
func compareContent(filename, content string) error {
b, err := ioutil.ReadFile(filename)
if err != nil {
return fmt.Errorf("Cannot read test file %s: %s", filename, err)
}
compare := base64.StdEncoding.EncodeToString(b)
if content != compare {
return fmt.Errorf("Expected member content\n%s\ngot\n%s", compare, content)
}
return nil
}
......@@ -34,6 +34,8 @@ type Chartfile struct {
Home string `yaml:"home"`
Dependencies []*Dependency `yaml:"dependencies,omitempty"`
Environment []*EnvConstraint `yaml:"environment,omitempty"`
Expander *Expander `yaml:"expander,omitempty"`
Schema string `yaml:"schema,omitempty"`
}
// Maintainer describes a chart maintainer.
......@@ -57,6 +59,14 @@ type EnvConstraint struct {
APIGroups []string `yaml:"apiGroups,omitempty"`
}
// Expander controls how template/ is evaluated.
type Expander struct {
// Currently just Expandybird or GoTemplate
Name string `json:"name"`
// During evaluation, which file to start from.
Entrypoint string `json:"entrypoint"`
}
// LoadChartfile loads a Chart.yaml file into a *Chart.
func LoadChartfile(filename string) (*Chartfile, error) {
b, err := ioutil.ReadFile(filename)
......
......@@ -50,6 +50,23 @@ func TestLoadChartfile(t *testing.T) {
if f.Source[0] != "https://example.com/foo/bar" {
t.Errorf("Expected https://example.com/foo/bar, got %s", f.Source)
}
expander := f.Expander
if expander == nil {
t.Errorf("No expander found in %s", testfile)
} else {
if expander.Name != "Expandybird" {
t.Errorf("Expected expander name Expandybird, got %s", expander.Name)
}
if expander.Entrypoint != "templates/wordpress.jinja" {
t.Errorf("Expected expander entrypoint templates/wordpress.jinja, got %s", expander.Entrypoint)
}
}
if f.Schema != "wordpress.jinja.schema" {
t.Errorf("Expected schema wordpress.jinja.schema, got %s", f.Schema)
}
}
func TestVersionOK(t *testing.T) {
......
......@@ -26,3 +26,8 @@ environment:
- extensions/v1beta1/daemonset
apiGroups:
- 3rdParty
expander:
name: Expandybird
entrypoint: templates/wordpress.jinja
schema: wordpress.jinja.schema
\ No newline at end of file
......@@ -97,28 +97,6 @@ type Manifest struct {
Layout *Layout `json:"layout,omitempty"`
}
// Expander controls how template/ is evaluated.
type Expander struct {
// Currently just Expandybird or GoTemplate
Name string `json:"name"`
// During evaluation, which file to start from.
Entrypoint string `json:"entry_point"`
}
// ChartFile is a file in a chart that is not chart.yaml.
type ChartFile struct {
Path string `json:"path"` // Path from the root of the chart.
Content string `json:"content"` // Base64 encoded file content.
}
// Chart is our internal representation of the chart.yaml (in structured form) + all supporting files.
type Chart struct {
Name string `json:"name"`
Expander *Expander `json:"expander"`
Schema interface{} `json:"schema"`
Files []*ChartFile `json:"files"`
}
// Template describes a set of resources to be deployed.
// Manager expands a Template into a Configuration, which
// describes the set in a form that can be instantiated.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment