浏览代码

Add initial backend proto and example

Signed-off-by: Michael Crosby <[email protected]>
Michael Crosby 5 年之前
父节点
当前提交
bae830a1b1
共有 7 个文件被更改,包括 405 次插入1 次删除
  1. 1 0
      .gitignore
  2. 6 1
      Makefile
  3. 9 0
      README.md
  4. 172 0
      backend/v1/backend.pb.go
  5. 49 0
      client/client.go
  6. 112 0
      example/backend/main.go
  7. 56 0
      server/server.go

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+bin/

+ 6 - 1
Makefile

@@ -27,11 +27,16 @@ PACKAGES=$(shell go list ./... | grep -v /vendor/)
 GIT_COMMIT=$(shell git rev-parse --short HEAD)
 GOOS ?= $(shell go env GOOS)
 
+export GO111MODULE=off
+
 all: protos
 
 protos:
 	@protobuild --quiet ${PACKAGES}
 
+example:
+	cd example/backend && go build -v -o ../../bin/backend-example
+
 FORCE:
 
-.PHONY: protos
+.PHONY: protos example

+ 9 - 0
README.md

@@ -10,3 +10,12 @@ to install the correct version of protobufs on your system and get the protobuil
 ```bash
 > make
 ```
+
+## Build the example backend
+
+The example backend code is located in `/example/backend`.
+Build the service with the resulting binary placed in the `/bin` directory.
+
+```bash
+> make example
+```

+ 172 - 0
backend/v1/backend.pb.go

