etcd-agent: support rootless operation and configurable gofail ports

This commit is contained in:
Anthony Romano
2016-09-08 14:52:10 -07:00
parent bb3ba1ee1c
commit 2e25a772a5
4 changed files with 49 additions and 14 deletions

View File

@ -39,36 +39,44 @@ type Agent struct {
cmd *exec.Cmd cmd *exec.Cmd
logfile *os.File logfile *os.File
logDir string
cfg AgentConfig
} }
func newAgent(etcd, logDir string) (*Agent, error) { type AgentConfig struct {
EtcdPath string
LogDir string
FailpointAddr string
UseRoot bool
}
func newAgent(cfg AgentConfig) (*Agent, error) {
// check if the file exists // check if the file exists
_, err := os.Stat(etcd) _, err := os.Stat(cfg.EtcdPath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
c := exec.Command(etcd) c := exec.Command(cfg.EtcdPath)
err = fileutil.TouchDirAll(logDir) err = fileutil.TouchDirAll(cfg.LogDir)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var f *os.File var f *os.File
f, err = os.Create(filepath.Join(logDir, "etcd.log")) f, err = os.Create(filepath.Join(cfg.LogDir, "etcd.log"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Agent{state: stateUninitialized, cmd: c, logfile: f, logDir: logDir}, nil return &Agent{state: stateUninitialized, cmd: c, logfile: f, cfg: cfg}, nil
} }
// start starts a new etcd process with the given args. // start starts a new etcd process with the given args.
func (a *Agent) start(args ...string) error { func (a *Agent) start(args ...string) error {
a.cmd = exec.Command(a.cmd.Path, args...) a.cmd = exec.Command(a.cmd.Path, args...)
a.cmd.Env = []string{"GOFAIL_HTTP=:2381"} a.cmd.Env = []string{"GOFAIL_HTTP=" + a.cfg.FailpointAddr}
a.cmd.Stdout = a.logfile a.cmd.Stdout = a.logfile
a.cmd.Stderr = a.logfile a.cmd.Stderr = a.logfile
err := a.cmd.Start() err := a.cmd.Start()
@ -131,15 +139,15 @@ func (a *Agent) cleanup() error {
a.state = stateUninitialized a.state = stateUninitialized
a.logfile.Close() a.logfile.Close()
if err := archiveLogAndDataDir(a.logDir, a.dataDir()); err != nil { if err := archiveLogAndDataDir(a.cfg.LogDir, a.dataDir()); err != nil {
return err return err
} }
if err := fileutil.TouchDirAll(a.logDir); err != nil { if err := fileutil.TouchDirAll(a.cfg.LogDir); err != nil {
return err return err
} }
f, err := os.Create(filepath.Join(a.logDir, "etcd.log")) f, err := os.Create(filepath.Join(a.cfg.LogDir, "etcd.log"))
if err != nil { if err != nil {
return err return err
} }
@ -170,14 +178,23 @@ func (a *Agent) terminate() error {
} }
func (a *Agent) dropPort(port int) error { func (a *Agent) dropPort(port int) error {
if !a.cfg.UseRoot {
return nil
}
return netutil.DropPort(port) return netutil.DropPort(port)
} }
func (a *Agent) recoverPort(port int) error { func (a *Agent) recoverPort(port int) error {
if !a.cfg.UseRoot {
return nil
}
return netutil.RecoverPort(port) return netutil.RecoverPort(port)
} }
func (a *Agent) setLatency(ms, rv int) error { func (a *Agent) setLatency(ms, rv int) error {
if !a.cfg.UseRoot {
return nil
}
if ms == 0 { if ms == 0 {
return netutil.RemoveLatency() return netutil.RemoveLatency()
} }

View File

@ -79,7 +79,7 @@ func TestAgentTerminate(t *testing.T) {
// newTestAgent creates a test agent and with a temp data directory. // newTestAgent creates a test agent and with a temp data directory.
func newTestAgent(t *testing.T) (*Agent, string) { func newTestAgent(t *testing.T) (*Agent, string) {
a, err := newAgent(etcdPath, "etcd.log") a, err := newAgent(AgentConfig{EtcdPath: etcdPath, LogDir: "etcd.log"})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -16,6 +16,7 @@ package main
import ( import (
"flag" "flag"
"fmt"
"os" "os"
"path/filepath" "path/filepath"
@ -28,9 +29,26 @@ func main() {
etcdPath := flag.String("etcd-path", filepath.Join(os.Getenv("GOPATH"), "bin/etcd"), "the path to etcd binary") etcdPath := flag.String("etcd-path", filepath.Join(os.Getenv("GOPATH"), "bin/etcd"), "the path to etcd binary")
etcdLogDir := flag.String("etcd-log-dir", "etcd-log", "directory to store etcd logs") etcdLogDir := flag.String("etcd-log-dir", "etcd-log", "directory to store etcd logs")
port := flag.String("port", ":9027", "port to serve agent server") port := flag.String("port", ":9027", "port to serve agent server")
useRoot := flag.Bool("use-root", true, "use root permissions")
failpointAddr := flag.String("failpoint-addr", ":2381", "interface for gofail's HTTP server")
flag.Parse() flag.Parse()
a, err := newAgent(*etcdPath, *etcdLogDir) cfg := AgentConfig{
EtcdPath: *etcdPath,
LogDir: *etcdLogDir,
FailpointAddr: *failpointAddr,
UseRoot: *useRoot,
}
if *useRoot && os.Getuid() != 0 {
fmt.Println("got --use-root=true but not root user")
os.Exit(1)
}
if *useRoot == false {
fmt.Println("root permissions disabled, agent will not modify network")
}
a, err := newAgent(cfg)
if err != nil { if err != nil {
plog.Fatal(err) plog.Fatal(err)
} }

View File

@ -25,7 +25,7 @@ import (
) )
func init() { func init() {
defaultAgent, err := newAgent(etcdPath, "etcd.log") defaultAgent, err := newAgent(AgentConfig{EtcdPath: etcdPath, LogDir: "etcd.log"})
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)
} }