command/connect/proxy: accept -service and -upstream
This commit is contained in:
parent
27aa0743ec
commit
3e8ea58585
|
@ -0,0 +1,54 @@
|
||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/connect/proxy"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FlagUpstreams implements the flag.Value interface and allows specifying
|
||||||
|
// the -upstream flag multiple times and keeping track of the name of the
|
||||||
|
// upstream and the local port.
|
||||||
|
//
|
||||||
|
// The syntax of the value is "name:addr" where addr can be "port" or
|
||||||
|
// "host:port". Examples: "db:8181", "db:127.0.0.10:8282", etc.
|
||||||
|
type FlagUpstreams map[string]proxy.UpstreamConfig
|
||||||
|
|
||||||
|
func (f *FlagUpstreams) String() string {
|
||||||
|
return fmt.Sprintf("%v", *f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FlagUpstreams) Set(value string) error {
|
||||||
|
idx := strings.Index(value, ":")
|
||||||
|
if idx == -1 {
|
||||||
|
return fmt.Errorf("Upstream value should be name:addr in %q", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
addr := ""
|
||||||
|
name := value[:idx]
|
||||||
|
portRaw := value[idx+1:]
|
||||||
|
if idx := strings.Index(portRaw, ":"); idx != -1 {
|
||||||
|
addr = portRaw[:idx]
|
||||||
|
portRaw = portRaw[idx+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
port, err := strconv.ParseInt(portRaw, 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if *f == nil {
|
||||||
|
*f = make(map[string]proxy.UpstreamConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
(*f)[name] = proxy.UpstreamConfig{
|
||||||
|
LocalBindAddress: addr,
|
||||||
|
LocalBindPort: int(port),
|
||||||
|
DestinationName: name,
|
||||||
|
DestinationType: "service",
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/connect/proxy"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFlagUpstreams_impl(t *testing.T) {
|
||||||
|
var _ flag.Value = new(FlagUpstreams)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFlagUpstreams(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
Name string
|
||||||
|
Input []string
|
||||||
|
Expected map[string]proxy.UpstreamConfig
|
||||||
|
Error string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"bad format",
|
||||||
|
[]string{"foo"},
|
||||||
|
nil,
|
||||||
|
"should be name:addr",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"port not int",
|
||||||
|
[]string{"db:hello"},
|
||||||
|
nil,
|
||||||
|
"invalid syntax",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"4 parts",
|
||||||
|
[]string{"db:127.0.0.1:8181:foo"},
|
||||||
|
nil,
|
||||||
|
"invalid syntax",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"single value",
|
||||||
|
[]string{"db:8181"},
|
||||||
|
map[string]proxy.UpstreamConfig{
|
||||||
|
"db": proxy.UpstreamConfig{
|
||||||
|
LocalBindPort: 8181,
|
||||||
|
DestinationName: "db",
|
||||||
|
DestinationType: "service",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"address specified",
|
||||||
|
[]string{"db:127.0.0.55:8181"},
|
||||||
|
map[string]proxy.UpstreamConfig{
|
||||||
|
"db": proxy.UpstreamConfig{
|
||||||
|
LocalBindAddress: "127.0.0.55",
|
||||||
|
LocalBindPort: 8181,
|
||||||
|
DestinationName: "db",
|
||||||
|
DestinationType: "service",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"repeat value, overwrite",
|
||||||
|
[]string{"db:8181", "db:8282"},
|
||||||
|
map[string]proxy.UpstreamConfig{
|
||||||
|
"db": proxy.UpstreamConfig{
|
||||||
|
LocalBindPort: 8282,
|
||||||
|
DestinationName: "db",
|
||||||
|
DestinationType: "service",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.Name, func(t *testing.T) {
|
||||||
|
require := require.New(t)
|
||||||
|
|
||||||
|
var actual map[string]proxy.UpstreamConfig
|
||||||
|
f := (*FlagUpstreams)(&actual)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
for _, input := range tc.Input {
|
||||||
|
err = f.Set(input)
|
||||||
|
// Note we only test the last error. This could make some
|
||||||
|
// test failures confusing but it shouldn't be too bad.
|
||||||
|
}
|
||||||
|
if tc.Error != "" {
|
||||||
|
require.Error(err)
|
||||||
|
require.Contains(err.Error(), tc.Error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
require.Equal(tc.Expected, actual)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,6 +42,8 @@ type cmd struct {
|
||||||
cfgFile string
|
cfgFile string
|
||||||
proxyID string
|
proxyID string
|
||||||
pprofAddr string
|
pprofAddr string
|
||||||
|
service string
|
||||||
|
upstreams map[string]proxyImpl.UpstreamConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cmd) init() {
|
func (c *cmd) init() {
|
||||||
|
@ -66,6 +68,14 @@ func (c *cmd) init() {
|
||||||
"Enable debugging via pprof. Providing a host:port (or just ':port') "+
|
"Enable debugging via pprof. Providing a host:port (or just ':port') "+
|
||||||
"enables profiling HTTP endpoints on that address.")
|
"enables profiling HTTP endpoints on that address.")
|
||||||
|
|
||||||
|
c.flags.StringVar(&c.service, "service", "",
|
||||||
|
"Name of the service this proxy is representing.")
|
||||||
|
|
||||||
|
c.flags.Var((*FlagUpstreams)(&c.upstreams), "upstream",
|
||||||
|
"Upstream service to support connecting to. The format should be "+
|
||||||
|
"'name:addr', such as 'db:8181'. This will make 'db' available "+
|
||||||
|
"on port 8181.")
|
||||||
|
|
||||||
c.http = &flags.HTTPFlags{}
|
c.http = &flags.HTTPFlags{}
|
||||||
flags.Merge(c.flags, c.http.ClientFlags())
|
flags.Merge(c.flags, c.http.ClientFlags())
|
||||||
flags.Merge(c.flags, c.http.ServerFlags())
|
flags.Merge(c.flags, c.http.ServerFlags())
|
||||||
|
@ -158,13 +168,27 @@ func (c *cmd) configWatcher(client *api.Client) (proxyImpl.ConfigWatcher, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the configured proxy ID
|
// Use the configured proxy ID
|
||||||
if c.proxyID == "" {
|
if c.proxyID != "" {
|
||||||
|
return proxyImpl.NewAgentConfigWatcher(client, c.proxyID, c.logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we're representing a manually specified service.
|
||||||
|
if c.service == "" {
|
||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
"-service or -proxy-id must be specified so that proxy can " +
|
"-service or -proxy-id must be specified so that proxy can " +
|
||||||
"configure itself.")
|
"configure itself.")
|
||||||
}
|
}
|
||||||
|
|
||||||
return proxyImpl.NewAgentConfigWatcher(client, c.proxyID, c.logger)
|
// Convert our upstreams to a slice of configurations
|
||||||
|
upstreams := make([]proxyImpl.UpstreamConfig, 0, len(c.upstreams))
|
||||||
|
for _, u := range c.upstreams {
|
||||||
|
upstreams = append(upstreams, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
return proxyImpl.NewStaticConfigWatcher(&proxyImpl.Config{
|
||||||
|
ProxiedServiceName: c.service,
|
||||||
|
Upstreams: upstreams,
|
||||||
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cmd) Synopsis() string {
|
func (c *cmd) Synopsis() string {
|
||||||
|
|
Loading…
Reference in New Issue