Merge pull request #1 from technosophos/feat/grpc

feat(cmd): add grpc client and server
pull/613/head
Matt Butcher 8 years ago
commit 8948bf74ec

1
.gitignore vendored

@ -0,0 +1 @@
vendor/

@ -1,2 +1,6 @@
# tiller
helmd
# Runtime Requirements
- kubectl 1.2 or later

@ -0,0 +1,32 @@
syntax = "proto3";
option java_package = "sh.helm";
// hapi: The Helm API
package hapi;
// Probe is used to check liveness and readiness.
service Probe {
// Run a readiness test.
rpc Ready (PingRequest) returns (PingResponse) {}
}
// The readiness test request.
message PingRequest {
string name = 1;
}
// The readiness test response.
message PingResponse {
string status = 1;
}
message Chart {
string name = 1;
}
message Values {
string name = 1;
}
message Release {
string name = 1;
}

@ -0,0 +1,40 @@
package main
import (
"fmt"
"os"
"github.com/codegangsta/cli"
"github.com/deis/tiller/pkg/hapi"
ctx "golang.org/x/net/context"
"google.golang.org/grpc"
)
func main() {
app := cli.NewApp()
app.Name = "helmet"
app.Usage = "The Helm Easy Tester (HelmET)"
app.Action = run
app.Run(os.Args)
}
func run(c *cli.Context) {
conn, err := grpc.Dial("localhost:44134", grpc.WithInsecure())
if err != nil {
fmt.Fprintf(os.Stderr, "Could not connect to server: %s\n", err)
os.Exit(1)
}
defer conn.Close()
pc := hapi.NewProbeClient(conn)
req := &hapi.PingRequest{Name: "helmet"}
res, err := pc.Ready(ctx.Background(), req)
if err != nil {
fmt.Fprintf(os.Stderr, "Error pinging server: %s\n", err)
os.Exit(1)
}
fmt.Printf("Server is %s\n", res.Status)
}

@ -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{}
}

@ -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))
}
}

@ -0,0 +1,30 @@
package main
import (
"net"
"github.com/deis/tiller/pkg/hapi"
ctx "golang.org/x/net/context"
"google.golang.org/grpc"
)
type server struct{}
func (s *server) Ready(c ctx.Context, req *hapi.PingRequest) (*hapi.PingResponse, error) {
return &hapi.PingResponse{Status: "OK"}, nil
}
func startServer(addr string) error {
lstn, err := net.Listen("tcp", addr)
if err != nil {
return nil
}
hserver := &server{}
srv := grpc.NewServer()
hapi.RegisterProbeServer(srv, hserver)
srv.Serve(lstn)
return nil
}

@ -0,0 +1,24 @@
package main
import (
"fmt"
"os"
"github.com/codegangsta/cli"
)
func main() {
app := cli.NewApp()
app.Name = "tiller"
app.Usage = `The Helm server.`
app.Action = start
app.Run(os.Args)
}
func start(c *cli.Context) {
if err := startServer(":44134"); err != nil {
fmt.Fprintf(os.Stderr, "Server died: %s\n", err)
os.Exit(1)
}
}

@ -0,0 +1,26 @@
# Developers Guide
This guide explains how to set up your environment for developing on
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
[here](https://github.com/google/protobuf/releases)
- Install the protoc Go plugin: `go get -u github.com/golang/protobuf/protoc-gen-go`
Note that you need to be on protobuf 3.x (`protoc --version`) and use the latest Go plugin.
## The Helm API (HAPI)
We use gRPC as an API layer. See `pkg/hapi` for the generated Go code,
and `_proto` for the protocol buffer definitions.
To regenerate `hapi`, use `go generate pkg/hapi`.

29
glide.lock generated

@ -0,0 +1,29 @@
hash: 9bf35c0cd5fd9a87324b8b410499579fd983072338d8b6522987b630353bf986
updated: 2016-04-11T15:22:12.013812164-06:00
imports:
- name: github.com/codegangsta/cli
version: 71f57d300dd6a780ac1856c005c4b518cfd498ec
- name: github.com/golang/protobuf
version: dda510ac0fd43b39770f22ac6260eb91d377bce3
subpackages:
- proto
- name: golang.org/x/net
version: 589fda73dd0faec3dc59e7d7dab5b069e3fce0f9
subpackages:
- context
- http2
- trace
- http2/hpack
- internal/timeseries
- name: google.golang.org/grpc
version: d07d0562ffca36dd7ee333b5d236209f98fe9ba0
subpackages:
- codes
- credentials
- grpclog
- internal
- metadata
- naming
- transport
- peer
devImports: []

@ -0,0 +1,6 @@
package: github.com/deis/tiller
import:
- package: google.golang.org/grpc
- package: golang.org/x/net
subpackages:
- context

@ -0,0 +1,10 @@
//go:generate protoc -I ../../_proto ../../_proto/helm.proto --go_out=plugins=grpc:.
/*Package hapi contains the Helm API (HAPI).
Helm uses gRPC to handle communication between client and server. This package
contains the definitions of the API objeccts.
The files in this package that end with the extension *.pb.go are automatically
generated by Protobuf for use with gRPC.
*/
package hapi

@ -0,0 +1,176 @@
// Code generated by protoc-gen-go.
// source: helm.proto
// DO NOT EDIT!
/*
Package hapi is a generated protocol buffer package.
hapi: The Helm API
It is generated from these files:
helm.proto
It has these top-level messages:
PingRequest
PingResponse
Chart
Values
Release
*/
package hapi
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
const _ = proto.ProtoPackageIsVersion1
// The readiness test request.
type PingRequest struct {
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
}
func (m *PingRequest) Reset() { *m = PingRequest{} }
func (m *PingRequest) String() string { return proto.CompactTextString(m) }
func (*PingRequest) ProtoMessage() {}
func (*PingRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
// The readiness test response.
type PingResponse struct {
Status string `protobuf:"bytes,1,opt,name=status" json:"status,omitempty"`
}
func (m *PingResponse) Reset() { *m = PingResponse{} }
func (m *PingResponse) String() string { return proto.CompactTextString(m) }
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.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion1
// Client API for Probe service
type ProbeClient interface {
// Run a readiness test.
Ready(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error)
}
type probeClient struct {
cc *grpc.ClientConn
}
func NewProbeClient(cc *grpc.ClientConn) ProbeClient {
return &probeClient{cc}
}
func (c *probeClient) Ready(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) {
out := new(PingResponse)
err := grpc.Invoke(ctx, "/hapi.Probe/Ready", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for Probe service
type ProbeServer interface {
// Run a readiness test.
Ready(context.Context, *PingRequest) (*PingResponse, error)
}
func RegisterProbeServer(s *grpc.Server, srv ProbeServer) {
s.RegisterService(&_Probe_serviceDesc, srv)
}
func _Probe_Ready_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(PingRequest)
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(ProbeServer).Ready(ctx, in)
if err != nil {
return nil, err
}
return out, nil
}
var _Probe_serviceDesc = grpc.ServiceDesc{
ServiceName: "hapi.Probe",
HandlerType: (*ProbeServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Ready",
Handler: _Probe_Ready_Handler,
},
},
Streams: []grpc.StreamDesc{},
}
var fileDescriptor0 = []byte{
// 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, 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,
}
Loading…
Cancel
Save