diff --git a/agent/local/proxy.go b/agent/local/proxy.go new file mode 100644 index 0000000000..7f004a7abc --- /dev/null +++ b/agent/local/proxy.go @@ -0,0 +1,26 @@ +package local + +import ( + "fmt" + "os/exec" + + "github.com/hashicorp/consul/agent/proxy" + "github.com/hashicorp/consul/agent/structs" +) + +// newProxyProcess returns the proxy.Proxy for the given ManagedProxy +// state entry. proxy.Proxy is the actual managed process. The returned value +// is the initialized struct but isn't explicitly started. +func (s *State) newProxyProcess(p *structs.ConnectManagedProxy, pToken string) (proxy.Proxy, error) { + switch p.ExecMode { + case structs.ProxyExecModeDaemon: + return &proxy.Daemon{ + Command: exec.Command(p.Command), + ProxyToken: pToken, + Logger: s.logger, + }, nil + + default: + return nil, fmt.Errorf("unsupported managed proxy type: %q", p.ExecMode) + } +} diff --git a/agent/local/state.go b/agent/local/state.go index 8df600b32f..ccb4d77e1a 100644 --- a/agent/local/state.go +++ b/agent/local/state.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/go-uuid" "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/agent/proxy" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/token" "github.com/hashicorp/consul/api" @@ -126,6 +127,9 @@ type ManagedProxy struct { // use service-scoped ACL tokens distributed externally. ProxyToken string + // ManagedProxy is the managed proxy itself that is running. + ManagedProxy proxy.Proxy + // WatchCh is a close-only chan that is closed when the proxy is removed or // updated. WatchCh chan struct{} @@ -603,6 +607,14 @@ func (l *State) AddProxy(proxy *structs.ConnectManagedProxy, token string) (*str return nil, err } + // Initialize the managed proxy process. This doesn't start anything, + // it only sets up the structures we'll use. To start the proxy, the + // caller should call Proxy and use the returned ManagedProxy instance. + proxyProcess, err := l.newProxyProcess(proxy, pToken) + if err != nil { + return nil, err + } + // Lock now. We can't lock earlier as l.Service would deadlock and shouldn't // anyway to minimise the critical section. l.Lock() @@ -650,9 +662,10 @@ func (l *State) AddProxy(proxy *structs.ConnectManagedProxy, token string) (*str close(old.WatchCh) } l.managedProxies[svc.ID] = &ManagedProxy{ - Proxy: proxy, - ProxyToken: pToken, - WatchCh: make(chan struct{}), + Proxy: proxy, + ProxyToken: pToken, + ManagedProxy: proxyProcess, + WatchCh: make(chan struct{}), } // No need to trigger sync as proxy state is local only. diff --git a/agent/proxy/daemon_test.go b/agent/proxy/daemon_test.go index 0af971b931..dbd2099bcc 100644 --- a/agent/proxy/daemon_test.go +++ b/agent/proxy/daemon_test.go @@ -11,6 +11,10 @@ import ( "github.com/stretchr/testify/require" ) +func TestDaemon_impl(t *testing.T) { + var _ Proxy = new(Daemon) +} + func TestDaemonStartStop(t *testing.T) { require := require.New(t) td, closer := testTempDir(t) diff --git a/agent/proxy/proxy.go b/agent/proxy/proxy.go index d42ec3903a..44228b5213 100644 --- a/agent/proxy/proxy.go +++ b/agent/proxy/proxy.go @@ -10,3 +10,19 @@ package proxy // EnvProxyToken is the name of the environment variable that is passed // to managed proxies containing the proxy token. const EnvProxyToken = "CONNECT_PROXY_TOKEN" + +// Proxy is the interface implemented by all types of managed proxies. +// +// Calls to all the functions on this interface must be concurrency safe. +// Please read the documentation carefully on top of each function for expected +// behavior. +type Proxy interface { + // Start starts the proxy. If an error is returned then the managed + // proxy registration is rejected. Therefore, this should only fail if + // the configuration of the proxy itself is irrecoverable, and should + // retry starting for other failures. + Start() error + + // Stop stops the proxy. + Stop() error +}