Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(plugin): execute from function #3899

Merged
merged 10 commits into from
Jan 24, 2024
Merged

Conversation

tbruyelle
Copy link
Contributor

This change introduces a plugin.Execute() function that can be used to run arbitrary code without affecting the Ignite CLI dependencies. The code lives in its own repo, like any other plugins. Arguments can be passed to update the behavior.

Originally, plugins were designed to add new commands to the CLI, but it seems that, with minimal changes, it can be used for other purposes, such as the one described above.

Once merged, this will be used to remove the interchain-security dependency from Ignite CLI which we currently have in #3660 (see discussions 0)

Because this will be used internally in Ignite CLI for specific cases, I don't feel that we need to document this feature in the official documentation.

This change introduces a `plugin.Execute()` function that can be used to
run arbitrary code without affecting the Ignite CLI dependencies. The
code lives in its own repo, like any other plugins. Arguments can be
passed to update the behavior.

Once merged, this will be used to remove the interchain-security dependency
from Ignite CLI which we currently have in #3660 (see discussions [0])

Because this will be used internally in Ignite CLI for specific cases,
I don't feel that we need to document this feature in the official
documentation.

[0]: #3660 (comment)
@jeronimoalbi
Copy link
Member

@tbruyelle I left a comment in the original discussion that could eventually solve the original issue.

The Execute function looks good and seems it could be useful but where would it be used right now?

@tbruyelle
Copy link
Contributor Author

tbruyelle commented Jan 22, 2024

The Execute function looks good and seems it could be useful but where would it be used right now?

@jeronimoalbi There's currently two specific locations where the interchain-security package is imported:

To remove the interchain-security import, the idea is to move that code into a plugin repo, like https://github.com/tbruyelle/cli-plugin-consumer, and then replace the moved code by plugin.Execute. So for instance, for the writeConsumerGenesis, it would look like that :

    if cfg.IsConsumerChain() {
		// Consumer chain writes validators in the consumer module genesis
		err := plugin.Execute(ctx, "github.com/tbruyelle/cli-plugin-consumer", "writeGenesis")
		if err != nil {
			return fmt.Errorf("execute consumer plugin: %w", err)
		}
	} 

For the IsInitialized() func, it would look a bit different because this time we have a value to return (true or false), we can rely on the error to determine that:

   if cfg.IsConsumerChain() {
		// Consumer chain writes validators in the consumer module genesis
		// FIXME use constant for plugin path and args (or introduce new method in plugin/consumer.go)
		err := plugin.Execute(context.Background(), "/home/tom/src/ignite/cli-plugin-consumer", "isInitialized")
		if err != nil {
			// FIXME convert to rpc status.Error to get access to desc
			if errors.Cause(err).Error() == "not initialized" {
				return false, nil
			}
			return false, fmt.Errorf("execute consumer plugin %q %T: %w", err.Error(), err, err)
		}
	}

With these changes, the interchain-security is no longer present in the Ignite CLI go.mod.

@jeronimoalbi
Copy link
Member

For the IsInitialized() func, it would look a bit different because this time we have a value to return (true or false), we can rely on the error to determine that

I wonder if adding Call to plugin.Interface would make sense for cases like this where we would expect to get a value back from an RPC call. In any case, is just a though which we could implement as an improvement if it makes sense.

@tbruyelle
Copy link
Contributor Author

I wonder if adding Call to plugin.Interface would make sense for cases like this where we would expect to get a value back from an RPC call. In any case, is just a though which we could implement as an improvement if it makes sense.

That would be better yes, but I didn't want to change the plugin interface and break existing plugins. But maybe that doesn't really matter. The other point is there's already too many methods in the plugin interface, and adding a new one will increase again its complexity. Finally, since it's internal and not exposed to Ignite users, I think it's acceptable to use the Execute method.

@tbruyelle
Copy link
Contributor Author

Sorry this is wrong, writeConsumerGenesis is called during ignite c init (or ignite c serve). No genesis are written during the scaffold phase.

jeronimoalbi
jeronimoalbi previously approved these changes Jan 23, 2024
Also:
- redirect stdout/stderr to buffer, so Execute's client can read the
  plugin output
- unwrap rpc status error
- add more tests
- add ChainInfo.Home (will be used for consumer plugin)
- update .gitignore in plugin template to ignore also *.ign files
@tbruyelle tbruyelle force-pushed the tbruyelle/feat/plugin-exec branch from 4dd4e3b to 8e8cddc Compare January 23, 2024 11:13
@julienrbrt julienrbrt enabled auto-merge (squash) January 24, 2024 19:59
@julienrbrt julienrbrt merged commit cf24d7e into main Jan 24, 2024
47 of 48 checks passed
@julienrbrt julienrbrt deleted the tbruyelle/feat/plugin-exec branch January 24, 2024 20:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component:ci CI/CD workflow and automated jobs. component:configs type:services Service-related issues.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants