diff --git a/README.md b/README.md index 3aab6ef08..1ceae5fc6 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,6 @@ # tiller helmd + +# Runtime Requirements + +- kubectl 1.2 or later diff --git a/_proto/helm.proto b/_proto/helm.proto index c14fc00b1..bf6f4bbeb 100644 --- a/_proto/helm.proto +++ b/_proto/helm.proto @@ -20,3 +20,13 @@ message PingRequest { message PingResponse { string status = 1; } + +message Chart { + string name = 1; +} +message Values { + string name = 1; +} +message Release { + string name = 1; +} diff --git a/cmd/tiller/environment/environment.go b/cmd/tiller/environment/environment.go new file mode 100644 index 000000000..e92eb77cc --- /dev/null +++ b/cmd/tiller/environment/environment.go @@ -0,0 +1,56 @@ +package environment + +import ( + "github.com/deis/tiller/pkg/hapi" +) + +// EngineYard maps engine names to engine implementations. +type EngineYard map[string]Engine + +func (y EngineYard) Get(k string) (Engine, bool) { + e, ok := y[k] + return e, ok +} + +// Engine represents a template engine that can render templates. +// +// For some engines, "rendering" includes both compiling and executing. (Other +// engines do not distinguish between phases.) +// +// 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) ([]byte, error) +} + +// ReleaseStorage represents a storage engine for a Release. +// +// Release storage must be concurrency safe. +type ReleaseStorage interface { + Get(key string) (*hapi.Release, error) + Set(key string, val *hapi.Release) error +} + +// KubeClient represents a client capable of communicating with the Kubernetes API. +// +// A KubeClient must be concurrency safe. +type KubeClient interface { + Install(manifest []byte) error +} + +// Environment provides the context for executing a client request. +// +// All services in a context are concurrency safe. +type Environment struct { + // EngineYard provides access to the known template engines. + EngineYard EngineYard + // Releases stores records of releases. + Releases ReleaseStorage + // KubeClient is a Kubernetes API client. + KubeClient KubeClient +} + +// New returns an environment initialized with the defaults. +func New() *Environment { + return &Environment{} +} diff --git a/cmd/tiller/environment/environment_test.go b/cmd/tiller/environment/environment_test.go new file mode 100644 index 000000000..d265fd26a --- /dev/null +++ b/cmd/tiller/environment/environment_test.go @@ -0,0 +1,32 @@ +package environment + +import ( + "testing" + + "github.com/deis/tiller/pkg/hapi" +) + +type mockEngine struct { + out []byte +} + +func (e *mockEngine) Render(chrt *hapi.Chart, v *hapi.Values) ([]byte, error) { + return e.out, nil +} + +var _ Engine = &mockEngine{} + +func TestEngine(t *testing.T) { + eng := &mockEngine{out: []byte("test")} + + env := New() + env.EngineYard = EngineYard(map[string]Engine{"test": eng}) + + 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 { + t.Errorf("unexpected template error: %s", err) + } else if string(out) != "test" { + t.Errorf("expected 'test', got %q", string(out)) + } +} diff --git a/docs/developers.md b/docs/developers.md index c6975f6b8..73edcfa52 100644 --- a/docs/developers.md +++ b/docs/developers.md @@ -5,6 +5,11 @@ Helm and Tiller. ## Prerequisites +- Go 1.6.0 or later +- kubectl 1.2 or later +- A Kubernetes cluster (optional) +- The gRPC toolchain + Tiller uses gRPC. To get started with gRPC, you will need to... - Install `protoc` for compiling protobuf files. Releases are diff --git a/pkg/hapi/helm.pb.go b/pkg/hapi/helm.pb.go index e0f45463c..f8dd39fff 100644 --- a/pkg/hapi/helm.pb.go +++ b/pkg/hapi/helm.pb.go @@ -13,6 +13,9 @@ It is generated from these files: It has these top-level messages: PingRequest PingResponse + Chart + Values + Release */ package hapi @@ -54,9 +57,39 @@ func (m *PingResponse) String() string { return proto.CompactTextStri func (*PingResponse) ProtoMessage() {} func (*PingResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +type Chart struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *Chart) Reset() { *m = Chart{} } +func (m *Chart) String() string { return proto.CompactTextString(m) } +func (*Chart) ProtoMessage() {} +func (*Chart) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +type Values struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *Values) Reset() { *m = Values{} } +func (m *Values) String() string { return proto.CompactTextString(m) } +func (*Values) ProtoMessage() {} +func (*Values) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +type Release struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *Release) Reset() { *m = Release{} } +func (m *Release) String() string { return proto.CompactTextString(m) } +func (*Release) ProtoMessage() {} +func (*Release) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + func init() { proto.RegisterType((*PingRequest)(nil), "hapi.PingRequest") proto.RegisterType((*PingResponse)(nil), "hapi.PingResponse") + proto.RegisterType((*Chart)(nil), "hapi.Chart") + proto.RegisterType((*Values)(nil), "hapi.Values") + proto.RegisterType((*Release)(nil), "hapi.Release") } // Reference imports to suppress errors if they are not otherwise used. @@ -127,15 +160,17 @@ var _Probe_serviceDesc = grpc.ServiceDesc{ } var fileDescriptor0 = []byte{ - // 149 bytes of a gzipped FileDescriptorProto + // 182 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xca, 0x48, 0xcd, 0xc9, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xc9, 0x48, 0x2c, 0xc8, 0x54, 0x52, 0xe4, 0xe2, 0x0e, 0xc8, 0xcc, 0x4b, 0x0f, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0x12, 0xe2, 0x62, 0xc9, 0x4b, 0xcc, 0x4d, 0x95, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0xb3, 0x95, 0xd4, 0xb8, 0x78, 0x20, 0x4a, 0x8a, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x85, 0xc4, 0xb8, 0xd8, 0x8a, 0x4b, 0x12, 0x4b, - 0x4a, 0x8b, 0xa1, 0xaa, 0xa0, 0x3c, 0x23, 0x4b, 0x2e, 0xd6, 0x80, 0xa2, 0xfc, 0xa4, 0x54, 0x21, - 0x03, 0x2e, 0xd6, 0xa0, 0xd4, 0xc4, 0x94, 0x4a, 0x21, 0x41, 0x3d, 0x90, 0x1d, 0x7a, 0x48, 0x16, - 0x48, 0x09, 0x21, 0x0b, 0x41, 0x0c, 0x54, 0x62, 0x70, 0xe2, 0xe4, 0x62, 0x2f, 0xce, 0xd0, 0x03, - 0x39, 0x2e, 0x89, 0x0d, 0xec, 0x3a, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x04, 0x87, 0x54, - 0xa0, 0xab, 0x00, 0x00, 0x00, + 0x4a, 0x8b, 0xa1, 0xaa, 0xa0, 0x3c, 0x25, 0x69, 0x2e, 0x56, 0xe7, 0x8c, 0xc4, 0x22, 0xec, 0x86, + 0xc8, 0x70, 0xb1, 0x85, 0x25, 0xe6, 0x00, 0xed, 0xc0, 0x2a, 0x2b, 0xcb, 0xc5, 0x1e, 0x94, 0x9a, + 0x93, 0x9a, 0x08, 0x34, 0x1d, 0x8b, 0xb4, 0x91, 0x25, 0x17, 0x6b, 0x40, 0x51, 0x7e, 0x52, 0xaa, + 0x90, 0x01, 0x17, 0x6b, 0x50, 0x6a, 0x62, 0x4a, 0xa5, 0x90, 0xa0, 0x1e, 0xc8, 0xf5, 0x7a, 0x48, + 0x4e, 0x97, 0x12, 0x42, 0x16, 0x82, 0x38, 0x55, 0x89, 0xc1, 0x89, 0x93, 0x8b, 0xbd, 0x38, 0x43, + 0x0f, 0xe4, 0xed, 0x24, 0x36, 0xb0, 0xbf, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x1e, 0x2f, + 0xf3, 0xed, 0x05, 0x01, 0x00, 0x00, }