func main() { log.SetPrefix("[master log] ") path := "plugin_provider" if runtime.GOOS == "windows" { path = path + ".exe" } client, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, os.Stderr, path) if err != nil { log.Fatalf("Error running plugin: %s", err) } defer client.Close() p := plug{client} res, err := p.SayHi("master") if err != nil { log.Fatalf("error calling SayHi: %s", err) } log.Printf("Response from plugin: %q", res) res, err = p.SayBye("master") if err != nil { log.Fatalf("error calling SayBye: %s", err) } log.Printf("Response from plugin2: %q", res) }
func executeTests(config Config, tests []string) error { var commands []string var err error codec := jsonrpc.NewClientCodec plugin, err := pie.StartProviderCodec(codec, os.Stderr, config.Executor.Command, config.Executor.Args...) if err != nil { return err } if err = plugin.Call("Executor.GetCommands", tests, commands); err != nil { return err } for _, command := range commands { // FIXME this only works on Unixes cmd := exec.Command("sh", "-c", command) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err = cmd.Run() if err != nil { return err } } return nil }
func (p *rpcPlugin) newClient() error { client, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, os.Stderr, p.path) if err != nil { log.Fatalf("Error running plugin: %s", err) } p.client = client return nil }
// This function should be called from the master program that wants to run // plugins to extend its functionality. // // This example shows the master program starting a plugin at path // "/var/lib/foo", using JSON-RPC, and writing its output to this application's // Stderr. The application can then call methods on the rpc client returned // using the standard rpc pattern. func ExampleStartProviderCodec() { client, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, os.Stderr, "/var/lib/foo") if err != nil { log.Fatalf("failed to load foo plugin: %s", err) } var reply string client.Call("Foo.ToUpper", "something", &reply) }
func createClient() *plug { log.Printf("Creating plugin") client, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, os.Stderr, path) if err != nil { log.Printf("Create error: %v", err) } p := &plug{client} return p }
func LoadProvisioner(name string) *ProvisionerPlugin { if provisioner == nil { driverPath := fmt.Sprintf("anvil-provisioner-%s", name) client, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, os.Stderr, driverPath) if err != nil { log.Fatalf("Can't load provisioner %s", name) } provisioner = &ProvisionerPlugin{client} } return provisioner }
func LoadVerifier(name string) *VerifierPlugin { if verifier == nil { driverPath := fmt.Sprintf("anvil-verifier-%s", name) client, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, os.Stderr, driverPath) if err != nil { log.Fatalf("Can't load verifier %s", name) } verifier = &VerifierPlugin{client} } return verifier }
func LoadVerifyResultFormatter(name string) *VerifyResultFormatterPlugin { if formatterPlugin == nil { driverPath := fmt.Sprintf("anvil-formatter-%s", name) client, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, os.Stderr, driverPath) if err != nil { log.Fatalf("Can't load verify result formatter %s", name) } formatterPlugin = &VerifyResultFormatterPlugin{client} } return formatterPlugin }
func LoadDriver(name string) *DriverPlugin { if driver == nil { driverPath := fmt.Sprintf("anvil-driver-%s", name) client, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, os.Stderr, driverPath) if err != nil { log.Fatalf("Can't load driver %s", name) } driver = &DriverPlugin{client} driver.Init(config.Cfg.Driver.Options) } return driver }
func (p *pi) newClient() { // note if the client is still running we can't p.client.Close() without a data-race // TODO investigate if there is a better way to clean-up if p.useJSON { p.client, p.err = pie.StartProviderCodec( jsonrpc.NewClientCodec, os.Stderr, p.cmdPath, p.args...) } else { p.client, p.err = pie.StartProvider(os.Stderr, p.cmdPath, p.args...) } if p.err != nil { p.err = fmt.Errorf("plugin %#v failed, error %v", *p, p.err) } }
func NewCephPlugin() *CephPlugin { //ceph plugin path := "./plugin_provider" cephclient, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, os.Stderr, path) if err != nil { fmt.Println("Error running plugin:") } cplug := &CephPlugin{} cplug.Name = "ceph" cplug.Client = cephclient return cplug }
func NewGlusterPlugin() *GlusterPlugin { //gluster plugin path := "./plugin_provider" glusterclient, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, os.Stderr, path) if err != nil { fmt.Println("Error running plugin:") } gplug := &GlusterPlugin{} gplug.Name = "gluster" gplug.Client = glusterclient return gplug }
func determineTestsToExecute(config Config, changedFiles []string) ([]string, error) { var testsToRun []string var err error codec := jsonrpc.NewClientCodec plugin, err := pie.StartProviderCodec(codec, os.Stderr, config.Locator.Command, config.Locator.Args...) if err != nil { return nil, err } if err = plugin.Call("Locator.Locate", changedFiles, testsToRun); err != nil { return nil, err } return testsToRun, nil }
// StartComputationPlugin starts the plugin process func StartComputationPlugin(name string, compID StreamID) (ComputationPlugin, error) { log.Printf("[computations] Launching computation plugin '%s'", name) path := path.Join(os.Getenv("DAGGER_PLUGIN_PATH"), "computation-"+name) client, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, os.Stderr, path, ) if err != nil { return nil, fmt.Errorf("Error starting plugin %s: %s", name, err) } plugin := &computationPlugin{ name: name, compID: compID, client: client, } return plugin, nil }
func findChangedFiles(config Config) ([]string, error) { var changedFiles []string var err error var workingDir string codec := jsonrpc.NewClientCodec plugin, err := pie.StartProviderCodec(codec, os.Stderr, config.Differ.Command, config.Differ.Args...) if err != nil { return nil, err } if workingDir, err = os.Getwd(); err != nil { return nil, err } if err = plugin.Call("Differ.Diff", workingDir, changedFiles); err != nil { return nil, err } return changedFiles, nil }
func (a *App) StartProviders(configDir string, binDir string) error { key, err := ioutil.ReadFile(models.SKYRING_ENC_KEY_FILE) if err != nil { panic(fmt.Sprintf("Unable to read enc key file. err: %v", err)) } providerBinaryPath := path.Join(binDir, conf.ProviderBinaryDir) configs := conf.LoadProviderConfig(path.Join(configDir, conf.ProviderConfDir)) logger.Get().Info("Config:", configs) for _, config := range configs { logger.Get().Debug("Config:", config) //check if the routes are unique //Load the routes later after the provider starts //successfully, otherwise we have to remove the routes if the provider //fails to start var found bool for _, element := range config.Routes { if _, ok := a.routes[element.Name]; ok { logger.Get().Error("Error in Route configuration, Duplicate route: %s", element.Name) //Dont proceed further found = true break } } //If duplicate routes are detected, dont proceed loading this provider if found { logger.Get().Error("Duplicate routes detected, skipping the provider", config) continue } //Start the provider if configured if config.Provider != (conf.ProviderConfig{}) { if config.Provider.Name == "" { logger.Get().Error("Provider Name Empty, skipping the provider", config) continue } //check whether the plugin is initialized already if _, ok := a.providers[config.Provider.Name]; ok { //Provider already initialized logger.Get().Info("Provider already initialized, skipping the provider", config) continue } //Initilaize the provisioner prov, err := provisioner.InitializeProvisioner(config.Provisioner) if err != nil { logger.Get().Error("Unable to initialize the provisioner, skipping the provider:%v", config) continue } if config.Provider.ProviderBinary == "" { //set the default if not provided in config file config.Provider.ProviderBinary = path.Join(providerBinaryPath, config.Provider.Name) } else { config.Provider.ProviderBinary = path.Join(providerBinaryPath, config.Provider.ProviderBinary) } confStr, _ := json.Marshal(conf.SystemConfig) enConfStr, err := crypto.Encrypt(key, []byte(confStr)) if err != nil { logger.Get().Error("Error encrypting the configurations. err: %v", err) continue } enConfStr1 := make([]byte, base64.StdEncoding.EncodedLen(len(enConfStr))) base64.StdEncoding.Encode(enConfStr1, []byte(enConfStr)) eventTypesStr, _ := json.Marshal(EventTypes) providerConfStr, _ := json.Marshal(config) client, err := pie.StartProviderCodec( jsonrpc.NewClientCodec, os.Stderr, config.Provider.ProviderBinary, string(enConfStr1), string(eventTypesStr), string(providerConfStr)) if err != nil { logger.Get().Error("Error starting provider for %s. error: %v", config.Provider.Name, err) continue } //Load the routes for _, element := range config.Routes { //prefix the provider name to the route element.Pattern = fmt.Sprintf("%s/%s", config.Provider.Name, element.Pattern) a.routes[element.Name] = element } //add the provider to the map a.providers[config.Provider.Name] = Provider{Name: config.Provider.Name, Client: client, ProvisionerName: prov} } } if len(a.providers) < 1 { return errors.New("None of the providers are initialized successfully") } return nil }
// Takes a Lua state and a term Output (should be nil if not in a REPL) func exportPluginFunctions(L *lua.LState, o *term.TextOutput) { // Expose the functionality of a given plugin (executable file). // If on Windows, ".exe" is added to the path. // Returns true of successful. L.SetGlobal("Plugin", L.NewFunction(func(L *lua.LState) int { path := L.ToString(1) givenPath := path if runtime.GOOS == "windows" { path = path + ".exe" } if !fs.exists(path) { path = filepath.Join(serverDir, path) } // Connect with the Plugin client, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, os.Stderr, path) if err != nil { if o != nil { o.Err("[Plugin] Could not run plugin!") o.Err("Error: " + err.Error()) } L.Push(lua.LBool(false)) // Fail return 1 // number of results } // May cause a data race //defer client.Close() p := &luaPlugin{client} // Retrieve the Lua code luacode, err := p.LuaCode(givenPath) if err != nil { if o != nil { o.Err("[Plugin] Could not call the LuaCode function!") o.Err("Error: " + err.Error()) } L.Push(lua.LBool(false)) // Fail return 1 // number of results } // Retrieve the help text luahelp, err := p.LuaHelp() if err != nil { if o != nil { o.Err("[Plugin] Could not call the LuaHelp function!") o.Err("Error: " + err.Error()) } L.Push(lua.LBool(false)) // Fail return 1 // number of results } // Run luacode on the current LuaState luacode = strings.TrimSpace(luacode) if L.DoString(luacode) != nil { if o != nil { o.Err("[Plugin] Error in Lua code provided by plugin!") o.Err("Error: " + err.Error()) } L.Push(lua.LBool(false)) // Fail return 1 // number of results } // If in a REPL, output the Plugin help text if o != nil { luahelp = strings.TrimSpace(luahelp) // Add syntax highlighting and output the text o.Println(highlight(o, luahelp)) } L.Push(lua.LBool(true)) // Success return 1 // number of results })) // Retrieve the code from the Lua.Code function of the plugin L.SetGlobal("PluginCode", L.NewFunction(func(L *lua.LState) int { path := L.ToString(1) givenPath := path if runtime.GOOS == "windows" { path = path + ".exe" } if !fs.exists(path) { path = filepath.Join(serverDir, path) } // Connect with the Plugin client, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, os.Stderr, path) if err != nil { if o != nil { o.Err("[PluginCode] Could not run plugin!") o.Err("Error: " + err.Error()) } L.Push(lua.LString("")) // Fail return 1 // number of results } // May cause a data race //defer client.Close() p := &luaPlugin{client} // Retrieve the Lua code luacode, err := p.LuaCode(givenPath) if err != nil { if o != nil { o.Err("[PluginCode] Could not call the LuaCode function!") o.Err("Error: " + err.Error()) } L.Push(lua.LString("")) // Fail return 1 // number of results } L.Push(lua.LString(luacode)) return 1 // number of results })) // Call a function exposed by a plugin (executable file) // Returns either nil (fail) or a string (success) L.SetGlobal("CallPlugin", L.NewFunction(func(L *lua.LState) int { if L.GetTop() < 2 { if o != nil { o.Err("[CallPlugin] Needs at least 2 arguments") } L.Push(lua.LString("")) // Fail return 1 // number of results } path := L.ToString(1) if runtime.GOOS == "windows" { path = path + ".exe" } if !fs.exists(path) { path = filepath.Join(serverDir, path) } fn := L.ToString(2) var args []lua.LValue if L.GetTop() > 2 { for i := 3; i <= L.GetTop(); i++ { args = append(args, L.Get(i)) } } // Connect with the Plugin logto := os.Stderr if o != nil { logto = os.Stdout } client, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, logto, path) if err != nil { if o != nil { o.Err("[CallPlugin] Could not run plugin!") o.Err("Error: " + err.Error()) } L.Push(lua.LString("")) // Fail return 1 // number of results } // May cause a data race //defer client.Close() jsonargs, err := json.Marshal(args) if err != nil { if o != nil { o.Err("[CallPlugin] Error when marshalling arguments to JSON") o.Err("Error: " + err.Error()) } L.Push(lua.LString("")) // Fail return 1 // number of results } // Attempt to call the given function name var jsonreply []byte if err := client.Call(namespace+"."+fn, jsonargs, &jsonreply); err != nil { if o != nil { o.Err("[CallPlugin] Error when calling function!") o.Err("Function: " + namespace + "." + fn) o.Err("JSON Arguments: " + string(jsonargs)) o.Err("Error: " + err.Error()) } L.Push(lua.LString("")) // Fail return 1 // number of results } L.Push(lua.LString(jsonreply)) // Resulting string return 1 // number of results })) }
func (a *App) StartProviders(configDir string, binDir string) error { providerBinaryPath := path.Join(binDir, ProviderBinaryDir) configs := conf.LoadProviderConfig(path.Join(configDir, ProviderConfDir)) logger.Get().Info("Config:", configs) for _, config := range configs { logger.Get().Debug("Config:", config) //check if the routes are unique //Load the routes later after the provider starts //successfully, otherwise we have to remove the routes if the provider //fails to start var found bool for _, element := range config.Routes { if _, ok := a.routes[element.Name]; ok { logger.Get().Error("Error in Route configuration, Duplicate route: %s", element.Name) //Dont proceed further found = true break } } //If duplicate routes are detected, dont proceed loading this provider if found { logger.Get().Error("Duplicate routes detected, skipping the provider", config) continue } //Start the provider if configured if config.Provider != (conf.ProviderConfig{}) { if config.Provider.Name == "" { logger.Get().Error("Provider Name Empty, skipping the provider", config) continue } //check whether the plugin is initialized already if _, ok := a.providers[config.Provider.Name]; ok { //Provider already initialized logger.Get().Info("Provider already initialized, skipping the provider", config) continue } if config.Provider.ProviderBinary == "" { //set the default if not provided in config file config.Provider.ProviderBinary = path.Join(providerBinaryPath, config.Provider.Name) } else { config.Provider.ProviderBinary = path.Join(providerBinaryPath, config.Provider.ProviderBinary) } confStr, _ := json.Marshal(conf.SystemConfig) client, err := pie.StartProviderCodec(jsonrpc.NewClientCodec, os.Stderr, config.Provider.ProviderBinary, string(confStr)) if err != nil { logger.Get().Error("Error starting provider for %s. error: %v", config.Provider.Name, err) continue } //Load the routes for _, element := range config.Routes { //prefix the provider name to the route element.Pattern = fmt.Sprintf("%s/%s", config.Provider.Name, element.Pattern) a.routes[element.Name] = element } //add the provider to the map a.providers[config.Provider.Name] = Provider{Name: config.Provider.Name, Client: client} } } if len(a.providers) < 1 { return errors.New("None of the providers are initialized successfully") } return nil }