Merge branch 'master' of ssh://github.com/micro/go-micro

This commit is contained in:
Asim Aslam 2020-08-11 10:32:25 +01:00
commit 28d6340f04
13 changed files with 57 additions and 1029 deletions

View File

@ -5,14 +5,13 @@ import (
"fmt" "fmt"
"net" "net"
"net/http" "net/http"
"sync"
"testing" "testing"
"github.com/micro/go-micro/v3/client" "github.com/micro/go-micro/v3/client"
cmucp "github.com/micro/go-micro/v3/client/mucp"
"github.com/micro/go-micro/v3/registry/memory" "github.com/micro/go-micro/v3/registry/memory"
"github.com/micro/go-micro/v3/server" "github.com/micro/go-micro/v3/server"
"github.com/micro/go-micro/v3/service" "github.com/micro/go-micro/v3/server/mucp"
"github.com/micro/go-micro/v3/service/mucp"
) )
type testHandler struct{} type testHandler struct{}
@ -53,37 +52,31 @@ func TestHTTPProxy(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
var wg sync.WaitGroup reg := memory.NewRegistry()
wg.Add(1)
// new micro service // new micro service
service := mucp.NewService( service := mucp.NewServer(
service.Context(ctx), server.Context(ctx),
service.Name("foobar"), server.Name("foobar"),
service.Registry(memory.NewRegistry()), server.Registry(reg),
service.AfterStart(func() error {
wg.Done()
return nil
}),
)
// set router
service.Server().Init(
server.WithRouter(p), server.WithRouter(p),
) )
service.Start()
defer service.Stop()
// run service // run service
// server // server
go http.Serve(c, nil) go http.Serve(c, nil)
go service.Run()
// wait till service is started cl := cmucp.NewClient(
wg.Wait() client.Registry(reg),
)
for _, test := range testCases { for _, test := range testCases {
req := service.Client().NewRequest("foobar", test.rpcEp, map[string]string{"foo": "bar"}, client.WithContentType("application/json")) req := cl.NewRequest("foobar", test.rpcEp, map[string]string{"foo": "bar"}, client.WithContentType("application/json"))
var rsp map[string]string var rsp map[string]string
err := service.Client().Call(ctx, req, &rsp) err := cl.Call(ctx, req, &rsp)
if err != nil && test.err == false { if err != nil && test.err == false {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -1,129 +0,0 @@
package grpc
import (
"github.com/micro/go-micro/v3/client"
gclient "github.com/micro/go-micro/v3/client/grpc"
"github.com/micro/go-micro/v3/model"
"github.com/micro/go-micro/v3/server"
gserver "github.com/micro/go-micro/v3/server/grpc"
"github.com/micro/go-micro/v3/service"
)
type grpcService struct {
opts service.Options
}
func newService(opts ...service.Option) service.Service {
options := service.NewOptions(opts...)
return &grpcService{
opts: options,
}
}
func (s *grpcService) Name() string {
return s.opts.Server.Options().Name
}
// Init initialises options. Additionally it calls cmd.Init
// which parses command line flags. cmd.Init is only called
// on first Init.
func (s *grpcService) Init(opts ...service.Option) {
// process options
for _, o := range opts {
o(&s.opts)
}
}
func (s *grpcService) Options() service.Options {
return s.opts
}
func (s *grpcService) Client() client.Client {
return s.opts.Client
}
func (s *grpcService) Server() server.Server {
return s.opts.Server
}
func (s *grpcService) Model() model.Model {
return s.opts.Model
}
func (s *grpcService) String() string {
return "grpc"
}
func (s *grpcService) Start() error {
for _, fn := range s.opts.BeforeStart {
if err := fn(); err != nil {
return err
}
}
if err := s.opts.Server.Start(); err != nil {
return err
}
for _, fn := range s.opts.AfterStart {
if err := fn(); err != nil {
return err
}
}
return nil
}
func (s *grpcService) Stop() error {
var gerr error
for _, fn := range s.opts.BeforeStop {
if err := fn(); err != nil {
gerr = err
}
}
if err := s.opts.Server.Stop(); err != nil {
return err
}
for _, fn := range s.opts.AfterStop {
if err := fn(); err != nil {
gerr = err
}
}
return gerr
}
func (s *grpcService) Run() error {
if err := s.Start(); err != nil {
return err
}
// wait on context cancel
<-s.opts.Context.Done()
return s.Stop()
}
// NewService returns a grpc service compatible with go-micro.Service
func NewService(opts ...service.Option) service.Service {
// our grpc client
c := gclient.NewClient()
// our grpc server
s := gserver.NewServer()
// create options with priority for our opts
options := []service.Option{
service.Client(c),
service.Server(s),
}
// append passed in opts
options = append(options, opts...)
// generate and return a service
return newService(options...)
}

View File

@ -1,155 +0,0 @@
package grpc
import (
"context"
"crypto/tls"
"sync"
"testing"
"time"
"github.com/micro/go-micro/v3/registry/memory"
"github.com/micro/go-micro/v3/service"
hello "github.com/micro/go-micro/v3/service/grpc/proto"
mls "github.com/micro/go-micro/v3/util/tls"
)
type testHandler struct{}
func (t *testHandler) Call(ctx context.Context, req *hello.Request, rsp *hello.Response) error {
rsp.Msg = "Hello " + req.Name
return nil
}
func TestGRPCService(t *testing.T) {
var wg sync.WaitGroup
wg.Add(1)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// create memory registry
r := memory.NewRegistry()
// create GRPC service
service := NewService(
service.Name("test.service"),
service.Registry(r),
service.AfterStart(func() error {
wg.Done()
return nil
}),
service.Context(ctx),
)
// register test handler
hello.RegisterTestHandler(service.Server(), &testHandler{})
// run service
errCh := make(chan error, 1)
go func() {
defer close(errCh)
errCh <- service.Run()
}()
// wait for start
wg.Wait()
// create client
test := hello.NewTestService("test.service", service.Client())
// call service
ctx2, cancel2 := context.WithTimeout(context.Background(), time.Duration(time.Second))
defer cancel2()
rsp, err := test.Call(ctx2, &hello.Request{
Name: "John",
})
if err != nil {
t.Fatal(err)
}
// check server
select {
case err := <-errCh:
t.Fatal(err)
case <-time.After(time.Second):
break
}
// check message
if rsp.Msg != "Hello John" {
t.Fatalf("unexpected response %s", rsp.Msg)
}
}
func TestGRPCTLSService(t *testing.T) {
var wg sync.WaitGroup
wg.Add(1)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// create memory registry
r := memory.NewRegistry()
// create cert
cert, err := mls.Certificate("test.service")
if err != nil {
t.Fatal(err)
}
config := &tls.Config{
Certificates: []tls.Certificate{cert},
InsecureSkipVerify: true,
}
// create GRPC service
service := NewService(
service.Name("test.service"),
service.Registry(r),
service.AfterStart(func() error {
wg.Done()
return nil
}),
service.Context(ctx),
// set TLS config
WithTLS(config),
)
// register test handler
hello.RegisterTestHandler(service.Server(), &testHandler{})
// run service
errCh := make(chan error, 1)
go func() {
defer close(errCh)
errCh <- service.Run()
}()
// wait for start
wg.Wait()
// create client
test := hello.NewTestService("test.service", service.Client())
// call service
ctx2, cancel2 := context.WithTimeout(context.Background(), time.Duration(time.Second))
defer cancel2()
rsp, err := test.Call(ctx2, &hello.Request{
Name: "John",
})
if err != nil {
t.Fatal(err)
}
// check server
select {
case err := <-errCh:
t.Fatal(err)
case <-time.After(time.Second):
break
}
// check message
if rsp.Msg != "Hello John" {
t.Fatalf("unexpected response %s", rsp.Msg)
}
}

View File

@ -1,21 +0,0 @@
package grpc
import (
"crypto/tls"
gc "github.com/micro/go-micro/v3/client/grpc"
gs "github.com/micro/go-micro/v3/server/grpc"
"github.com/micro/go-micro/v3/service"
)
// WithTLS sets the TLS config for the service
func WithTLS(t *tls.Config) service.Option {
return func(o *service.Options) {
o.Client.Init(
gc.AuthTLS(t),
)
o.Server.Init(
gs.AuthTLS(t),
)
}
}

View File

@ -1,203 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: service/grpc/proto/test.proto
package test
import (
context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
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.ProtoPackageIsVersion3 // please upgrade the proto package
type Request struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Request) Reset() { *m = Request{} }
func (m *Request) String() string { return proto.CompactTextString(m) }
func (*Request) ProtoMessage() {}
func (*Request) Descriptor() ([]byte, []int) {
return fileDescriptor_06b01994cb662112, []int{0}
}
func (m *Request) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Request.Unmarshal(m, b)
}
func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Request.Marshal(b, m, deterministic)
}
func (m *Request) XXX_Merge(src proto.Message) {
xxx_messageInfo_Request.Merge(m, src)
}
func (m *Request) XXX_Size() int {
return xxx_messageInfo_Request.Size(m)
}
func (m *Request) XXX_DiscardUnknown() {
xxx_messageInfo_Request.DiscardUnknown(m)
}
var xxx_messageInfo_Request proto.InternalMessageInfo
func (m *Request) GetName() string {
if m != nil {
return m.Name
}
return ""
}
type Response struct {
Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Response) Reset() { *m = Response{} }
func (m *Response) String() string { return proto.CompactTextString(m) }
func (*Response) ProtoMessage() {}
func (*Response) Descriptor() ([]byte, []int) {
return fileDescriptor_06b01994cb662112, []int{1}
}
func (m *Response) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Response.Unmarshal(m, b)
}
func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Response.Marshal(b, m, deterministic)
}
func (m *Response) XXX_Merge(src proto.Message) {
xxx_messageInfo_Response.Merge(m, src)
}
func (m *Response) XXX_Size() int {
return xxx_messageInfo_Response.Size(m)
}
func (m *Response) XXX_DiscardUnknown() {
xxx_messageInfo_Response.DiscardUnknown(m)
}
var xxx_messageInfo_Response proto.InternalMessageInfo
func (m *Response) GetMsg() string {
if m != nil {
return m.Msg
}
return ""
}
func init() {
proto.RegisterType((*Request)(nil), "Request")
proto.RegisterType((*Response)(nil), "Response")
}
func init() { proto.RegisterFile("service/grpc/proto/test.proto", fileDescriptor_06b01994cb662112) }
var fileDescriptor_06b01994cb662112 = []byte{
// 133 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2d, 0x4e, 0x2d, 0x2a,
0xcb, 0x4c, 0x4e, 0xd5, 0x4f, 0x2f, 0x2a, 0x48, 0xd6, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0xd7, 0x2f,
0x49, 0x2d, 0x2e, 0xd1, 0x03, 0x33, 0x95, 0x64, 0xb9, 0xd8, 0x83, 0x52, 0x0b, 0x4b, 0x53, 0x8b,
0x4b, 0x84, 0x84, 0xb8, 0x58, 0xf2, 0x12, 0x73, 0x53, 0x25, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83,
0xc0, 0x6c, 0x25, 0x19, 0x2e, 0x8e, 0xa0, 0xd4, 0xe2, 0x82, 0xfc, 0xbc, 0xe2, 0x54, 0x21, 0x01,
0x2e, 0xe6, 0xdc, 0xe2, 0x74, 0xa8, 0x34, 0x88, 0x69, 0xa4, 0xca, 0xc5, 0x12, 0x02, 0xd2, 0x29,
0xcb, 0xc5, 0xe2, 0x9c, 0x98, 0x93, 0x23, 0xc4, 0xa1, 0x07, 0x35, 0x4b, 0x8a, 0x53, 0x0f, 0xa6,
0x4d, 0x89, 0x21, 0x89, 0x0d, 0x6c, 0x95, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xe6, 0x7f, 0x80,
0xd4, 0x8b, 0x00, 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
// TestClient is the client API for Test service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type TestClient interface {
Call(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error)
}
type testClient struct {
cc *grpc.ClientConn
}
func NewTestClient(cc *grpc.ClientConn) TestClient {
return &testClient{cc}
}
func (c *testClient) Call(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) {
out := new(Response)
err := c.cc.Invoke(ctx, "/Test/Call", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// TestServer is the server API for Test service.
type TestServer interface {
Call(context.Context, *Request) (*Response, error)
}
// UnimplementedTestServer can be embedded to have forward compatible implementations.
type UnimplementedTestServer struct {
}
func (*UnimplementedTestServer) Call(ctx context.Context, req *Request) (*Response, error) {
return nil, status.Errorf(codes.Unimplemented, "method Call not implemented")
}
func RegisterTestServer(s *grpc.Server, srv TestServer) {
s.RegisterService(&_Test_serviceDesc, srv)
}
func _Test_Call_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Request)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TestServer).Call(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/Test/Call",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TestServer).Call(ctx, req.(*Request))
}
return interceptor(ctx, in, info, handler)
}
var _Test_serviceDesc = grpc.ServiceDesc{
ServiceName: "Test",
HandlerType: (*TestServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Call",
Handler: _Test_Call_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "service/grpc/proto/test.proto",
}

View File

@ -1,93 +0,0 @@
// Code generated by protoc-gen-micro. DO NOT EDIT.
// source: service/grpc/proto/test.proto
package test
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
import (
context "context"
api "github.com/micro/go-micro/v3/api"
client "github.com/micro/go-micro/v3/client"
server "github.com/micro/go-micro/v3/server"
)
// 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.ProtoPackageIsVersion3 // please upgrade the proto package
// Reference imports to suppress errors if they are not otherwise used.
var _ api.Endpoint
var _ context.Context
var _ client.Option
var _ server.Option
// Api Endpoints for Test service
func NewTestEndpoints() []*api.Endpoint {
return []*api.Endpoint{}
}
// Client API for Test service
type TestService interface {
Call(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error)
}
type testService struct {
c client.Client
name string
}
func NewTestService(name string, c client.Client) TestService {
return &testService{
c: c,
name: name,
}
}
func (c *testService) Call(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error) {
req := c.c.NewRequest(c.name, "Test.Call", in)
out := new(Response)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for Test service
type TestHandler interface {
Call(context.Context, *Request, *Response) error
}
func RegisterTestHandler(s server.Server, hdlr TestHandler, opts ...server.HandlerOption) error {
type test interface {
Call(ctx context.Context, in *Request, out *Response) error
}
type Test struct {
test
}
h := &testHandler{hdlr}
return s.Handle(s.NewHandler(&Test{h}, opts...))
}
type testHandler struct {
TestHandler
}
func (h *testHandler) Call(ctx context.Context, in *Request, out *Response) error {
return h.TestHandler.Call(ctx, in, out)
}

View File

@ -1,13 +0,0 @@
syntax = "proto3";
service Test {
rpc Call(Request) returns (Response) {}
}
message Request {
string name = 1;
}
message Response {
string msg = 1;
}

View File

@ -1,122 +0,0 @@
// Package mucp initialises a mucp service
package mucp
import (
"github.com/micro/go-micro/v3/client"
cmucp "github.com/micro/go-micro/v3/client/mucp"
"github.com/micro/go-micro/v3/model"
"github.com/micro/go-micro/v3/server"
smucp "github.com/micro/go-micro/v3/server/mucp"
"github.com/micro/go-micro/v3/service"
)
type mucpService struct {
opts service.Options
}
func newService(opts ...service.Option) service.Service {
options := service.NewOptions(opts...)
return &mucpService{
opts: options,
}
}
func (s *mucpService) Name() string {
return s.opts.Server.Options().Name
}
// Init initialises options. Additionally it calls cmd.Init
// which parses command line flags. cmd.Init is only called
// on first Init.
func (s *mucpService) Init(opts ...service.Option) {
// process options
for _, o := range opts {
o(&s.opts)
}
}
func (s *mucpService) Options() service.Options {
return s.opts
}
func (s *mucpService) Client() client.Client {
return s.opts.Client
}
func (s *mucpService) Server() server.Server {
return s.opts.Server
}
func (s *mucpService) Model() model.Model {
return s.opts.Model
}
func (s *mucpService) String() string {
return "mucp"
}
func (s *mucpService) Start() error {
for _, fn := range s.opts.BeforeStart {
if err := fn(); err != nil {
return err
}
}
if err := s.opts.Server.Start(); err != nil {
return err
}
for _, fn := range s.opts.AfterStart {
if err := fn(); err != nil {
return err
}
}
return nil
}
func (s *mucpService) Stop() error {
var gerr error
for _, fn := range s.opts.BeforeStop {
if err := fn(); err != nil {
gerr = err
}
}
if err := s.opts.Server.Stop(); err != nil {
return err
}
for _, fn := range s.opts.AfterStop {
if err := fn(); err != nil {
gerr = err
}
}
return gerr
}
func (s *mucpService) Run() error {
if err := s.Start(); err != nil {
return err
}
// wait on context cancel
<-s.opts.Context.Done()
return s.Stop()
}
// NewService returns a new mucp service
func NewService(opts ...service.Option) service.Service {
options := []service.Option{
service.Client(cmucp.NewClient()),
service.Server(smucp.NewServer()),
}
options = append(options, opts...)
return newService(options...)
}

View File

@ -1,236 +0,0 @@
package service
import (
"context"
"time"
"github.com/micro/go-micro/v3/broker"
"github.com/micro/go-micro/v3/broker/http"
"github.com/micro/go-micro/v3/client"
mucpClient "github.com/micro/go-micro/v3/client/mucp"
"github.com/micro/go-micro/v3/model"
"github.com/micro/go-micro/v3/registry"
"github.com/micro/go-micro/v3/registry/mdns"
"github.com/micro/go-micro/v3/server"
mucpServer "github.com/micro/go-micro/v3/server/mucp"
"github.com/micro/go-micro/v3/transport"
thttp "github.com/micro/go-micro/v3/transport/http"
)
type Options struct {
Broker broker.Broker
Client client.Client
Server server.Server
Model model.Model
Registry registry.Registry
Transport transport.Transport
// Before and After funcs
BeforeStart []func() error
BeforeStop []func() error
AfterStart []func() error
AfterStop []func() error
// Other options for implementations of the interface
// can be stored in a context
Context context.Context
}
type Option func(*Options)
func NewOptions(opts ...Option) Options {
opt := Options{
Broker: http.NewBroker(),
Client: mucpClient.NewClient(),
Server: mucpServer.NewServer(),
Registry: mdns.NewRegistry(),
Transport: thttp.NewTransport(),
Context: context.Background(),
}
for _, o := range opts {
o(&opt)
}
return opt
}
func Broker(b broker.Broker) Option {
return func(o *Options) {
o.Broker = b
// Update Client and Server
o.Client.Init(client.Broker(b))
o.Server.Init(server.Broker(b))
}
}
func Client(c client.Client) Option {
return func(o *Options) {
o.Client = c
}
}
// Context specifies a context for the service.
// Can be used to signal shutdown of the service.
// Can be used for extra option values.
func Context(ctx context.Context) Option {
return func(o *Options) {
o.Context = ctx
}
}
// Server sets the server for handling requests
func Server(s server.Server) Option {
return func(o *Options) {
o.Server = s
}
}
// Model sets the model for data access
func Model(m model.Model) Option {
return func(o *Options) {
o.Model = m
}
}
// Registry sets the registry for the service
// and the underlying components
func Registry(r registry.Registry) Option {
return func(o *Options) {
o.Registry = r
// Update server
o.Server.Init(server.Registry(r))
// Update Broker
o.Broker.Init(broker.Registry(r))
// Update router
o.Client.Init(client.Registry(r))
}
}
// Transport sets the transport for the service
// and the underlying components
func Transport(t transport.Transport) Option {
return func(o *Options) {
o.Transport = t
// Update Client and Server
o.Client.Init(client.Transport(t))
o.Server.Init(server.Transport(t))
}
}
// Convenience options
// Address sets the address of the server
func Address(addr string) Option {
return func(o *Options) {
o.Server.Init(server.Address(addr))
}
}
// Name of the service
func Name(n string) Option {
return func(o *Options) {
o.Server.Init(server.Name(n))
}
}
// Version of the service
func Version(v string) Option {
return func(o *Options) {
o.Server.Init(server.Version(v))
}
}
// Metadata associated with the service
func Metadata(md map[string]string) Option {
return func(o *Options) {
o.Server.Init(server.Metadata(md))
}
}
// RegisterTTL specifies the TTL to use when registering the service
func RegisterTTL(t time.Duration) Option {
return func(o *Options) {
o.Server.Init(server.RegisterTTL(t))
}
}
// RegisterInterval specifies the interval on which to re-register
func RegisterInterval(t time.Duration) Option {
return func(o *Options) {
o.Server.Init(server.RegisterInterval(t))
}
}
// WrapClient is a convenience method for wrapping a Client with
// some middleware component. A list of wrappers can be provided.
// Wrappers are applied in reverse order so the last is executed first.
func WrapClient(w ...client.Wrapper) Option {
return func(o *Options) {
// apply in reverse
for i := len(w); i > 0; i-- {
o.Client = w[i-1](o.Client)
}
}
}
// WrapCall is a convenience method for wrapping a Client CallFunc
func WrapCall(w ...client.CallWrapper) Option {
return func(o *Options) {
o.Client.Init(client.WrapCall(w...))
}
}
// WrapHandler adds a handler Wrapper to a list of options passed into the server
func WrapHandler(w ...server.HandlerWrapper) Option {
return func(o *Options) {
var wrappers []server.Option
for _, wrap := range w {
wrappers = append(wrappers, server.WrapHandler(wrap))
}
// Init once
o.Server.Init(wrappers...)
}
}
// WrapSubscriber adds a subscriber Wrapper to a list of options passed into the server
func WrapSubscriber(w ...server.SubscriberWrapper) Option {
return func(o *Options) {
var wrappers []server.Option
for _, wrap := range w {
wrappers = append(wrappers, server.WrapSubscriber(wrap))
}
// Init once
o.Server.Init(wrappers...)
}
}
// Before and Afters
func BeforeStart(fn func() error) Option {
return func(o *Options) {
o.BeforeStart = append(o.BeforeStart, fn)
}
}
func BeforeStop(fn func() error) Option {
return func(o *Options) {
o.BeforeStop = append(o.BeforeStop, fn)
}
}
func AfterStart(fn func() error) Option {
return func(o *Options) {
o.AfterStart = append(o.AfterStart, fn)
}
}
func AfterStop(fn func() error) Option {
return func(o *Options) {
o.AfterStop = append(o.AfterStop, fn)
}
}

View File

@ -1,28 +0,0 @@
// Package service encapsulates the client, server and other interfaces to provide a complete micro service.
package service
import (
"github.com/micro/go-micro/v3/client"
"github.com/micro/go-micro/v3/model"
"github.com/micro/go-micro/v3/server"
)
// Service is an interface for a micro service
type Service interface {
// The service name
Name() string
// Init initialises options
Init(...Option)
// Options returns the current options
Options() Options
// Client is used to call services
Client() client.Client
// Server is for handling requests and events
Server() server.Server
// Model is used to access data
Model() model.Model
// Run the service
Run() error
// The service implementation
String() string
}

View File

@ -321,6 +321,13 @@ func NewDeployment(name, version, typ, namespace string) *Deployment {
Name: "service-port", Name: "service-port",
ContainerPort: 8080, ContainerPort: 8080,
}}, }},
ReadinessProbe: &Probe{
TCPSocket: TCPSocketAction{
Port: 8080,
},
PeriodSeconds: 10,
InitialDelaySeconds: 10,
},
}}, }},
}, },
}, },

