Commit 50f43495 authored by Matt Butcher's avatar Matt Butcher

feat(tiller): add template and release to install

parent d3cff27b
......@@ -18,7 +18,7 @@ message Chart {
hapi.chart.Metadata metadata = 1;
// Templates for this chart.
hapi.chart.Templates templates = 2;
repeated hapi.chart.Template templates = 2;
// Charts that this chart depends on.
repeated Chart dependencies = 3;
......
......@@ -4,20 +4,14 @@ package hapi.chart;
option go_package = "chart";
// Template represents a template as a name/value pair.
//
// Template:
//
// TODO
//
message Templates {
// TODO
repeated Template templates = 1;
}
// By convention, name is a relative path within the scope of the chart's
// base directory.
message Template {
// TODO
string template_name = 1;
// Name is the path-like name of the template.
string name = 1;
// TODO
bytes template_data = 2;
// Data is the template as byte data.
bytes data = 2;
}
......@@ -3,6 +3,7 @@ package environment
import (
"github.com/deis/tiller/pkg/engine"
"github.com/deis/tiller/pkg/hapi"
"github.com/deis/tiller/pkg/proto/hapi/chart"
"github.com/deis/tiller/pkg/storage"
)
......@@ -51,7 +52,7 @@ func (y EngineYard) Default() Engine {
// An Engine must be capable of executing multiple concurrent requests, but
// without tainting one request's environment with data from another request.
type Engine interface {
Render(*hapi.Chart, *hapi.Values) (map[string]string, error)
Render(*chart.Chart, *chart.Config) (map[string]string, error)
}
// ReleaseStorage represents a storage engine for a Release.
......
......@@ -4,13 +4,14 @@ import (
"testing"
"github.com/deis/tiller/pkg/hapi"
"github.com/deis/tiller/pkg/proto/hapi/chart"
)
type mockEngine struct {
out map[string]string
}
func (e *mockEngine) Render(chrt *hapi.Chart, v *hapi.Values) (map[string]string, error) {
func (e *mockEngine) Render(chrt *chart.Chart, v *chart.Config) (map[string]string, error) {
return e.out, nil
}
......@@ -63,7 +64,7 @@ func TestEngine(t *testing.T) {
if engine, ok := env.EngineYard.Get("test"); !ok {
t.Errorf("failed to get engine from EngineYard")
} else if out, err := engine.Render(&hapi.Chart{}, &hapi.Values{}); err != nil {
} else if out, err := engine.Render(&chart.Chart{}, &chart.Config{}); err != nil {
t.Errorf("unexpected template error: %s", err)
} else if out["albatross"] != "test" {
t.Errorf("expected 'test', got %q", out["albatross"])
......
......@@ -4,7 +4,9 @@ import (
"errors"
"github.com/deis/tiller/cmd/tiller/environment"
"github.com/deis/tiller/pkg/proto/hapi/release"
"github.com/deis/tiller/pkg/proto/hapi/services"
"github.com/technosophos/moniker"
ctx "golang.org/x/net/context"
)
......@@ -19,8 +21,11 @@ type releaseServer struct {
env *environment.Environment
}
// errNotImplemented is a temporary error for uninmplemented callbacks.
var errNotImplemented = errors.New("not implemented")
var (
// errNotImplemented is a temporary error for uninmplemented callbacks.
errNotImplemented = errors.New("not implemented")
errMissingChart = errors.New("no chart provided")
)
func (s *releaseServer) ListReleases(req *services.ListReleasesRequest, stream services.ReleaseService_ListReleasesServer) error {
return errNotImplemented
......@@ -39,7 +44,32 @@ func (s *releaseServer) UpdateRelease(c ctx.Context, req *services.UpdateRelease
}
func (s *releaseServer) InstallRelease(c ctx.Context, req *services.InstallReleaseRequest) (*services.InstallReleaseResponse, error) {
return &services.InstallReleaseResponse{}, errNotImplemented
if req.Chart == nil {
return nil, errMissingChart
}
// We should probably make a name generator part of the Environment.
namer := moniker.New()
// TODO: Make sure this is unique.
name := namer.Name()
// Render the templates
_, err := s.env.EngineYard.Default().Render(req.Chart, req.Values)
if err != nil {
return nil, err
}
// Store a release.
r := &release.Release{
Name: name,
Chart: req.Chart,
Config: req.Values,
Info: &release.Info{
Status: &release.Status{Code: release.Status_UNKNOWN},
},
}
return &services.InstallReleaseResponse{Release: r}, errNotImplemented
}
func (s *releaseServer) UninstallRelease(c ctx.Context, req *services.UninstallReleaseRequest) (*services.UninstallReleaseResponse, error) {
......
hash: e7c99013acb06eb359cf20390579af9a4553ef0fbed3f7bbb784b4ab7c8df807
updated: 2016-04-15T15:15:21.87772545-06:00
hash: 264d156a2a07d53efbf5f608ead3eb31c261de5124e0235139b3f99c6ead4dba
updated: 2016-04-18T17:25:07.662942088-06:00
imports:
- name: github.com/aokoli/goutils
version: 9c37978a95bd5c709a15883b6242714ea6709e64
......@@ -11,6 +11,8 @@ imports:
version: f0a097ddac24fb00e07d2ac17f8671423f3ea47c
subpackages:
- proto
- ptypes/any
- ptypes/timestamp
- name: github.com/Masterminds/semver
version: 808ed7761c233af2de3f9729a041d68c62527f3a
- name: github.com/Masterminds/sprig
......@@ -21,6 +23,8 @@ imports:
- cobra
- name: github.com/spf13/pflag
version: 8f6a28b0916586e7f22fe931ae2fcfc380b1c0e6
- name: github.com/technosophos/moniker
version: 9f956786b91d9786ca11aa5be6104542fa911546
- name: golang.org/x/net
version: fb93926129b8ec0056f2f458b1f519654814edf0
subpackages:
......@@ -30,7 +34,7 @@ imports:
- http2/hpack
- internal/timeseries
- name: google.golang.org/grpc
version: 8eeecf2291de9d171d0b1392a27ff3975679f4f5
version: dec33edc378cf4971a2741cfd86ed70a644d6ba3
subpackages:
- codes
- credentials
......
......@@ -13,3 +13,4 @@ import:
- package: github.com/Masterminds/semver
version: 1.1.0
- package: github.com/BurntSushi/toml
- package: github.com/technosophos/moniker
......@@ -6,7 +6,8 @@ import (
"text/template"
"github.com/Masterminds/sprig"
"github.com/deis/tiller/pkg/hapi"
chartutil "github.com/deis/tiller/pkg/chart"
"github.com/deis/tiller/pkg/proto/hapi/chart"
)
// Engine is an implementation of 'cmd/tiller/environment'.Engine that uses Go templates.
......@@ -38,13 +39,41 @@ func New() *Engine {
//
// This will look in the chart's 'templates' data (e.g. the 'templates/' directory)
// and attempt to render the templates there using the values passed in.
func (e *Engine) Render(chart *hapi.Chart, vals *hapi.Values) (map[string]string, error) {
// Uncomment this once the proto files compile.
//return render(chart.Chartfile.Name, chart.Templates, vals)
return map[string]string{}, nil
func (e *Engine) Render(chrt *chart.Chart, vals *chart.Config) (map[string]string, error) {
var cvals chartutil.Values
if chrt.Values == nil {
cvals = map[string]interface{}{}
} else {
var err error
cvals, err = chartutil.ReadValues([]byte(chrt.Values.Raw))
if err != nil {
return map[string]string{}, err
}
}
// Parse values if not nil
if vals != nil {
evals, err := chartutil.ReadValues([]byte(vals.Raw))
if err != nil {
return map[string]string{}, err
}
// Coalesce chart default values and values
for k, v := range evals {
// FIXME: This needs to merge tables. Ideally, this feature should
// be part of the Values type.
cvals[k] = v
}
}
// Render the charts
tmap := make(map[string]string, len(chrt.Templates))
for _, tpl := range chrt.Templates {
tmap[tpl.Name] = string(tpl.Data)
}
return e.render(tmap, cvals)
}
func (e *Engine) render(name string, tpls map[string]string, v interface{}) (map[string]string, error) {
func (e *Engine) render(tpls map[string]string, v interface{}) (map[string]string, error) {
// Basically, what we do here is start with an empty parent template and then
// build up a list of templates -- one for each file. Once all of the templates
// have been parsed, we loop through again and execute every template.
......@@ -52,7 +81,7 @@ func (e *Engine) render(name string, tpls map[string]string, v interface{}) (map
// The idea with this process is to make it possible for more complex templates
// to share common blocks, but to make the entire thing feel like a file-based
// template engine.
t := template.New(name)
t := template.New("gotpl")
files := []string{}
for fname, tpl := range tpls {
t = t.New(fname).Funcs(e.FuncMap)
......
......@@ -35,7 +35,7 @@ func TestRenderInternals(t *testing.T) {
}
vals := map[string]string{"Name": "one", "Value": "two"}
out, err := e.render("irrelevant", tpls, vals)
out, err := e.render(tpls, vals)
if err != nil {
t.Fatalf("Failed template rendering: %s", err)
}
......@@ -68,7 +68,7 @@ func TestParallelRenderInternals(t *testing.T) {
tt := fmt.Sprintf("expect-%d", i)
tpls := map[string]string{fname: `{{.val}}`}
v := map[string]string{"val": tt}
out, err := e.render("intentionally_duplicated", tpls, v)
out, err := e.render(tpls, v)
if err != nil {
t.Errorf("Failed to render %s: %s", tt, err)
}
......
......@@ -16,7 +16,6 @@ It has these top-level messages:
Config
Maintainer
Metadata
Templates
Template
*/
package chart
......@@ -43,7 +42,7 @@ type Chart struct {
// Contents of the Chartfile.
Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata" json:"metadata,omitempty"`
// Templates for this chart.
Templates *Templates `protobuf:"bytes,2,opt,name=templates" json:"templates,omitempty"`
Templates []*Template `protobuf:"bytes,2,rep,name=templates" json:"templates,omitempty"`
// Charts that this chart depends on.
Dependencies []*Chart `protobuf:"bytes,3,rep,name=dependencies" json:"dependencies,omitempty"`
// Default config for this template.
......@@ -62,7 +61,7 @@ func (m *Chart) GetMetadata() *Metadata {
return nil
}
func (m *Chart) GetTemplates() *Templates {
func (m *Chart) GetTemplates() []*Template {
if m != nil {
return m.Templates
}
......@@ -88,18 +87,18 @@ func init() {
}
var fileDescriptor0 = []byte{
// 200 bytes of a gzipped FileDescriptorProto
// 197 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x12, 0xcb, 0x48, 0x2c, 0xc8,
0xd4, 0x4f, 0xce, 0x48, 0x2c, 0x2a, 0x81, 0x90, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0x5c,
0x20, 0x71, 0x3d, 0xb0, 0x88, 0x94, 0x38, 0xb2, 0x9a, 0xfc, 0xbc, 0xb4, 0xcc, 0x74, 0x88, 0x22,
0x29, 0x49, 0x24, 0x89, 0xdc, 0xd4, 0x92, 0xc4, 0x94, 0xc4, 0x92, 0x44, 0x2c, 0x52, 0x25, 0xa9,
0xb9, 0x05, 0x39, 0x89, 0x25, 0xa9, 0x10, 0x29, 0xa5, 0x8b, 0x8c, 0x5c, 0xac, 0xce, 0x20, 0x09,
0xb9, 0x05, 0x39, 0x89, 0x25, 0xa9, 0x10, 0x29, 0xa5, 0x0b, 0x8c, 0x5c, 0xac, 0xce, 0x20, 0x09,
0x21, 0x03, 0x2e, 0x0e, 0x98, 0x36, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x6e, 0x23, 0x11, 0x3d, 0x84,
0xbd, 0x7a, 0xbe, 0x50, 0xb9, 0x20, 0xb8, 0x2a, 0x21, 0x63, 0x2e, 0x4e, 0x98, 0x69, 0xc5, 0x12,
0x4c, 0x60, 0x2d, 0xa2, 0xc8, 0x5a, 0x42, 0x60, 0x92, 0x41, 0x08, 0x75, 0x42, 0xa6, 0x5c, 0x3c,
0x29, 0xa9, 0x05, 0xa9, 0x79, 0x29, 0xa9, 0x79, 0xc9, 0x99, 0x40, 0x7d, 0xcc, 0x0a, 0xcc, 0x40,
0x7d, 0x82, 0xc8, 0xfa, 0xc0, 0xee, 0x09, 0x42, 0x51, 0x26, 0xa4, 0xc5, 0xc5, 0x56, 0x96, 0x98,
0x53, 0x0a, 0xd4, 0xc0, 0x02, 0xb6, 0x48, 0x08, 0x45, 0x03, 0x38, 0x1c, 0x82, 0xa0, 0x2a, 0x9c,
0xd8, 0xa3, 0x58, 0xc1, 0xe2, 0x49, 0x6c, 0x60, 0x3f, 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff,
0x12, 0xa6, 0x6a, 0xa8, 0x58, 0x01, 0x00, 0x00,
0xbd, 0x7a, 0xbe, 0x50, 0xb9, 0x20, 0xb8, 0x2a, 0x21, 0x23, 0x2e, 0x4e, 0x98, 0x69, 0xc5, 0x12,
0x4c, 0x0a, 0xcc, 0xe8, 0x5a, 0x42, 0xa0, 0x92, 0x41, 0x08, 0x65, 0x42, 0xa6, 0x5c, 0x3c, 0x29,
0xa9, 0x05, 0xa9, 0x79, 0x29, 0xa9, 0x79, 0xc9, 0x99, 0x40, 0x6d, 0xcc, 0x60, 0x6d, 0x82, 0xc8,
0xda, 0xc0, 0xce, 0x09, 0x42, 0x51, 0x26, 0xa4, 0xc5, 0xc5, 0x56, 0x96, 0x98, 0x53, 0x0a, 0xd4,
0xc0, 0x02, 0x76, 0x9a, 0x10, 0x8a, 0x06, 0x70, 0x30, 0x04, 0x41, 0x55, 0x38, 0xb1, 0x47, 0xb1,
0x82, 0xc5, 0x93, 0xd8, 0xc0, 0x5e, 0x34, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xb5, 0xff, 0x0f,
0xec, 0x57, 0x01, 0x00, 0x00,
}
......@@ -13,55 +13,33 @@ var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// Template represents a template as a name/value pair.
//
// Template:
//
// TODO
//
type Templates struct {
// TODO
Templates []*Template `protobuf:"bytes,1,rep,name=templates" json:"templates,omitempty"`
}
func (m *Templates) Reset() { *m = Templates{} }
func (m *Templates) String() string { return proto.CompactTextString(m) }
func (*Templates) ProtoMessage() {}
func (*Templates) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0} }
func (m *Templates) GetTemplates() []*Template {
if m != nil {
return m.Templates
}
return nil
}
// By convention, name is a relative path within the scope of the chart's
// base directory.
type Template struct {
// TODO
TemplateName string `protobuf:"bytes,1,opt,name=template_name,json=templateName" json:"template_name,omitempty"`
// TODO
TemplateData []byte `protobuf:"bytes,2,opt,name=template_data,json=templateData,proto3" json:"template_data,omitempty"`
// Name is the path-like name of the template.
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
// Data is the template as byte data.
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
}
func (m *Template) Reset() { *m = Template{} }
func (m *Template) String() string { return proto.CompactTextString(m) }
func (*Template) ProtoMessage() {}
func (*Template) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{1} }
func (*Template) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0} }
func init() {
proto.RegisterType((*Templates)(nil), "hapi.chart.Templates")
proto.RegisterType((*Template)(nil), "hapi.chart.Template")
}
var fileDescriptor3 = []byte{
// 146 bytes of a gzipped FileDescriptorProto
// 106 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x92, 0xcc, 0x48, 0x2c, 0xc8,
0xd4, 0x4f, 0xce, 0x48, 0x2c, 0x2a, 0xd1, 0x2f, 0x49, 0xcd, 0x2d, 0xc8, 0x49, 0x2c, 0x49, 0xd5,
0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x02, 0x49, 0xe9, 0x81, 0xa5, 0x94, 0xec, 0xb9, 0x38,
0x43, 0xa0, 0xb2, 0xc5, 0x42, 0x46, 0x5c, 0x9c, 0x30, 0xa5, 0xc5, 0x12, 0x8c, 0x0a, 0xcc, 0x1a,
0xdc, 0x46, 0x22, 0x7a, 0x08, 0xc5, 0x7a, 0x30, 0x95, 0x41, 0x08, 0x65, 0x4a, 0x21, 0x5c, 0x1c,
0x30, 0x61, 0x21, 0x65, 0x2e, 0x5e, 0x98, 0x44, 0x7c, 0x5e, 0x62, 0x6e, 0x2a, 0xd0, 0x0c, 0x46,
0x0d, 0xce, 0x20, 0x1e, 0x98, 0xa0, 0x1f, 0x50, 0x0c, 0x45, 0x51, 0x4a, 0x62, 0x49, 0xa2, 0x04,
0x13, 0x50, 0x11, 0x0f, 0x42, 0x91, 0x0b, 0x50, 0xcc, 0x89, 0x3d, 0x8a, 0x15, 0x6c, 0x65, 0x12,
0x1b, 0xd8, 0xc9, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x48, 0xda, 0x77, 0x0e, 0xcf, 0x00,
0x00, 0x00,
0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x02, 0x49, 0xe9, 0x81, 0xa5, 0x94, 0x8c, 0xb8, 0x38,
0x42, 0xa0, 0xb2, 0x42, 0x42, 0x5c, 0x2c, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a,
0x9c, 0x41, 0x60, 0x36, 0x48, 0x2c, 0x25, 0xb1, 0x24, 0x51, 0x82, 0x09, 0x28, 0xc6, 0x13, 0x04,
0x66, 0x3b, 0xb1, 0x47, 0xb1, 0x82, 0x35, 0x27, 0xb1, 0x81, 0xcd, 0x33, 0x06, 0x04, 0x00, 0x00,
0xff, 0xff, 0x53, 0xee, 0x0e, 0x67, 0x6c, 0x00, 0x00, 0x00,
}
Markdown is supported
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