github.com/ranjib/nomad@v0.1.1-0.20160225204057-97751b02f70b/client/driver/utils.go (about) 1 package driver 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "strings" 8 9 "github.com/hashicorp/go-multierror" 10 "github.com/hashicorp/go-plugin" 11 "github.com/hashicorp/nomad/client/config" 12 "github.com/hashicorp/nomad/client/driver/executor" 13 "github.com/hashicorp/nomad/client/driver/logging" 14 ) 15 16 // createExecutor launches an executor plugin and returns an instance of the 17 // Executor interface 18 func createExecutor(config *plugin.ClientConfig, w io.Writer, 19 clientConfig *config.Config) (executor.Executor, *plugin.Client, error) { 20 config.HandshakeConfig = HandshakeConfig 21 config.Plugins = GetPluginMap(w) 22 config.MaxPort = clientConfig.ClientMaxPort 23 config.MinPort = clientConfig.ClientMinPort 24 25 // setting the setsid of the plugin process so that it doesn't get signals sent to 26 // the nomad client. 27 if config.Cmd != nil { 28 isolateCommand(config.Cmd) 29 } 30 31 executorClient := plugin.NewClient(config) 32 rpcClient, err := executorClient.Client() 33 if err != nil { 34 return nil, nil, fmt.Errorf("error creating rpc client for executor plugin: %v", err) 35 } 36 37 raw, err := rpcClient.Dispense("executor") 38 if err != nil { 39 return nil, nil, fmt.Errorf("unable to dispense the executor plugin: %v", err) 40 } 41 executorPlugin := raw.(executor.Executor) 42 return executorPlugin, executorClient, nil 43 } 44 45 func createLogCollector(config *plugin.ClientConfig, w io.Writer, 46 clientConfig *config.Config) (logging.LogCollector, *plugin.Client, error) { 47 config.HandshakeConfig = HandshakeConfig 48 config.Plugins = GetPluginMap(w) 49 config.MaxPort = clientConfig.ClientMaxPort 50 config.MinPort = clientConfig.ClientMinPort 51 if config.Cmd != nil { 52 isolateCommand(config.Cmd) 53 } 54 55 syslogClient := plugin.NewClient(config) 56 rpcCLient, err := syslogClient.Client() 57 if err != nil { 58 return nil, nil, fmt.Errorf("error creating rpc client for syslog plugin: %v", err) 59 } 60 61 raw, err := rpcCLient.Dispense("syslogcollector") 62 if err != nil { 63 return nil, nil, fmt.Errorf("unable to dispense the syslog plugin: %v", err) 64 } 65 logCollector := raw.(logging.LogCollector) 66 return logCollector, syslogClient, nil 67 } 68 69 // killProcess kills a process with the given pid 70 func killProcess(pid int) error { 71 proc, err := os.FindProcess(pid) 72 if err != nil { 73 return err 74 } 75 return proc.Kill() 76 } 77 78 // destroyPlugin kills the plugin with the given pid and also kills the user 79 // process 80 func destroyPlugin(pluginPid int, userPid int) error { 81 var merr error 82 if err := killProcess(pluginPid); err != nil { 83 merr = multierror.Append(merr, err) 84 } 85 86 if err := killProcess(userPid); err != nil { 87 merr = multierror.Append(merr, err) 88 } 89 return merr 90 } 91 92 // validateCommand validates that the command only has a single value and 93 // returns a user friendly error message telling them to use the passed 94 // argField. 95 func validateCommand(command, argField string) error { 96 trimmed := strings.TrimSpace(command) 97 if len(trimmed) == 0 { 98 return fmt.Errorf("command empty: %q", command) 99 } 100 101 if len(trimmed) != len(command) { 102 return fmt.Errorf("command contains extra white space: %q", command) 103 } 104 105 split := strings.Split(trimmed, " ") 106 if len(split) != 1 { 107 return fmt.Errorf("command contained more than one input. Use %q field to pass arguments", argField) 108 } 109 110 return nil 111 }