172 lines
4.4 KiB
Go
172 lines
4.4 KiB
Go
|
|
/*
|
||
|
|
* Copyright (c) 2019 Huawei Technologies Co., Ltd.
|
||
|
|
* A-Tune is licensed under the Mulan PSL v1.
|
||
|
|
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
||
|
|
* You may obtain a copy of Mulan PSL v1 at:
|
||
|
|
* http://license.coscl.org.cn/MulanPSL
|
||
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
|
||
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
|
||
|
|
* PURPOSE.
|
||
|
|
* See the Mulan PSL v1 for more details.
|
||
|
|
* Create: 2019-10-29
|
||
|
|
*/
|
||
|
|
|
||
|
|
package client
|
||
|
|
|
||
|
|
import (
|
||
|
|
"atune/common/config"
|
||
|
|
"fmt"
|
||
|
|
"os"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/urfave/cli"
|
||
|
|
"google.golang.org/grpc"
|
||
|
|
)
|
||
|
|
|
||
|
|
type clientOpts struct {
|
||
|
|
defaultns string
|
||
|
|
dialOptions []grpc.DialOption
|
||
|
|
}
|
||
|
|
|
||
|
|
// Opt allows callers to set options on the client
|
||
|
|
type Opt func(c *clientOpts) error
|
||
|
|
|
||
|
|
//Client :The grpc client structer
|
||
|
|
type Client struct {
|
||
|
|
conn *grpc.ClientConn
|
||
|
|
defaultns string
|
||
|
|
services map[string]interface{}
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetService method return the grpc client command plugin service
|
||
|
|
func (c *Client) GetService(name string) (interface{}, error) {
|
||
|
|
_, ok := c.services[name]
|
||
|
|
if !ok {
|
||
|
|
return nil, fmt.Errorf("There is no service %s available", name)
|
||
|
|
}
|
||
|
|
|
||
|
|
return c.services[name], nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewService method call the function to new a grpc client plugin service
|
||
|
|
func (c *Client) NewService(name string, fn func(cc *grpc.ClientConn) (interface{}, error)) error {
|
||
|
|
if _, ok := c.services[name]; ok {
|
||
|
|
return fmt.Errorf("Service %s client has existed")
|
||
|
|
}
|
||
|
|
svc, err := fn(c.conn)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
c.services[name] = svc
|
||
|
|
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Connection method return the grpc connection of the client
|
||
|
|
func (c *Client) Connection() *grpc.ClientConn {
|
||
|
|
return c.conn
|
||
|
|
}
|
||
|
|
|
||
|
|
//Close method close the grpc connection
|
||
|
|
func (c *Client) Close() {
|
||
|
|
c.conn.Close()
|
||
|
|
}
|
||
|
|
|
||
|
|
//GetState method return the state of the grpc connection
|
||
|
|
func (c *Client) GetState() string {
|
||
|
|
return c.conn.GetState().String()
|
||
|
|
}
|
||
|
|
|
||
|
|
//NewWithConn method create a grpc client depend the connection
|
||
|
|
func NewWithConn(conn *grpc.ClientConn, opts ...Opt) (*Client, error) {
|
||
|
|
return &Client{
|
||
|
|
conn: conn,
|
||
|
|
services: make(map[string]interface{}),
|
||
|
|
}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
//NewClientFromContext method create a grpc client depend the command context
|
||
|
|
func NewClientFromContext(ctx *cli.Context, opts ...Opt) (*Client, error) {
|
||
|
|
addr, port := parseAddr(ctx)
|
||
|
|
return newClient(addr+":"+port, opts...)
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewClientWithoutCli method create a grpc client depend the address and port
|
||
|
|
func NewClientWithoutCli(addr string, port string, opts ...Opt) (*Client, error) {
|
||
|
|
if addr == config.DefaultTgtAddr {
|
||
|
|
addr, _ = ParseEnvAddr()
|
||
|
|
}
|
||
|
|
if port == config.DefaultTgtPort {
|
||
|
|
_, port = ParseEnvAddr()
|
||
|
|
}
|
||
|
|
return newClient(addr+":"+port, opts...)
|
||
|
|
}
|
||
|
|
|
||
|
|
//NewClientFromConn method create a grpc client depend the conn, which is address:port format
|
||
|
|
func NewClientFromConn(conn string, opts ...Opt) (*Client, error) {
|
||
|
|
return newClient(conn, opts...)
|
||
|
|
}
|
||
|
|
|
||
|
|
//NewClient method create a grpc client depend the address and port
|
||
|
|
func NewClient(addr string, port string, opts ...Opt) (*Client, error) {
|
||
|
|
return newClient(addr+":"+port, opts...)
|
||
|
|
}
|
||
|
|
|
||
|
|
func newClient(address string, opts ...Opt) (*Client, error) {
|
||
|
|
var copts clientOpts
|
||
|
|
for _, o := range opts {
|
||
|
|
if err := o(&copts); err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
}
|
||
|
|
gopts := []grpc.DialOption{
|
||
|
|
grpc.WithBlock(),
|
||
|
|
grpc.WithInsecure(),
|
||
|
|
grpc.WithTimeout(60 * time.Second),
|
||
|
|
grpc.FailOnNonTempDialError(true),
|
||
|
|
grpc.WithBackoffMaxDelay(3 * time.Second),
|
||
|
|
}
|
||
|
|
if len(copts.dialOptions) > 0 {
|
||
|
|
gopts = copts.dialOptions
|
||
|
|
}
|
||
|
|
conn, err := grpc.Dial(address, gopts...)
|
||
|
|
if err != nil {
|
||
|
|
return nil, fmt.Errorf("failed to dial %q : %s", address, err)
|
||
|
|
}
|
||
|
|
return NewWithConn(conn, opts...)
|
||
|
|
}
|
||
|
|
|
||
|
|
//ParseEnvAddr method return the ip and port depend the Env, if not return the default value
|
||
|
|
func ParseEnvAddr() (string, string) {
|
||
|
|
addr := os.Getenv(config.EnvAddr)
|
||
|
|
if addr == "" {
|
||
|
|
addr = config.DefaultTgtAddr
|
||
|
|
}
|
||
|
|
|
||
|
|
port := os.Getenv(config.EnvPort)
|
||
|
|
if port == "" {
|
||
|
|
port = config.DefaultTgtPort
|
||
|
|
}
|
||
|
|
|
||
|
|
return addr, port
|
||
|
|
}
|
||
|
|
|
||
|
|
//ParseCliAddr method return the ip and port depend the command context
|
||
|
|
func ParseCliAddr(ctx *cli.Context) (string, string) {
|
||
|
|
return ctx.GlobalString("address"), ctx.GlobalString("port")
|
||
|
|
}
|
||
|
|
|
||
|
|
func parseAddr(ctx *cli.Context) (string, string) {
|
||
|
|
addr, port := ParseCliAddr(ctx)
|
||
|
|
|
||
|
|
if addr == config.DefaultTgtAddr {
|
||
|
|
addr, _ = ParseEnvAddr()
|
||
|
|
}
|
||
|
|
if port == config.DefaultTgtPort {
|
||
|
|
_, port = ParseEnvAddr()
|
||
|
|
}
|
||
|
|
|
||
|
|
return addr, port
|
||
|
|
}
|