View File

@ -92,8 +92,22 @@ spec:
name: {{ .Name }} name: {{ .Name }}
{{- end}} {{- end}}
{{- end}} {{- end}}
{{- if .ReadinessProbe }}
{{- with .ReadinessProbe }}
readinessProbe:
{{- with .TCPSocket }}
tcpSocket:
{{- if .Host }}
host: {{ .Host }}
{{- end }}
port: {{ .Port }}
{{- end }}
initialDelaySeconds: {{ .InitialDelaySeconds }}
periodSeconds: {{ .PeriodSeconds }}
{{- end }}
{{- end }}
{{- end }}
{{- end }} {{- end }}
{{- end}}
` `
var serviceTmpl = ` var serviceTmpl = `

View File

@ -35,12 +35,13 @@ type Condition struct {
// Container defined container runtime values // Container defined container runtime values
type Container struct { type Container struct {
Name string `json:"name"` Name string `json:"name"`
Image string `json:"image"` Image string `json:"image"`
Env []EnvVar `json:"env,omitempty"` Env []EnvVar `json:"env,omitempty"`
Command []string `json:"command,omitempty"` Command []string `json:"command,omitempty"`
Args []string `json:"args,omitempty"` Args []string `json:"args,omitempty"`
Ports []ContainerPort `json:"ports,omitempty"` Ports []ContainerPort `json:"ports,omitempty"`
ReadinessProbe *Probe `json:"readinessProbe,omitempty"`
} }
// DeploymentSpec defines micro deployment spec // DeploymentSpec defines micro deployment spec
@ -220,3 +221,16 @@ type ServiceAccount struct {
Metadata *Metadata `json:"metadata,omitempty"` Metadata *Metadata `json:"metadata,omitempty"`
ImagePullSecrets []ImagePullSecret `json:"imagePullSecrets,omitempty"` ImagePullSecrets []ImagePullSecret `json:"imagePullSecrets,omitempty"`
} }
// Probe describes a health check to be performed against a container to determine whether it is alive or ready to receive traffic.
type Probe struct {
TCPSocket TCPSocketAction `json:"tcpSocket,omitempty"`
PeriodSeconds int `json:"periodSeconds"`
InitialDelaySeconds int `json:"initialDelaySeconds"`
}
// TCPSocketAction describes an action based on opening a socket
type TCPSocketAction struct {
Host string `json:"host,omitempty"`
Port int `json:"port,omitempty"`
}