Skip to content

Commit

Permalink
grpc client default in plaintext mode (#19412)
Browse files Browse the repository at this point in the history
* grpc client default in plaintext mode

* renaming and fix linter

* update the description and remove the context

* trim tests
  • Loading branch information
xwa153 authored Nov 28, 2023
1 parent 419677c commit 9dc2444
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 11 deletions.
9 changes: 2 additions & 7 deletions command/resource/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ import (
"sync"
"time"

"github.com/hashicorp/consul/api"
"github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-rootcerts"

"github.com/hashicorp/consul/api"
)

// NOTE: This client is copied from the api module to temporarily facilitate the resource cli commands
Expand Down Expand Up @@ -72,12 +73,6 @@ const (
// whether or not to disable certificate checking.
HTTPSSLVerifyEnvName = "CONSUL_HTTP_SSL_VERIFY"

// GRPCAddrEnvName defines an environment variable name which sets the gRPC
// address for consul connect envoy. Note this isn't actually used by the api
// client in this package but is defined here for consistency with all the
// other ENV names we use.
GRPCAddrEnvName = "CONSUL_GRPC_ADDR"

// GRPCCAFileEnvName defines an environment variable name which sets the
// CA file to use for talking to Consul gRPC over TLS.
GRPCCAFileEnvName = "CONSUL_GRPC_CACERT"
Expand Down
39 changes: 39 additions & 0 deletions command/resource/client/grpc-client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1

package client

import (
"fmt"

"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

"github.com/hashicorp/consul/proto-public/pbresource"
)

type GRPCClient struct {
Client pbresource.ResourceServiceClient
Config *GRPCConfig
Conn *grpc.ClientConn
}

func NewGRPCClient(config *GRPCConfig) (*GRPCClient, error) {
conn, err := dial(config)
if err != nil {
return nil, fmt.Errorf("**** error dialing grpc: %+v", err)
}
return &GRPCClient{
Client: pbresource.NewResourceServiceClient(conn),
Config: config,
Conn: conn,
}, nil
}

func dial(c *GRPCConfig) (*grpc.ClientConn, error) {
// TODO: decide if we use TLS mode based on the config
dialOpts := []grpc.DialOption{
grpc.WithTransportCredentials(insecure.NewCredentials()),
}
return grpc.Dial(c.Address, dialOpts...)
}
51 changes: 51 additions & 0 deletions command/resource/client/grpc-client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1

package client

import (
"context"
"fmt"
"testing"

"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"

"github.com/hashicorp/consul/agent"
"github.com/hashicorp/consul/internal/resource/demo"
"github.com/hashicorp/consul/proto-public/pbresource"
"github.com/hashicorp/consul/proto/private/prototest"
"github.com/hashicorp/consul/sdk/testutil"
"github.com/hashicorp/consul/testrpc"
)

func TestResourceRead(t *testing.T) {
t.Parallel()

a := agent.NewTestAgent(t, "ports { grpc = 8502 }")
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
grpcConfig := GetDefaultGRPCConfig()
gRPCClient, err := NewGRPCClient(grpcConfig)

t.Cleanup(func() {
a.Shutdown()
gRPCClient.Conn.Close()
})

t.Run("test", func(t *testing.T) {
if err != nil {
fmt.Println("error when create new grpc client")
}

v2Artist, err := demo.GenerateV2Artist()
require.NoError(t, err)

writeRsp, err := gRPCClient.Client.Write(testutil.TestContext(t), &pbresource.WriteRequest{Resource: v2Artist})
require.NoError(t, err)

readRsp, err := gRPCClient.Client.Read(context.Background(), &pbresource.ReadRequest{Id: v2Artist.Id})
require.NoError(t, err)
require.Equal(t, proto.Equal(readRsp.Resource.Id.Type, demo.TypeV2Artist), true)
prototest.AssertDeepEqual(t, writeRsp.Resource, readRsp.Resource)
})
}
43 changes: 43 additions & 0 deletions command/resource/client/grpc-config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1

package client

import (
"os"
)

const (
// GRPCAddrEnvName defines an environment variable name which sets the gRPC
// server address for the consul CLI.
GRPCAddrEnvName = "CONSUL_GRPC_ADDR"
)

type GRPCConfig struct {
Address string
}

func GetDefaultGRPCConfig() *GRPCConfig {
return &GRPCConfig{
Address: "localhost:8502",
}
}

func LoadGRPCConfig(defaultConfig *GRPCConfig) *GRPCConfig {
if defaultConfig == nil {
defaultConfig = GetDefaultGRPCConfig()
}

overwrittenConfig := loadEnvToDefaultConfig(defaultConfig)

return overwrittenConfig
}

func loadEnvToDefaultConfig(config *GRPCConfig) *GRPCConfig {

if addr := os.Getenv(GRPCAddrEnvName); addr != "" {
config.Address = addr
}

return config
}
58 changes: 58 additions & 0 deletions command/resource/client/grpc-flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1

package client

import (
"flag"
)

type GRPCFlags struct {
address StringValue
}

// mergeFlagsIntoGRPCConfig merges flag values into grpc config
// caller has to parse the CLI args before loading them into flag values
func (f *GRPCFlags) mergeFlagsIntoGRPCConfig(c *GRPCConfig) {
f.address.Merge(&c.Address)
}

func (f *GRPCFlags) ClientFlags() *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.Var(&f.address, "grpc-addr",
"The `address` and port of the Consul GRPC agent. The value can be an IP "+
"address or DNS address, but it must also include the port. This can "+
"also be specified via the CONSUL_GRPC_ADDR environment variable. The "+
"default value is 127.0.0.1:8502. It supports TLS communication "+
"by setting the environment variable CONSUL_GRPC_TLS=true.")
return fs
}

type StringValue struct {
v *string
}

// Set implements the flag.Value interface.
func (s *StringValue) Set(v string) error {
if s.v == nil {
s.v = new(string)
}
*(s.v) = v
return nil
}

// String implements the flag.Value interface.
func (s *StringValue) String() string {
var current string
if s.v != nil {
current = *(s.v)
}
return current
}

// Merge will overlay this value if it has been set.
func (s *StringValue) Merge(onto *string) {
if s.v != nil {
*onto = *(s.v)
}
}
4 changes: 0 additions & 4 deletions command/resource/read/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,6 @@ func (c *cmd) Run(args []string) int {
return 1
}
} else {
if len(args) < 2 {
c.UI.Error("Incorrect argument format: Must specify two arguments: resource type and resource name")
return 1
}
var err error
gvk, resourceName, err = resource.GetTypeAndResourceName(args)
if err != nil {
Expand Down

0 comments on commit 9dc2444

Please sign in to comment.