From 0868355d3ec4ef5b4784b732056e7dc148b27784 Mon Sep 17 00:00:00 2001
From: Matt Butcher <mbutcher@engineyard.com>
Date: Fri, 8 Apr 2016 16:41:21 -0600
Subject: [PATCH] feat(cmd): add grpc client and server

So far, they just have basic readiness checks.
---
 .gitignore           |   1 +
 _proto/helm.proto    |  22 +++++++
 cmd/helmet/helmet.go |  40 ++++++++++++
 cmd/tiller/server.go |  30 +++++++++
 cmd/tiller/tiller.go |  24 ++++++++
 docs/developers.md   |  21 +++++++
 glide.lock           |  49 +++++++++++++++
 glide.yaml           |   6 ++
 pkg/hapi/doc.go      |  10 +++
 pkg/hapi/helm.pb.go  | 141 +++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 344 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 _proto/helm.proto
 create mode 100644 cmd/helmet/helmet.go
 create mode 100644 cmd/tiller/server.go
 create mode 100644 cmd/tiller/tiller.go
 create mode 100644 docs/developers.md
 create mode 100644 glide.lock
 create mode 100644 glide.yaml
 create mode 100644 pkg/hapi/doc.go
 create mode 100644 pkg/hapi/helm.pb.go

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..48b8bf907
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+vendor/
diff --git a/_proto/helm.proto b/_proto/helm.proto
new file mode 100644
index 000000000..c14fc00b1
--- /dev/null
+++ b/_proto/helm.proto
@@ -0,0 +1,22 @@
+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;
+}
diff --git a/cmd/helmet/helmet.go b/cmd/helmet/helmet.go
new file mode 100644
index 000000000..02fe1e450
--- /dev/null
+++ b/cmd/helmet/helmet.go
@@ -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)
+}
diff --git a/cmd/tiller/server.go b/cmd/tiller/server.go
new file mode 100644
index 000000000..1ccb3abfc
--- /dev/null
+++ b/cmd/tiller/server.go
@@ -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
+}
diff --git a/cmd/tiller/tiller.go b/cmd/tiller/tiller.go
new file mode 100644
index 000000000..5fb3b524b
--- /dev/null
+++ b/cmd/tiller/tiller.go
@@ -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)
+	}
+}
diff --git a/docs/developers.md b/docs/developers.md
new file mode 100644
index 000000000..c6975f6b8
--- /dev/null
+++ b/docs/developers.md
@@ -0,0 +1,21 @@
+# Developers Guide
+
+This guide explains how to set up your environment for developing on
+Helm and Tiller.
+
+## Prerequisites
+
+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`.
diff --git a/glide.lock b/glide.lock
new file mode 100644
index 000000000..414732a28
--- /dev/null
+++ b/glide.lock
@@ -0,0 +1,49 @@
+hash: 9bf35c0cd5fd9a87324b8b410499579fd983072338d8b6522987b630353bf986
+updated: 2016-04-08T15:50:43.442411072-06:00
+imports:
+- name: github.com/aokoli/goutils
+  version: 45307ec16e3cd47cd841506c081f7afd8237d210
+- name: github.com/cloudfoundry-incubator/candiedyaml
+  version: 5cef21e2e4f0fd147973b558d4db7395176bcd95
+- name: github.com/codegangsta/cli
+  version: 71f57d300dd6a780ac1856c005c4b518cfd498ec
+- name: github.com/ghodss/yaml
+  version: 1a6f069841556a7bcaff4a397ca6e8328d266c2f
+- name: github.com/golang/protobuf
+  version: dda510ac0fd43b39770f22ac6260eb91d377bce3
+  subpackages:
+  - proto
+- name: github.com/kubernetes/helm
+  version: d11dd488257d4ed3f5c861b9ca8d35cd3b49fa75
+  subpackages:
+  - pkg/log
+  - pkg/common
+  - pkg/httputil
+  - pkg/kubectl
+  - pkg/version
+- name: github.com/Masterminds/semver
+  version: 7e56b5cd00f9666fc899aa9c11c9a7d51f2a9995
+- name: github.com/Masterminds/sprig
+  version: 679bb747f11c6ffc3373965988fea8877c40b47b
+- name: golang.org/x/net
+  version: e45385e9b226f570b1f086bf287b25d3d4117776
+  subpackages:
+  - context
+  - http2
+  - trace
+  - http2/hpack
+  - internal/timeseries
+- name: google.golang.org/grpc
+  version: 7834b974e55fbf85a5b01afb5821391c71084efd
+  subpackages:
+  - codes
+  - credentials
+  - grpclog
+  - internal
+  - metadata
+  - naming
+  - transport
+  - peer
+- name: gopkg.in/yaml.v2
+  version: a83829b6f1293c91addabc89d0571c246397bbf4
+devImports: []
diff --git a/glide.yaml b/glide.yaml
new file mode 100644
index 000000000..29d5af970
--- /dev/null
+++ b/glide.yaml
@@ -0,0 +1,6 @@
+package: github.com/deis/tiller
+import:
+- package: google.golang.org/grpc
+- package: golang.org/x/net
+  subpackages:
+  - context
diff --git a/pkg/hapi/doc.go b/pkg/hapi/doc.go
new file mode 100644
index 000000000..9f0ff7828
--- /dev/null
+++ b/pkg/hapi/doc.go
@@ -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
diff --git a/pkg/hapi/helm.pb.go b/pkg/hapi/helm.pb.go
new file mode 100644
index 000000000..e0f45463c
--- /dev/null
+++ b/pkg/hapi/helm.pb.go
@@ -0,0 +1,141 @@
+// 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
+*/
+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} }
+
+func init() {
+	proto.RegisterType((*PingRequest)(nil), "hapi.PingRequest")
+	proto.RegisterType((*PingResponse)(nil), "hapi.PingResponse")
+}
+
+// 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{
+	// 149 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,
+}
-- 
GitLab