@@ -0,0 +1,172 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: github.com/docker/api/backend/v1/backend.proto
+
+package v1
+
+import (
+	context "context"
+	fmt "fmt"
+	proto "github.com/gogo/protobuf/proto"
+	types "github.com/gogo/protobuf/types"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+	math "math"
+)
+
+// 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.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type BackendInformationResponse struct {
+	ID                   string   `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *BackendInformationResponse) Reset()         { *m = BackendInformationResponse{} }
+func (m *BackendInformationResponse) String() string { return proto.CompactTextString(m) }
+func (*BackendInformationResponse) ProtoMessage()    {}
+func (*BackendInformationResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_511f43e0e6c515ac, []int{0}
+}
+func (m *BackendInformationResponse) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_BackendInformationResponse.Unmarshal(m, b)
+}
+func (m *BackendInformationResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_BackendInformationResponse.Marshal(b, m, deterministic)
+}
+func (m *BackendInformationResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_BackendInformationResponse.Merge(m, src)
+}
+func (m *BackendInformationResponse) XXX_Size() int {
+	return xxx_messageInfo_BackendInformationResponse.Size(m)
+}
+func (m *BackendInformationResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_BackendInformationResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_BackendInformationResponse proto.InternalMessageInfo
+
+func (m *BackendInformationResponse) GetID() string {
+	if m != nil {
+		return m.ID
+	}
+	return ""
+}
+
+func init() {
+	proto.RegisterType((*BackendInformationResponse)(nil), "com.docker.api.backend.v1.BackendInformationResponse")
+}
+
+func init() {
+	proto.RegisterFile("github.com/docker/api/backend/v1/backend.proto", fileDescriptor_511f43e0e6c515ac)
+}
+
+var fileDescriptor_511f43e0e6c515ac = []byte{
+	// 218 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x4b, 0xcf, 0x2c, 0xc9,
+	0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xc9, 0x4f, 0xce, 0x4e, 0x2d, 0xd2, 0x4f, 0x2c,
+	0xc8, 0xd4, 0x4f, 0x4a, 0x4c, 0xce, 0x4e, 0xcd, 0x4b, 0xd1, 0x2f, 0x33, 0x84, 0x31, 0xf5, 0x0a,
+	0x8a, 0xf2, 0x4b, 0xf2, 0x85, 0x24, 0x93, 0xf3, 0x73, 0xf5, 0x20, 0x0a, 0xf5, 0x12, 0x0b, 0x32,
+	0xf5, 0x60, 0xb2, 0x65, 0x86, 0x52, 0x22, 0xe9, 0xf9, 0xe9, 0xf9, 0x60, 0x55, 0xfa, 0x20, 0x16,
+	0x44, 0x83, 0x94, 0x74, 0x7a, 0x7e, 0x7e, 0x7a, 0x4e, 0xaa, 0x3e, 0x98, 0x97, 0x54, 0x9a, 0xa6,
+	0x9f, 0x9a, 0x5b, 0x50, 0x52, 0x09, 0x91, 0x54, 0x32, 0xe1, 0x92, 0x72, 0x82, 0x18, 0xe0, 0x99,
+	0x97, 0x96, 0x5f, 0x94, 0x9b, 0x58, 0x92, 0x99, 0x9f, 0x17, 0x94, 0x5a, 0x5c, 0x90, 0x9f, 0x57,
+	0x9c, 0x2a, 0x24, 0xc6, 0xc5, 0x94, 0x99, 0x22, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0xe9, 0xc4, 0xf6,
+	0xe8, 0x9e, 0x3c, 0x93, 0xa7, 0x4b, 0x10, 0x53, 0x66, 0x8a, 0x51, 0x1e, 0x17, 0x3b, 0x54, 0x97,
+	0x50, 0x32, 0x97, 0x10, 0xa6, 0x01, 0x42, 0x62, 0x7a, 0x10, 0x4b, 0xf5, 0x60, 0x96, 0xea, 0xb9,
+	0x82, 0x2c, 0x95, 0x32, 0xd5, 0xc3, 0xe9, 0x7a, 0x3d, 0xdc, 0xee, 0x70, 0x52, 0x8d, 0x52, 0x26,
+	0x14, 0x4a, 0xd6, 0x65, 0x86, 0x11, 0x0c, 0x49, 0x6c, 0x60, 0xfb, 0x8c, 0x01, 0x01, 0x00, 0x00,
+	0xff, 0xff, 0x3d, 0x73, 0x02, 0xd8, 0x55, 0x01, 0x00, 0x00,
+}
+
+// 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.SupportPackageIsVersion4
+
+// BackendClient is the client API for Backend service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type BackendClient interface {
+	// BackendInformation returns implementation specific information on the backend.
+	BackendInformation(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*BackendInformationResponse, error)
+}
+
+type backendClient struct {
+	cc *grpc.ClientConn
+}
+
+func NewBackendClient(cc *grpc.ClientConn) BackendClient {
+	return &backendClient{cc}
+}
+
+func (c *backendClient) BackendInformation(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*BackendInformationResponse, error) {
+	out := new(BackendInformationResponse)
+	err := c.cc.Invoke(ctx, "/com.docker.api.backend.v1.Backend/BackendInformation", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// BackendServer is the server API for Backend service.
+type BackendServer interface {
+	// BackendInformation returns implementation specific information on the backend.
+	BackendInformation(context.Context, *types.Empty) (*BackendInformationResponse, error)
+}
+
+// UnimplementedBackendServer can be embedded to have forward compatible implementations.
+type UnimplementedBackendServer struct {
+}
+
+func (*UnimplementedBackendServer) BackendInformation(ctx context.Context, req *types.Empty) (*BackendInformationResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method BackendInformation not implemented")
+}
+
+func RegisterBackendServer(s *grpc.Server, srv BackendServer) {
+	s.RegisterService(&_Backend_serviceDesc, srv)
+}
+
+func _Backend_BackendInformation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(types.Empty)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(BackendServer).BackendInformation(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/com.docker.api.backend.v1.Backend/BackendInformation",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(BackendServer).BackendInformation(ctx, req.(*types.Empty))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _Backend_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "com.docker.api.backend.v1.Backend",
+	HandlerType: (*BackendServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "BackendInformation",
+			Handler:    _Backend_BackendInformation_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "github.com/docker/api/backend/v1/backend.proto",
+}

+ 49 - 0
client/client.go

@@ -0,0 +1,49 @@
+/*
+	Copyright (c) 2019 Docker Inc.
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use, copy,
+	modify, merge, publish, distribute, sublicense, and/or sell copies
+	of the Software, and to permit persons to whom the Software is
+	furnished to do so, subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED,
+	INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM,
+	DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT,
+	TORT OR OTHERWISE,
+	ARISING FROM, OUT OF OR IN CONNECTION WITH
+	THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package client
+
+import "google.golang.org/grpc"
+
+// New returns a GRPC client
+func New(address string) (*Client, error) {
+	conn, err := grpc.Dial(address, grpc.WithInsecure())
+	if err != nil {
+		return nil, err
+	}
+	return &Client{
+		conn: conn,
+	}, nil
+}
+
+type Client struct {
+	conn *grpc.ClientConn
+}
+
+func (c *Client) Close() error {
+	return c.conn.Close()
+}

+ 112 - 0
example/backend/main.go

@@ -0,0 +1,112 @@
+/*
+	Copyright (c) 2019 Docker Inc.
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use, copy,
+	modify, merge, publish, distribute, sublicense, and/or sell copies
+	of the Software, and to permit persons to whom the Software is
+	furnished to do so, subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED,
+	INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM,
+	DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT,
+	TORT OR OTHERWISE,
+	ARISING FROM, OUT OF OR IN CONNECTION WITH
+	THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package main
+
+import (
+	"context"
+	"fmt"
+	"net"
+	"os"
+	"os/signal"
+	"syscall"
+
+	"github.com/docker/api/server"
+	_ "github.com/gogo/googleapis/google/rpc"
+	_ "github.com/gogo/protobuf/types"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+	"github.com/urfave/cli"
+)
+
+func main() {
+	app := cli.NewApp()
+	app.Name = "example"
+	app.Usage = "example backend"
+	app.Description = ""
+	app.UseShortOptionHandling = true
+	app.EnableBashCompletion = true
+	app.Flags = []cli.Flag{
+		cli.BoolFlag{
+			Name:  "debug",
+			Usage: "enable debug output in the logs",
+		},
+		cli.StringFlag{
+			Name:  "address,a",
+			Usage: "address of the server",
+		},
+	}
+	app.Before = func(clix *cli.Context) error {
+		if clix.GlobalBool("debug") {
+			logrus.SetLevel(logrus.DebugLevel)
+		}
+		return nil
+	}
+	app.Action = func(clix *cli.Context) error {
+		ctx, cancel := cancelContext()
+		defer cancel()
+
+		// create a new GRPC server with the provided server package
+		s := server.New()
+
+		// listen on a socket to accept connects
+		l, err := net.Listen("tcp", clix.GlobalString("address"))
+		if err != nil {
+			return errors.Wrap(err, "listen tcp")
+		}
+		defer l.Close()
+
+		// handle context being closed or canceled
+		go func() {
+			<-ctx.Done()
+			logrus.Info("backend signaled to stop")
+
+			s.Stop()
+		}()
+
+		logrus.WithField("address", clix.GlobalString("address")).Info("serving daemon API")
+		// start the GRPC server to serve on the listener
+		return s.Serve(l)
+	}
+	if err := app.Run(os.Args); err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
+}
+
+// cancelContext is a context that is canceled when a signal is
+// sent to the process
+func cancelContext() (context.Context, func()) {
+	ctx, cancel := context.WithCancel(context.Background())
+	s := make(chan os.Signal)
+	signal.Notify(s, syscall.SIGTERM, syscall.SIGINT)
+	go func() {
+		<-s
+		cancel()
+	}()
+	return ctx, cancel
+}

+ 56 - 0
server/server.go

@@ -0,0 +1,56 @@
+/*
+	Copyright (c) 2019 Docker Inc.
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use, copy,
+	modify, merge, publish, distribute, sublicense, and/or sell copies
+	of the Software, and to permit persons to whom the Software is
+	furnished to do so, subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED,
+	INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM,
+	DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT,
+	TORT OR OTHERWISE,
+	ARISING FROM, OUT OF OR IN CONNECTION WITH
+	THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package server
+
+import (
+	"context"
+
+	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/health"
+	"google.golang.org/grpc/health/grpc_health_v1"
+)
+
+// New returns a new GRPC server.
+func New() *grpc.Server {
+	s := grpc.NewServer(
+		grpc.UnaryInterceptor(unary),
+		grpc.StreamInterceptor(stream),
+	)
+	hs := health.NewServer()
+	grpc_health_v1.RegisterHealthServer(s, hs)
+	return s
+}
+
+func unary(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
+	return grpc_prometheus.UnaryServerInterceptor(ctx, req, info, handler)
+}
+
+func stream(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
+	return grpc_prometheus.StreamServerInterceptor(srv, ss, info, handler)
+}