diff --git a/.github/workflows/proto-checker.yml b/.github/workflows/proto-checker.yml new file mode 100644 index 0000000000..1abdd37c38 --- /dev/null +++ b/.github/workflows/proto-checker.yml @@ -0,0 +1,31 @@ +name: Protobuf Files + +on: + pull_request: + paths: + - "proto/**" + +permissions: + contents: read + +jobs: + lint: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v3 + - uses: bufbuild/buf-setup-action@v1.22.0 + - uses: bufbuild/buf-lint-action@v1 + with: + input: "proto" + + # TODO: Uncomment after PR#3529 is merged + # break-check: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v3 + # - uses: bufbuild/buf-setup-action@v1.22.0 + # - uses: bufbuild/buf-breaking-action@v1 + # with: + # input: "proto" + # against: "https://github.com/${{ github.repository }}.git#branch=${{ github.event.pull_request.base.ref }},ref=HEAD~1,subdir=proto" diff --git a/.gitignore b/.gitignore index 9f3c28161b..671a36b808 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ scripts/**/nodetime-* dist/ node_modules .DS_Store -apps/ .idea .vscode docs/.vuepress/dist diff --git a/Makefile b/Makefile index 7347759283..7292ecdc66 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,26 @@ lint: .PHONY: govet format lint +## proto-all: Format, lint and generate code from proto files using buf. +proto-all: proto-format proto-lint proto-gen + +## proto-gen: Run buf generate. +proto-gen: + @echo Generating code from proto... + @buf generate --template ./proto/buf.gen.yaml --output ./ + +## proto-format: Run buf format and update files with invalid proto format> +proto-format: + @echo Formatting proto files... + @buf format --write + +## proto-lint: Run buf lint. +proto-lint: + @echo Linting proto files... + @buf lint + +.PHONY: proto-all proto-gen proto-format proto-lint + ## test-unit: Run the unit tests. test-unit: @echo Running unit tests... diff --git a/buf.work.yaml b/buf.work.yaml new file mode 100644 index 0000000000..1878b341be --- /dev/null +++ b/buf.work.yaml @@ -0,0 +1,3 @@ +version: v1 +directories: + - proto diff --git a/changelog.md b/changelog.md index c8c2957409..1dc1d03e52 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,17 @@ ### Features +- [#3544](https://github.com/ignite/cli/pull/3544) Add bidirectional communication to plugin system +- [#3561](https://github.com/ignite/cli/pull/3561) Add GetChainInfo method to plugin system API + +### Changes + +- [#3529](https://github.com/ignite/cli/pull/3529) Refactor plugin system to use gRPC + +## [`v0.27.1`](https://github.com/ignite/cli/releases/tag/v0.27.1) + +### Features + - [#3476](https://github.com/ignite/cli/pull/3476) Use `buf.build` binary to code generate from proto files - [#3614](https://github.com/ignite/cli/pull/3614) feat: use DefaultBaseappOptions for app.New method - [#3536](https://github.com/ignite/cli/pull/3536) Change app.go to v2 and add AppWiring feature diff --git a/docs/docs/apps/02-developing-apps.md b/docs/docs/apps/02-developing-apps.md index 1f5a13a508..57d1fdd58b 100644 --- a/docs/docs/apps/02-developing-apps.md +++ b/docs/docs/apps/02-developing-apps.md @@ -43,31 +43,35 @@ All apps must implement a predefined interface: ```go title=ignite/services/plugin/interface.go type Interface interface { // Manifest declares app's Command(s) and Hook(s). - Manifest() (Manifest, error) + Manifest(context.Context) (*Manifest, error) // Execute will be invoked by ignite when an app Command is executed. // It is global for all commands declared in Manifest, if you have declared // multiple commands, use cmd.Path to distinguish them. - Execute(cmd ExecutedCommand) error + // The ClientAPI argument can be used by plugins to get chain app analysis info. + Execute(context.Context, *ExecutedCommand, ClientAPI) error // ExecuteHookPre is invoked by ignite when a command specified by the Hook // path is invoked. // It is global for all hooks declared in Manifest, if you have declared // multiple hooks, use hook.Name to distinguish them. - ExecuteHookPre(hook ExecutedHook) error + // The ClientAPI argument can be used by plugins to get chain app analysis info. + ExecuteHookPre(context.Context, *ExecutedHook, ClientAPI) error // ExecuteHookPost is invoked by ignite when a command specified by the hook // path is invoked. // It is global for all hooks declared in Manifest, if you have declared // multiple hooks, use hook.Name to distinguish them. - ExecuteHookPost(hook ExecutedHook) error + // The ClientAPI argument can be used by plugins to get chain app analysis info. + ExecuteHookPost(context.Context, *ExecutedHook, ClientAPI) error // ExecuteHookCleanUp is invoked by ignite when a command specified by the // hook path is invoked. Unlike ExecuteHookPost, it is invoked regardless of // execution status of the command and hooks. // It is global for all hooks declared in Manifest, if you have declared // multiple hooks, use hook.Name to distinguish them. - ExecuteHookCleanUp(hook ExecutedHook) error + // The ClientAPI argument can be used by plugins to get chain app analysis info. + ExecuteHookCleanUp(context.Context, *ExecutedHook, ClientAPI) error } ``` @@ -76,35 +80,34 @@ the method's body. ## Defining app's manifest -Here is the `Manifest` struct: - -```go title=ignite/services/plugin/interface.go -type Manifest struct { - Name string - - // Commands contains the commands that will be added to the list of ignite - // commands. Each commands are independent, for nested commands use the - // inner Commands field. - Commands []Command - - // Hooks contains the hooks that will be attached to the existing ignite - // commands. - Hooks []Hook - - // SharedHost enables sharing a single app server across all running instances - // of an app. Useful if an app adds or extends long running commands - // - // Example: if an app defines a hook on `ignite chain serve`, a server is instanciated - // when the command is run. Now if you want to interact with that instance from commands - // defined in that app, you need to enable `SharedHost`, or else the commands will just - // instantiate separate app servers. - // - // When enabled, all apps of the same `Path` loaded from the same configuration will - // attach it's gRPC client to a an existing gRPC server. - // - // If an app instance has no other running app servers, it will create one and it - // will be the host. - SharedHost bool `yaml:"shared_host"` +Here is the `Manifest` proto message definition: + +```protobuf title=proto/ignite/services/plugin/grpc/v1/types.proto +message Manifest { + // App name. + string name = 1; + + // Commands contains the commands that will be added to the list of ignite commands. + // Each commands are independent, for nested commands use the inner Commands field. + bool shared_host = 2; + + // Hooks contains the hooks that will be attached to the existing ignite commands. + repeated Command commands = 3; + + // Enables sharing a single app server across all running instances of an Ignite App. + // Useful if an app adds or extends long running commands. + // + // Example: if an app defines a hook on `ignite chain serve`, a server is instanciated + // when the command is run. Now if you want to interact with that instance + // from commands defined in that app, you need to enable shared host, or else the + // commands will just instantiate separate app servers. + // + // When enabled, all apps of the same path loaded from the same configuration will + // attach it's RPC client to a an existing RPC server. + // + // If an app instance has no other running app servers, it will create one and it + // will be the host. + repeated Hook hooks = 4; } ``` @@ -132,16 +135,16 @@ For instance, let's say your app adds a new `oracle` command to `ignite scaffold`, then the `Manifest` method will look like : ```go -func (app) Manifest() (plugin.Manifest, error) { - return plugin.Manifest{ +func (app) Manifest(context.Context) (*plugin.Manifest, error) { + return &plugin.Manifest{ Name: "oracle", - Commands: []plugin.Command{ + Commands: []*plugin.Command{ { Use: "oracle [name]", Short: "Scaffold an oracle module", Long: "Long description goes here...", // Optionnal flags is required - Flags: []plugin.Flag{ + Flags: []*plugin.Flag{ {Name: "source", Type: plugin.FlagTypeString, Usage: "the oracle source"}, }, // Attach the command to `scaffold` @@ -156,14 +159,21 @@ To update the app execution, you have to change the `Execute` command. For example: ```go -func (app) Execute(cmd plugin.ExecutedCommand) error { +func (app) Execute(_ context.Context, cmd *plugin.ExecutedCommand, _ plugin.ClientAPI) error { if len(cmd.Args) == 0 { return fmt.Errorf("oracle name missing") } + + flags, err := cmd.NewFlags() + if err != nil { + return err + } + var ( name = cmd.Args[0] - source, _ = cmd.Flags().GetString("source") + source, _ = flags.GetString("source") ) + // Read chain information c, err := getChain(cmd) if err != nil { @@ -199,10 +209,10 @@ resulting in `post` and `clean up` not executing. The following is an example of a `hook` definition. ```go -func (app) Manifest() (plugin.Manifest, error) { - return plugin.Manifest{ +func (app) Manifest(context.Context) (*plugin.Manifest, error) { + return &plugin.Manifest{ Name: "oracle", - Hooks: []plugin.Hook{ + Hooks: []*plugin.Hook{ { Name: "my-hook", PlaceHookOn: "ignite chain build", @@ -211,8 +221,8 @@ func (app) Manifest() (plugin.Manifest, error) { }, nil } -func (app) ExecuteHookPre(hook plugin.ExecutedHook) error { - switch hook.Name { +func (app) ExecuteHookPre(_ context.Context, h *plugin.ExecutedHook, _ plugin.ClientAPI) error { + switch h.Hook.GetName() { case "my-hook": fmt.Println("I'm executed before ignite chain build") default: @@ -221,8 +231,8 @@ func (app) ExecuteHookPre(hook plugin.ExecutedHook) error { return nil } -func (app) ExecuteHookPost(hook plugin.ExecutedHook) error { - switch hook.Name { +func (app) ExecuteHookPost(_ context.Context, h *plugin.ExecutedHook, _ plugin.ClientAPI) error { + switch h.Hook.GetName() { case "my-hook": fmt.Println("I'm executed after ignite chain build (if no error)") default: @@ -231,8 +241,8 @@ func (app) ExecuteHookPost(hook plugin.ExecutedHook) error { return nil } -func (app) ExecuteHookCleanUp(hook plugin.ExecutedHook) error { - switch hook.Name { +func (app) ExecuteHookCleanUp(_ context.Context, h *plugin.ExecutedHook, _ plugin.ClientAPI) error { + switch h.Hook.GetName() { case "my-hook": fmt.Println("I'm executed after ignite chain build (regardless errors)") default: diff --git a/go.mod b/go.mod index 8492f9534f..be043fe2b4 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/DATA-DOG/go-sqlmock v1.5.0 github.com/blang/semver/v4 v4.0.0 github.com/briandowns/spinner v1.23.0 + github.com/bufbuild/buf v1.7.0 github.com/buger/jsonparser v1.1.1 github.com/cenkalti/backoff v2.2.1+incompatible github.com/charmbracelet/bubbles v0.7.6 @@ -70,6 +71,7 @@ require ( golang.org/x/tools v0.9.1 golang.org/x/vuln v0.1.0 google.golang.org/grpc v1.56.3 + google.golang.org/protobuf v1.30.0 gopkg.in/yaml.v2 v2.4.0 mvdan.cc/gofumpt v0.5.0 sigs.k8s.io/yaml v1.3.0 @@ -93,6 +95,7 @@ require ( github.com/Abirdcfly/dupword v0.0.7 // indirect github.com/Antonboom/errname v0.1.7 // indirect github.com/Antonboom/nilnil v0.1.1 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/BurntSushi/toml v1.2.1 // indirect github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect @@ -125,6 +128,8 @@ require ( github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect + github.com/bufbuild/connect-go v1.0.0 // indirect + github.com/bufbuild/protocompile v0.4.0 // indirect github.com/butuzov/ireturn v0.1.1 // indirect github.com/calmh/randomart v1.1.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect @@ -142,6 +147,7 @@ require ( github.com/confio/ics23/go v0.9.0 // indirect github.com/containerd/console v1.0.4-0.20230508195404-8d3c090fd31c // indirect github.com/containerd/containerd v1.7.0-beta.2 // indirect + github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect github.com/cosiner/argv v0.1.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect @@ -162,7 +168,10 @@ require ( github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/dlclark/regexp2 v1.2.0 // indirect + github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/docker v24.0.7+incompatible // indirect + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -174,6 +183,7 @@ require ( github.com/firefart/nonamedreturns v1.0.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect + github.com/go-chi/chi/v5 v5.0.7 // indirect github.com/go-critic/go-critic v0.6.5 // indirect github.com/go-delve/liner v1.2.3-0.20220127212407-d32d89dd2a5d // indirect github.com/go-git/gcfg v1.5.0 // indirect @@ -181,6 +191,8 @@ require ( github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-toolsmith/astcast v1.0.0 // indirect github.com/go-toolsmith/astcopy v1.0.2 // indirect @@ -201,6 +213,7 @@ require ( github.com/gofrs/uuid v4.3.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.1.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect @@ -241,7 +254,10 @@ require ( github.com/huandu/skiplist v1.2.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/jdxcode/netrc v0.0.0-20210204082910-926c7f70242a // indirect github.com/jgautheron/goconst v1.5.1 // indirect + github.com/jhump/protocompile v0.0.0-20220216033700-d705409f108f // indirect + github.com/jhump/protoreflect v1.15.1 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect github.com/jinzhu/copier v0.3.5 // indirect github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect @@ -257,6 +273,7 @@ require ( github.com/kisielk/gotool v1.0.0 // indirect github.com/kkHAIKE/contextcheck v1.1.3 // indirect github.com/klauspost/compress v1.16.5 // indirect + github.com/klauspost/pgzip v1.2.5 // indirect github.com/kulti/thelper v0.6.3 // indirect github.com/kunwardeep/paralleltest v1.0.6 // indirect github.com/kyoh86/exportloopref v0.1.8 // indirect @@ -284,9 +301,12 @@ require ( github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/moby/buildkit v0.10.4 // indirect github.com/moby/patternmatcher v0.5.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect github.com/moricho/tparallel v0.2.1 // indirect + github.com/morikuni/aec v1.0.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect @@ -300,11 +320,15 @@ require ( github.com/nishanths/predeclared v0.2.2 // indirect github.com/oklog/run v1.0.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect github.com/opencontainers/runc v1.1.7 // indirect github.com/pelletier/go-toml/v2 v2.0.7 // indirect github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pkg/profile v1.6.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/polyfloyd/go-errorlint v1.0.5 // indirect github.com/prometheus/client_golang v1.14.0 // indirect @@ -371,6 +395,10 @@ require ( github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect gitlab.com/bosi/decorder v0.2.3 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.4 // indirect + go.opentelemetry.io/otel v1.11.1 // indirect + go.opentelemetry.io/otel/trace v1.11.1 // indirect go.starlark.net v0.0.0-20220816155156-cfacd8902214 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/goleak v1.1.12 // indirect @@ -383,7 +411,6 @@ require ( golang.org/x/sys v0.13.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect - google.golang.org/protobuf v1.30.0 // indirect; indir ect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 893dbdfea9..b1f35cadd6 100644 --- a/go.sum +++ b/go.sum @@ -77,6 +77,8 @@ github.com/Antonboom/errname v0.1.7 h1:mBBDKvEYwPl4WFFNwec1CZO096G6vzK9vvDQzAwka github.com/Antonboom/errname v0.1.7/go.mod h1:g0ONh16msHIPgJSGsecu1G/dcF2hlYR/0SddnIAGavU= github.com/Antonboom/nilnil v0.1.1 h1:PHhrh5ANKFWRBh7TdYmyyq2gyT2lotnvFvvFbylF81Q= github.com/Antonboom/nilnil v0.1.1/go.mod h1:L1jBqoWM7AOeTD+tSquifKSesRHs4ZdaxvZR+xdJEaI= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -159,8 +161,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -209,6 +211,10 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/bufbuild/buf v1.7.0 h1:uWRjhIXcrWkzIkA5TqXGyJbF51VW54QJsQZ3nwaes5Q= +github.com/bufbuild/buf v1.7.0/go.mod h1:Go40fMAF46PnPLC7jJgTQhAI95pmC0+VtxFKVC0qLq0= +github.com/bufbuild/connect-go v1.0.0 h1:htSflKUT8y1jxhoPhPYTZMrsY3ipUXjjrbcZR5O2cVo= +github.com/bufbuild/connect-go v1.0.0/go.mod h1:9iNvh/NOsfhNBUH5CtvXeVUskQO1xsrEviH7ZArwZ3I= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= @@ -273,6 +279,8 @@ github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUK github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= github.com/cockroachdb/apd/v3 v3.1.0 h1:MK3Ow7LH0W8zkd5GMKA1PvS9qG3bWFI95WaVNfyZJ/w= @@ -291,6 +299,8 @@ github.com/containerd/console v1.0.4-0.20230508195404-8d3c090fd31c h1:sgmd9/Gm5S github.com/containerd/console v1.0.4-0.20230508195404-8d3c090fd31c/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd v1.7.0-beta.2 h1:GWmC96y8j7jlFJX0Wh+covft0M1hHBqQL7lo+N6qvxg= github.com/containerd/containerd v1.7.0-beta.2/go.mod h1:RR01Jsm/jovDKK48sFCVqWyKAH2APMPi88Aeu1on63I= +github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 h1:rQvjv7gRi6Ki/NS/U9oLZFhqyk4dh/GH2M3o/4BRkMM= +github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67/go.mod h1:HDkcKOXRnX6yKnXv3P0QrogFi0DoiauK/LpQi961f0A= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -334,6 +344,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8= github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cristalhq/acmd v0.8.1/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= @@ -379,8 +390,14 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUn github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk= github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= @@ -400,6 +417,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= +github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= @@ -436,6 +455,8 @@ github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlya github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= +github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8= +github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-critic/go-critic v0.6.5 h1:fDaR/5GWURljXwF8Eh31T2GZNz9X4jeboS912mWF8Uo= github.com/go-critic/go-critic v0.6.5/go.mod h1:ezfP/Lh7MA6dBNn4c6ab5ALv3sKnZVLx37tr00uuaOY= github.com/go-delve/delve v1.20.2 h1:rgPK7Iqb1oQk+i2Ilg0fpH6p5LqyixYiAt4N3Lhx4/Y= @@ -466,6 +487,11 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -533,8 +559,8 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0= +github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -611,6 +637,7 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -782,11 +809,15 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jdxcode/netrc v0.0.0-20210204082910-926c7f70242a h1:d4+I1YEKVmWZrgkt6jpXBnLgV2ZjO0YxEtLDdfIZfH4= +github.com/jdxcode/netrc v0.0.0-20210204082910-926c7f70242a/go.mod h1:Zi/ZFkEqFHTm7qkjyNJjaWH4LQA9LQhGJyF0lTYGpxw= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jhump/protocompile v0.0.0-20220216033700-d705409f108f h1:BNuUg9k2EiJmlMwjoef3e8vZLHplbVw6DrjGFjLL+Yo= +github.com/jhump/protocompile v0.0.0-20220216033700-d705409f108f/go.mod h1:qr2b5kx4HbFS7/g4uYO5qv9ei8303JMsC7ESbYiqr2Q= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= @@ -841,6 +872,8 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -959,12 +992,16 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM= +github.com/moby/buildkit v0.10.4 h1:FvC+buO8isGpUFZ1abdSLdGHZVqg9sqI4BbFL8tlzP4= +github.com/moby/buildkit v0.10.4/go.mod h1:Yajz9vt1Zw5q9Pp4pdb3TCSUXJBIroIQGQ3TTs/sLug= github.com/moby/moby v24.0.1+incompatible h1:VzcmrGPwKZLMsjylQP6yqYz3D+MTwFnPt2BDAPYuzQE= github.com/moby/moby v24.0.1+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc= github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= +github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -972,6 +1009,8 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moricho/tparallel v0.2.1 h1:95FytivzT6rYzdJLdtfn6m1bfFJylOJK41+lgv/EHf4= github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= @@ -1032,6 +1071,10 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8= +github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/opencontainers/runc v1.1.7 h1:y2EZDS8sNng4Ksf0GUYNhKbTShZJPJg1FiXJNH/uoCk= github.com/opencontainers/runc v1.1.7/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -1059,10 +1102,14 @@ github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d h1:CdDQnGF8Nq9oc github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.6.0 h1:hUDfIISABYI59DyeB3OTay/HxSRwTQ8rB/H83k6r5dM= +github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1331,6 +1378,12 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.4 h1:PRXhsszxTt5bbPriTjmaweWUsAnJYeWBhUMLRetUgBU= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.4/go.mod h1:05eWWy6ZWzmpeImD3UowLTB3VjDMU1yxQ+ENuVWDM3c= +go.opentelemetry.io/otel v1.11.1 h1:4WLLAmcfkmDk2ukNXJyq3/kiz/3UzCaYq6PskJsaou4= +go.opentelemetry.io/otel v1.11.1/go.mod h1:1nNhXBbWSD0nsL38H6btgnFN2k4i0sNLHNNMZMSbUGE= +go.opentelemetry.io/otel/trace v1.11.1 h1:ofxdnzsNrGBYXbP7t7zpUK281+go5rF7dvdIZXF8gdQ= +go.opentelemetry.io/otel/trace v1.11.1/go.mod h1:f/Q9G7vzk5u91PhbmKbg1Qn0rzH1LJ4vbPHFGkTPtOk= go.starlark.net v0.0.0-20220816155156-cfacd8902214 h1:MqijAN3S61c7KWasOk+zIqIjHQPN6WUra/X3+YAkQxQ= go.starlark.net v0.0.0-20220816155156-cfacd8902214/go.mod h1:VZcBMdr3cT3PnBoWunTabuSEXwVAH+ZJ5zxfs3AdASk= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1459,6 +1512,7 @@ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -1571,6 +1625,8 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1627,6 +1683,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1645,6 +1703,7 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1825,6 +1884,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1861,6 +1922,7 @@ gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/ignite/cmd/plugin.go b/ignite/cmd/plugin.go index eb51cfb319..21078b9318 100644 --- a/ignite/cmd/plugin.go +++ b/ignite/cmd/plugin.go @@ -64,7 +64,7 @@ func LoadPlugins(ctx context.Context, cmd *cobra.Command) error { return nil } - return linkPlugins(rootCmd, plugins) + return linkPlugins(ctx, rootCmd, plugins) } func parseLocalPlugins(cmd *cobra.Command) (*pluginsconfig.Config, error) { @@ -103,7 +103,7 @@ func parseGlobalPlugins() (cfg *pluginsconfig.Config, err error) { return } -func linkPlugins(rootCmd *cobra.Command, plugins []*plugin.Plugin) error { +func linkPlugins(ctx context.Context, rootCmd *cobra.Command, plugins []*plugin.Plugin) error { // Link plugins to related commands var linkErrors []*plugin.Plugin for _, p := range plugins { @@ -111,30 +111,37 @@ func linkPlugins(rootCmd *cobra.Command, plugins []*plugin.Plugin) error { linkErrors = append(linkErrors, p) continue } - manifest, err := p.Interface.Manifest() + + manifest, err := p.Interface.Manifest(ctx) if err != nil { - p.Error = fmt.Errorf("Manifest() error: %w", err) + p.Error = err + linkErrors = append(linkErrors, p) continue } + linkPluginHooks(rootCmd, p, manifest.Hooks) if p.Error != nil { linkErrors = append(linkErrors, p) continue } + linkPluginCmds(rootCmd, p, manifest.Commands) if p.Error != nil { linkErrors = append(linkErrors, p) continue } } + if len(linkErrors) > 0 { // unload any plugin that could have been loaded defer UnloadPlugins() - if err := printPlugins(cliui.New(cliui.WithStdout(os.Stdout))); err != nil { + + if err := printPlugins(ctx, cliui.New(cliui.WithStdout(os.Stdout))); err != nil { // content of loadErrors is more important than a print error, so we don't // return here, just print the error. fmt.Printf("fail to print: %v\n", err) } + var s strings.Builder for _, p := range linkErrors { fmt.Fprintf(&s, "%s: %v", p.Path, p.Error) @@ -152,7 +159,7 @@ func UnloadPlugins() { } } -func linkPluginHooks(rootCmd *cobra.Command, p *plugin.Plugin, hooks []plugin.Hook) { +func linkPluginHooks(rootCmd *cobra.Command, p *plugin.Plugin, hooks []*plugin.Hook) { if p.Error != nil { return } @@ -161,8 +168,8 @@ func linkPluginHooks(rootCmd *cobra.Command, p *plugin.Plugin, hooks []plugin.Ho } } -func linkPluginHook(rootCmd *cobra.Command, p *plugin.Plugin, hook plugin.Hook) { - cmdPath := hook.PlaceHookOnFull() +func linkPluginHook(rootCmd *cobra.Command, p *plugin.Plugin, hook *plugin.Hook) { + cmdPath := hook.CommandPath() cmd := findCommandByPath(rootCmd, cmdPath) if cmd == nil { p.Error = errors.Errorf("unable to find command path %q for app hook %q", cmdPath, hook.Name) @@ -173,30 +180,38 @@ func linkPluginHook(rootCmd *cobra.Command, p *plugin.Plugin, hook plugin.Hook) return } - newExecutedHook := func(hook plugin.Hook, cmd *cobra.Command, args []string) plugin.ExecutedHook { - execHook := plugin.ExecutedHook{ + newExecutedHook := func(hook *plugin.Hook, cmd *cobra.Command, args []string) *plugin.ExecutedHook { + execHook := &plugin.ExecutedHook{ Hook: hook, - ExecutedCommand: plugin.ExecutedCommand{ + ExecutedCommand: &plugin.ExecutedCommand{ Use: cmd.Use, Path: cmd.CommandPath(), Args: args, - OSArgs: os.Args, + OsArgs: os.Args, With: p.With, }, } - execHook.ExecutedCommand.SetFlags(cmd) + execHook.ExecutedCommand.ImportFlags(cmd) return execHook } preRun := cmd.PreRunE cmd.PreRunE = func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + if preRun != nil { err := preRun(cmd, args) if err != nil { return err } } - err := p.Interface.ExecuteHookPre(newExecutedHook(hook, cmd, args)) + + execHook := newExecutedHook(hook, cmd, args) + c, err := newChainWithHomeFlags(cmd) + if err != nil { + return err + } + err = p.Interface.ExecuteHookPre(ctx, execHook, plugin.NewClientAPI(c)) if err != nil { return fmt.Errorf("app %q ExecuteHookPre() error: %w", p.Path, err) } @@ -210,7 +225,13 @@ func linkPluginHook(rootCmd *cobra.Command, p *plugin.Plugin, hook plugin.Hook) err := runCmd(cmd, args) // if the command has failed the `PostRun` will not execute. here we execute the cleanup step before returnning. if err != nil { - err := p.Interface.ExecuteHookCleanUp(newExecutedHook(hook, cmd, args)) + ctx := cmd.Context() + execHook := newExecutedHook(hook, cmd, args) + c, err := newChainWithHomeFlags(cmd) + if err != nil { + return err + } + err = p.Interface.ExecuteHookCleanUp(ctx, execHook, plugin.NewClientAPI(c)) if err != nil { cmd.Printf("app %q ExecuteHookCleanUp() error: %v", p.Path, err) } @@ -224,10 +245,16 @@ func linkPluginHook(rootCmd *cobra.Command, p *plugin.Plugin, hook plugin.Hook) postCmd := cmd.PostRunE cmd.PostRunE = func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() execHook := newExecutedHook(hook, cmd, args) + c, err := newChainWithHomeFlags(cmd) + if err != nil { + return err + } + defer func() { - err := p.Interface.ExecuteHookCleanUp(execHook) + err := p.Interface.ExecuteHookCleanUp(ctx, execHook, plugin.NewClientAPI(c)) if err != nil { cmd.Printf("app %q ExecuteHookCleanUp() error: %v", p.Path, err) } @@ -241,7 +268,7 @@ func linkPluginHook(rootCmd *cobra.Command, p *plugin.Plugin, hook plugin.Hook) } } - err := p.Interface.ExecuteHookPost(execHook) + err = p.Interface.ExecuteHookPost(ctx, execHook, plugin.NewClientAPI(c)) if err != nil { return fmt.Errorf("app %q ExecuteHookPost() error : %w", p.Path, err) } @@ -251,7 +278,7 @@ func linkPluginHook(rootCmd *cobra.Command, p *plugin.Plugin, hook plugin.Hook) // linkPluginCmds tries to add the plugin commands to the legacy ignite // commands. -func linkPluginCmds(rootCmd *cobra.Command, p *plugin.Plugin, pluginCmds []plugin.Command) { +func linkPluginCmds(rootCmd *cobra.Command, p *plugin.Plugin, pluginCmds []*plugin.Command) { if p.Error != nil { return } @@ -263,8 +290,8 @@ func linkPluginCmds(rootCmd *cobra.Command, p *plugin.Plugin, pluginCmds []plugi } } -func linkPluginCmd(rootCmd *cobra.Command, p *plugin.Plugin, pluginCmd plugin.Command) { - cmdPath := pluginCmd.PlaceCommandUnderFull() +func linkPluginCmd(rootCmd *cobra.Command, p *plugin.Plugin, pluginCmd *plugin.Command) { + cmdPath := pluginCmd.Path() cmd := findCommandByPath(rootCmd, cmdPath) if cmd == nil { p.Error = errors.Errorf("unable to find command path %q for app %q", cmdPath, p.Path) @@ -302,17 +329,22 @@ func linkPluginCmd(rootCmd *cobra.Command, p *plugin.Plugin, pluginCmd plugin.Co if len(pluginCmd.Commands) == 0 { // pluginCmd has no sub commands, so it's runnable newCmd.RunE = func(cmd *cobra.Command, args []string) error { - return clictx.Do(cmd.Context(), func() error { - execCmd := plugin.ExecutedCommand{ + ctx := cmd.Context() + return clictx.Do(ctx, func() error { + execCmd := &plugin.ExecutedCommand{ Use: cmd.Use, Path: cmd.CommandPath(), Args: args, - OSArgs: os.Args, + OsArgs: os.Args, With: p.With, } - execCmd.SetFlags(cmd) + execCmd.ImportFlags(cmd) // Call the plugin Execute - err := p.Interface.Execute(execCmd) + c, err := newChainWithHomeFlags(cmd) + if err != nil { + return err + } + err = p.Interface.Execute(ctx, execCmd, plugin.NewClientAPI(c)) // NOTE(tb): This pause gives enough time for go-plugin to sync the // output from stdout/stderr of the plugin. Without that pause, this // output can be discarded and not printed in the user console. @@ -369,7 +401,7 @@ func NewAppList() *cobra.Command { Long: "Prints status and information of all installed Ignite Apps.", RunE: func(cmd *cobra.Command, args []string) error { s := cliui.New(cliui.WithStdout(os.Stdout)) - return printPlugins(s) + return printPlugins(cmd.Context(), s) }, } return lstCmd @@ -568,7 +600,7 @@ A git repository will be created with the given module name, unless the current return err } moduleName := args[0] - path, err := plugin.Scaffold(wd, moduleName, false) + path, err := plugin.Scaffold(cmd.Context(), wd, moduleName, false) if err != nil { return err } @@ -605,10 +637,11 @@ func NewAppDescribe() *cobra.Command { Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { s := cliui.New(cliui.WithStdout(os.Stdout)) + ctx := cmd.Context() for _, p := range plugins { if p.Path == args[0] { - manifest, err := p.Interface.Manifest() + manifest, err := p.Interface.Manifest(ctx) if err != nil { return fmt.Errorf("error while loading app manifest: %w", err) } @@ -616,7 +649,7 @@ func NewAppDescribe() *cobra.Command { if len(manifest.Commands) > 0 { s.Println("Commands:") for i, c := range manifest.Commands { - cmdPath := fmt.Sprintf("%s %s", c.PlaceCommandUnderFull(), c.Use) + cmdPath := fmt.Sprintf("%s %s", c.Path(), c.Use) s.Printf(" %d) %s\n", i+1, cmdPath) } } @@ -624,7 +657,7 @@ func NewAppDescribe() *cobra.Command { if len(manifest.Hooks) > 0 { s.Println("Hooks:") for i, h := range manifest.Hooks { - s.Printf(" %d) '%s' on command '%s'\n", i+1, h.Name, h.PlaceHookOnFull()) + s.Printf(" %d) '%s' on command '%s'\n", i+1, h.Name, h.CommandPath()) } } @@ -644,12 +677,12 @@ func getPluginLocationName(p *plugin.Plugin) string { return "local" } -func getPluginStatus(p *plugin.Plugin) string { +func getPluginStatus(ctx context.Context, p *plugin.Plugin) string { if p.Error != nil { return fmt.Sprintf("%s Error: %v", icons.NotOK, p.Error) } - _, err := p.Interface.Manifest() + _, err := p.Interface.Manifest(ctx) if err != nil { return fmt.Sprintf("%s Error: Manifest() returned %v", icons.NotOK, err) } @@ -657,10 +690,10 @@ func getPluginStatus(p *plugin.Plugin) string { return fmt.Sprintf("%s Loaded", icons.OK) } -func printPlugins(session *cliui.Session) error { +func printPlugins(ctx context.Context, session *cliui.Session) error { var entries [][]string for _, p := range plugins { - entries = append(entries, []string{p.Path, getPluginLocationName(p), getPluginStatus(p)}) + entries = append(entries, []string{p.Path, getPluginLocationName(p), getPluginStatus(ctx, p)}) } if err := session.PrintTable([]string{"Path", "Config", "Status"}, entries...); err != nil { diff --git a/ignite/cmd/plugin_default.go b/ignite/cmd/plugin_default.go index 6d9b995704..9ffcc189ad 100644 --- a/ignite/cmd/plugin_default.go +++ b/ignite/cmd/plugin_default.go @@ -90,7 +90,7 @@ func newPluginInstallCmd(dp defaultPlugin) *cobra.Command { // Remove this command before call to linkPlugins because a plugin is // usually not allowed to override an existing command. rootCmd.RemoveCommand(cmd) - if err := linkPlugins(rootCmd, plugins); err != nil { + if err := linkPlugins(cmd.Context(), rootCmd, plugins); err != nil { return err } // Execute the command diff --git a/ignite/cmd/plugin_test.go b/ignite/cmd/plugin_test.go index e8e154f62f..c0e4e13eca 100644 --- a/ignite/cmd/plugin_test.go +++ b/ignite/cmd/plugin_test.go @@ -1,6 +1,7 @@ package ignitecmd import ( + "context" "fmt" "io" "os" @@ -18,7 +19,7 @@ import ( "github.com/ignite/cli/ignite/services/plugin/mocks" ) -func buildRootCmd() *cobra.Command { +func buildRootCmd(ctx context.Context) *cobra.Command { var ( rootCmd = &cobra.Command{ Use: "ignite", @@ -39,24 +40,34 @@ func buildRootCmd() *cobra.Command { scaffoldCmd.AddCommand(scaffoldChainCmd) scaffoldCmd.AddCommand(scaffoldModuleCmd) rootCmd.AddCommand(scaffoldCmd) + rootCmd.SetContext(ctx) return rootCmd } -func assertFlags(t *testing.T, expectedFlags []plugin.Flag, execCmd plugin.ExecutedCommand) { +func assertFlags(t *testing.T, expectedFlags []*plugin.Flag, execCmd *plugin.ExecutedCommand) { var ( have []string expected []string ) - execCmd.Flags().VisitAll(func(f *pflag.Flag) { + + t.Helper() + + flags, err := execCmd.NewFlags() + assert.NoError(t, err) + + flags.VisitAll(func(f *pflag.Flag) { if f.Name == "help" { // ignore help flag return } + have = append(have, f.Name) }) + for _, f := range expectedFlags { expected = append(expected, f.Name) } + assert.Equal(t, expected, have) } @@ -65,49 +76,53 @@ func TestLinkPluginCmds(t *testing.T) { args = []string{"arg1", "arg2"} pluginParams = map[string]string{"key": "val"} // define a plugin with command flags - pluginWithFlags = plugin.Command{ + pluginWithFlags = &plugin.Command{ Use: "flaggy", - Flags: []plugin.Flag{ + Flags: []*plugin.Flag{ {Name: "flag1", Type: plugin.FlagTypeString}, - {Name: "flag2", Type: plugin.FlagTypeInt}, + {Name: "flag2", Type: plugin.FlagTypeInt, DefaultValue: "0"}, }, } ) // helper to assert pluginInterface.Execute() calls - expectExecute := func(t *testing.T, p *mocks.PluginInterface, cmd plugin.Command) { - p.EXPECT().Execute( - mock.MatchedBy(func(execCmd plugin.ExecutedCommand) bool { - return cmd.Use == execCmd.Use - }), - ).Run(func(execCmd plugin.ExecutedCommand) { - // Assert execCmd is populated correctly - assert.True(t, strings.HasSuffix(execCmd.Path, cmd.Use), "wrong path %s", execCmd.Path) - assert.Equal(t, args, execCmd.Args) - assertFlags(t, cmd.Flags, execCmd) - assert.Equal(t, pluginParams, execCmd.With) - }).Return(nil) + expectExecute := func(t *testing.T, ctx context.Context, p *mocks.PluginInterface, cmd *plugin.Command) { + t.Helper() + p.EXPECT(). + Execute( + mock.Anything, + mock.MatchedBy(func(execCmd *plugin.ExecutedCommand) bool { + fmt.Println(cmd.Use == execCmd.Use, cmd.Use, execCmd.Use) + return cmd.Use == execCmd.Use + }), + mock.Anything, + ). + Run(func(_ context.Context, execCmd *plugin.ExecutedCommand, _ plugin.ClientAPI) { + // Assert execCmd is populated correctly + assert.True(t, strings.HasSuffix(execCmd.Path, cmd.Use), "wrong path %s", execCmd.Path) + assert.Equal(t, args, execCmd.Args) + assertFlags(t, cmd.Flags, execCmd) + assert.Equal(t, pluginParams, execCmd.With) + }). + Return(nil) } tests := []struct { name string - setup func(*testing.T, *mocks.PluginInterface) + setup func(*testing.T, context.Context, *mocks.PluginInterface) expectedDumpCmd string expectedError string }{ { name: "ok: link foo at root", - setup: func(t *testing.T, p *mocks.PluginInterface) { - cmd := plugin.Command{ + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + cmd := &plugin.Command{ Use: "foo", } - p.EXPECT().Manifest().Return( - plugin.Manifest{ - Commands: []plugin.Command{cmd}, - }, - nil, - ) - expectExecute(t, p, cmd) + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{Commands: []*plugin.Command{cmd}}, nil) + expectExecute(t, ctx, p, cmd) }, expectedDumpCmd: ` ignite @@ -119,13 +134,15 @@ ignite }, { name: "ok: link foo at subcommand", - setup: func(t *testing.T, p *mocks.PluginInterface) { - cmd := plugin.Command{ + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + cmd := &plugin.Command{ Use: "foo", PlaceCommandUnder: "ignite scaffold", } - p.EXPECT().Manifest().Return(plugin.Manifest{Commands: []plugin.Command{cmd}}, nil) - expectExecute(t, p, cmd) + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{Commands: []*plugin.Command{cmd}}, nil) + expectExecute(t, ctx, p, cmd) }, expectedDumpCmd: ` ignite @@ -137,13 +154,15 @@ ignite }, { name: "ok: link foo at subcommand with incomplete PlaceCommandUnder", - setup: func(t *testing.T, p *mocks.PluginInterface) { - cmd := plugin.Command{ + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + cmd := &plugin.Command{ Use: "foo", PlaceCommandUnder: "scaffold", } - p.EXPECT().Manifest().Return(plugin.Manifest{Commands: []plugin.Command{cmd}}, nil) - expectExecute(t, p, cmd) + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{Commands: []*plugin.Command{cmd}}, nil) + expectExecute(t, ctx, p, cmd) }, expectedDumpCmd: ` ignite @@ -155,99 +174,111 @@ ignite }, { name: "fail: link to runnable command", - setup: func(t *testing.T, p *mocks.PluginInterface) { - p.EXPECT().Manifest().Return(plugin.Manifest{ - Commands: []plugin.Command{ - { - Use: "foo", - PlaceCommandUnder: "ignite scaffold chain", + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{ + Commands: []*plugin.Command{ + { + Use: "foo", + PlaceCommandUnder: "ignite scaffold chain", + }, }, }, - }, - nil, - ) + nil, + ) }, expectedError: `can't attach app command "foo" to runnable command "ignite scaffold chain"`, }, { name: "fail: link to unknown command", - setup: func(t *testing.T, p *mocks.PluginInterface) { - p.EXPECT().Manifest().Return(plugin.Manifest{ - Commands: []plugin.Command{ - { - Use: "foo", - PlaceCommandUnder: "ignite unknown", + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{ + Commands: []*plugin.Command{ + { + Use: "foo", + PlaceCommandUnder: "ignite unknown", + }, }, }, - }, - nil, - ) + nil, + ) }, expectedError: `unable to find command path "ignite unknown" for app "foo"`, }, { name: "fail: plugin name exists in legacy commands", - setup: func(t *testing.T, p *mocks.PluginInterface) { - p.EXPECT().Manifest().Return(plugin.Manifest{ - Commands: []plugin.Command{ - { - Use: "scaffold", + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{ + Commands: []*plugin.Command{ + { + Use: "scaffold", + }, }, }, - }, - nil, - ) + nil, + ) }, expectedError: `app command "scaffold" already exists in Ignite's commands`, }, { name: "fail: plugin name with args exists in legacy commands", - setup: func(t *testing.T, p *mocks.PluginInterface) { - p.EXPECT().Manifest().Return(plugin.Manifest{ - Commands: []plugin.Command{ - { - Use: "scaffold [args]", + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{ + Commands: []*plugin.Command{ + { + Use: "scaffold [args]", + }, }, }, - }, - nil, - ) + nil, + ) }, expectedError: `app command "scaffold" already exists in Ignite's commands`, }, { name: "fail: plugin name exists in legacy sub commands", - setup: func(t *testing.T, p *mocks.PluginInterface) { - p.EXPECT().Manifest().Return(plugin.Manifest{ - Commands: []plugin.Command{ - { - Use: "chain", - PlaceCommandUnder: "scaffold", + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{ + Commands: []*plugin.Command{ + { + Use: "chain", + PlaceCommandUnder: "scaffold", + }, }, }, - }, - nil, - ) + nil, + ) }, expectedError: `app command "chain" already exists in Ignite's commands`, }, { name: "ok: link multiple at root", - setup: func(t *testing.T, p *mocks.PluginInterface) { - fooCmd := plugin.Command{ + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + fooCmd := &plugin.Command{ Use: "foo", } - barCmd := plugin.Command{ + barCmd := &plugin.Command{ Use: "bar", } - p.EXPECT().Manifest().Return(plugin.Manifest{ - Commands: []plugin.Command{ - fooCmd, barCmd, pluginWithFlags, - }, - }, nil) - expectExecute(t, p, fooCmd) - expectExecute(t, p, barCmd) - expectExecute(t, p, pluginWithFlags) + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{ + Commands: []*plugin.Command{ + fooCmd, barCmd, pluginWithFlags, + }, + }, nil) + expectExecute(t, ctx, p, fooCmd) + expectExecute(t, ctx, p, barCmd) + expectExecute(t, ctx, p, pluginWithFlags) }, expectedDumpCmd: ` ignite @@ -261,21 +292,23 @@ ignite }, { name: "ok: link with subcommands", - setup: func(t *testing.T, p *mocks.PluginInterface) { - cmd := plugin.Command{ + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + cmd := &plugin.Command{ Use: "foo", - Commands: []plugin.Command{ + Commands: []*plugin.Command{ {Use: "bar"}, {Use: "baz"}, pluginWithFlags, }, } - p.EXPECT().Manifest().Return(plugin.Manifest{Commands: []plugin.Command{cmd}}, nil) + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{Commands: []*plugin.Command{cmd}}, nil) // cmd is not executed because it's not runnable, only sub-commands // are executed. - expectExecute(t, p, cmd.Commands[0]) - expectExecute(t, p, cmd.Commands[1]) - expectExecute(t, p, cmd.Commands[2]) + expectExecute(t, ctx, p, cmd.Commands[0]) + expectExecute(t, ctx, p, cmd.Commands[1]) + expectExecute(t, ctx, p, cmd.Commands[2]) }, expectedDumpCmd: ` ignite @@ -290,18 +323,20 @@ ignite }, { name: "ok: link with multiple subcommands", - setup: func(t *testing.T, p *mocks.PluginInterface) { - cmd := plugin.Command{ + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + cmd := &plugin.Command{ Use: "foo", - Commands: []plugin.Command{ - {Use: "bar", Commands: []plugin.Command{{Use: "baz"}}}, - {Use: "qux", Commands: []plugin.Command{{Use: "quux"}, {Use: "corge"}}}, + Commands: []*plugin.Command{ + {Use: "bar", Commands: []*plugin.Command{{Use: "baz"}}}, + {Use: "qux", Commands: []*plugin.Command{{Use: "quux"}, {Use: "corge"}}}, }, } - p.EXPECT().Manifest().Return(plugin.Manifest{Commands: []plugin.Command{cmd}}, nil) - expectExecute(t, p, cmd.Commands[0].Commands[0]) - expectExecute(t, p, cmd.Commands[1].Commands[0]) - expectExecute(t, p, cmd.Commands[1].Commands[1]) + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{Commands: []*plugin.Command{cmd}}, nil) + expectExecute(t, ctx, p, cmd.Commands[0].Commands[0]) + expectExecute(t, ctx, p, cmd.Commands[1].Commands[0]) + expectExecute(t, ctx, p, cmd.Commands[1].Commands[1]) }, expectedDumpCmd: ` ignite @@ -319,6 +354,9 @@ ignite } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + require := require.New(t) assert := assert.New(t) pi := mocks.NewPluginInterface(t) @@ -329,10 +367,10 @@ ignite }, Interface: pi, } - rootCmd := buildRootCmd() - tt.setup(t, pi) + rootCmd := buildRootCmd(ctx) + tt.setup(t, ctx, pi) - _ = linkPlugins(rootCmd, []*plugin.Plugin{p}) + _ = linkPlugins(ctx, rootCmd, []*plugin.Plugin{p}) if tt.expectedError != "" { require.Error(p.Error) @@ -370,18 +408,19 @@ func TestLinkPluginHooks(t *testing.T) { var ( args = []string{"arg1", "arg2"} pluginParams = map[string]string{"key": "val"} + ctx = context.Background() // helper to assert pluginInterface.ExecuteHook*() calls in expected order // (pre, then post, then cleanup) - expectExecuteHook = func(t *testing.T, p *mocks.PluginInterface, expectedFlags []plugin.Flag, hooks ...plugin.Hook) { - matcher := func(hook plugin.Hook) any { - return mock.MatchedBy(func(execHook plugin.ExecutedHook) bool { - return hook.Name == execHook.Name && - hook.PlaceHookOn == execHook.PlaceHookOn + expectExecuteHook = func(t *testing.T, p *mocks.PluginInterface, expectedFlags []*plugin.Flag, hooks ...*plugin.Hook) { + matcher := func(hook *plugin.Hook) any { + return mock.MatchedBy(func(execHook *plugin.ExecutedHook) bool { + return hook.Name == execHook.Hook.Name && + hook.PlaceHookOn == execHook.Hook.PlaceHookOn }) } - asserter := func(hook plugin.Hook) func(hook plugin.ExecutedHook) { - return func(execHook plugin.ExecutedHook) { + asserter := func(hook *plugin.Hook) func(_ context.Context, hook *plugin.ExecutedHook, _ plugin.ClientAPI) { + return func(_ context.Context, execHook *plugin.ExecutedHook, _ plugin.ClientAPI) { assert.True(t, strings.HasSuffix(execHook.ExecutedCommand.Path, hook.PlaceHookOn), "wrong path %q want %q", execHook.ExecutedCommand.Path, hook.PlaceHookOn) assert.Equal(t, args, execHook.ExecutedCommand.Args) assertFlags(t, expectedFlags, execHook.ExecutedCommand) @@ -390,18 +429,27 @@ func TestLinkPluginHooks(t *testing.T) { } var lastPre *mock.Call for _, hook := range hooks { - pre := p.EXPECT().ExecuteHookPre(matcher(hook)). - Run(asserter(hook)).Return(nil).Call + pre := p.EXPECT(). + ExecuteHookPre(ctx, matcher(hook), mock.Anything). + Run(asserter(hook)). + Return(nil). + Call if lastPre != nil { pre.NotBefore(lastPre) } lastPre = pre } for _, hook := range hooks { - post := p.EXPECT().ExecuteHookPost(matcher(hook)). - Run(asserter(hook)).Return(nil).Call - cleanup := p.EXPECT().ExecuteHookCleanUp(matcher(hook)). - Run(asserter(hook)).Return(nil).Call + post := p.EXPECT(). + ExecuteHookPost(ctx, matcher(hook), mock.Anything). + Run(asserter(hook)). + Return(nil). + Call + cleanup := p.EXPECT(). + ExecuteHookCleanUp(ctx, matcher(hook), mock.Anything). + Run(asserter(hook)). + Return(nil). + Call post.NotBefore(lastPre) cleanup.NotBefore(post) } @@ -410,90 +458,100 @@ func TestLinkPluginHooks(t *testing.T) { tests := []struct { name string expectedError string - setup func(*testing.T, *mocks.PluginInterface) + setup func(*testing.T, context.Context, *mocks.PluginInterface) }{ { name: "fail: command not runnable", - setup: func(t *testing.T, p *mocks.PluginInterface) { - p.EXPECT().Manifest().Return(plugin.Manifest{ - Hooks: []plugin.Hook{ - { - Name: "test-hook", - PlaceHookOn: "ignite scaffold", + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{ + Hooks: []*plugin.Hook{ + { + Name: "test-hook", + PlaceHookOn: "ignite scaffold", + }, }, }, - }, - nil, - ) + nil, + ) }, expectedError: `can't attach app hook "test-hook" to non executable command "ignite scaffold"`, }, { name: "fail: command doesn't exists", - setup: func(t *testing.T, p *mocks.PluginInterface) { - p.EXPECT().Manifest().Return(plugin.Manifest{ - Hooks: []plugin.Hook{ - { - Name: "test-hook", - PlaceHookOn: "ignite chain", + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{ + Hooks: []*plugin.Hook{ + { + Name: "test-hook", + PlaceHookOn: "ignite chain", + }, }, }, - }, - nil, - ) + nil, + ) }, expectedError: `unable to find command path "ignite chain" for app hook "test-hook"`, }, { name: "ok: single hook", - setup: func(t *testing.T, p *mocks.PluginInterface) { - hook := plugin.Hook{ + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + hook := &plugin.Hook{ Name: "test-hook", PlaceHookOn: "scaffold chain", } - p.EXPECT().Manifest().Return(plugin.Manifest{Hooks: []plugin.Hook{hook}}, nil) - expectExecuteHook(t, p, []plugin.Flag{{Name: "path"}}, hook) + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{Hooks: []*plugin.Hook{hook}}, nil) + expectExecuteHook(t, p, []*plugin.Flag{{Name: "path"}}, hook) }, }, { name: "ok: multiple hooks on same command", - setup: func(t *testing.T, p *mocks.PluginInterface) { - hook1 := plugin.Hook{ + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + hook1 := &plugin.Hook{ Name: "test-hook-1", PlaceHookOn: "scaffold chain", } - hook2 := plugin.Hook{ + hook2 := &plugin.Hook{ Name: "test-hook-2", PlaceHookOn: "scaffold chain", } - p.EXPECT().Manifest().Return(plugin.Manifest{Hooks: []plugin.Hook{hook1, hook2}}, nil) - expectExecuteHook(t, p, []plugin.Flag{{Name: "path"}}, hook1, hook2) + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{Hooks: []*plugin.Hook{hook1, hook2}}, nil) + expectExecuteHook(t, p, []*plugin.Flag{{Name: "path"}}, hook1, hook2) }, }, { name: "ok: multiple hooks on different commands", - setup: func(t *testing.T, p *mocks.PluginInterface) { - hookChain1 := plugin.Hook{ + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + hookChain1 := &plugin.Hook{ Name: "test-hook-1", PlaceHookOn: "scaffold chain", } - hookChain2 := plugin.Hook{ + hookChain2 := &plugin.Hook{ Name: "test-hook-2", PlaceHookOn: "scaffold chain", } - hookModule := plugin.Hook{ + hookModule := &plugin.Hook{ Name: "test-hook-3", PlaceHookOn: "scaffold module", } - p.EXPECT().Manifest().Return(plugin.Manifest{Hooks: []plugin.Hook{hookChain1, hookChain2, hookModule}}, nil) - expectExecuteHook(t, p, []plugin.Flag{{Name: "path"}}, hookChain1, hookChain2) + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{Hooks: []*plugin.Hook{hookChain1, hookChain2, hookModule}}, nil) + expectExecuteHook(t, p, []*plugin.Flag{{Name: "path"}}, hookChain1, hookChain2) expectExecuteHook(t, p, nil, hookModule) }, }, { name: "ok: duplicate hook names on same command", - setup: func(t *testing.T, p *mocks.PluginInterface) { - hooks := []plugin.Hook{ + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + hooks := []*plugin.Hook{ { Name: "test-hook", PlaceHookOn: "ignite scaffold chain", @@ -503,23 +561,27 @@ func TestLinkPluginHooks(t *testing.T) { PlaceHookOn: "ignite scaffold chain", }, } - p.EXPECT().Manifest().Return(plugin.Manifest{Hooks: hooks}, nil) - expectExecuteHook(t, p, []plugin.Flag{{Name: "path"}}, hooks...) + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{Hooks: hooks}, nil) + expectExecuteHook(t, p, []*plugin.Flag{{Name: "path"}}, hooks...) }, }, { name: "ok: duplicate hook names on different commands", - setup: func(t *testing.T, p *mocks.PluginInterface) { - hookChain := plugin.Hook{ + setup: func(t *testing.T, ctx context.Context, p *mocks.PluginInterface) { + hookChain := &plugin.Hook{ Name: "test-hook", PlaceHookOn: "ignite scaffold chain", } - hookModule := plugin.Hook{ + hookModule := &plugin.Hook{ Name: "test-hook", PlaceHookOn: "ignite scaffold module", } - p.EXPECT().Manifest().Return(plugin.Manifest{Hooks: []plugin.Hook{hookChain, hookModule}}, nil) - expectExecuteHook(t, p, []plugin.Flag{{Name: "path"}}, hookChain) + p.EXPECT(). + Manifest(ctx). + Return(&plugin.Manifest{Hooks: []*plugin.Hook{hookChain, hookModule}}, nil) + expectExecuteHook(t, p, []*plugin.Flag{{Name: "path"}}, hookChain) expectExecuteHook(t, p, nil, hookModule) }, }, @@ -527,6 +589,9 @@ func TestLinkPluginHooks(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + require := require.New(t) // assert := assert.New(t) pi := mocks.NewPluginInterface(t) @@ -537,10 +602,10 @@ func TestLinkPluginHooks(t *testing.T) { }, Interface: pi, } - rootCmd := buildRootCmd() - tt.setup(t, pi) + rootCmd := buildRootCmd(ctx) + tt.setup(t, ctx, pi) - _ = linkPlugins(rootCmd, []*plugin.Plugin{p}) + _ = linkPlugins(ctx, rootCmd, []*plugin.Plugin{p}) if tt.expectedError != "" { require.EqualError(p.Error, tt.expectedError) diff --git a/ignite/config/chain/config.go b/ignite/config/chain/config.go index b19cc7fbe3..3724442cbf 100644 --- a/ignite/config/chain/config.go +++ b/ignite/config/chain/config.go @@ -15,7 +15,6 @@ import ( ) var ( - // ConfigFilenames is a list of recognized names as Ignite's chain config file. ConfigFilenames = []string{"config.yml", "config.yaml"} diff --git a/ignite/internal/tools/tools.go b/ignite/internal/tools/tools.go index ce7e689a69..dbc2316bd9 100644 --- a/ignite/internal/tools/tools.go +++ b/ignite/internal/tools/tools.go @@ -4,6 +4,7 @@ package tools import ( + _ "github.com/bufbuild/buf/cmd/buf" _ "github.com/golangci/golangci-lint/cmd/golangci-lint" _ "github.com/tbruyelle/mdgofmt/cmd/mdgofmt" _ "github.com/vektra/mockery/v2" diff --git a/ignite/pkg/cosmosanalysis/module/module.go b/ignite/pkg/cosmosanalysis/module/module.go index 1f73179ecb..0b506cb393 100644 --- a/ignite/pkg/cosmosanalysis/module/module.go +++ b/ignite/pkg/cosmosanalysis/module/module.go @@ -22,57 +22,58 @@ type Msgs map[string][]string // Module keeps metadata about a Cosmos SDK module. type Module struct { // Name of the module. - Name string + Name string `json:"name,omitempty"` // GoModulePath of the app where the module is defined. - GoModulePath string + GoModulePath string `json:"go_module_path,omitempty"` // Pkg holds the proto package info. - Pkg protoanalysis.Package + Pkg protoanalysis.Package `json:"package,omitempty"` - // Msg is a list of sdk.Msg implementation of the module. - Msgs []Msg + // Msgs is a list of sdk.Msg implementation of the module. + Msgs []Msg `json:"messages,omitempty"` // HTTPQueries is a list of module queries. - HTTPQueries []HTTPQuery + HTTPQueries []HTTPQuery `json:"http_queries,omitempty"` // Types is a list of proto types that might be used by module. - Types []Type + Types []Type `json:"types,omitempty"` } // Msg keeps metadata about an sdk.Msg implementation. type Msg struct { // Name of the type. - Name string + Name string `json:"name,omitempty"` // URI of the type. - URI string + URI string `json:"uri,omitempty"` - // FilePath is the path of the .proto file where message is defined at. - FilePath string + // FilePath is the path of the proto file where message is defined. + FilePath string `json:"file_path,omitempty"` } // HTTPQuery is an sdk Query. type HTTPQuery struct { // Name of the RPC func. - Name string + Name string `json:"name,omitempty"` // FullName of the query with service name and rpc func name. - FullName string + FullName string `json:"full_name,omitempty"` - // HTTPAnnotations keeps info about http annotations of query. - Rules []protoanalysis.HTTPRule + // Rules keeps info about configured HTTP rules of RPC functions. + Rules []protoanalysis.HTTPRule `json:"rules,omitempty"` // Paginated indicates that the query is using pagination. - Paginated bool + Paginated bool `json:"paginated,omitempty"` } // Type is a proto type that might be used by module. type Type struct { - Name string + // Name of the type. + Name string `json:"name,omitempty"` // FilePath is the path of the .proto file where message is defined at. - FilePath string + FilePath string `json:"file_path,omitempty"` } type moduleDiscoverer struct { diff --git a/ignite/pkg/cosmosclient/mocks/account_retriever.go b/ignite/pkg/cosmosclient/mocks/account_retriever.go index c5ed1de1f6..d01a5c6f6a 100644 --- a/ignite/pkg/cosmosclient/mocks/account_retriever.go +++ b/ignite/pkg/cosmosclient/mocks/account_retriever.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.22.1. DO NOT EDIT. +// Code generated by mockery v2.27.1. DO NOT EDIT. package mocks diff --git a/ignite/pkg/cosmosclient/mocks/bank_query_client.go b/ignite/pkg/cosmosclient/mocks/bank_query_client.go index 76793e1c4b..32b4722b69 100644 --- a/ignite/pkg/cosmosclient/mocks/bank_query_client.go +++ b/ignite/pkg/cosmosclient/mocks/bank_query_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.22.1. DO NOT EDIT. +// Code generated by mockery v2.27.1. DO NOT EDIT. package mocks diff --git a/ignite/pkg/cosmosclient/mocks/faucet_client.go b/ignite/pkg/cosmosclient/mocks/faucet_client.go index 6c808dce58..12ac46772e 100644 --- a/ignite/pkg/cosmosclient/mocks/faucet_client.go +++ b/ignite/pkg/cosmosclient/mocks/faucet_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.16.0. DO NOT EDIT. +// Code generated by mockery v2.27.1. DO NOT EDIT. package mocks @@ -28,13 +28,16 @@ func (_m *FaucetClient) Transfer(_a0 context.Context, _a1 cosmosfaucet.TransferR ret := _m.Called(_a0, _a1) var r0 cosmosfaucet.TransferResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, cosmosfaucet.TransferRequest) (cosmosfaucet.TransferResponse, error)); ok { + return rf(_a0, _a1) + } if rf, ok := ret.Get(0).(func(context.Context, cosmosfaucet.TransferRequest) cosmosfaucet.TransferResponse); ok { r0 = rf(_a0, _a1) } else { r0 = ret.Get(0).(cosmosfaucet.TransferResponse) } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, cosmosfaucet.TransferRequest) error); ok { r1 = rf(_a0, _a1) } else { @@ -68,6 +71,11 @@ func (_c *FaucetClient_Transfer_Call) Return(_a0 cosmosfaucet.TransferResponse, return _c } +func (_c *FaucetClient_Transfer_Call) RunAndReturn(run func(context.Context, cosmosfaucet.TransferRequest) (cosmosfaucet.TransferResponse, error)) *FaucetClient_Transfer_Call { + _c.Call.Return(run) + return _c +} + type mockConstructorTestingTNewFaucetClient interface { mock.TestingT Cleanup(func()) diff --git a/ignite/pkg/cosmosclient/mocks/gasometer.go b/ignite/pkg/cosmosclient/mocks/gasometer.go index 26b8149585..2bb356b37e 100644 --- a/ignite/pkg/cosmosclient/mocks/gasometer.go +++ b/ignite/pkg/cosmosclient/mocks/gasometer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.16.0. DO NOT EDIT. +// Code generated by mockery v2.27.1. DO NOT EDIT. package mocks @@ -38,6 +38,11 @@ func (_m *Gasometer) CalculateGas(clientCtx grpc.ClientConn, txf tx.Factory, msg ret := _m.Called(_ca...) var r0 *typestx.SimulateResponse + var r1 uint64 + var r2 error + if rf, ok := ret.Get(0).(func(grpc.ClientConn, tx.Factory, ...types.Msg) (*typestx.SimulateResponse, uint64, error)); ok { + return rf(clientCtx, txf, msgs...) + } if rf, ok := ret.Get(0).(func(grpc.ClientConn, tx.Factory, ...types.Msg) *typestx.SimulateResponse); ok { r0 = rf(clientCtx, txf, msgs...) } else { @@ -46,14 +51,12 @@ func (_m *Gasometer) CalculateGas(clientCtx grpc.ClientConn, txf tx.Factory, msg } } - var r1 uint64 if rf, ok := ret.Get(1).(func(grpc.ClientConn, tx.Factory, ...types.Msg) uint64); ok { r1 = rf(clientCtx, txf, msgs...) } else { r1 = ret.Get(1).(uint64) } - var r2 error if rf, ok := ret.Get(2).(func(grpc.ClientConn, tx.Factory, ...types.Msg) error); ok { r2 = rf(clientCtx, txf, msgs...) } else { @@ -95,6 +98,11 @@ func (_c *Gasometer_CalculateGas_Call) Return(_a0 *typestx.SimulateResponse, _a1 return _c } +func (_c *Gasometer_CalculateGas_Call) RunAndReturn(run func(grpc.ClientConn, tx.Factory, ...types.Msg) (*typestx.SimulateResponse, uint64, error)) *Gasometer_CalculateGas_Call { + _c.Call.Return(run) + return _c +} + type mockConstructorTestingTNewGasometer interface { mock.TestingT Cleanup(func()) diff --git a/ignite/pkg/cosmosclient/mocks/rpc_client.go b/ignite/pkg/cosmosclient/mocks/rpc_client.go index d76eae984d..a8b39d43ee 100644 --- a/ignite/pkg/cosmosclient/mocks/rpc_client.go +++ b/ignite/pkg/cosmosclient/mocks/rpc_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.22.1. DO NOT EDIT. +// Code generated by mockery v2.27.1. DO NOT EDIT. package mocks diff --git a/ignite/pkg/cosmosclient/mocks/signer.go b/ignite/pkg/cosmosclient/mocks/signer.go index b199b10fcf..53914d8a73 100644 --- a/ignite/pkg/cosmosclient/mocks/signer.go +++ b/ignite/pkg/cosmosclient/mocks/signer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.16.0. DO NOT EDIT. +// Code generated by mockery v2.27.1. DO NOT EDIT. package mocks @@ -63,6 +63,11 @@ func (_c *Signer_Sign_Call) Return(_a0 error) *Signer_Sign_Call { return _c } +func (_c *Signer_Sign_Call) RunAndReturn(run func(tx.Factory, string, client.TxBuilder, bool) error) *Signer_Sign_Call { + _c.Call.Return(run) + return _c +} + type mockConstructorTestingTNewSigner interface { mock.TestingT Cleanup(func()) diff --git a/ignite/pkg/cosmostxcollector/mocks/saver.go b/ignite/pkg/cosmostxcollector/mocks/saver.go index 734e1f1c11..0f28067f30 100644 --- a/ignite/pkg/cosmostxcollector/mocks/saver.go +++ b/ignite/pkg/cosmostxcollector/mocks/saver.go @@ -1,13 +1,12 @@ -// Code generated by mockery v2.16.0. DO NOT EDIT. +// Code generated by mockery v2.27.1. DO NOT EDIT. package mocks import ( context "context" - mock "github.com/stretchr/testify/mock" - cosmosclient "github.com/ignite/cli/ignite/pkg/cosmosclient" + mock "github.com/stretchr/testify/mock" ) // Saver is an autogenerated mock type for the Saver type @@ -61,6 +60,11 @@ func (_c *Saver_Save_Call) Return(_a0 error) *Saver_Save_Call { return _c } +func (_c *Saver_Save_Call) RunAndReturn(run func(context.Context, []cosmosclient.TX) error) *Saver_Save_Call { + _c.Call.Return(run) + return _c +} + type mockConstructorTestingTNewSaver interface { mock.TestingT Cleanup(func()) diff --git a/ignite/pkg/cosmostxcollector/mocks/txs_collector.go b/ignite/pkg/cosmostxcollector/mocks/txs_collector.go index a80ee11808..9ee77bed6e 100644 --- a/ignite/pkg/cosmostxcollector/mocks/txs_collector.go +++ b/ignite/pkg/cosmostxcollector/mocks/txs_collector.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.16.0. DO NOT EDIT. +// Code generated by mockery v2.27.1. DO NOT EDIT. package mocks @@ -62,6 +62,11 @@ func (_c *TXsCollector_CollectTXs_Call) Return(_a0 error) *TXsCollector_CollectT return _c } +func (_c *TXsCollector_CollectTXs_Call) RunAndReturn(run func(context.Context, int64, chan<- []cosmosclient.TX) error) *TXsCollector_CollectTXs_Call { + _c.Call.Return(run) + return _c +} + type mockConstructorTestingTNewTXsCollector interface { mock.TestingT Cleanup(func()) diff --git a/ignite/pkg/protoanalysis/package.go b/ignite/pkg/protoanalysis/package.go index 3e139c164d..9beb7122cc 100644 --- a/ignite/pkg/protoanalysis/package.go +++ b/ignite/pkg/protoanalysis/package.go @@ -17,35 +17,27 @@ type ( // Package represents a proto pkg. Package struct { // Name of the proto pkg. - Name string + Name string `json:"name,omitempty"` // Path of the package in the fs. - Path string + Path string `json:"path,omitempty"` // Files is a list of .proto files in the package. - Files Files + Files Files `json:"files,omitempty"` // GoImportName is the go package name of proto package. - GoImportName string + GoImportName string `json:"go_import_name,omitempty"` // Messages is a list of proto messages defined in the package. - Messages []Message + Messages []Message `json:"messages,omitempty"` // Services is a list of RPC services. - Services []Service + Services []Service `json:"services,omitempty"` } ) var regexBetaVersion = regexp.MustCompile("^v[0-9]+(beta|alpha)[0-9]+") -func (p Packages) Files() Files { - var files []File - for _, pkg := range p { - files = append(files, pkg.Files...) - } - return files -} - // ModuleName retrieves the single module name of the package. func (p Package) ModuleName() (name string) { names := strings.Split(p.Name, ".") @@ -73,18 +65,28 @@ func (p Package) GoImportPath() string { return strings.Split(p.GoImportName, ";")[0] } +// Files retrieves the files from the package list. +func (p Packages) Files() Files { + var files []File + for _, pkg := range p { + files = append(files, pkg.Files...) + } + return files +} + type ( Files []File File struct { // Path of the file. - Path string + Path string `json:"path,omitempty"` - // Dependencies is a list of imported .proto files in this package. - Dependencies []string + // Dependencies is a list of imported proto packages. + Dependencies []string `json:"dependencies,omitempty"` } ) +// Paths retrieves the list of paths from the files. func (f Files) Paths() []string { var paths []string for _, ff := range f { @@ -97,57 +99,57 @@ type ( // Message represents a proto message. Message struct { // Name of the message. - Name string + Name string `json:"name,omitempty"` - // Path of the file where message is defined at. - Path string + // Path of the proto file where the message is defined. + Path string `json:"path,omitempty"` - // HighestFieldNumber is the highest field number among fields of the message - // This allows to determine new field number when writing to proto message - HighestFieldNumber int + // HighestFieldNumber is the highest field number among fields of the message. + // This allows to determine new field number when writing to proto message. + HighestFieldNumber int `json:"highest_field_number,omitempty"` - // Fields contains message's field names and types - Fields map[string]string + // Fields contains message's field names and types. + Fields map[string]string `json:"fields,omitempty"` } // Service is an RPC service. Service struct { // Name of the services. - Name string + Name string `json:"name,omitempty"` - // RPC is a list of RPC funcs of the service. - RPCFuncs []RPCFunc + // RPCFuncs is a list of RPC funcs of the service. + RPCFuncs []RPCFunc `json:"functions,omitempty"` } // RPCFunc is an RPC func. RPCFunc struct { // Name of the RPC func. - Name string + Name string `json:"name,omitempty"` // RequestType is the request type of RPC func. - RequestType string + RequestType string `json:"request_type,omitempty"` // ReturnsType is the response type of RPC func. - ReturnsType string + ReturnsType string `json:"return_type,omitempty"` // HTTPRules keeps info about http rules of an RPC func. // spec: // https://github.com/googleapis/googleapis/blob/master/google/api/http.proto. - HTTPRules []HTTPRule + HTTPRules []HTTPRule `json:"http_rules,omitempty"` // Paginated indicates that the RPC function is using pagination. - Paginated bool + Paginated bool `json:"paginated,omitempty"` } // HTTPRule keeps info about a configured http rule of an RPC func. HTTPRule struct { - // Params is a list of parameters defined in the http endpoint itself. - Params []string + // Params is a list of parameters defined in the HTTP endpoint itself. + Params []string `json:"params,omitempty"` // HasQuery indicates if there is a request query. - HasQuery bool + HasQuery bool `json:"has_query,omitempty"` // HasBody indicates if there is a request payload. - HasBody bool + HasBody bool `json:"has_body,omitempty"` } ) diff --git a/ignite/services/chain/chain.go b/ignite/services/chain/chain.go index 2bc222ab57..4e8af01382 100644 --- a/ignite/services/chain/chain.go +++ b/ignite/services/chain/chain.go @@ -314,6 +314,11 @@ func (c *Chain) Home() (string, error) { return home, nil } +// AppPath returns the configured App's path. +func (c *Chain) AppPath() string { + return c.app.Path +} + // DefaultHome returns the blockchain node's default home dir when not specified in the app. func (c *Chain) DefaultHome() (string, error) { // check if home is defined in config diff --git a/ignite/services/plugin/cache.go b/ignite/services/plugin/cache.go index a0832da6ce..bcdce5fa28 100644 --- a/ignite/services/plugin/cache.go +++ b/ignite/services/plugin/cache.go @@ -16,6 +16,9 @@ const ( cacheNamespace = "plugin.rpc.context" ) +// Caches configuration for shared plugin hosts. +// The cached configuration can be used to re-attach to running plugins. +// These type of plugins must have "shared_host: true" in their manifest. var storageCache *cache.Cache[hplugin.ReattachConfig] func init() { diff --git a/ignite/services/plugin/cache_test.go b/ignite/services/plugin/cache_test.go index c11ca8b033..44dbb9ec4e 100644 --- a/ignite/services/plugin/cache_test.go +++ b/ignite/services/plugin/cache_test.go @@ -14,7 +14,7 @@ func TestReadWriteConfigCache(t *testing.T) { unixFD, _ := net.ResolveUnixAddr("unix", "/var/folders/5k/sv4bxrs102n_6rr7430jc7j80000gn/T/plugin193424090") rc := hplugin.ReattachConfig{ - Protocol: hplugin.ProtocolNetRPC, + Protocol: hplugin.ProtocolGRPC, ProtocolVersion: hplugin.CoreProtocolVersion, Addr: unixFD, Pid: 24464, @@ -31,7 +31,7 @@ func TestReadWriteConfigCache(t *testing.T) { t.Run("Should error writing bad plugin config to cache", func(t *testing.T) { const path = "/path/to/awesome/plugin" rc := hplugin.ReattachConfig{ - Protocol: hplugin.ProtocolNetRPC, + Protocol: hplugin.ProtocolGRPC, ProtocolVersion: hplugin.CoreProtocolVersion, Addr: nil, Pid: 24464, @@ -44,7 +44,7 @@ func TestReadWriteConfigCache(t *testing.T) { t.Run("Should error with invalid plugin path", func(t *testing.T) { const path = "" rc := hplugin.ReattachConfig{ - Protocol: hplugin.ProtocolNetRPC, + Protocol: hplugin.ProtocolGRPC, ProtocolVersion: hplugin.CoreProtocolVersion, Addr: nil, Pid: 24464, @@ -61,7 +61,7 @@ func TestDeleteConfCache(t *testing.T) { unixFD, _ := net.ResolveUnixAddr("unix", "/var/folders/5k/sv4bxrs102n_6rr7430jc7j80000gn/T/plugin193424090") rc := hplugin.ReattachConfig{ - Protocol: hplugin.ProtocolNetRPC, + Protocol: hplugin.ProtocolGRPC, ProtocolVersion: hplugin.CoreProtocolVersion, Addr: unixFD, Pid: 24464, @@ -90,7 +90,7 @@ func TestCheckConfCache(t *testing.T) { unixFD, _ := net.ResolveUnixAddr("unix", "/var/folders/5k/sv4bxrs102n_6rr7430jc7j80000gn/T/plugin193424090") rc := hplugin.ReattachConfig{ - Protocol: hplugin.ProtocolNetRPC, + Protocol: hplugin.ProtocolGRPC, ProtocolVersion: hplugin.CoreProtocolVersion, Addr: unixFD, Pid: 24464, diff --git a/ignite/services/plugin/client_api.go b/ignite/services/plugin/client_api.go new file mode 100644 index 0000000000..6bfde13ccf --- /dev/null +++ b/ignite/services/plugin/client_api.go @@ -0,0 +1,47 @@ +package plugin + +import ( + "context" +) + +type Chainer interface { + // AppPath returns the configured App's path. + AppPath() string + + // ID returns the configured App's chain id. + ID() (string, error) + + // ConfigPath returns the path to the App's config file. + ConfigPath() string + + // RPCPublicAddress returns the configured App's rpc endpoint. + RPCPublicAddress() (string, error) +} + +// NewClientAPI creates a new app ClientAPI. +func NewClientAPI(c Chainer) ClientAPI { + return clientAPI{chain: c} +} + +type clientAPI struct { + chain Chainer +} + +func (api clientAPI) GetChainInfo(context.Context) (*ChainInfo, error) { + chainID, err := api.chain.ID() + if err != nil { + return nil, err + } + + rpc, err := api.chain.RPCPublicAddress() + if err != nil { + return nil, err + } + + return &ChainInfo{ + ChainId: chainID, + AppPath: api.chain.AppPath(), + ConfigPath: api.chain.ConfigPath(), + RpcAddress: rpc, + }, nil +} diff --git a/ignite/services/plugin/grpc/v1/client_api.pb.go b/ignite/services/plugin/grpc/v1/client_api.pb.go new file mode 100644 index 0000000000..d0a5a00f68 --- /dev/null +++ b/ignite/services/plugin/grpc/v1/client_api.pb.go @@ -0,0 +1,178 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc (unknown) +// source: ignite/services/plugin/grpc/v1/client_api.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ChainInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + AppPath string `protobuf:"bytes,2,opt,name=app_path,json=appPath,proto3" json:"app_path,omitempty"` + ConfigPath string `protobuf:"bytes,3,opt,name=config_path,json=configPath,proto3" json:"config_path,omitempty"` + RpcAddress string `protobuf:"bytes,4,opt,name=rpc_address,json=rpcAddress,proto3" json:"rpc_address,omitempty"` +} + +func (x *ChainInfo) Reset() { + *x = ChainInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_client_api_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ChainInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChainInfo) ProtoMessage() {} + +func (x *ChainInfo) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_client_api_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChainInfo.ProtoReflect.Descriptor instead. +func (*ChainInfo) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_client_api_proto_rawDescGZIP(), []int{0} +} + +func (x *ChainInfo) GetChainId() string { + if x != nil { + return x.ChainId + } + return "" +} + +func (x *ChainInfo) GetAppPath() string { + if x != nil { + return x.AppPath + } + return "" +} + +func (x *ChainInfo) GetConfigPath() string { + if x != nil { + return x.ConfigPath + } + return "" +} + +func (x *ChainInfo) GetRpcAddress() string { + if x != nil { + return x.RpcAddress + } + return "" +} + +var File_ignite_services_plugin_grpc_v1_client_api_proto protoreflect.FileDescriptor + +var file_ignite_services_plugin_grpc_v1_client_api_proto_rawDesc = []byte{ + 0x0a, 0x2f, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x76, 0x31, + 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x1e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, + 0x31, 0x22, 0x83, 0x01, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, + 0x70, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, + 0x70, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, + 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x70, 0x63, 0x5f, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x70, 0x63, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2f, 0x63, 0x6c, 0x69, + 0x2f, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x76, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_ignite_services_plugin_grpc_v1_client_api_proto_rawDescOnce sync.Once + file_ignite_services_plugin_grpc_v1_client_api_proto_rawDescData = file_ignite_services_plugin_grpc_v1_client_api_proto_rawDesc +) + +func file_ignite_services_plugin_grpc_v1_client_api_proto_rawDescGZIP() []byte { + file_ignite_services_plugin_grpc_v1_client_api_proto_rawDescOnce.Do(func() { + file_ignite_services_plugin_grpc_v1_client_api_proto_rawDescData = protoimpl.X.CompressGZIP(file_ignite_services_plugin_grpc_v1_client_api_proto_rawDescData) + }) + return file_ignite_services_plugin_grpc_v1_client_api_proto_rawDescData +} + +var file_ignite_services_plugin_grpc_v1_client_api_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_ignite_services_plugin_grpc_v1_client_api_proto_goTypes = []interface{}{ + (*ChainInfo)(nil), // 0: ignite.services.plugin.grpc.v1.ChainInfo +} +var file_ignite_services_plugin_grpc_v1_client_api_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_ignite_services_plugin_grpc_v1_client_api_proto_init() } +func file_ignite_services_plugin_grpc_v1_client_api_proto_init() { + if File_ignite_services_plugin_grpc_v1_client_api_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_ignite_services_plugin_grpc_v1_client_api_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ChainInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_ignite_services_plugin_grpc_v1_client_api_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_ignite_services_plugin_grpc_v1_client_api_proto_goTypes, + DependencyIndexes: file_ignite_services_plugin_grpc_v1_client_api_proto_depIdxs, + MessageInfos: file_ignite_services_plugin_grpc_v1_client_api_proto_msgTypes, + }.Build() + File_ignite_services_plugin_grpc_v1_client_api_proto = out.File + file_ignite_services_plugin_grpc_v1_client_api_proto_rawDesc = nil + file_ignite_services_plugin_grpc_v1_client_api_proto_goTypes = nil + file_ignite_services_plugin_grpc_v1_client_api_proto_depIdxs = nil +} diff --git a/ignite/services/plugin/grpc/v1/interface.pb.go b/ignite/services/plugin/grpc/v1/interface.pb.go new file mode 100644 index 0000000000..2c294ad841 --- /dev/null +++ b/ignite/services/plugin/grpc/v1/interface.pb.go @@ -0,0 +1,856 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc (unknown) +// source: ignite/services/plugin/grpc/v1/interface.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Type represents the flag type. +type Flag_Type int32 + +const ( + Flag_TYPE_FLAG_STRING_UNSPECIFIED Flag_Type = 0 + Flag_TYPE_FLAG_INT Flag_Type = 1 + Flag_TYPE_FLAG_UINT Flag_Type = 2 + Flag_TYPE_FLAG_INT64 Flag_Type = 3 + Flag_TYPE_FLAG_UINT64 Flag_Type = 4 + Flag_TYPE_FLAG_BOOL Flag_Type = 5 + Flag_TYPE_FLAG_STRING_SLICE Flag_Type = 6 +) + +// Enum value maps for Flag_Type. +var ( + Flag_Type_name = map[int32]string{ + 0: "TYPE_FLAG_STRING_UNSPECIFIED", + 1: "TYPE_FLAG_INT", + 2: "TYPE_FLAG_UINT", + 3: "TYPE_FLAG_INT64", + 4: "TYPE_FLAG_UINT64", + 5: "TYPE_FLAG_BOOL", + 6: "TYPE_FLAG_STRING_SLICE", + } + Flag_Type_value = map[string]int32{ + "TYPE_FLAG_STRING_UNSPECIFIED": 0, + "TYPE_FLAG_INT": 1, + "TYPE_FLAG_UINT": 2, + "TYPE_FLAG_INT64": 3, + "TYPE_FLAG_UINT64": 4, + "TYPE_FLAG_BOOL": 5, + "TYPE_FLAG_STRING_SLICE": 6, + } +) + +func (x Flag_Type) Enum() *Flag_Type { + p := new(Flag_Type) + *p = x + return p +} + +func (x Flag_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Flag_Type) Descriptor() protoreflect.EnumDescriptor { + return file_ignite_services_plugin_grpc_v1_interface_proto_enumTypes[0].Descriptor() +} + +func (Flag_Type) Type() protoreflect.EnumType { + return &file_ignite_services_plugin_grpc_v1_interface_proto_enumTypes[0] +} + +func (x Flag_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Flag_Type.Descriptor instead. +func (Flag_Type) EnumDescriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_interface_proto_rawDescGZIP(), []int{4, 0} +} + +// ExecutedCommand represents a plugin command under execution. +type ExecutedCommand struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Use is the one-line usage message. + Use string `protobuf:"bytes,1,opt,name=use,proto3" json:"use,omitempty"` + // Path contains the command path, e.g. `ignite scaffold foo`. + Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` + // Args are the command arguments. + Args []string `protobuf:"bytes,3,rep,name=args,proto3" json:"args,omitempty"` + // Full list of args taken from the command line. + OsArgs []string `protobuf:"bytes,4,rep,name=os_args,json=osArgs,proto3" json:"os_args,omitempty"` + // With contains the plugin config parameters. + With map[string]string `protobuf:"bytes,5,rep,name=with,proto3" json:"with,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // Flags holds the list of command flags. + Flags []*Flag `protobuf:"bytes,6,rep,name=flags,proto3" json:"flags,omitempty"` +} + +func (x *ExecutedCommand) Reset() { + *x = ExecutedCommand{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecutedCommand) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecutedCommand) ProtoMessage() {} + +func (x *ExecutedCommand) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecutedCommand.ProtoReflect.Descriptor instead. +func (*ExecutedCommand) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_interface_proto_rawDescGZIP(), []int{0} +} + +func (x *ExecutedCommand) GetUse() string { + if x != nil { + return x.Use + } + return "" +} + +func (x *ExecutedCommand) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *ExecutedCommand) GetArgs() []string { + if x != nil { + return x.Args + } + return nil +} + +func (x *ExecutedCommand) GetOsArgs() []string { + if x != nil { + return x.OsArgs + } + return nil +} + +func (x *ExecutedCommand) GetWith() map[string]string { + if x != nil { + return x.With + } + return nil +} + +func (x *ExecutedCommand) GetFlags() []*Flag { + if x != nil { + return x.Flags + } + return nil +} + +// ExecutedHook represents a plugin hook under execution. +type ExecutedHook struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Hook is a copy of the original Hook defined in the Manifest. + Hook *Hook `protobuf:"bytes,1,opt,name=hook,proto3" json:"hook,omitempty"` + // ExecutedCommand gives access to the command attached by the hook. + ExecutedCommand *ExecutedCommand `protobuf:"bytes,2,opt,name=executed_command,json=executedCommand,proto3" json:"executed_command,omitempty"` +} + +func (x *ExecutedHook) Reset() { + *x = ExecutedHook{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecutedHook) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecutedHook) ProtoMessage() {} + +func (x *ExecutedHook) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecutedHook.ProtoReflect.Descriptor instead. +func (*ExecutedHook) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_interface_proto_rawDescGZIP(), []int{1} +} + +func (x *ExecutedHook) GetHook() *Hook { + if x != nil { + return x.Hook + } + return nil +} + +func (x *ExecutedHook) GetExecutedCommand() *ExecutedCommand { + if x != nil { + return x.ExecutedCommand + } + return nil +} + +// Manifest represents the plugin behavior. +type Manifest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Plugin name. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Commands contains the commands that will be added to the list of ignite commands. + // Each commands are independent, for nested commands use the inner Commands field. + SharedHost bool `protobuf:"varint,2,opt,name=shared_host,json=sharedHost,proto3" json:"shared_host,omitempty"` + // Hooks contains the hooks that will be attached to the existing ignite commands. + Commands []*Command `protobuf:"bytes,3,rep,name=commands,proto3" json:"commands,omitempty"` + // Enables sharing a single plugin server across all running instances of a plugin. + // Useful if a plugin adds or extends long running commands. + // + // Example: if a plugin defines a hook on `ignite chain serve`, a plugin server is + // instanciated when the command is run. Now if you want to interact with that instance + // from commands defined in that plugin, you need to enable shared host, or else the + // commands will just instantiate separate plugin servers. + // + // When enabled, all plugins of the same path loaded from the same configuration will + // attach it's RPC client to a an existing RPC server. + // + // If a plugin instance has no other running plugin servers, it will create one and it + // will be the host. + Hooks []*Hook `protobuf:"bytes,4,rep,name=hooks,proto3" json:"hooks,omitempty"` +} + +func (x *Manifest) Reset() { + *x = Manifest{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Manifest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Manifest) ProtoMessage() {} + +func (x *Manifest) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Manifest.ProtoReflect.Descriptor instead. +func (*Manifest) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_interface_proto_rawDescGZIP(), []int{2} +} + +func (x *Manifest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Manifest) GetSharedHost() bool { + if x != nil { + return x.SharedHost + } + return false +} + +func (x *Manifest) GetCommands() []*Command { + if x != nil { + return x.Commands + } + return nil +} + +func (x *Manifest) GetHooks() []*Hook { + if x != nil { + return x.Hooks + } + return nil +} + +// Command represents a plugin command. +type Command struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Use is the one-line usage message. + // + // Recommended syntax is as follow: + // + // [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required. + // ... indicates that you can specify multiple values for the previous argument. + // | indicates mutually exclusive information. You can use the argument to the left of the separator or the + // argument to the right of the separator. You cannot use both arguments in a single use of the command. + // { } delimits a set of mutually exclusive arguments when one of the arguments is required. If the arguments are + // optional, they are enclosed in brackets ([ ]). + // + // Example: add [-F file | -D dir]... [-f format] profile + Use string `protobuf:"bytes,1,opt,name=use,proto3" json:"use,omitempty"` + // Aliases is an array of aliases that can be used instead of the first word in Use. + Aliases []string `protobuf:"bytes,2,rep,name=aliases,proto3" json:"aliases,omitempty"` + // Short is the short description shown in the 'help' output. + Short string `protobuf:"bytes,3,opt,name=short,proto3" json:"short,omitempty"` + // Long is the long message shown in the 'help ' output. + Long string `protobuf:"bytes,4,opt,name=long,proto3" json:"long,omitempty"` + // Hidden defines, if this command is hidden and should NOT show up in the list of available commands. + Hidden bool `protobuf:"varint,5,opt,name=hidden,proto3" json:"hidden,omitempty"` + // Flags holds the list of command flags. + Flags []*Flag `protobuf:"bytes,6,rep,name=flags,proto3" json:"flags,omitempty"` + // Indicates where the command should be placed. + // For instance `ignite scaffold` will place the command at the `scaffold` command. + // An empty value is interpreted as `ignite` (==root). + PlaceCommandUnder string `protobuf:"bytes,7,opt,name=place_command_under,json=placeCommandUnder,proto3" json:"place_command_under,omitempty"` + // List of sub commands. + Commands []*Command `protobuf:"bytes,8,rep,name=commands,proto3" json:"commands,omitempty"` +} + +func (x *Command) Reset() { + *x = Command{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command) ProtoMessage() {} + +func (x *Command) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command.ProtoReflect.Descriptor instead. +func (*Command) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_interface_proto_rawDescGZIP(), []int{3} +} + +func (x *Command) GetUse() string { + if x != nil { + return x.Use + } + return "" +} + +func (x *Command) GetAliases() []string { + if x != nil { + return x.Aliases + } + return nil +} + +func (x *Command) GetShort() string { + if x != nil { + return x.Short + } + return "" +} + +func (x *Command) GetLong() string { + if x != nil { + return x.Long + } + return "" +} + +func (x *Command) GetHidden() bool { + if x != nil { + return x.Hidden + } + return false +} + +func (x *Command) GetFlags() []*Flag { + if x != nil { + return x.Flags + } + return nil +} + +func (x *Command) GetPlaceCommandUnder() string { + if x != nil { + return x.PlaceCommandUnder + } + return "" +} + +func (x *Command) GetCommands() []*Command { + if x != nil { + return x.Commands + } + return nil +} + +// Flag represents of a command line flag. +type Flag struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Name as it appears in the command line. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // One letter abbreviation of the flag. + Shorthand string `protobuf:"bytes,2,opt,name=shorthand,proto3" json:"shorthand,omitempty"` + // Help message. + Usage string `protobuf:"bytes,3,opt,name=usage,proto3" json:"usage,omitempty"` + // Default flag value. + DefaultValue string `protobuf:"bytes,4,opt,name=default_value,json=defaultValue,proto3" json:"default_value,omitempty"` + // Flag type. + Type Flag_Type `protobuf:"varint,5,opt,name=type,proto3,enum=ignite.services.plugin.grpc.v1.Flag_Type" json:"type,omitempty"` + // Flag value. + Value string `protobuf:"bytes,6,opt,name=value,proto3" json:"value,omitempty"` + // Indicates wether or not the flag is propagated on children commands. + Persistent bool `protobuf:"varint,7,opt,name=persistent,proto3" json:"persistent,omitempty"` +} + +func (x *Flag) Reset() { + *x = Flag{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Flag) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Flag) ProtoMessage() {} + +func (x *Flag) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Flag.ProtoReflect.Descriptor instead. +func (*Flag) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_interface_proto_rawDescGZIP(), []int{4} +} + +func (x *Flag) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Flag) GetShorthand() string { + if x != nil { + return x.Shorthand + } + return "" +} + +func (x *Flag) GetUsage() string { + if x != nil { + return x.Usage + } + return "" +} + +func (x *Flag) GetDefaultValue() string { + if x != nil { + return x.DefaultValue + } + return "" +} + +func (x *Flag) GetType() Flag_Type { + if x != nil { + return x.Type + } + return Flag_TYPE_FLAG_STRING_UNSPECIFIED +} + +func (x *Flag) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *Flag) GetPersistent() bool { + if x != nil { + return x.Persistent + } + return false +} + +// Hook represents a user defined action within a plugin. +type Hook struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Identifies the hook for the client to invoke the correct hook. + // It must be unique. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Indicates the command where to register the hooks. + PlaceHookOn string `protobuf:"bytes,2,opt,name=place_hook_on,json=placeHookOn,proto3" json:"place_hook_on,omitempty"` +} + +func (x *Hook) Reset() { + *x = Hook{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Hook) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Hook) ProtoMessage() {} + +func (x *Hook) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Hook.ProtoReflect.Descriptor instead. +func (*Hook) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_interface_proto_rawDescGZIP(), []int{5} +} + +func (x *Hook) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Hook) GetPlaceHookOn() string { + if x != nil { + return x.PlaceHookOn + } + return "" +} + +var File_ignite_services_plugin_grpc_v1_interface_proto protoreflect.FileDescriptor + +var file_ignite_services_plugin_grpc_v1_interface_proto_rawDesc = []byte{ + 0x0a, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x76, 0x31, + 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x12, 0x1e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, + 0x22, 0xa8, 0x02, 0x0a, 0x0f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x75, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, + 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x17, + 0x0a, 0x07, 0x6f, 0x73, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x06, 0x6f, 0x73, 0x41, 0x72, 0x67, 0x73, 0x12, 0x4d, 0x0a, 0x04, 0x77, 0x69, 0x74, 0x68, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, + 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x43, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x04, 0x77, 0x69, 0x74, 0x68, 0x12, 0x3a, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, + 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, + 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6c, 0x61, 0x67, 0x52, 0x05, 0x66, 0x6c, 0x61, + 0x67, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x57, 0x69, 0x74, 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa4, 0x01, 0x0a, 0x0c, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x48, 0x6f, 0x6f, 0x6b, 0x12, 0x38, 0x0a, 0x04, + 0x68, 0x6f, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x69, 0x67, 0x6e, + 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, + 0x52, 0x04, 0x68, 0x6f, 0x6f, 0x6b, 0x12, 0x5a, 0x0a, 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2f, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, + 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x52, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x22, 0xc0, 0x01, 0x0a, 0x08, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x68, 0x6f, + 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, + 0x48, 0x6f, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, + 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x12, 0x3a, 0x0a, 0x05, 0x68, 0x6f, 0x6f, + 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, + 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x05, + 0x68, 0x6f, 0x6f, 0x6b, 0x73, 0x22, 0xa8, 0x02, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x75, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x14, 0x0a, + 0x05, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x6f, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6c, 0x6f, 0x6e, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x69, 0x64, 0x64, 0x65, + 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x12, + 0x3a, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, + 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, + 0x46, 0x6c, 0x61, 0x67, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x70, + 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x75, 0x6e, 0x64, + 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x43, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x43, 0x0a, 0x08, 0x63, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, + 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, + 0x22, 0x95, 0x03, 0x0a, 0x04, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, + 0x09, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x68, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x68, 0x61, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x75, + 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6c, 0x61, 0x67, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, + 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x22, 0xaa, 0x01, 0x0a, 0x04, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4c, 0x41, + 0x47, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, + 0x4c, 0x41, 0x47, 0x5f, 0x49, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x13, 0x0a, + 0x0f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x5f, 0x49, 0x4e, 0x54, 0x36, 0x34, + 0x10, 0x03, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x5f, + 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10, 0x05, 0x12, 0x1a, 0x0a, 0x16, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, + 0x5f, 0x53, 0x4c, 0x49, 0x43, 0x45, 0x10, 0x06, 0x22, 0x3e, 0x0a, 0x04, 0x48, 0x6f, 0x6f, 0x6b, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x68, 0x6f, + 0x6f, 0x6b, 0x5f, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x6c, 0x61, + 0x63, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x4f, 0x6e, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2f, 0x63, 0x6c, + 0x69, 0x2f, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x76, 0x31, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_ignite_services_plugin_grpc_v1_interface_proto_rawDescOnce sync.Once + file_ignite_services_plugin_grpc_v1_interface_proto_rawDescData = file_ignite_services_plugin_grpc_v1_interface_proto_rawDesc +) + +func file_ignite_services_plugin_grpc_v1_interface_proto_rawDescGZIP() []byte { + file_ignite_services_plugin_grpc_v1_interface_proto_rawDescOnce.Do(func() { + file_ignite_services_plugin_grpc_v1_interface_proto_rawDescData = protoimpl.X.CompressGZIP(file_ignite_services_plugin_grpc_v1_interface_proto_rawDescData) + }) + return file_ignite_services_plugin_grpc_v1_interface_proto_rawDescData +} + +var file_ignite_services_plugin_grpc_v1_interface_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_ignite_services_plugin_grpc_v1_interface_proto_goTypes = []interface{}{ + (Flag_Type)(0), // 0: ignite.services.plugin.grpc.v1.Flag.Type + (*ExecutedCommand)(nil), // 1: ignite.services.plugin.grpc.v1.ExecutedCommand + (*ExecutedHook)(nil), // 2: ignite.services.plugin.grpc.v1.ExecutedHook + (*Manifest)(nil), // 3: ignite.services.plugin.grpc.v1.Manifest + (*Command)(nil), // 4: ignite.services.plugin.grpc.v1.Command + (*Flag)(nil), // 5: ignite.services.plugin.grpc.v1.Flag + (*Hook)(nil), // 6: ignite.services.plugin.grpc.v1.Hook + nil, // 7: ignite.services.plugin.grpc.v1.ExecutedCommand.WithEntry +} +var file_ignite_services_plugin_grpc_v1_interface_proto_depIdxs = []int32{ + 7, // 0: ignite.services.plugin.grpc.v1.ExecutedCommand.with:type_name -> ignite.services.plugin.grpc.v1.ExecutedCommand.WithEntry + 5, // 1: ignite.services.plugin.grpc.v1.ExecutedCommand.flags:type_name -> ignite.services.plugin.grpc.v1.Flag + 6, // 2: ignite.services.plugin.grpc.v1.ExecutedHook.hook:type_name -> ignite.services.plugin.grpc.v1.Hook + 1, // 3: ignite.services.plugin.grpc.v1.ExecutedHook.executed_command:type_name -> ignite.services.plugin.grpc.v1.ExecutedCommand + 4, // 4: ignite.services.plugin.grpc.v1.Manifest.commands:type_name -> ignite.services.plugin.grpc.v1.Command + 6, // 5: ignite.services.plugin.grpc.v1.Manifest.hooks:type_name -> ignite.services.plugin.grpc.v1.Hook + 5, // 6: ignite.services.plugin.grpc.v1.Command.flags:type_name -> ignite.services.plugin.grpc.v1.Flag + 4, // 7: ignite.services.plugin.grpc.v1.Command.commands:type_name -> ignite.services.plugin.grpc.v1.Command + 0, // 8: ignite.services.plugin.grpc.v1.Flag.type:type_name -> ignite.services.plugin.grpc.v1.Flag.Type + 9, // [9:9] is the sub-list for method output_type + 9, // [9:9] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name +} + +func init() { file_ignite_services_plugin_grpc_v1_interface_proto_init() } +func file_ignite_services_plugin_grpc_v1_interface_proto_init() { + if File_ignite_services_plugin_grpc_v1_interface_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecutedCommand); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecutedHook); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Manifest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Flag); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Hook); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_ignite_services_plugin_grpc_v1_interface_proto_rawDesc, + NumEnums: 1, + NumMessages: 7, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_ignite_services_plugin_grpc_v1_interface_proto_goTypes, + DependencyIndexes: file_ignite_services_plugin_grpc_v1_interface_proto_depIdxs, + EnumInfos: file_ignite_services_plugin_grpc_v1_interface_proto_enumTypes, + MessageInfos: file_ignite_services_plugin_grpc_v1_interface_proto_msgTypes, + }.Build() + File_ignite_services_plugin_grpc_v1_interface_proto = out.File + file_ignite_services_plugin_grpc_v1_interface_proto_rawDesc = nil + file_ignite_services_plugin_grpc_v1_interface_proto_goTypes = nil + file_ignite_services_plugin_grpc_v1_interface_proto_depIdxs = nil +} diff --git a/ignite/services/plugin/grpc/v1/interface_command.go b/ignite/services/plugin/grpc/v1/interface_command.go new file mode 100644 index 0000000000..c396c75146 --- /dev/null +++ b/ignite/services/plugin/grpc/v1/interface_command.go @@ -0,0 +1,92 @@ +package v1 + +import ( + "strings" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" +) + +const igniteBinaryName = "ignite" + +// Path returns the absolute command path including the binary name as prefix. +func (c *Command) Path() string { + return ensureFullCommandPath(c.PlaceCommandUnder) +} + +// ToCobraCommand returns a new Cobra command that matches the current command. +func (c *Command) ToCobraCommand() (*cobra.Command, error) { + cmd := &cobra.Command{ + Use: c.Use, + Aliases: c.Aliases, + Short: c.Short, + Long: c.Long, + Hidden: c.Hidden, + } + + for _, f := range c.Flags { + var fs *pflag.FlagSet + if f.Persistent { + fs = cmd.PersistentFlags() + } else { + fs = cmd.Flags() + } + + if err := f.exportToFlagSet(fs); err != nil { + return nil, err + } + } + + return cmd, nil +} + +// ImportFlags imports flags from a Cobra command. +func (c *ExecutedCommand) ImportFlags(cmd *cobra.Command) { + c.Flags = extractCobraFlags(cmd) +} + +// NewFlags creates a new flags set initialized with the executed command's flags. +func (c *ExecutedCommand) NewFlags() (*pflag.FlagSet, error) { + fs := pflag.NewFlagSet(igniteBinaryName, pflag.ContinueOnError) + + for _, f := range c.Flags { + if f.Persistent { + continue + } + + if err := f.exportToFlagSet(fs); err != nil { + return nil, err + } + } + + return fs, nil +} + +// NewPersistentFlags creates a new flags set initialized with the executed command's persistent flags. +func (c *ExecutedCommand) NewPersistentFlags() (*pflag.FlagSet, error) { + fs := pflag.NewFlagSet(igniteBinaryName, pflag.ContinueOnError) + + for _, f := range c.Flags { + if !f.Persistent { + continue + } + + if err := f.exportToFlagSet(fs); err != nil { + return nil, err + } + } + + return fs, nil +} + +func ensureFullCommandPath(path string) string { + path = strings.TrimSpace(path) + if path == "" { + return igniteBinaryName + } + + if !strings.HasPrefix(path, igniteBinaryName) { + path = igniteBinaryName + " " + path + } + return path +} diff --git a/ignite/services/plugin/grpc/v1/interface_flag.go b/ignite/services/plugin/grpc/v1/interface_flag.go new file mode 100644 index 0000000000..c458315760 --- /dev/null +++ b/ignite/services/plugin/grpc/v1/interface_flag.go @@ -0,0 +1,129 @@ +package v1 + +import ( + "fmt" + "strconv" + "strings" + + "github.com/spf13/pflag" +) + +const ( + cobraFlagTypeBool = "bool" + cobraFlagTypeInt = "int" + cobraFlagTypeInt64 = "int64" + cobraFlagTypeString = "string" + cobraFlagTypeStringSlice = "stringSlice" + cobraFlagTypeUint = "uint" + cobraFlagTypeUint64 = "uint64" +) + +var flagTypes = map[string]Flag_Type{ + cobraFlagTypeBool: Flag_TYPE_FLAG_BOOL, + cobraFlagTypeInt: Flag_TYPE_FLAG_INT, + cobraFlagTypeInt64: Flag_TYPE_FLAG_INT64, + cobraFlagTypeString: Flag_TYPE_FLAG_STRING_UNSPECIFIED, + cobraFlagTypeStringSlice: Flag_TYPE_FLAG_STRING_SLICE, + cobraFlagTypeUint: Flag_TYPE_FLAG_UINT, + cobraFlagTypeUint64: Flag_TYPE_FLAG_UINT64, +} + +func newDefaultFlagValueError(typeName, value string) error { + return fmt.Errorf("invalid default value for plugin command %s flag: %s", typeName, value) +} + +func (f *Flag) exportToFlagSet(fs *pflag.FlagSet) error { + switch f.Type { + case Flag_TYPE_FLAG_BOOL: + v, err := strconv.ParseBool(f.DefaultValue) + if err != nil { + return newDefaultFlagValueError(cobraFlagTypeBool, f.DefaultValue) + } + + fs.BoolP(f.Name, f.Shorthand, v, f.Usage) + fs.Set(f.Name, f.Value) + case Flag_TYPE_FLAG_INT: + v, err := strconv.Atoi(f.DefaultValue) + if err != nil { + return newDefaultFlagValueError(cobraFlagTypeInt, f.DefaultValue) + } + + fs.IntP(f.Name, f.Shorthand, v, f.Usage) + fs.Set(f.Name, f.Value) + case Flag_TYPE_FLAG_UINT: + v, err := strconv.ParseUint(f.DefaultValue, 10, 64) + if err != nil { + return newDefaultFlagValueError(cobraFlagTypeUint, f.DefaultValue) + } + + fs.UintP(f.Name, f.Shorthand, uint(v), f.Usage) + fs.Set(f.Name, f.Value) + case Flag_TYPE_FLAG_INT64: + v, err := strconv.ParseInt(f.DefaultValue, 10, 64) + if err != nil { + return newDefaultFlagValueError(cobraFlagTypeInt64, f.DefaultValue) + } + + fs.Int64P(f.Name, f.Shorthand, v, f.Usage) + fs.Set(f.Name, f.Value) + case Flag_TYPE_FLAG_UINT64: + v, err := strconv.ParseUint(f.DefaultValue, 10, 64) + if err != nil { + return newDefaultFlagValueError(cobraFlagTypeInt64, f.DefaultValue) + } + + fs.Uint64P(f.Name, f.Shorthand, v, f.Usage) + fs.Set(f.Name, f.Value) + case Flag_TYPE_FLAG_STRING_SLICE: + s := strings.Trim(f.DefaultValue, "[]") + fs.StringSliceP(f.Name, f.Shorthand, strings.Fields(s), f.Usage) + fs.Set(f.Name, strings.Trim(f.Value, "[]")) + case Flag_TYPE_FLAG_STRING_UNSPECIFIED: + fs.StringP(f.Name, f.Shorthand, f.DefaultValue, f.Usage) + fs.Set(f.Name, f.Value) + } + return nil +} + +type flagger interface { + Flags() *pflag.FlagSet + PersistentFlags() *pflag.FlagSet +} + +func extractCobraFlags(cmd flagger) []*Flag { + var flags []*Flag + + if cmd.Flags() != nil { + cmd.Flags().VisitAll(func(pf *pflag.Flag) { + // Skip persistent flags + if cmd.PersistentFlags().Lookup(pf.Name) != nil { + return + } + + flags = append(flags, &Flag{ + Name: pf.Name, + Shorthand: pf.Shorthand, + Usage: pf.Usage, + DefaultValue: pf.DefValue, + Value: pf.Value.String(), + Type: flagTypes[pf.Value.Type()], + }) + }) + } + + if cmd.PersistentFlags() != nil { + cmd.PersistentFlags().VisitAll(func(pf *pflag.Flag) { + flags = append(flags, &Flag{ + Name: pf.Name, + Shorthand: pf.Shorthand, + Usage: pf.Usage, + DefaultValue: pf.DefValue, + Value: pf.Value.String(), + Type: flagTypes[pf.Value.Type()], + Persistent: true, + }) + }) + } + + return flags +} diff --git a/ignite/services/plugin/grpc/v1/interface_hook.go b/ignite/services/plugin/grpc/v1/interface_hook.go new file mode 100644 index 0000000000..db5d02484a --- /dev/null +++ b/ignite/services/plugin/grpc/v1/interface_hook.go @@ -0,0 +1,6 @@ +package v1 + +// CommandPath returns the absolute command path including the binary name as prefix. +func (h *Hook) CommandPath() string { + return ensureFullCommandPath(h.PlaceHookOn) +} diff --git a/ignite/services/plugin/grpc/v1/interface_manifest.go b/ignite/services/plugin/grpc/v1/interface_manifest.go new file mode 100644 index 0000000000..1c67f579cf --- /dev/null +++ b/ignite/services/plugin/grpc/v1/interface_manifest.go @@ -0,0 +1,27 @@ +package v1 + +import "github.com/spf13/cobra" + +// ImportCobraCommand appends Cobra command definitions to the list of plugin commands. +// This method can be used in cases where a plugin defines the commands using Cobra. +func (m *Manifest) ImportCobraCommand(cmd *cobra.Command, placeCommandUnder string) { + m.Commands = append(m.Commands, convertCobraCommand(cmd, placeCommandUnder)) +} + +func convertCobraCommand(c *cobra.Command, placeCommandUnder string) *Command { + cmd := &Command{ + Use: c.Use, + Aliases: c.Aliases, + Short: c.Short, + Long: c.Long, + Hidden: c.Hidden, + PlaceCommandUnder: placeCommandUnder, + Flags: extractCobraFlags(c), + } + + for _, c := range c.Commands() { + cmd.Commands = append(cmd.Commands, convertCobraCommand(c, "")) + } + + return cmd +} diff --git a/ignite/services/plugin/grpc/v1/service.pb.go b/ignite/services/plugin/grpc/v1/service.pb.go new file mode 100644 index 0000000000..7cd54c135e --- /dev/null +++ b/ignite/services/plugin/grpc/v1/service.pb.go @@ -0,0 +1,914 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc (unknown) +// source: ignite/services/plugin/grpc/v1/service.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ManifestRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ManifestRequest) Reset() { + *x = ManifestRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ManifestRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ManifestRequest) ProtoMessage() {} + +func (x *ManifestRequest) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ManifestRequest.ProtoReflect.Descriptor instead. +func (*ManifestRequest) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_service_proto_rawDescGZIP(), []int{0} +} + +type ManifestResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Manifest *Manifest `protobuf:"bytes,1,opt,name=manifest,proto3" json:"manifest,omitempty"` +} + +func (x *ManifestResponse) Reset() { + *x = ManifestResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ManifestResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ManifestResponse) ProtoMessage() {} + +func (x *ManifestResponse) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ManifestResponse.ProtoReflect.Descriptor instead. +func (*ManifestResponse) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_service_proto_rawDescGZIP(), []int{1} +} + +func (x *ManifestResponse) GetManifest() *Manifest { + if x != nil { + return x.Manifest + } + return nil +} + +type ExecuteRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cmd *ExecutedCommand `protobuf:"bytes,1,opt,name=cmd,proto3" json:"cmd,omitempty"` + ClientApi uint32 `protobuf:"varint,2,opt,name=client_api,json=clientApi,proto3" json:"client_api,omitempty"` +} + +func (x *ExecuteRequest) Reset() { + *x = ExecuteRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecuteRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteRequest) ProtoMessage() {} + +func (x *ExecuteRequest) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecuteRequest.ProtoReflect.Descriptor instead. +func (*ExecuteRequest) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_service_proto_rawDescGZIP(), []int{2} +} + +func (x *ExecuteRequest) GetCmd() *ExecutedCommand { + if x != nil { + return x.Cmd + } + return nil +} + +func (x *ExecuteRequest) GetClientApi() uint32 { + if x != nil { + return x.ClientApi + } + return 0 +} + +type ExecuteResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ExecuteResponse) Reset() { + *x = ExecuteResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecuteResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteResponse) ProtoMessage() {} + +func (x *ExecuteResponse) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecuteResponse.ProtoReflect.Descriptor instead. +func (*ExecuteResponse) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_service_proto_rawDescGZIP(), []int{3} +} + +type ExecuteHookPreRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Hook *ExecutedHook `protobuf:"bytes,1,opt,name=hook,proto3" json:"hook,omitempty"` + ClientApi uint32 `protobuf:"varint,2,opt,name=client_api,json=clientApi,proto3" json:"client_api,omitempty"` +} + +func (x *ExecuteHookPreRequest) Reset() { + *x = ExecuteHookPreRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecuteHookPreRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteHookPreRequest) ProtoMessage() {} + +func (x *ExecuteHookPreRequest) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecuteHookPreRequest.ProtoReflect.Descriptor instead. +func (*ExecuteHookPreRequest) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_service_proto_rawDescGZIP(), []int{4} +} + +func (x *ExecuteHookPreRequest) GetHook() *ExecutedHook { + if x != nil { + return x.Hook + } + return nil +} + +func (x *ExecuteHookPreRequest) GetClientApi() uint32 { + if x != nil { + return x.ClientApi + } + return 0 +} + +type ExecuteHookPreResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ExecuteHookPreResponse) Reset() { + *x = ExecuteHookPreResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecuteHookPreResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteHookPreResponse) ProtoMessage() {} + +func (x *ExecuteHookPreResponse) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecuteHookPreResponse.ProtoReflect.Descriptor instead. +func (*ExecuteHookPreResponse) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_service_proto_rawDescGZIP(), []int{5} +} + +type ExecuteHookPostRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Hook *ExecutedHook `protobuf:"bytes,1,opt,name=hook,proto3" json:"hook,omitempty"` + ClientApi uint32 `protobuf:"varint,2,opt,name=client_api,json=clientApi,proto3" json:"client_api,omitempty"` +} + +func (x *ExecuteHookPostRequest) Reset() { + *x = ExecuteHookPostRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecuteHookPostRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteHookPostRequest) ProtoMessage() {} + +func (x *ExecuteHookPostRequest) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecuteHookPostRequest.ProtoReflect.Descriptor instead. +func (*ExecuteHookPostRequest) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_service_proto_rawDescGZIP(), []int{6} +} + +func (x *ExecuteHookPostRequest) GetHook() *ExecutedHook { + if x != nil { + return x.Hook + } + return nil +} + +func (x *ExecuteHookPostRequest) GetClientApi() uint32 { + if x != nil { + return x.ClientApi + } + return 0 +} + +type ExecuteHookPostResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ExecuteHookPostResponse) Reset() { + *x = ExecuteHookPostResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecuteHookPostResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteHookPostResponse) ProtoMessage() {} + +func (x *ExecuteHookPostResponse) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecuteHookPostResponse.ProtoReflect.Descriptor instead. +func (*ExecuteHookPostResponse) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_service_proto_rawDescGZIP(), []int{7} +} + +type ExecuteHookCleanUpRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Hook *ExecutedHook `protobuf:"bytes,1,opt,name=hook,proto3" json:"hook,omitempty"` + ClientApi uint32 `protobuf:"varint,2,opt,name=client_api,json=clientApi,proto3" json:"client_api,omitempty"` +} + +func (x *ExecuteHookCleanUpRequest) Reset() { + *x = ExecuteHookCleanUpRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecuteHookCleanUpRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteHookCleanUpRequest) ProtoMessage() {} + +func (x *ExecuteHookCleanUpRequest) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecuteHookCleanUpRequest.ProtoReflect.Descriptor instead. +func (*ExecuteHookCleanUpRequest) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_service_proto_rawDescGZIP(), []int{8} +} + +func (x *ExecuteHookCleanUpRequest) GetHook() *ExecutedHook { + if x != nil { + return x.Hook + } + return nil +} + +func (x *ExecuteHookCleanUpRequest) GetClientApi() uint32 { + if x != nil { + return x.ClientApi + } + return 0 +} + +type ExecuteHookCleanUpResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ExecuteHookCleanUpResponse) Reset() { + *x = ExecuteHookCleanUpResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecuteHookCleanUpResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteHookCleanUpResponse) ProtoMessage() {} + +func (x *ExecuteHookCleanUpResponse) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecuteHookCleanUpResponse.ProtoReflect.Descriptor instead. +func (*ExecuteHookCleanUpResponse) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_service_proto_rawDescGZIP(), []int{9} +} + +type GetChainInfoRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetChainInfoRequest) Reset() { + *x = GetChainInfoRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetChainInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetChainInfoRequest) ProtoMessage() {} + +func (x *GetChainInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetChainInfoRequest.ProtoReflect.Descriptor instead. +func (*GetChainInfoRequest) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_service_proto_rawDescGZIP(), []int{10} +} + +type GetChainInfoResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ChainInfo *ChainInfo `protobuf:"bytes,1,opt,name=chain_info,json=chainInfo,proto3" json:"chain_info,omitempty"` +} + +func (x *GetChainInfoResponse) Reset() { + *x = GetChainInfoResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetChainInfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetChainInfoResponse) ProtoMessage() {} + +func (x *GetChainInfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetChainInfoResponse.ProtoReflect.Descriptor instead. +func (*GetChainInfoResponse) Descriptor() ([]byte, []int) { + return file_ignite_services_plugin_grpc_v1_service_proto_rawDescGZIP(), []int{11} +} + +func (x *GetChainInfoResponse) GetChainInfo() *ChainInfo { + if x != nil { + return x.ChainInfo + } + return nil +} + +var File_ignite_services_plugin_grpc_v1_service_proto protoreflect.FileDescriptor + +var file_ignite_services_plugin_grpc_v1_service_proto_rawDesc = []byte{ + 0x0a, 0x2c, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x76, 0x31, + 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, + 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x1a, 0x2f, + 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x76, 0x31, 0x2f, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x76, 0x31, 0x2f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, + 0x11, 0x0a, 0x0f, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x58, 0x0a, 0x10, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, + 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, + 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, + 0x73, 0x74, 0x52, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x22, 0x72, 0x0a, 0x0e, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, + 0x0a, 0x03, 0x63, 0x6d, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x69, 0x67, + 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x03, 0x63, 0x6d, + 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x70, 0x69, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x69, + 0x22, 0x11, 0x0a, 0x0f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x78, 0x0a, 0x15, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, + 0x6f, 0x6b, 0x50, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x04, + 0x68, 0x6f, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x69, 0x67, 0x6e, + 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x65, 0x64, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x04, 0x68, 0x6f, 0x6f, 0x6b, 0x12, 0x1d, + 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x70, 0x69, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x69, 0x22, 0x18, 0x0a, + 0x16, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x50, 0x72, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x79, 0x0a, 0x16, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x40, 0x0a, 0x04, 0x68, 0x6f, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2c, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x04, 0x68, + 0x6f, 0x6f, 0x6b, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x70, + 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41, + 0x70, 0x69, 0x22, 0x19, 0x0a, 0x17, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, + 0x6b, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7c, 0x0a, + 0x19, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x43, 0x6c, 0x65, 0x61, + 0x6e, 0x55, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x68, 0x6f, + 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, + 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x64, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x04, 0x68, 0x6f, 0x6f, 0x6b, 0x12, 0x1d, 0x0a, 0x0a, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x70, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x69, 0x22, 0x1c, 0x0a, 0x1a, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x55, + 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x0a, 0x13, 0x47, 0x65, 0x74, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x22, 0x60, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x69, + 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, + 0x66, 0x6f, 0x32, 0x81, 0x05, 0x0a, 0x10, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6d, 0x0a, 0x08, 0x4d, 0x61, 0x6e, 0x69, 0x66, + 0x65, 0x73, 0x74, 0x12, 0x2f, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x07, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x12, 0x2e, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2f, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x7f, 0x0a, 0x0e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, + 0x6b, 0x50, 0x72, 0x65, 0x12, 0x35, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, + 0x6b, 0x50, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x69, 0x67, + 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x50, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x0f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, + 0x6f, 0x6f, 0x6b, 0x50, 0x6f, 0x73, 0x74, 0x12, 0x36, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, + 0x48, 0x6f, 0x6f, 0x6b, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x37, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x50, 0x6f, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8b, 0x01, 0x0a, 0x12, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x55, 0x70, 0x12, + 0x39, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x43, 0x6c, 0x65, 0x61, + 0x6e, 0x55, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x69, 0x67, 0x6e, + 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x55, 0x70, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x8d, 0x01, 0x0a, 0x10, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x41, 0x50, 0x49, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x79, 0x0a, 0x0c, 0x47, + 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x33, 0x2e, 0x69, 0x67, + 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x34, 0x2e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2f, 0x63, 0x6c, 0x69, 0x2f, + 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x76, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_ignite_services_plugin_grpc_v1_service_proto_rawDescOnce sync.Once + file_ignite_services_plugin_grpc_v1_service_proto_rawDescData = file_ignite_services_plugin_grpc_v1_service_proto_rawDesc +) + +func file_ignite_services_plugin_grpc_v1_service_proto_rawDescGZIP() []byte { + file_ignite_services_plugin_grpc_v1_service_proto_rawDescOnce.Do(func() { + file_ignite_services_plugin_grpc_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_ignite_services_plugin_grpc_v1_service_proto_rawDescData) + }) + return file_ignite_services_plugin_grpc_v1_service_proto_rawDescData +} + +var file_ignite_services_plugin_grpc_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_ignite_services_plugin_grpc_v1_service_proto_goTypes = []interface{}{ + (*ManifestRequest)(nil), // 0: ignite.services.plugin.grpc.v1.ManifestRequest + (*ManifestResponse)(nil), // 1: ignite.services.plugin.grpc.v1.ManifestResponse + (*ExecuteRequest)(nil), // 2: ignite.services.plugin.grpc.v1.ExecuteRequest + (*ExecuteResponse)(nil), // 3: ignite.services.plugin.grpc.v1.ExecuteResponse + (*ExecuteHookPreRequest)(nil), // 4: ignite.services.plugin.grpc.v1.ExecuteHookPreRequest + (*ExecuteHookPreResponse)(nil), // 5: ignite.services.plugin.grpc.v1.ExecuteHookPreResponse + (*ExecuteHookPostRequest)(nil), // 6: ignite.services.plugin.grpc.v1.ExecuteHookPostRequest + (*ExecuteHookPostResponse)(nil), // 7: ignite.services.plugin.grpc.v1.ExecuteHookPostResponse + (*ExecuteHookCleanUpRequest)(nil), // 8: ignite.services.plugin.grpc.v1.ExecuteHookCleanUpRequest + (*ExecuteHookCleanUpResponse)(nil), // 9: ignite.services.plugin.grpc.v1.ExecuteHookCleanUpResponse + (*GetChainInfoRequest)(nil), // 10: ignite.services.plugin.grpc.v1.GetChainInfoRequest + (*GetChainInfoResponse)(nil), // 11: ignite.services.plugin.grpc.v1.GetChainInfoResponse + (*Manifest)(nil), // 12: ignite.services.plugin.grpc.v1.Manifest + (*ExecutedCommand)(nil), // 13: ignite.services.plugin.grpc.v1.ExecutedCommand + (*ExecutedHook)(nil), // 14: ignite.services.plugin.grpc.v1.ExecutedHook + (*ChainInfo)(nil), // 15: ignite.services.plugin.grpc.v1.ChainInfo +} +var file_ignite_services_plugin_grpc_v1_service_proto_depIdxs = []int32{ + 12, // 0: ignite.services.plugin.grpc.v1.ManifestResponse.manifest:type_name -> ignite.services.plugin.grpc.v1.Manifest + 13, // 1: ignite.services.plugin.grpc.v1.ExecuteRequest.cmd:type_name -> ignite.services.plugin.grpc.v1.ExecutedCommand + 14, // 2: ignite.services.plugin.grpc.v1.ExecuteHookPreRequest.hook:type_name -> ignite.services.plugin.grpc.v1.ExecutedHook + 14, // 3: ignite.services.plugin.grpc.v1.ExecuteHookPostRequest.hook:type_name -> ignite.services.plugin.grpc.v1.ExecutedHook + 14, // 4: ignite.services.plugin.grpc.v1.ExecuteHookCleanUpRequest.hook:type_name -> ignite.services.plugin.grpc.v1.ExecutedHook + 15, // 5: ignite.services.plugin.grpc.v1.GetChainInfoResponse.chain_info:type_name -> ignite.services.plugin.grpc.v1.ChainInfo + 0, // 6: ignite.services.plugin.grpc.v1.InterfaceService.Manifest:input_type -> ignite.services.plugin.grpc.v1.ManifestRequest + 2, // 7: ignite.services.plugin.grpc.v1.InterfaceService.Execute:input_type -> ignite.services.plugin.grpc.v1.ExecuteRequest + 4, // 8: ignite.services.plugin.grpc.v1.InterfaceService.ExecuteHookPre:input_type -> ignite.services.plugin.grpc.v1.ExecuteHookPreRequest + 6, // 9: ignite.services.plugin.grpc.v1.InterfaceService.ExecuteHookPost:input_type -> ignite.services.plugin.grpc.v1.ExecuteHookPostRequest + 8, // 10: ignite.services.plugin.grpc.v1.InterfaceService.ExecuteHookCleanUp:input_type -> ignite.services.plugin.grpc.v1.ExecuteHookCleanUpRequest + 10, // 11: ignite.services.plugin.grpc.v1.ClientAPIService.GetChainInfo:input_type -> ignite.services.plugin.grpc.v1.GetChainInfoRequest + 1, // 12: ignite.services.plugin.grpc.v1.InterfaceService.Manifest:output_type -> ignite.services.plugin.grpc.v1.ManifestResponse + 3, // 13: ignite.services.plugin.grpc.v1.InterfaceService.Execute:output_type -> ignite.services.plugin.grpc.v1.ExecuteResponse + 5, // 14: ignite.services.plugin.grpc.v1.InterfaceService.ExecuteHookPre:output_type -> ignite.services.plugin.grpc.v1.ExecuteHookPreResponse + 7, // 15: ignite.services.plugin.grpc.v1.InterfaceService.ExecuteHookPost:output_type -> ignite.services.plugin.grpc.v1.ExecuteHookPostResponse + 9, // 16: ignite.services.plugin.grpc.v1.InterfaceService.ExecuteHookCleanUp:output_type -> ignite.services.plugin.grpc.v1.ExecuteHookCleanUpResponse + 11, // 17: ignite.services.plugin.grpc.v1.ClientAPIService.GetChainInfo:output_type -> ignite.services.plugin.grpc.v1.GetChainInfoResponse + 12, // [12:18] is the sub-list for method output_type + 6, // [6:12] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name +} + +func init() { file_ignite_services_plugin_grpc_v1_service_proto_init() } +func file_ignite_services_plugin_grpc_v1_service_proto_init() { + if File_ignite_services_plugin_grpc_v1_service_proto != nil { + return + } + file_ignite_services_plugin_grpc_v1_client_api_proto_init() + file_ignite_services_plugin_grpc_v1_interface_proto_init() + if !protoimpl.UnsafeEnabled { + file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ManifestRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ManifestResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecuteRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecuteResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecuteHookPreRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecuteHookPreResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecuteHookPostRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecuteHookPostResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecuteHookCleanUpRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecuteHookCleanUpResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetChainInfoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ignite_services_plugin_grpc_v1_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetChainInfoResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_ignite_services_plugin_grpc_v1_service_proto_rawDesc, + NumEnums: 0, + NumMessages: 12, + NumExtensions: 0, + NumServices: 2, + }, + GoTypes: file_ignite_services_plugin_grpc_v1_service_proto_goTypes, + DependencyIndexes: file_ignite_services_plugin_grpc_v1_service_proto_depIdxs, + MessageInfos: file_ignite_services_plugin_grpc_v1_service_proto_msgTypes, + }.Build() + File_ignite_services_plugin_grpc_v1_service_proto = out.File + file_ignite_services_plugin_grpc_v1_service_proto_rawDesc = nil + file_ignite_services_plugin_grpc_v1_service_proto_goTypes = nil + file_ignite_services_plugin_grpc_v1_service_proto_depIdxs = nil +} diff --git a/ignite/services/plugin/grpc/v1/service_grpc.pb.go b/ignite/services/plugin/grpc/v1/service_grpc.pb.go new file mode 100644 index 0000000000..f369c94a1e --- /dev/null +++ b/ignite/services/plugin/grpc/v1/service_grpc.pb.go @@ -0,0 +1,383 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc (unknown) +// source: ignite/services/plugin/grpc/v1/service.proto + +package v1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + InterfaceService_Manifest_FullMethodName = "/ignite.services.plugin.grpc.v1.InterfaceService/Manifest" + InterfaceService_Execute_FullMethodName = "/ignite.services.plugin.grpc.v1.InterfaceService/Execute" + InterfaceService_ExecuteHookPre_FullMethodName = "/ignite.services.plugin.grpc.v1.InterfaceService/ExecuteHookPre" + InterfaceService_ExecuteHookPost_FullMethodName = "/ignite.services.plugin.grpc.v1.InterfaceService/ExecuteHookPost" + InterfaceService_ExecuteHookCleanUp_FullMethodName = "/ignite.services.plugin.grpc.v1.InterfaceService/ExecuteHookCleanUp" +) + +// InterfaceServiceClient is the client API for InterfaceService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type InterfaceServiceClient interface { + // Manifest declares the plugin's Command(s) and Hook(s). + Manifest(ctx context.Context, in *ManifestRequest, opts ...grpc.CallOption) (*ManifestResponse, error) + // Execute will be invoked by ignite when a plugin Command is executed. + // It is global for all commands declared in Manifest, if you have declared + // multiple commands, use cmd.Path to distinguish them. + Execute(ctx context.Context, in *ExecuteRequest, opts ...grpc.CallOption) (*ExecuteResponse, error) + // ExecuteHookPre is invoked by ignite when a command specified by the Hook + // path is invoked. + // It is global for all hooks declared in Manifest, if you have declared + // multiple hooks, use hook.Name to distinguish them. + ExecuteHookPre(ctx context.Context, in *ExecuteHookPreRequest, opts ...grpc.CallOption) (*ExecuteHookPreResponse, error) + // ExecuteHookPost is invoked by ignite when a command specified by the hook + // path is invoked. + // It is global for all hooks declared in Manifest, if you have declared + // multiple hooks, use hook.Name to distinguish them. + ExecuteHookPost(ctx context.Context, in *ExecuteHookPostRequest, opts ...grpc.CallOption) (*ExecuteHookPostResponse, error) + // ExecuteHookCleanUp is invoked by ignite when a command specified by the + // hook path is invoked. Unlike ExecuteHookPost, it is invoked regardless of + // execution status of the command and hooks. + // It is global for all hooks declared in Manifest, if you have declared + // multiple hooks, use hook.Name to distinguish them. + ExecuteHookCleanUp(ctx context.Context, in *ExecuteHookCleanUpRequest, opts ...grpc.CallOption) (*ExecuteHookCleanUpResponse, error) +} + +type interfaceServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewInterfaceServiceClient(cc grpc.ClientConnInterface) InterfaceServiceClient { + return &interfaceServiceClient{cc} +} + +func (c *interfaceServiceClient) Manifest(ctx context.Context, in *ManifestRequest, opts ...grpc.CallOption) (*ManifestResponse, error) { + out := new(ManifestResponse) + err := c.cc.Invoke(ctx, InterfaceService_Manifest_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *interfaceServiceClient) Execute(ctx context.Context, in *ExecuteRequest, opts ...grpc.CallOption) (*ExecuteResponse, error) { + out := new(ExecuteResponse) + err := c.cc.Invoke(ctx, InterfaceService_Execute_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *interfaceServiceClient) ExecuteHookPre(ctx context.Context, in *ExecuteHookPreRequest, opts ...grpc.CallOption) (*ExecuteHookPreResponse, error) { + out := new(ExecuteHookPreResponse) + err := c.cc.Invoke(ctx, InterfaceService_ExecuteHookPre_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *interfaceServiceClient) ExecuteHookPost(ctx context.Context, in *ExecuteHookPostRequest, opts ...grpc.CallOption) (*ExecuteHookPostResponse, error) { + out := new(ExecuteHookPostResponse) + err := c.cc.Invoke(ctx, InterfaceService_ExecuteHookPost_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *interfaceServiceClient) ExecuteHookCleanUp(ctx context.Context, in *ExecuteHookCleanUpRequest, opts ...grpc.CallOption) (*ExecuteHookCleanUpResponse, error) { + out := new(ExecuteHookCleanUpResponse) + err := c.cc.Invoke(ctx, InterfaceService_ExecuteHookCleanUp_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// InterfaceServiceServer is the server API for InterfaceService service. +// All implementations must embed UnimplementedInterfaceServiceServer +// for forward compatibility +type InterfaceServiceServer interface { + // Manifest declares the plugin's Command(s) and Hook(s). + Manifest(context.Context, *ManifestRequest) (*ManifestResponse, error) + // Execute will be invoked by ignite when a plugin Command is executed. + // It is global for all commands declared in Manifest, if you have declared + // multiple commands, use cmd.Path to distinguish them. + Execute(context.Context, *ExecuteRequest) (*ExecuteResponse, error) + // ExecuteHookPre is invoked by ignite when a command specified by the Hook + // path is invoked. + // It is global for all hooks declared in Manifest, if you have declared + // multiple hooks, use hook.Name to distinguish them. + ExecuteHookPre(context.Context, *ExecuteHookPreRequest) (*ExecuteHookPreResponse, error) + // ExecuteHookPost is invoked by ignite when a command specified by the hook + // path is invoked. + // It is global for all hooks declared in Manifest, if you have declared + // multiple hooks, use hook.Name to distinguish them. + ExecuteHookPost(context.Context, *ExecuteHookPostRequest) (*ExecuteHookPostResponse, error) + // ExecuteHookCleanUp is invoked by ignite when a command specified by the + // hook path is invoked. Unlike ExecuteHookPost, it is invoked regardless of + // execution status of the command and hooks. + // It is global for all hooks declared in Manifest, if you have declared + // multiple hooks, use hook.Name to distinguish them. + ExecuteHookCleanUp(context.Context, *ExecuteHookCleanUpRequest) (*ExecuteHookCleanUpResponse, error) + mustEmbedUnimplementedInterfaceServiceServer() +} + +// UnimplementedInterfaceServiceServer must be embedded to have forward compatible implementations. +type UnimplementedInterfaceServiceServer struct { +} + +func (UnimplementedInterfaceServiceServer) Manifest(context.Context, *ManifestRequest) (*ManifestResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Manifest not implemented") +} +func (UnimplementedInterfaceServiceServer) Execute(context.Context, *ExecuteRequest) (*ExecuteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Execute not implemented") +} +func (UnimplementedInterfaceServiceServer) ExecuteHookPre(context.Context, *ExecuteHookPreRequest) (*ExecuteHookPreResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ExecuteHookPre not implemented") +} +func (UnimplementedInterfaceServiceServer) ExecuteHookPost(context.Context, *ExecuteHookPostRequest) (*ExecuteHookPostResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ExecuteHookPost not implemented") +} +func (UnimplementedInterfaceServiceServer) ExecuteHookCleanUp(context.Context, *ExecuteHookCleanUpRequest) (*ExecuteHookCleanUpResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ExecuteHookCleanUp not implemented") +} +func (UnimplementedInterfaceServiceServer) mustEmbedUnimplementedInterfaceServiceServer() {} + +// UnsafeInterfaceServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to InterfaceServiceServer will +// result in compilation errors. +type UnsafeInterfaceServiceServer interface { + mustEmbedUnimplementedInterfaceServiceServer() +} + +func RegisterInterfaceServiceServer(s grpc.ServiceRegistrar, srv InterfaceServiceServer) { + s.RegisterService(&InterfaceService_ServiceDesc, srv) +} + +func _InterfaceService_Manifest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ManifestRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InterfaceServiceServer).Manifest(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InterfaceService_Manifest_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InterfaceServiceServer).Manifest(ctx, req.(*ManifestRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _InterfaceService_Execute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExecuteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InterfaceServiceServer).Execute(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InterfaceService_Execute_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InterfaceServiceServer).Execute(ctx, req.(*ExecuteRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _InterfaceService_ExecuteHookPre_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExecuteHookPreRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InterfaceServiceServer).ExecuteHookPre(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InterfaceService_ExecuteHookPre_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InterfaceServiceServer).ExecuteHookPre(ctx, req.(*ExecuteHookPreRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _InterfaceService_ExecuteHookPost_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExecuteHookPostRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InterfaceServiceServer).ExecuteHookPost(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InterfaceService_ExecuteHookPost_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InterfaceServiceServer).ExecuteHookPost(ctx, req.(*ExecuteHookPostRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _InterfaceService_ExecuteHookCleanUp_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExecuteHookCleanUpRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InterfaceServiceServer).ExecuteHookCleanUp(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InterfaceService_ExecuteHookCleanUp_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InterfaceServiceServer).ExecuteHookCleanUp(ctx, req.(*ExecuteHookCleanUpRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// InterfaceService_ServiceDesc is the grpc.ServiceDesc for InterfaceService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var InterfaceService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "ignite.services.plugin.grpc.v1.InterfaceService", + HandlerType: (*InterfaceServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Manifest", + Handler: _InterfaceService_Manifest_Handler, + }, + { + MethodName: "Execute", + Handler: _InterfaceService_Execute_Handler, + }, + { + MethodName: "ExecuteHookPre", + Handler: _InterfaceService_ExecuteHookPre_Handler, + }, + { + MethodName: "ExecuteHookPost", + Handler: _InterfaceService_ExecuteHookPost_Handler, + }, + { + MethodName: "ExecuteHookCleanUp", + Handler: _InterfaceService_ExecuteHookCleanUp_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "ignite/services/plugin/grpc/v1/service.proto", +} + +const ( + ClientAPIService_GetChainInfo_FullMethodName = "/ignite.services.plugin.grpc.v1.ClientAPIService/GetChainInfo" +) + +// ClientAPIServiceClient is the client API for ClientAPIService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type ClientAPIServiceClient interface { + // GetChainInfo returns basic chain info for the configured app + GetChainInfo(ctx context.Context, in *GetChainInfoRequest, opts ...grpc.CallOption) (*GetChainInfoResponse, error) +} + +type clientAPIServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewClientAPIServiceClient(cc grpc.ClientConnInterface) ClientAPIServiceClient { + return &clientAPIServiceClient{cc} +} + +func (c *clientAPIServiceClient) GetChainInfo(ctx context.Context, in *GetChainInfoRequest, opts ...grpc.CallOption) (*GetChainInfoResponse, error) { + out := new(GetChainInfoResponse) + err := c.cc.Invoke(ctx, ClientAPIService_GetChainInfo_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ClientAPIServiceServer is the server API for ClientAPIService service. +// All implementations must embed UnimplementedClientAPIServiceServer +// for forward compatibility +type ClientAPIServiceServer interface { + // GetChainInfo returns basic chain info for the configured app + GetChainInfo(context.Context, *GetChainInfoRequest) (*GetChainInfoResponse, error) + mustEmbedUnimplementedClientAPIServiceServer() +} + +// UnimplementedClientAPIServiceServer must be embedded to have forward compatible implementations. +type UnimplementedClientAPIServiceServer struct { +} + +func (UnimplementedClientAPIServiceServer) GetChainInfo(context.Context, *GetChainInfoRequest) (*GetChainInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetChainInfo not implemented") +} +func (UnimplementedClientAPIServiceServer) mustEmbedUnimplementedClientAPIServiceServer() {} + +// UnsafeClientAPIServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ClientAPIServiceServer will +// result in compilation errors. +type UnsafeClientAPIServiceServer interface { + mustEmbedUnimplementedClientAPIServiceServer() +} + +func RegisterClientAPIServiceServer(s grpc.ServiceRegistrar, srv ClientAPIServiceServer) { + s.RegisterService(&ClientAPIService_ServiceDesc, srv) +} + +func _ClientAPIService_GetChainInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetChainInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ClientAPIServiceServer).GetChainInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ClientAPIService_GetChainInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ClientAPIServiceServer).GetChainInfo(ctx, req.(*GetChainInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// ClientAPIService_ServiceDesc is the grpc.ServiceDesc for ClientAPIService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ClientAPIService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "ignite.services.plugin.grpc.v1.ClientAPIService", + HandlerType: (*ClientAPIServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetChainInfo", + Handler: _ClientAPIService_GetChainInfo_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "ignite/services/plugin/grpc/v1/service.proto", +} diff --git a/ignite/services/plugin/grpc/v1/types_command_test.go b/ignite/services/plugin/grpc/v1/types_command_test.go new file mode 100644 index 0000000000..c74034e656 --- /dev/null +++ b/ignite/services/plugin/grpc/v1/types_command_test.go @@ -0,0 +1,343 @@ +package v1_test + +import ( + "fmt" + "testing" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + v1 "github.com/ignite/cli/ignite/services/plugin/grpc/v1" +) + +func TestCommandToCobraCommand(t *testing.T) { + var ( + require = require.New(t) + assert = assert.New(t) + pcmd = v1.Command{ + Use: "new", + Aliases: []string{"n"}, + Short: "short", + Long: "long", + Hidden: true, + Flags: []*v1.Flag{ + { + Name: "bool", + Shorthand: "b", + DefaultValue: "true", + Value: "true", + Usage: "a bool", + Type: v1.Flag_TYPE_FLAG_BOOL, + }, + { + Name: "string", + DefaultValue: "hello", + Value: "hello", + Usage: "a string", + Type: v1.Flag_TYPE_FLAG_STRING_UNSPECIFIED, + Persistent: true, + }, + }, + Commands: []*v1.Command{ + { + Use: "sub", + Aliases: []string{"s"}, + Short: "sub short", + Long: "sub long", + }, + }, + } + ) + + cmd, err := pcmd.ToCobraCommand() + + require.NoError(err) + require.NotNil(cmd) + assert.Empty(cmd.Commands()) // subcommands aren't converted + assert.Equal(pcmd.Use, cmd.Use) + assert.Equal(pcmd.Short, cmd.Short) + assert.Equal(pcmd.Long, cmd.Long) + assert.Equal(pcmd.Aliases, cmd.Aliases) + assert.Equal(pcmd.Hidden, cmd.Hidden) + for _, f := range pcmd.Flags { + if f.Persistent { + assert.NotNil(cmd.PersistentFlags().Lookup(f.Name), "missing pflag %s", f.Name) + } else { + assert.NotNil(cmd.Flags().Lookup(f.Name), "missing flag %s", f.Name) + } + } +} + +func TestCommandPath(t *testing.T) { + cases := []struct { + name, wantPath string + cmd *v1.Command + }{ + { + name: "relative path", + cmd: &v1.Command{ + PlaceCommandUnder: "chain", + }, + wantPath: "ignite chain", + }, + { + name: "full path", + cmd: &v1.Command{ + PlaceCommandUnder: "ignite chain", + }, + wantPath: "ignite chain", + }, + { + name: "path with spaces", + cmd: &v1.Command{ + PlaceCommandUnder: " ignite scaffold ", + }, + wantPath: "ignite scaffold", + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + path := tc.cmd.Path() + require.Equal(t, tc.wantPath, path) + }) + } +} + +func TestExecutedCommandImportFlags(t *testing.T) { + // Arrange + execCmd := &v1.ExecutedCommand{} + wantFlags := []*v1.Flag{ + { + Name: "foo", + Shorthand: "f", + Usage: "foo usage", + DefaultValue: "bar", + Value: "baz", + Type: v1.Flag_TYPE_FLAG_STRING_UNSPECIFIED, + }, { + Name: "test", + Shorthand: "t", + Usage: "test usage", + DefaultValue: "1", + Value: "42", + Type: v1.Flag_TYPE_FLAG_INT, + Persistent: true, + }, + } + + cmd := cobra.Command{} + cmd.Flags().StringP("foo", "f", "bar", "foo usage") + cmd.PersistentFlags().IntP("test", "t", 1, "test usage") + cmd.ParseFlags([]string{"--foo", "baz", "--test", "42"}) + + // Act + execCmd.ImportFlags(&cmd) + + // Assert + require.Equal(t, wantFlags, execCmd.Flags) +} + +func TestExecutedCommandNewFlags(t *testing.T) { + // Arrange + execCmd := &v1.ExecutedCommand{ + Flags: []*v1.Flag{ + { + Name: "bool", + Shorthand: "b", + Usage: "bool usage", + DefaultValue: "false", + Type: v1.Flag_TYPE_FLAG_BOOL, + }, + { + Name: "int", + Shorthand: "i", + Usage: "int usage", + DefaultValue: "0", + Type: v1.Flag_TYPE_FLAG_INT, + }, + { + Name: "uint", + Shorthand: "u", + Usage: "uint usage", + DefaultValue: "0", + Type: v1.Flag_TYPE_FLAG_UINT, + }, + { + Name: "int64", + Shorthand: "j", + Usage: "int64 usage", + DefaultValue: "0", + Type: v1.Flag_TYPE_FLAG_INT64, + }, + { + Name: "uint64", + Shorthand: "k", + Usage: "uint64 usage", + DefaultValue: "0", + Type: v1.Flag_TYPE_FLAG_UINT64, + }, + { + Name: "string", + Shorthand: "s", + Usage: "string usage", + DefaultValue: "", + Type: v1.Flag_TYPE_FLAG_STRING_UNSPECIFIED, + }, + { + Name: "string-slice", + Shorthand: "l", + Usage: "string slice usage", + DefaultValue: "[]", + Type: v1.Flag_TYPE_FLAG_STRING_SLICE, + }, + { + Name: "persistent", + Persistent: true, + }, + }, + } + + wantFlags := make(map[string]pflag.Flag) + for _, f := range execCmd.Flags { + wantFlags[f.Name] = pflag.Flag{ + Name: f.Name, + Shorthand: f.Shorthand, + Usage: f.Usage, + DefValue: f.DefaultValue, + } + } + + var ( + flagCount int + + // Persistent flag should not be included + wantFlagCount = len(execCmd.Flags) - 1 + ) + + // Act + flags, err := execCmd.NewFlags() + + // Assert + require.NoError(t, err) + + flags.VisitAll(func(f *pflag.Flag) { + flag, ok := wantFlags[f.Name] + + require.True(t, ok, fmt.Sprintf("missing flag: %s", f.Name)) + require.Equal(t, flag.Name, f.Name) + require.Equal(t, flag.Shorthand, f.Shorthand) + require.Equal(t, flag.Usage, f.Usage) + require.Equal(t, flag.DefValue, f.DefValue) + + flagCount++ + }) + + require.Equal(t, wantFlagCount, flagCount) +} + +func TestExecutedCommandNewPersistentFlags(t *testing.T) { + // Arrange + execCmd := &v1.ExecutedCommand{ + Flags: []*v1.Flag{ + { + Name: "bool", + Shorthand: "b", + Usage: "bool usage", + DefaultValue: "false", + Type: v1.Flag_TYPE_FLAG_BOOL, + Persistent: true, + }, + { + Name: "int", + Shorthand: "i", + Usage: "int usage", + DefaultValue: "0", + Type: v1.Flag_TYPE_FLAG_INT, + Persistent: true, + }, + { + Name: "uint", + Shorthand: "u", + Usage: "uint usage", + DefaultValue: "0", + Type: v1.Flag_TYPE_FLAG_UINT, + Persistent: true, + }, + { + Name: "int64", + Shorthand: "j", + Usage: "int64 usage", + DefaultValue: "0", + Type: v1.Flag_TYPE_FLAG_INT64, + Persistent: true, + }, + { + Name: "uint64", + Shorthand: "k", + Usage: "uint64 usage", + DefaultValue: "0", + Type: v1.Flag_TYPE_FLAG_UINT64, + Persistent: true, + }, + { + Name: "string", + Shorthand: "s", + Usage: "string usage", + DefaultValue: "", + Type: v1.Flag_TYPE_FLAG_STRING_UNSPECIFIED, + Persistent: true, + }, + { + Name: "string-slice", + Shorthand: "l", + Usage: "string slice usage", + DefaultValue: "[]", + Type: v1.Flag_TYPE_FLAG_STRING_SLICE, + Persistent: true, + }, + { + Name: "non-persistent", + }, + }, + } + + wantFlags := make(map[string]pflag.Flag) + for _, f := range execCmd.Flags { + wantFlags[f.Name] = pflag.Flag{ + Name: f.Name, + Shorthand: f.Shorthand, + Usage: f.Usage, + DefValue: f.DefaultValue, + } + } + + var ( + flagCount int + + // Non persistent flag should not be included + wantFlagCount = len(execCmd.Flags) - 1 + ) + + // Act + flags, err := execCmd.NewPersistentFlags() + + // Assert + require.NoError(t, err) + + flags.VisitAll(func(f *pflag.Flag) { + flag, ok := wantFlags[f.Name] + + require.True(t, ok, fmt.Sprintf("missing flag: %s", f.Name)) + require.Equal(t, flag.Name, f.Name) + require.Equal(t, flag.Shorthand, f.Shorthand) + require.Equal(t, flag.Usage, f.Usage) + require.Equal(t, flag.DefValue, f.DefValue) + + flagCount++ + }) + + require.Equal(t, wantFlagCount, flagCount) +} diff --git a/ignite/services/plugin/grpc/v1/types_hook_test.go b/ignite/services/plugin/grpc/v1/types_hook_test.go new file mode 100644 index 0000000000..4fed09ed08 --- /dev/null +++ b/ignite/services/plugin/grpc/v1/types_hook_test.go @@ -0,0 +1,45 @@ +package v1_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + v1 "github.com/ignite/cli/ignite/services/plugin/grpc/v1" +) + +func TestHookCommandPath(t *testing.T) { + cases := []struct { + name, wantPath string + hook *v1.Hook + }{ + { + name: "relative path", + hook: &v1.Hook{ + PlaceHookOn: "chain", + }, + wantPath: "ignite chain", + }, + { + name: "full path", + hook: &v1.Hook{ + PlaceHookOn: "ignite chain", + }, + wantPath: "ignite chain", + }, + { + name: "path with spaces", + hook: &v1.Hook{ + PlaceHookOn: " ignite scaffold ", + }, + wantPath: "ignite scaffold", + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + path := tc.hook.CommandPath() + require.Equal(t, tc.wantPath, path) + }) + } +} diff --git a/ignite/services/plugin/grpc/v1/types_manifest_test.go b/ignite/services/plugin/grpc/v1/types_manifest_test.go new file mode 100644 index 0000000000..73246d9c93 --- /dev/null +++ b/ignite/services/plugin/grpc/v1/types_manifest_test.go @@ -0,0 +1,110 @@ +package v1_test + +import ( + "testing" + + "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" + + v1 "github.com/ignite/cli/ignite/services/plugin/grpc/v1" +) + +func TestManifestImportCobraCommand(t *testing.T) { + manifest := &v1.Manifest{ + Name: "hey", + Commands: []*v1.Command{ + {Use: "existing"}, + }, + } + cmd := &cobra.Command{ + Use: "new", + Aliases: []string{"n"}, + Short: "short", + Long: "long", + Hidden: true, + } + cmd.Flags().BoolP("bool", "b", true, "a bool") + cmd.Flags().String("string", "hello", "a string") + cmd.PersistentFlags().String("persistent", "hello", "a persistent string") + subcmd := &cobra.Command{ + Use: "sub", + Aliases: []string{"s"}, + Short: "sub short", + Long: "sub long", + } + subcmd.Flags().BoolP("subbool", "b", true, "a bool") + subcmd.Flags().String("substring", "hello", "a string") + subcmd.AddCommand(&cobra.Command{ + Use: "subsub", + }) + cmd.AddCommand(subcmd) + + manifest.ImportCobraCommand(cmd, "under") + + expectedManifest := &v1.Manifest{ + Name: "hey", + Commands: []*v1.Command{ + {Use: "existing"}, + { + Use: "new", + Aliases: []string{"n"}, + Short: "short", + Long: "long", + Hidden: true, + PlaceCommandUnder: "under", + Flags: []*v1.Flag{ + { + Name: "bool", + Shorthand: "b", + DefaultValue: "true", + Value: "true", + Usage: "a bool", + Type: v1.Flag_TYPE_FLAG_BOOL, + }, + { + Name: "string", + DefaultValue: "hello", + Value: "hello", + Usage: "a string", + Type: v1.Flag_TYPE_FLAG_STRING_UNSPECIFIED, + }, + { + Name: "persistent", + DefaultValue: "hello", + Value: "hello", + Usage: "a persistent string", + Type: v1.Flag_TYPE_FLAG_STRING_UNSPECIFIED, + Persistent: true, + }, + }, + Commands: []*v1.Command{ + { + Use: "sub", + Aliases: []string{"s"}, + Short: "sub short", + Long: "sub long", + Flags: []*v1.Flag{ + { + Name: "subbool", + Shorthand: "b", + DefaultValue: "true", + Value: "true", + Usage: "a bool", + Type: v1.Flag_TYPE_FLAG_BOOL, + }, + { + Name: "substring", + DefaultValue: "hello", + Value: "hello", + Usage: "a string", + Type: v1.Flag_TYPE_FLAG_STRING_UNSPECIFIED, + }, + }, + Commands: []*v1.Command{{Use: "subsub"}}, + }, + }, + }, + }, + } + assert.Equal(t, expectedManifest, manifest) +} diff --git a/ignite/services/plugin/interface.go b/ignite/services/plugin/interface.go index 9a735d1fad..9eb44b008c 100644 --- a/ignite/services/plugin/interface.go +++ b/ignite/services/plugin/interface.go @@ -1,481 +1,74 @@ package plugin import ( - "bytes" - "encoding/gob" - "fmt" - "net/rpc" - "os" - "strconv" - "strings" + "context" - "github.com/hashicorp/go-plugin" - "github.com/spf13/cobra" - "github.com/spf13/pflag" + v1 "github.com/ignite/cli/ignite/services/plugin/grpc/v1" ) -func init() { - gob.Register(Manifest{}) - gob.Register(ExecutedCommand{}) - gob.Register(ExecutedHook{}) -} +// Flag type aliases. +const ( + FlagTypeString = v1.Flag_TYPE_FLAG_STRING_UNSPECIFIED + FlagTypeInt = v1.Flag_TYPE_FLAG_INT + FlagTypeUint = v1.Flag_TYPE_FLAG_UINT + FlagTypeInt64 = v1.Flag_TYPE_FLAG_INT64 + FlagTypeUint64 = v1.Flag_TYPE_FLAG_UINT64 + FlagTypeBool = v1.Flag_TYPE_FLAG_BOOL + FlagTypeStringSlice = v1.Flag_TYPE_FLAG_STRING_SLICE +) + +// Type aliases for the current plugin version. +type ( + Command = v1.Command + ChainInfo = v1.ChainInfo + ExecutedCommand = v1.ExecutedCommand + ExecutedHook = v1.ExecutedHook + Flag = v1.Flag + FlagType = v1.Flag_Type + Hook = v1.Hook + Manifest = v1.Manifest +) // Interface defines the interface that all Ignite App must implement. // //go:generate mockery --srcpkg . --name Interface --structname PluginInterface --filename interface.go --with-expecter type Interface interface { // Manifest declares the app's Command(s) and Hook(s). - Manifest() (Manifest, error) + Manifest(context.Context) (*Manifest, error) // Execute will be invoked by ignite when an app Command is executed. // It is global for all commands declared in Manifest, if you have declared // multiple commands, use cmd.Path to distinguish them. - Execute(cmd ExecutedCommand) error + // The clientAPI argument can be used by plugins to get chain app analysis info. + Execute(context.Context, *ExecutedCommand, ClientAPI) error // ExecuteHookPre is invoked by ignite when a command specified by the Hook // path is invoked. // It is global for all hooks declared in Manifest, if you have declared // multiple hooks, use hook.Name to distinguish them. - ExecuteHookPre(hook ExecutedHook) error + // The clientAPI argument can be used by plugins to get chain app analysis info. + ExecuteHookPre(context.Context, *ExecutedHook, ClientAPI) error // ExecuteHookPost is invoked by ignite when a command specified by the hook // path is invoked. // It is global for all hooks declared in Manifest, if you have declared // multiple hooks, use hook.Name to distinguish them. - ExecuteHookPost(hook ExecutedHook) error + // The clientAPI argument can be used by plugins to get chain app analysis info. + ExecuteHookPost(context.Context, *ExecutedHook, ClientAPI) error // ExecuteHookCleanUp is invoked by ignite when a command specified by the // hook path is invoked. Unlike ExecuteHookPost, it is invoked regardless of // execution status of the command and hooks. // It is global for all hooks declared in Manifest, if you have declared // multiple hooks, use hook.Name to distinguish them. - ExecuteHookCleanUp(hook ExecutedHook) error -} - -// Manifest represents the Ignite App behavior. -type Manifest struct { - Name string - - // Commands contains the commands that will be added to the list of ignite - // commands. Each commands are independent, for nested commands use the - // inner Commands field. - Commands []Command - - // Hooks contains the hooks that will be attached to the existing ignite - // commands. - Hooks []Hook - - // SharedHost enables sharing a single app server across all running instances - // of an app. Useful if an app adds or extends long running commands - // - // Example: if an app defines a hook on `ignite chain serve`, a server is instanciated - // when the command is run. Now if you want to interact with that instance from commands - // defined in that app, you need to enable `SharedHost`, or else the commands will just - // instantiate separate app servers. - // - // When enabled, all apps of the same `Path` loaded from the same configuration will - // attach it's RPC client to a an existing RPC server. - // - // If an app instance has no other running app servers, it will create one and it - // will be the host. - SharedHost bool `yaml:"shared_host"` -} - -// ImportCobraCommand allows to hydrate m with a standard root cobra commands. -func (m *Manifest) ImportCobraCommand(c *cobra.Command, placeCommandUnder string) { - m.Commands = append(m.Commands, convertCobraCommand(c, placeCommandUnder)) -} - -func convertCobraCommand(c *cobra.Command, placeCommandUnder string) Command { - cmd := Command{ - Use: c.Use, - Aliases: c.Aliases, - Short: c.Short, - Long: c.Long, - Hidden: c.Hidden, - PlaceCommandUnder: placeCommandUnder, - Flags: convertPFlags(c), - } - for _, c := range c.Commands() { - cmd.Commands = append(cmd.Commands, convertCobraCommand(c, "")) - } - return cmd + // The clientAPI argument can be used by plugins to get chain app analysis info. + ExecuteHookCleanUp(context.Context, *ExecutedHook, ClientAPI) error } -// Command represents an app command. -type Command struct { - // Same as cobra.Command.Use - Use string - - // Same as cobra.Command.Aliases - Aliases []string - - // Same as cobra.Command.Short - Short string - - // Same as cobra.Command.Long - Long string - - // Same as cobra.Command.Hidden - Hidden bool - - // Flags holds the list of command flags - Flags []Flag - - // PlaceCommandUnder indicates where the command should be placed. - // For instance `ignite scaffold` will place the command at the - // `scaffold` command. - // An empty value is interpreted as `ignite` (==root). - PlaceCommandUnder string - - // List of sub commands - Commands []Command -} - -// PlaceCommandUnderFull returns a normalized p.PlaceCommandUnder, -// by adding the `ignite ` prefix if not present. -func (c Command) PlaceCommandUnderFull() string { - return commandFull(c.PlaceCommandUnder) -} - -func commandFull(cmdPath string) string { - const rootCmdName = "ignite" - if !strings.HasPrefix(cmdPath, rootCmdName) { - cmdPath = rootCmdName + " " + cmdPath - } - return strings.TrimSpace(cmdPath) -} - -// ToCobraCommand turns Command into a cobra.Command so it can be added to a parent command. -func (c Command) ToCobraCommand() (*cobra.Command, error) { - cmd := &cobra.Command{ - Use: c.Use, - Aliases: c.Aliases, - Short: c.Short, - Long: c.Long, - Hidden: c.Hidden, - } - for _, f := range c.Flags { - err := f.feedFlagSet(cmd) - if err != nil { - return nil, err - } - } - return cmd, nil -} - -// Hook represents a user defined action within an app. -type Hook struct { - // Name identifies the hook for the client to invoke the correct hook - // must be unique - Name string - - // PlaceHookOn indicates the command to register the hooks for - PlaceHookOn string -} - -// PlaceHookOnFull returns a normalized p.PlaceCommandUnder, by adding the -// `ignite ` prefix if not present. -func (h Hook) PlaceHookOnFull() string { - return commandFull(h.PlaceHookOn) -} - -// ExecutedCommand represents an app command under execution. -type ExecutedCommand struct { - // Use is copied from Command.Use - Use string - - // Path contains the command path, e.g. `ignite scaffold foo` - Path string - - // Args are the command arguments - Args []string - - // Full list of args taken from os.Args - OSArgs []string - - // With contains the app config parameters - With map[string]string - - flags *pflag.FlagSet - pflags *pflag.FlagSet -} - -// ExecutedHook represents an app hook under execution. -type ExecutedHook struct { - // ExecutedCommand gives access to the command attached by the hook. - ExecutedCommand ExecutedCommand - // Hook is a copy of the original Hook defined in the Manifest. - Hook -} - -// Flags gives access to the commands' flags, like cobra.Command.Flags. -func (c *ExecutedCommand) Flags() *pflag.FlagSet { - if c.flags == nil { - c.flags = pflag.NewFlagSet(os.Args[0], pflag.ContinueOnError) - } - return c.flags -} - -// PersistentFlags gives access to the commands' persistent flags, like -// cobra.Command.PersistentFlags. -func (c *ExecutedCommand) PersistentFlags() *pflag.FlagSet { - if c.pflags == nil { - c.pflags = pflag.NewFlagSet(os.Args[0], pflag.ContinueOnError) - } - return c.pflags -} - -// SetFlags set the flags. -// As an app developer, you probably don't need to use it. -func (c *ExecutedCommand) SetFlags(cmd *cobra.Command) { - c.flags = cmd.Flags() - c.pflags = cmd.PersistentFlags() -} - -// Flag is a serializable representation of pflag.Flag. -type Flag struct { - Name string // name as it appears on command line - Shorthand string // one-letter abbreviated flag - Usage string // help message - DefValue string // default value (as text); for usage message - Type FlagType - Value string - - // Persistent indicates wether or not the flag is propagated on children commands - Persistent bool -} - -// FlagType represents the pflag.Flag.Value.Type(). -type FlagType string - -const ( - // NOTE(tb): we declare only the main used cobra flag types for simplicity - // If an app receives an unhandled type, it will output an error. - FlagTypeString FlagType = "string" - FlagTypeInt FlagType = "int" - FlagTypeUint FlagType = "uint" - FlagTypeInt64 FlagType = "int64" - FlagTypeUint64 FlagType = "uint64" - FlagTypeBool FlagType = "bool" - FlagTypeStringSlice FlagType = "stringSlice" -) - -// feedFlagSet fills flagger with f. -func (f Flag) feedFlagSet(fgr flagger) error { - fs := fgr.Flags() - if f.Persistent { - fs = fgr.PersistentFlags() - } - switch f.Type { - case FlagTypeBool: - defVal, _ := strconv.ParseBool(f.DefValue) - fs.BoolP(f.Name, f.Shorthand, defVal, f.Usage) - _ = fs.Set(f.Name, f.Value) - case FlagTypeInt: - defVal, _ := strconv.Atoi(f.DefValue) - fs.IntP(f.Name, f.Shorthand, defVal, f.Usage) - _ = fs.Set(f.Name, f.Value) - case FlagTypeUint: - defVal, _ := strconv.ParseUint(f.DefValue, 10, 64) - fs.UintP(f.Name, f.Shorthand, uint(defVal), f.Usage) - _ = fs.Set(f.Name, f.Value) - case FlagTypeInt64: - defVal, _ := strconv.ParseInt(f.DefValue, 10, 64) - fs.Int64P(f.Name, f.Shorthand, defVal, f.Usage) - _ = fs.Set(f.Name, f.Value) - case FlagTypeUint64: - defVal, _ := strconv.ParseUint(f.DefValue, 10, 64) - fs.Uint64P(f.Name, f.Shorthand, defVal, f.Usage) - _ = fs.Set(f.Name, f.Value) - case FlagTypeString: - fs.StringP(f.Name, f.Shorthand, f.DefValue, f.Usage) - _ = fs.Set(f.Name, f.Value) - case FlagTypeStringSlice: - s := strings.Trim(f.DefValue, "[]") - defValue := strings.Fields(s) - fs.StringSliceP(f.Name, f.Shorthand, defValue, f.Usage) - _ = fs.Set(f.Name, strings.Trim(f.Value, "[]")) - default: - return fmt.Errorf("flagset unmarshal: unhandled flag type %q in flag %#v", f.Type, f) - } - return nil -} - -// gobCommandFlags is used to gob encode/decode Command. -// Command can't be encoded because : -// - flags is unexported (because we want to expose it via the Flags() method, -// like a regular cobra.Command) -// - flags type is *pflag.FlagSet which is also full of unexported fields. -type gobCommandContextFlags struct { - CommandContext gobCommandContext - Flags []Flag -} - -// gobCommandContext is the same as ExecutedCommand but without GobDecode -// attached, which avoids infinite loops. -type gobCommandContext ExecutedCommand - -// GobEncode implements gob.Encoder. -// It actually encodes a gobCommandContext struct built from c. -func (c ExecutedCommand) GobEncode() ([]byte, error) { - var b bytes.Buffer - err := gob.NewEncoder(&b).Encode(gobCommandContextFlags{ - CommandContext: gobCommandContext(c), - Flags: convertPFlags(&c), - }) - return b.Bytes(), err -} - -// flagger matches both cobra.Command and Command. -type flagger interface { - Flags() *pflag.FlagSet - PersistentFlags() *pflag.FlagSet -} - -func convertPFlags(fgr flagger) []Flag { - var ff []Flag - if fgr.Flags() != nil { - fgr.Flags().VisitAll(func(pf *pflag.Flag) { - ff = append(ff, Flag{ - Name: pf.Name, - Shorthand: pf.Shorthand, - Usage: pf.Usage, - DefValue: pf.DefValue, - Value: pf.Value.String(), - Type: FlagType(pf.Value.Type()), - }) - }) - } - if fgr.PersistentFlags() != nil { - fgr.PersistentFlags().VisitAll(func(pf *pflag.Flag) { - ff = append(ff, Flag{ - Name: pf.Name, - Shorthand: pf.Shorthand, - Usage: pf.Usage, - DefValue: pf.DefValue, - Value: pf.Value.String(), - Type: FlagType(pf.Value.Type()), - Persistent: true, - }) - }) - } - return ff -} - -// GobDecode implements gob.Decoder. -// It actually decodes a gobCommandContext struct and fills c with it. -func (c *ExecutedCommand) GobDecode(bz []byte) error { - var gb gobCommandContextFlags - err := gob.NewDecoder(bytes.NewReader(bz)).Decode(&gb) - if err != nil { - return err - } - *c = ExecutedCommand(gb.CommandContext) - for _, f := range gb.Flags { - err := f.feedFlagSet(c) - if err != nil { - return err - } - } - return nil -} - -// handshakeConfigs are used to just do a basic handshake between -// an app and host. If the handshake fails, a user friendly error is shown. -// This prevents users from executing bad apps or executing an app -// directory. It is a UX feature, not a security feature. -var handshakeConfig = plugin.HandshakeConfig{ - ProtocolVersion: 1, - MagicCookieKey: "BASIC_PLUGIN", - MagicCookieValue: "hello", -} - -func HandshakeConfig() plugin.HandshakeConfig { - return handshakeConfig -} - -// InterfaceRPC is an implementation that talks over RPC. -type InterfaceRPC struct{ client *rpc.Client } - -// Manifest implements Interface.Manifest. -func (g *InterfaceRPC) Manifest() (Manifest, error) { - var resp Manifest - return resp, g.client.Call("Plugin.Manifest", new(interface{}), &resp) -} - -// Execute implements Interface.Commands. -func (g *InterfaceRPC) Execute(c ExecutedCommand) error { - var resp interface{} - return g.client.Call("Plugin.Execute", map[string]interface{}{ - "executedCommand": c, - }, &resp) -} - -func (g *InterfaceRPC) ExecuteHookPre(hook ExecutedHook) error { - var resp interface{} - return g.client.Call("Plugin.ExecuteHookPre", map[string]interface{}{ - "executedHook": hook, - }, &resp) -} - -func (g *InterfaceRPC) ExecuteHookPost(hook ExecutedHook) error { - var resp interface{} - return g.client.Call("Plugin.ExecuteHookPost", map[string]interface{}{ - "executedHook": hook, - }, &resp) -} - -func (g *InterfaceRPC) ExecuteHookCleanUp(hook ExecutedHook) error { - var resp interface{} - return g.client.Call("Plugin.ExecuteHookCleanUp", map[string]interface{}{ - "executedHook": hook, - }, &resp) -} - -// InterfaceRPCServer is the RPC server that InterfaceRPC talks to, conforming to -// the requirements of net/rpc. -type InterfaceRPCServer struct { - Impl Interface -} - -func (s *InterfaceRPCServer) Manifest(_ interface{}, resp *Manifest) error { - var err error - *resp, err = s.Impl.Manifest() - return err -} - -func (s *InterfaceRPCServer) Execute(args map[string]interface{}, _ *interface{}) error { - return s.Impl.Execute(args["executedCommand"].(ExecutedCommand)) -} - -func (s *InterfaceRPCServer) ExecuteHookPre(args map[string]interface{}, _ *interface{}) error { - return s.Impl.ExecuteHookPre(args["executedHook"].(ExecutedHook)) -} - -func (s *InterfaceRPCServer) ExecuteHookPost(args map[string]interface{}, _ *interface{}) error { - return s.Impl.ExecuteHookPost(args["executedHook"].(ExecutedHook)) -} - -func (s *InterfaceRPCServer) ExecuteHookCleanUp(args map[string]interface{}, _ *interface{}) error { - return s.Impl.ExecuteHookCleanUp(args["executedHook"].(ExecutedHook)) -} - -// InterfacePlugin is the implementation of Interface. -// -// This has two methods: Server must return an RPC server for this plugin -// type. We construct a InterfaceRPCServer for this. +// ClientAPI defines the interface for plugins to get chain app code analysis info. // -// Client must return an implementation of our interface that communicates -// over an RPC client. We return InterfaceRPC for this. -type InterfacePlugin struct { - Impl Interface -} - -func (p *InterfacePlugin) Server(*plugin.MuxBroker) (interface{}, error) { - return &InterfaceRPCServer{Impl: p.Impl}, nil -} - -func (InterfacePlugin) Client(_ *plugin.MuxBroker, c *rpc.Client) (interface{}, error) { - return &InterfaceRPC{client: c}, nil +//go:generate mockery --srcpkg . --name ClientAPI --structname PluginClientAPI --filename client_api.go --with-expecter +type ClientAPI interface { + // GetChainInfo returns basic info for the configured blockchain app. + GetChainInfo(context.Context) (*ChainInfo, error) } diff --git a/ignite/services/plugin/interface_test.go b/ignite/services/plugin/interface_test.go deleted file mode 100644 index f36fb9f89d..0000000000 --- a/ignite/services/plugin/interface_test.go +++ /dev/null @@ -1,169 +0,0 @@ -package plugin_test - -import ( - "testing" - - "github.com/spf13/cobra" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/ignite/cli/ignite/services/plugin" -) - -func TestCommandToCobraCommand(t *testing.T) { - var ( - require = require.New(t) - assert = assert.New(t) - pcmd = plugin.Command{ - Use: "new", - Aliases: []string{"n"}, - Short: "short", - Long: "long", - Hidden: true, - Flags: []plugin.Flag{ - { - Name: "bool", - Shorthand: "b", - DefValue: "true", - Value: "true", - Usage: "a bool", - Type: plugin.FlagTypeBool, - }, - { - Name: "string", - DefValue: "hello", - Value: "hello", - Usage: "a string", - Type: plugin.FlagTypeString, - Persistent: true, - }, - }, - Commands: []plugin.Command{ - { - Use: "sub", - Aliases: []string{"s"}, - Short: "sub short", - Long: "sub long", - }, - }, - } - ) - - cmd, err := pcmd.ToCobraCommand() - - require.NoError(err) - require.NotNil(cmd) - assert.Empty(cmd.Commands()) // subcommands aren't converted - assert.Equal(pcmd.Use, cmd.Use) - assert.Equal(pcmd.Short, cmd.Short) - assert.Equal(pcmd.Long, cmd.Long) - assert.Equal(pcmd.Aliases, cmd.Aliases) - assert.Equal(pcmd.Hidden, cmd.Hidden) - for _, f := range pcmd.Flags { - if f.Persistent { - assert.NotNil(cmd.PersistentFlags().Lookup(f.Name), "missing pflag %s", f.Name) - } else { - assert.NotNil(cmd.Flags().Lookup(f.Name), "missing flag %s", f.Name) - } - } -} - -func TestManifestImportCobraCommand(t *testing.T) { - manifest := plugin.Manifest{ - Name: "hey", - Commands: []plugin.Command{ - {Use: "existing"}, - }, - } - cmd := &cobra.Command{ - Use: "new", - Aliases: []string{"n"}, - Short: "short", - Long: "long", - Hidden: true, - } - cmd.Flags().BoolP("bool", "b", true, "a bool") - cmd.Flags().String("string", "hello", "a string") - cmd.PersistentFlags().String("persistent", "hello", "a persistent string") - subcmd := &cobra.Command{ - Use: "sub", - Aliases: []string{"s"}, - Short: "sub short", - Long: "sub long", - } - subcmd.Flags().BoolP("subbool", "b", true, "a bool") - subcmd.Flags().String("substring", "hello", "a string") - subcmd.AddCommand(&cobra.Command{ - Use: "subsub", - }) - cmd.AddCommand(subcmd) - - manifest.ImportCobraCommand(cmd, "under") - - expectedManifest := plugin.Manifest{ - Name: "hey", - Commands: []plugin.Command{ - {Use: "existing"}, - { - Use: "new", - Aliases: []string{"n"}, - Short: "short", - Long: "long", - Hidden: true, - PlaceCommandUnder: "under", - Flags: []plugin.Flag{ - { - Name: "bool", - Shorthand: "b", - DefValue: "true", - Value: "true", - Usage: "a bool", - Type: plugin.FlagTypeBool, - }, - { - Name: "string", - DefValue: "hello", - Value: "hello", - Usage: "a string", - Type: plugin.FlagTypeString, - }, - { - Name: "persistent", - DefValue: "hello", - Value: "hello", - Usage: "a persistent string", - Type: plugin.FlagTypeString, - Persistent: true, - }, - }, - Commands: []plugin.Command{ - { - Use: "sub", - Aliases: []string{"s"}, - Short: "sub short", - Long: "sub long", - Flags: []plugin.Flag{ - { - Name: "subbool", - Shorthand: "b", - DefValue: "true", - Value: "true", - Usage: "a bool", - Type: plugin.FlagTypeBool, - }, - { - Name: "substring", - DefValue: "hello", - Value: "hello", - Usage: "a string", - Type: plugin.FlagTypeString, - }, - }, - Commands: []plugin.Command{{Use: "subsub"}}, - }, - }, - }, - }, - } - assert.Equal(t, expectedManifest, manifest) -} diff --git a/ignite/services/plugin/mocks/client_api.go b/ignite/services/plugin/mocks/client_api.go new file mode 100644 index 0000000000..c9bffda3e3 --- /dev/null +++ b/ignite/services/plugin/mocks/client_api.go @@ -0,0 +1,93 @@ +// Code generated by mockery v2.27.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + + v1 "github.com/ignite/cli/ignite/services/plugin/grpc/v1" +) + +// PluginClientAPI is an autogenerated mock type for the ClientAPI type +type PluginClientAPI struct { + mock.Mock +} + +type PluginClientAPI_Expecter struct { + mock *mock.Mock +} + +func (_m *PluginClientAPI) EXPECT() *PluginClientAPI_Expecter { + return &PluginClientAPI_Expecter{mock: &_m.Mock} +} + +// GetChainInfo provides a mock function with given fields: _a0 +func (_m *PluginClientAPI) GetChainInfo(_a0 context.Context) (*v1.ChainInfo, error) { + ret := _m.Called(_a0) + + var r0 *v1.ChainInfo + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*v1.ChainInfo, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(context.Context) *v1.ChainInfo); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*v1.ChainInfo) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PluginClientAPI_GetChainInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetChainInfo' +type PluginClientAPI_GetChainInfo_Call struct { + *mock.Call +} + +// GetChainInfo is a helper method to define mock.On call +// - _a0 context.Context +func (_e *PluginClientAPI_Expecter) GetChainInfo(_a0 interface{}) *PluginClientAPI_GetChainInfo_Call { + return &PluginClientAPI_GetChainInfo_Call{Call: _e.mock.On("GetChainInfo", _a0)} +} + +func (_c *PluginClientAPI_GetChainInfo_Call) Run(run func(_a0 context.Context)) *PluginClientAPI_GetChainInfo_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *PluginClientAPI_GetChainInfo_Call) Return(_a0 *v1.ChainInfo, _a1 error) *PluginClientAPI_GetChainInfo_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *PluginClientAPI_GetChainInfo_Call) RunAndReturn(run func(context.Context) (*v1.ChainInfo, error)) *PluginClientAPI_GetChainInfo_Call { + _c.Call.Return(run) + return _c +} + +type mockConstructorTestingTNewPluginClientAPI interface { + mock.TestingT + Cleanup(func()) +} + +// NewPluginClientAPI creates a new instance of PluginClientAPI. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewPluginClientAPI(t mockConstructorTestingTNewPluginClientAPI) *PluginClientAPI { + mock := &PluginClientAPI{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/ignite/services/plugin/mocks/interface.go b/ignite/services/plugin/mocks/interface.go index cdf4f810df..e03d029aa8 100644 --- a/ignite/services/plugin/mocks/interface.go +++ b/ignite/services/plugin/mocks/interface.go @@ -1,11 +1,14 @@ -// Code generated by mockery v2.22.1. DO NOT EDIT. +// Code generated by mockery v2.27.1. DO NOT EDIT. package mocks import ( - mock "github.com/stretchr/testify/mock" + context "context" plugin "github.com/ignite/cli/ignite/services/plugin" + mock "github.com/stretchr/testify/mock" + + v1 "github.com/ignite/cli/ignite/services/plugin/grpc/v1" ) // PluginInterface is an autogenerated mock type for the Interface type @@ -21,13 +24,13 @@ func (_m *PluginInterface) EXPECT() *PluginInterface_Expecter { return &PluginInterface_Expecter{mock: &_m.Mock} } -// Execute provides a mock function with given fields: cmd -func (_m *PluginInterface) Execute(cmd plugin.ExecutedCommand) error { - ret := _m.Called(cmd) +// Execute provides a mock function with given fields: _a0, _a1, _a2 +func (_m *PluginInterface) Execute(_a0 context.Context, _a1 *v1.ExecutedCommand, _a2 plugin.ClientAPI) error { + ret := _m.Called(_a0, _a1, _a2) var r0 error - if rf, ok := ret.Get(0).(func(plugin.ExecutedCommand) error); ok { - r0 = rf(cmd) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ExecutedCommand, plugin.ClientAPI) error); ok { + r0 = rf(_a0, _a1, _a2) } else { r0 = ret.Error(0) } @@ -41,14 +44,16 @@ type PluginInterface_Execute_Call struct { } // Execute is a helper method to define mock.On call -// - cmd plugin.ExecutedCommand -func (_e *PluginInterface_Expecter) Execute(cmd interface{}) *PluginInterface_Execute_Call { - return &PluginInterface_Execute_Call{Call: _e.mock.On("Execute", cmd)} +// - _a0 context.Context +// - _a1 *v1.ExecutedCommand +// - _a2 plugin.ClientAPI +func (_e *PluginInterface_Expecter) Execute(_a0 interface{}, _a1 interface{}, _a2 interface{}) *PluginInterface_Execute_Call { + return &PluginInterface_Execute_Call{Call: _e.mock.On("Execute", _a0, _a1, _a2)} } -func (_c *PluginInterface_Execute_Call) Run(run func(cmd plugin.ExecutedCommand)) *PluginInterface_Execute_Call { +func (_c *PluginInterface_Execute_Call) Run(run func(_a0 context.Context, _a1 *v1.ExecutedCommand, _a2 plugin.ClientAPI)) *PluginInterface_Execute_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(plugin.ExecutedCommand)) + run(args[0].(context.Context), args[1].(*v1.ExecutedCommand), args[2].(plugin.ClientAPI)) }) return _c } @@ -58,18 +63,18 @@ func (_c *PluginInterface_Execute_Call) Return(_a0 error) *PluginInterface_Execu return _c } -func (_c *PluginInterface_Execute_Call) RunAndReturn(run func(plugin.ExecutedCommand) error) *PluginInterface_Execute_Call { +func (_c *PluginInterface_Execute_Call) RunAndReturn(run func(context.Context, *v1.ExecutedCommand, plugin.ClientAPI) error) *PluginInterface_Execute_Call { _c.Call.Return(run) return _c } -// ExecuteHookCleanUp provides a mock function with given fields: hook -func (_m *PluginInterface) ExecuteHookCleanUp(hook plugin.ExecutedHook) error { - ret := _m.Called(hook) +// ExecuteHookCleanUp provides a mock function with given fields: _a0, _a1, _a2 +func (_m *PluginInterface) ExecuteHookCleanUp(_a0 context.Context, _a1 *v1.ExecutedHook, _a2 plugin.ClientAPI) error { + ret := _m.Called(_a0, _a1, _a2) var r0 error - if rf, ok := ret.Get(0).(func(plugin.ExecutedHook) error); ok { - r0 = rf(hook) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ExecutedHook, plugin.ClientAPI) error); ok { + r0 = rf(_a0, _a1, _a2) } else { r0 = ret.Error(0) } @@ -83,14 +88,16 @@ type PluginInterface_ExecuteHookCleanUp_Call struct { } // ExecuteHookCleanUp is a helper method to define mock.On call -// - hook plugin.ExecutedHook -func (_e *PluginInterface_Expecter) ExecuteHookCleanUp(hook interface{}) *PluginInterface_ExecuteHookCleanUp_Call { - return &PluginInterface_ExecuteHookCleanUp_Call{Call: _e.mock.On("ExecuteHookCleanUp", hook)} +// - _a0 context.Context +// - _a1 *v1.ExecutedHook +// - _a2 plugin.ClientAPI +func (_e *PluginInterface_Expecter) ExecuteHookCleanUp(_a0 interface{}, _a1 interface{}, _a2 interface{}) *PluginInterface_ExecuteHookCleanUp_Call { + return &PluginInterface_ExecuteHookCleanUp_Call{Call: _e.mock.On("ExecuteHookCleanUp", _a0, _a1, _a2)} } -func (_c *PluginInterface_ExecuteHookCleanUp_Call) Run(run func(hook plugin.ExecutedHook)) *PluginInterface_ExecuteHookCleanUp_Call { +func (_c *PluginInterface_ExecuteHookCleanUp_Call) Run(run func(_a0 context.Context, _a1 *v1.ExecutedHook, _a2 plugin.ClientAPI)) *PluginInterface_ExecuteHookCleanUp_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(plugin.ExecutedHook)) + run(args[0].(context.Context), args[1].(*v1.ExecutedHook), args[2].(plugin.ClientAPI)) }) return _c } @@ -100,18 +107,18 @@ func (_c *PluginInterface_ExecuteHookCleanUp_Call) Return(_a0 error) *PluginInte return _c } -func (_c *PluginInterface_ExecuteHookCleanUp_Call) RunAndReturn(run func(plugin.ExecutedHook) error) *PluginInterface_ExecuteHookCleanUp_Call { +func (_c *PluginInterface_ExecuteHookCleanUp_Call) RunAndReturn(run func(context.Context, *v1.ExecutedHook, plugin.ClientAPI) error) *PluginInterface_ExecuteHookCleanUp_Call { _c.Call.Return(run) return _c } -// ExecuteHookPost provides a mock function with given fields: hook -func (_m *PluginInterface) ExecuteHookPost(hook plugin.ExecutedHook) error { - ret := _m.Called(hook) +// ExecuteHookPost provides a mock function with given fields: _a0, _a1, _a2 +func (_m *PluginInterface) ExecuteHookPost(_a0 context.Context, _a1 *v1.ExecutedHook, _a2 plugin.ClientAPI) error { + ret := _m.Called(_a0, _a1, _a2) var r0 error - if rf, ok := ret.Get(0).(func(plugin.ExecutedHook) error); ok { - r0 = rf(hook) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ExecutedHook, plugin.ClientAPI) error); ok { + r0 = rf(_a0, _a1, _a2) } else { r0 = ret.Error(0) } @@ -125,14 +132,16 @@ type PluginInterface_ExecuteHookPost_Call struct { } // ExecuteHookPost is a helper method to define mock.On call -// - hook plugin.ExecutedHook -func (_e *PluginInterface_Expecter) ExecuteHookPost(hook interface{}) *PluginInterface_ExecuteHookPost_Call { - return &PluginInterface_ExecuteHookPost_Call{Call: _e.mock.On("ExecuteHookPost", hook)} +// - _a0 context.Context +// - _a1 *v1.ExecutedHook +// - _a2 plugin.ClientAPI +func (_e *PluginInterface_Expecter) ExecuteHookPost(_a0 interface{}, _a1 interface{}, _a2 interface{}) *PluginInterface_ExecuteHookPost_Call { + return &PluginInterface_ExecuteHookPost_Call{Call: _e.mock.On("ExecuteHookPost", _a0, _a1, _a2)} } -func (_c *PluginInterface_ExecuteHookPost_Call) Run(run func(hook plugin.ExecutedHook)) *PluginInterface_ExecuteHookPost_Call { +func (_c *PluginInterface_ExecuteHookPost_Call) Run(run func(_a0 context.Context, _a1 *v1.ExecutedHook, _a2 plugin.ClientAPI)) *PluginInterface_ExecuteHookPost_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(plugin.ExecutedHook)) + run(args[0].(context.Context), args[1].(*v1.ExecutedHook), args[2].(plugin.ClientAPI)) }) return _c } @@ -142,18 +151,18 @@ func (_c *PluginInterface_ExecuteHookPost_Call) Return(_a0 error) *PluginInterfa return _c } -func (_c *PluginInterface_ExecuteHookPost_Call) RunAndReturn(run func(plugin.ExecutedHook) error) *PluginInterface_ExecuteHookPost_Call { +func (_c *PluginInterface_ExecuteHookPost_Call) RunAndReturn(run func(context.Context, *v1.ExecutedHook, plugin.ClientAPI) error) *PluginInterface_ExecuteHookPost_Call { _c.Call.Return(run) return _c } -// ExecuteHookPre provides a mock function with given fields: hook -func (_m *PluginInterface) ExecuteHookPre(hook plugin.ExecutedHook) error { - ret := _m.Called(hook) +// ExecuteHookPre provides a mock function with given fields: _a0, _a1, _a2 +func (_m *PluginInterface) ExecuteHookPre(_a0 context.Context, _a1 *v1.ExecutedHook, _a2 plugin.ClientAPI) error { + ret := _m.Called(_a0, _a1, _a2) var r0 error - if rf, ok := ret.Get(0).(func(plugin.ExecutedHook) error); ok { - r0 = rf(hook) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ExecutedHook, plugin.ClientAPI) error); ok { + r0 = rf(_a0, _a1, _a2) } else { r0 = ret.Error(0) } @@ -167,14 +176,16 @@ type PluginInterface_ExecuteHookPre_Call struct { } // ExecuteHookPre is a helper method to define mock.On call -// - hook plugin.ExecutedHook -func (_e *PluginInterface_Expecter) ExecuteHookPre(hook interface{}) *PluginInterface_ExecuteHookPre_Call { - return &PluginInterface_ExecuteHookPre_Call{Call: _e.mock.On("ExecuteHookPre", hook)} +// - _a0 context.Context +// - _a1 *v1.ExecutedHook +// - _a2 plugin.ClientAPI +func (_e *PluginInterface_Expecter) ExecuteHookPre(_a0 interface{}, _a1 interface{}, _a2 interface{}) *PluginInterface_ExecuteHookPre_Call { + return &PluginInterface_ExecuteHookPre_Call{Call: _e.mock.On("ExecuteHookPre", _a0, _a1, _a2)} } -func (_c *PluginInterface_ExecuteHookPre_Call) Run(run func(hook plugin.ExecutedHook)) *PluginInterface_ExecuteHookPre_Call { +func (_c *PluginInterface_ExecuteHookPre_Call) Run(run func(_a0 context.Context, _a1 *v1.ExecutedHook, _a2 plugin.ClientAPI)) *PluginInterface_ExecuteHookPre_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(plugin.ExecutedHook)) + run(args[0].(context.Context), args[1].(*v1.ExecutedHook), args[2].(plugin.ClientAPI)) }) return _c } @@ -184,28 +195,30 @@ func (_c *PluginInterface_ExecuteHookPre_Call) Return(_a0 error) *PluginInterfac return _c } -func (_c *PluginInterface_ExecuteHookPre_Call) RunAndReturn(run func(plugin.ExecutedHook) error) *PluginInterface_ExecuteHookPre_Call { +func (_c *PluginInterface_ExecuteHookPre_Call) RunAndReturn(run func(context.Context, *v1.ExecutedHook, plugin.ClientAPI) error) *PluginInterface_ExecuteHookPre_Call { _c.Call.Return(run) return _c } -// Manifest provides a mock function with given fields: -func (_m *PluginInterface) Manifest() (plugin.Manifest, error) { - ret := _m.Called() +// Manifest provides a mock function with given fields: _a0 +func (_m *PluginInterface) Manifest(_a0 context.Context) (*v1.Manifest, error) { + ret := _m.Called(_a0) - var r0 plugin.Manifest + var r0 *v1.Manifest var r1 error - if rf, ok := ret.Get(0).(func() (plugin.Manifest, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (*v1.Manifest, error)); ok { + return rf(_a0) } - if rf, ok := ret.Get(0).(func() plugin.Manifest); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) *v1.Manifest); ok { + r0 = rf(_a0) } else { - r0 = ret.Get(0).(plugin.Manifest) + if ret.Get(0) != nil { + r0 = ret.Get(0).(*v1.Manifest) + } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(_a0) } else { r1 = ret.Error(1) } @@ -219,23 +232,24 @@ type PluginInterface_Manifest_Call struct { } // Manifest is a helper method to define mock.On call -func (_e *PluginInterface_Expecter) Manifest() *PluginInterface_Manifest_Call { - return &PluginInterface_Manifest_Call{Call: _e.mock.On("Manifest")} +// - _a0 context.Context +func (_e *PluginInterface_Expecter) Manifest(_a0 interface{}) *PluginInterface_Manifest_Call { + return &PluginInterface_Manifest_Call{Call: _e.mock.On("Manifest", _a0)} } -func (_c *PluginInterface_Manifest_Call) Run(run func()) *PluginInterface_Manifest_Call { +func (_c *PluginInterface_Manifest_Call) Run(run func(_a0 context.Context)) *PluginInterface_Manifest_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } -func (_c *PluginInterface_Manifest_Call) Return(_a0 plugin.Manifest, _a1 error) *PluginInterface_Manifest_Call { +func (_c *PluginInterface_Manifest_Call) Return(_a0 *v1.Manifest, _a1 error) *PluginInterface_Manifest_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *PluginInterface_Manifest_Call) RunAndReturn(run func() (plugin.Manifest, error)) *PluginInterface_Manifest_Call { +func (_c *PluginInterface_Manifest_Call) RunAndReturn(run func(context.Context) (*v1.Manifest, error)) *PluginInterface_Manifest_Call { _c.Call.Return(run) return _c } diff --git a/ignite/services/plugin/plugin.go b/ignite/services/plugin/plugin.go index 240effab4d..b23a46711b 100644 --- a/ignite/services/plugin/plugin.go +++ b/ignite/services/plugin/plugin.go @@ -37,11 +37,13 @@ var PluginsPath = xfilepath.Mkdir(xfilepath.Join( // Plugin represents a ignite plugin. type Plugin struct { - // Embed the plugin configuration + // Embed the plugin configuration. pluginsconfig.Plugin - // Interface allows to communicate with the plugin via net/rpc. + + // Interface allows to communicate with the plugin via RPC. Interface Interface - // If any error occurred during the plugin load, it's stored here + + // If any error occurred during the plugin load, it's stored here. Error error name string @@ -53,11 +55,13 @@ type Plugin struct { client *hplugin.Client - // holds a cache of the plugin manifest to prevent mant calls over the rpc boundary - manifest Manifest + // Holds a cache of the plugin manifest to prevent mant calls over the rpc boundary. + manifest *Manifest + // If a plugin's ShareHost flag is set to true, isHost is used to discern if a // plugin instance is controlling the rpc server. - isHost bool + isHost bool + isSharedHost bool ev events.Bus } @@ -100,8 +104,7 @@ func Load(ctx context.Context, plugins []pluginsconfig.Plugin, options ...Option // Update removes the cache directory of plugins and fetch them again. func Update(plugins ...*Plugin) error { for _, p := range plugins { - err := p.clean() - if err != nil { + if err := p.clean(); err != nil { return err } p.fetch() @@ -176,7 +179,7 @@ func newPlugin(pluginsDir string, cp pluginsconfig.Plugin, options ...Option) *P // KillClient kills the running plugin client. func (p *Plugin) KillClient() { - if p.manifest.SharedHost && !p.isHost { + if p.isSharedHost && !p.isHost { // Don't send kill signal to a shared-host plugin when this process isn't // the one who initiated it. return @@ -192,6 +195,12 @@ func (p *Plugin) KillClient() { } } +// Manifest returns plugin's manigest. +// The manifest is available after the plugin has been loaded. +func (p Plugin) Manifest() *Manifest { + return p.manifest +} + func (p Plugin) binaryName() string { return fmt.Sprintf("%s.app", p.name) } @@ -232,7 +241,7 @@ func (p *Plugin) load(ctx context.Context) { } // pluginMap is the map of plugins we can dispense. pluginMap := map[string]hplugin.Plugin{ - p.name: &InterfacePlugin{}, + p.name: NewGRPC(nil), } // Create an hclog.Logger logLevel := hclog.Error @@ -245,6 +254,16 @@ func (p *Plugin) load(ctx context.Context) { Level: logLevel, }) + // Common plugin client configuration values + cfg := &hplugin.ClientConfig{ + HandshakeConfig: HandshakeConfig(), + Plugins: pluginMap, + Logger: logger, + SyncStderr: os.Stderr, + SyncStdout: os.Stdout, + AllowedProtocols: []hplugin.Protocol{hplugin.ProtocolGRPC}, + } + if checkConfCache(p.Path) { rconf, err := readConfigCache(p.Path) if err != nil { @@ -252,29 +271,16 @@ func (p *Plugin) load(ctx context.Context) { return } - // We're attaching to an existing server, supply attachment configuration - p.client = hplugin.NewClient(&hplugin.ClientConfig{ - HandshakeConfig: handshakeConfig, - Plugins: pluginMap, - Logger: logger, - Reattach: &rconf, - SyncStderr: os.Stderr, - SyncStdout: os.Stdout, - }) - + // Attach to an existing plugin process + cfg.Reattach = &rconf + p.client = hplugin.NewClient(cfg) } else { - // We're a host! Start by launching the plugin process. - p.client = hplugin.NewClient(&hplugin.ClientConfig{ - HandshakeConfig: handshakeConfig, - Plugins: pluginMap, - Logger: logger, - Cmd: exec.Command(p.binaryPath()), - SyncStderr: os.Stderr, - SyncStdout: os.Stdout, - }) - } - - // :Connect via RPC + // Launch a new plugin process + cfg.Cmd = exec.Command(p.binaryPath()) + p.client = hplugin.NewClient(cfg) + } + + // Connect via gRPC rpcClient, err := p.client.Client() if err != nil { p.Error = errors.Wrapf(err, "connecting") @@ -289,14 +295,18 @@ func (p *Plugin) load(ctx context.Context) { } // We should have an Interface now! This feels like a normal interface - // implementation but is in fact over an RPC connection. + // implementation but is in fact over an gRPC connection. p.Interface = raw.(Interface) - m, err := p.Interface.Manifest() + m, err := p.Interface.Manifest(ctx) if err != nil { p.Error = errors.Wrapf(err, "manifest load") + return } + p.isSharedHost = m.SharedHost + + // Cache the manifest to avoid extra plugin requests p.manifest = m // write the rpc context to cache if the plugin is declared as host. diff --git a/ignite/services/plugin/plugin_test.go b/ignite/services/plugin/plugin_test.go index b3e6682dd0..7ddca88daf 100644 --- a/ignite/services/plugin/plugin_test.go +++ b/ignite/services/plugin/plugin_test.go @@ -157,33 +157,47 @@ func TestNewPlugin(t *testing.T) { } } +// Helper to make a local git repository with gofile committed. +// Returns the repo directory and the git.Repository +func makeGitRepo(t *testing.T, name string) (string, *git.Repository) { + t.Helper() + + require := require.New(t) + repoDir := t.TempDir() + scaffoldPlugin(t, repoDir, "github.com/ignite/"+name, false) + + repo, err := git.PlainInit(repoDir, false) + require.NoError(err) + + w, err := repo.Worktree() + require.NoError(err) + + _, err = w.Add(".") + require.NoError(err) + + _, err = w.Commit("msg", &git.CommitOptions{ + Author: &object.Signature{ + Name: "bob", + Email: "bob@example.com", + When: time.Now(), + }, + }) + require.NoError(err) + return repoDir, repo +} + +type TestClientAPI struct{ ClientAPI } + +func (TestClientAPI) GetChainInfo(context.Context) (*ChainInfo, error) { + return &ChainInfo{}, nil +} + func TestPluginLoad(t *testing.T) { wd, err := os.Getwd() require.NoError(t, err) - // Helper to make a local git repository with gofile committed. - // Returns the repo directory and the git.Repository - makeGitRepo := func(t *testing.T, name string) (string, *git.Repository) { - require := require.New(t) - repoDir := t.TempDir() - scaffoldPlugin(t, repoDir, "github.com/ignite/"+name, false) - require.NoError(err) - repo, err := git.PlainInit(repoDir, false) - require.NoError(err) - w, err := repo.Worktree() - require.NoError(err) - _, err = w.Add(".") - require.NoError(err) - _, err = w.Commit("msg", &git.CommitOptions{ - Author: &object.Signature{ - Name: "bob", - Email: "bob@example.com", - When: time.Now(), - }, - }) - require.NoError(err) - return repoDir, repo - } + clientAPI := &TestClientAPI{} + tests := []struct { name string buildPlugin func(t *testing.T) Plugin @@ -330,6 +344,7 @@ func TestPluginLoad(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() require := require.New(t) assert := assert.New(t) p := tt.buildPlugin(t) @@ -345,13 +360,13 @@ func TestPluginLoad(t *testing.T) { require.NoError(p.Error) require.NotNil(p.Interface) - manifest, err := p.Interface.Manifest() + manifest, err := p.Interface.Manifest(ctx) require.NoError(err) assert.Equal(p.name, manifest.Name) - assert.NoError(p.Interface.Execute(ExecutedCommand{})) - assert.NoError(p.Interface.ExecuteHookPre(ExecutedHook{})) - assert.NoError(p.Interface.ExecuteHookPost(ExecutedHook{})) - assert.NoError(p.Interface.ExecuteHookCleanUp(ExecutedHook{})) + assert.NoError(p.Interface.Execute(ctx, &ExecutedCommand{}, clientAPI)) + assert.NoError(p.Interface.ExecuteHookPre(ctx, &ExecutedHook{}, clientAPI)) + assert.NoError(p.Interface.ExecuteHookPost(ctx, &ExecutedHook{}, clientAPI)) + assert.NoError(p.Interface.ExecuteHookCleanUp(ctx, &ExecutedHook{}, clientAPI)) }) } } @@ -491,14 +506,18 @@ func TestPluginClean(t *testing.T) { // scaffoldPlugin runs Scaffold and updates the go.mod so it uses the // current ignite/cli sources. func scaffoldPlugin(t *testing.T, dir, name string, sharedHost bool) string { + t.Helper() + require := require.New(t) - path, err := Scaffold(dir, name, sharedHost) + path, err := Scaffold(context.Background(), dir, name, sharedHost) require.NoError(err) + // We want the scaffolded plugin to use the current version of ignite/cli, // for that we need to update the plugin go.mod and add a replace to target // current ignite/cli gomod, err := gomodule.ParseAt(path) require.NoError(err) + // use GOMOD env to get current directory module path modpath, err := gocmd.Env(gocmd.EnvGOMOD) require.NoError(err) @@ -515,12 +534,14 @@ func scaffoldPlugin(t *testing.T, dir, name string, sharedHost bool) string { func assertPlugin(t *testing.T, want, have Plugin) { t.Helper() + if want.Error != nil { require.Error(t, have.Error) assert.Regexp(t, want.Error.Error(), have.Error.Error()) } else { require.NoError(t, have.Error) } + // Errors aren't comparable with assert.Equal, because of the different stacks want.Error = nil have.Error = nil diff --git a/ignite/services/plugin/protocol.go b/ignite/services/plugin/protocol.go new file mode 100644 index 0000000000..0423e2e9b6 --- /dev/null +++ b/ignite/services/plugin/protocol.go @@ -0,0 +1,233 @@ +package plugin + +import ( + "context" + + hplugin "github.com/hashicorp/go-plugin" + "google.golang.org/grpc" + + v1 "github.com/ignite/cli/ignite/services/plugin/grpc/v1" +) + +var handshakeConfig = hplugin.HandshakeConfig{ + ProtocolVersion: 1, + MagicCookieKey: "IGNITE_APP", + MagicCookieValue: "ignite", +} + +// HandshakeConfig are used to just do a basic handshake between a plugin and host. +// If the handshake fails, a user friendly error is shown. This prevents users from +// executing bad plugins or executing a plugin directory. It is a UX feature, not a +// security feature. +func HandshakeConfig() hplugin.HandshakeConfig { + return handshakeConfig +} + +// NewGRPC returns a new gRPC plugin that implements the interface over gRPC. +func NewGRPC(impl Interface) hplugin.Plugin { + return grpcPlugin{impl: impl} +} + +type grpcPlugin struct { + hplugin.NetRPCUnsupportedPlugin + + impl Interface +} + +// GRPCServer returns a new server that implements the plugin interface over gRPC. +func (p grpcPlugin) GRPCServer(broker *hplugin.GRPCBroker, s *grpc.Server) error { + v1.RegisterInterfaceServiceServer(s, &server{ + impl: p.impl, + broker: broker, + }) + return nil +} + +// GRPCClient returns a new plugin client that allows calling the plugin interface over gRPC. +func (p grpcPlugin) GRPCClient(_ context.Context, broker *hplugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) { + return &client{ + grpc: v1.NewInterfaceServiceClient(c), + broker: broker, + }, nil +} + +type client struct { + grpc v1.InterfaceServiceClient + broker *hplugin.GRPCBroker +} + +func (c client) Manifest(ctx context.Context) (*Manifest, error) { + r, err := c.grpc.Manifest(ctx, &v1.ManifestRequest{}) + if err != nil { + return nil, err + } + + return r.Manifest, nil +} + +func (c client) Execute(ctx context.Context, cmd *ExecutedCommand, api ClientAPI) error { + brokerID, stopServer := c.startClientAPIServer(api) + _, err := c.grpc.Execute(ctx, &v1.ExecuteRequest{ + Cmd: cmd, + ClientApi: brokerID, + }) + stopServer() + return err +} + +func (c client) ExecuteHookPre(ctx context.Context, h *ExecutedHook, api ClientAPI) error { + brokerID, stopServer := c.startClientAPIServer(api) + _, err := c.grpc.ExecuteHookPre(ctx, &v1.ExecuteHookPreRequest{ + Hook: h, + ClientApi: brokerID, + }) + stopServer() + return err +} + +func (c client) ExecuteHookPost(ctx context.Context, h *ExecutedHook, api ClientAPI) error { + brokerID, stopServer := c.startClientAPIServer(api) + _, err := c.grpc.ExecuteHookPost(ctx, &v1.ExecuteHookPostRequest{ + Hook: h, + ClientApi: brokerID, + }) + stopServer() + return err +} + +func (c client) ExecuteHookCleanUp(ctx context.Context, h *ExecutedHook, api ClientAPI) error { + brokerID, stopServer := c.startClientAPIServer(api) + _, err := c.grpc.ExecuteHookCleanUp(ctx, &v1.ExecuteHookCleanUpRequest{ + Hook: h, + ClientApi: brokerID, + }) + stopServer() + return err +} + +func (c client) startClientAPIServer(api ClientAPI) (uint32, func()) { + var ( + srv *grpc.Server + brokerID = c.broker.NextId() + ) + + go c.broker.AcceptAndServe(brokerID, func(opts []grpc.ServerOption) *grpc.Server { + srv = grpc.NewServer(opts...) + v1.RegisterClientAPIServiceServer(srv, &clientAPIServer{impl: api}) + return srv + }) + + return brokerID, func() { srv.Stop() } +} + +type server struct { + v1.UnimplementedInterfaceServiceServer + + impl Interface + broker *hplugin.GRPCBroker +} + +func (s server) Manifest(ctx context.Context, _ *v1.ManifestRequest) (*v1.ManifestResponse, error) { + m, err := s.impl.Manifest(ctx) + if err != nil { + return nil, err + } + + return &v1.ManifestResponse{Manifest: m}, nil +} + +func (s server) Execute(ctx context.Context, r *v1.ExecuteRequest) (*v1.ExecuteResponse, error) { + conn, err := s.broker.Dial(r.ClientApi) + if err != nil { + return nil, err + } + + defer conn.Close() + + err = s.impl.Execute(ctx, r.GetCmd(), newClientAPIClient(conn)) + if err != nil { + return nil, err + } + + return &v1.ExecuteResponse{}, nil +} + +func (s server) ExecuteHookPre(ctx context.Context, r *v1.ExecuteHookPreRequest) (*v1.ExecuteHookPreResponse, error) { + conn, err := s.broker.Dial(r.ClientApi) + if err != nil { + return nil, err + } + + defer conn.Close() + + err = s.impl.ExecuteHookPre(ctx, r.GetHook(), newClientAPIClient(conn)) + if err != nil { + return nil, err + } + + return &v1.ExecuteHookPreResponse{}, nil +} + +func (s server) ExecuteHookPost(ctx context.Context, r *v1.ExecuteHookPostRequest) (*v1.ExecuteHookPostResponse, error) { + conn, err := s.broker.Dial(r.ClientApi) + if err != nil { + return nil, err + } + + defer conn.Close() + + err = s.impl.ExecuteHookPost(ctx, r.GetHook(), newClientAPIClient(conn)) + if err != nil { + return nil, err + } + + return &v1.ExecuteHookPostResponse{}, nil +} + +func (s server) ExecuteHookCleanUp(ctx context.Context, r *v1.ExecuteHookCleanUpRequest) (*v1.ExecuteHookCleanUpResponse, error) { + conn, err := s.broker.Dial(r.ClientApi) + if err != nil { + return nil, err + } + + defer conn.Close() + + err = s.impl.ExecuteHookCleanUp(ctx, r.GetHook(), newClientAPIClient(conn)) + if err != nil { + return nil, err + } + + return &v1.ExecuteHookCleanUpResponse{}, nil +} + +func newClientAPIClient(c *grpc.ClientConn) *clientAPIClient { + return &clientAPIClient{v1.NewClientAPIServiceClient(c)} +} + +type clientAPIClient struct { + grpc v1.ClientAPIServiceClient +} + +func (c clientAPIClient) GetChainInfo(ctx context.Context) (*ChainInfo, error) { + r, err := c.grpc.GetChainInfo(ctx, &v1.GetChainInfoRequest{}) + if err != nil { + return nil, err + } + + return r.ChainInfo, nil +} + +type clientAPIServer struct { + v1.UnimplementedClientAPIServiceServer + + impl ClientAPI +} + +func (s clientAPIServer) GetChainInfo(ctx context.Context, _ *v1.GetChainInfoRequest) (*v1.GetChainInfoResponse, error) { + chainInfo, err := s.impl.GetChainInfo(ctx) + if err != nil { + return nil, err + } + + return &v1.GetChainInfoResponse{ChainInfo: chainInfo}, nil +} diff --git a/ignite/services/plugin/scaffold.go b/ignite/services/plugin/scaffold.go index ff2a7fe093..500e1f6645 100644 --- a/ignite/services/plugin/scaffold.go +++ b/ignite/services/plugin/scaffold.go @@ -19,7 +19,7 @@ import ( var fsPluginSource embed.FS // Scaffold generates a plugin structure under dir/path.Base(moduleName). -func Scaffold(dir, moduleName string, sharedHost bool) (string, error) { +func Scaffold(ctx context.Context, dir, moduleName string, sharedHost bool) (string, error) { var ( name = filepath.Base(moduleName) finalDir = path.Join(dir, name) @@ -30,29 +30,35 @@ func Scaffold(dir, moduleName string, sharedHost bool) (string, error) { finalDir, ) ) + if _, err := os.Stat(finalDir); err == nil { // finalDir already exists, don't overwrite stuff return "", errors.Errorf("directory %q already exists, abort scaffolding", finalDir) } + if err := g.Box(template); err != nil { return "", errors.WithStack(err) } - ctx := plush.NewContext() - ctx.Set("ModuleName", moduleName) - ctx.Set("Name", name) - ctx.Set("SharedHost", sharedHost) - g.Transformer(xgenny.Transformer(ctx)) + pctx := plush.NewContextWithContext(ctx) + pctx.Set("ModuleName", moduleName) + pctx.Set("Name", name) + pctx.Set("SharedHost", sharedHost) + + g.Transformer(xgenny.Transformer(pctx)) r := genny.WetRunner(ctx) err := r.With(g) if err != nil { return "", errors.WithStack(err) } + if err := r.Run(); err != nil { return "", errors.WithStack(err) } - if err := gocmd.ModTidy(context.TODO(), finalDir); err != nil { + + if err := gocmd.ModTidy(ctx, finalDir); err != nil { return "", errors.WithStack(err) } + return finalDir, nil } diff --git a/ignite/services/plugin/scaffold_test.go b/ignite/services/plugin/scaffold_test.go index 8d7f122df3..a6b66a9db1 100644 --- a/ignite/services/plugin/scaffold_test.go +++ b/ignite/services/plugin/scaffold_test.go @@ -1,16 +1,24 @@ package plugin import ( + "context" + "path/filepath" "testing" "github.com/stretchr/testify/require" ) func TestScaffold(t *testing.T) { + // Arrange tmp := t.TempDir() + ctx := context.Background() - path, err := Scaffold(tmp, "github.com/foo/bar", false) + // Act + path, err := Scaffold(ctx, tmp, "github.com/foo/bar", false) + // Assert require.NoError(t, err) require.DirExists(t, path) + require.FileExists(t, filepath.Join(path, "go.mod")) + require.FileExists(t, filepath.Join(path, "main.go")) } diff --git a/ignite/services/plugin/template/go.mod.plush b/ignite/services/plugin/template/go.mod.plush index fe8fffd05b..97ea5b9955 100644 --- a/ignite/services/plugin/template/go.mod.plush +++ b/ignite/services/plugin/template/go.mod.plush @@ -4,5 +4,5 @@ go 1.21 require ( github.com/hashicorp/go-plugin v1.4.9 - github.com/ignite/cli v0.26.2-0.20230504112712-4324e2ff958f -) \ No newline at end of file + github.com/ignite/cli v0.27.2-0.20230905140057-d3918a77b607 +) diff --git a/ignite/services/plugin/template/main.go.plush b/ignite/services/plugin/template/main.go.plush index 077f10f250..83181ccd76 100644 --- a/ignite/services/plugin/template/main.go.plush +++ b/ignite/services/plugin/template/main.go.plush @@ -1,7 +1,7 @@ package main import ( - "encoding/gob" + "context" "fmt" "path/filepath" @@ -11,55 +11,56 @@ import ( "github.com/ignite/cli/ignite/services/plugin" ) -func init() { - gob.Register(plugin.Manifest{}) - gob.Register(plugin.ExecutedCommand{}) - gob.Register(plugin.ExecutedHook{}) -} - type app struct{} -func (app) Manifest() (plugin.Manifest, error) { - return plugin.Manifest{ +func (app) Manifest(ctx context.Context) (*plugin.Manifest, error) { + return &plugin.Manifest{ Name: "<%= Name %>", - // Add commands here - Commands: []plugin.Command{ + // TODO: Add commands here + Commands: []*plugin.Command{ // Example of a command { Use: "<%= Name %>", Short: "Explain what the command is doing...", Long: "Long description goes here...", - Flags: []plugin.Flag{ + Flags: []*plugin.Flag{ {Name: "my-flag", Type: plugin.FlagTypeString, Usage: "my flag description"}, }, PlaceCommandUnder: "ignite", // Examples of adding subcommands: - /* - Commands: []plugin.Command{ - {Use: "add"}, - {Use: "list"}, - {Use: "delete"}, - }, - */ + // Commands: []*plugin.Command{ + // {Use: "add"}, + // {Use: "list"}, + // {Use: "delete"}, + // }, }, }, - // Add hooks here - Hooks: []plugin.Hook{}, + // TODO: Add hooks here + Hooks: []*plugin.Hook{}, SharedHost: <%= SharedHost %>, }, nil } -func (app) Execute(cmd plugin.ExecutedCommand) error { +func (app) Execute(ctx context.Context, cmd *plugin.ExecutedCommand, api plugin.ClientAPI) error { // TODO: write command execution here - fmt.Printf("Hello I'm the <%= Name %> plugin\n") + fmt.Printf("Hello I'm the example-plugin plugin\n") fmt.Printf("My executed command: %q\n", cmd.Path) fmt.Printf("My args: %v\n", cmd.Args) - myFlag, _ := cmd.Flags().GetString("my-flag") + + flags, err := cmd.NewFlags() + if err != nil { + return err + } + + myFlag, _ := flags.GetString("my-flag") fmt.Printf("My flags: my-flag=%q\n", myFlag) fmt.Printf("My config parameters: %v\n", cmd.With) // This is how the plugin can access the chain: // c, err := getChain(cmd) + // if err != nil { + // return err + // } // According to the number of declared commands, you may need a switch: /* @@ -72,28 +73,37 @@ func (app) Execute(cmd plugin.ExecutedCommand) error { fmt.Println("Deleting stuff...") } */ + + // ClientAPI call example + fmt.Println(api.GetChainInfo(ctx)) + return nil } -func (app) ExecuteHookPre(hook plugin.ExecutedHook) error { - fmt.Printf("Executing hook pre %q\n", hook.Name) +func (app) ExecuteHookPre(ctx context.Context, h *plugin.ExecutedHook, api plugin.ClientAPI) error { + fmt.Printf("Executing hook pre %q\n", h.Hook.GetName()) return nil } -func (app) ExecuteHookPost(hook plugin.ExecutedHook) error { - fmt.Printf("Executing hook post %q\n", hook.Name) +func (app) ExecuteHookPost(ctx context.Context, h *plugin.ExecutedHook, api plugin.ClientAPI) error { + fmt.Printf("Executing hook post %q\n", h.Hook.GetName()) return nil } -func (app) ExecuteHookCleanUp(hook plugin.ExecutedHook) error { - fmt.Printf("Executing hook cleanup %q\n", hook.Name) +func (app) ExecuteHookCleanUp(ctx context.Context, h *plugin.ExecutedHook, api plugin.ClientAPI) error { + fmt.Printf("Executing hook cleanup %q\n", h.Hook.GetName()) return nil } -func getChain(cmd plugin.ExecutedCommand, chainOption ...chain.Option) (*chain.Chain, error) { +func getChain(cmd *plugin.ExecutedCommand, chainOption ...chain.Option) (*chain.Chain, error) { + flags, err := cmd.NewFlags() + if err != nil { + return nil, err + } + var ( - home, _ = cmd.Flags().GetString("home") - path, _ = cmd.Flags().GetString("path") + home, _ = flags.GetString("home") + path, _ = flags.GetString("path") ) if home != "" { chainOption = append(chainOption, chain.HomePath(home)) @@ -106,12 +116,11 @@ func getChain(cmd plugin.ExecutedCommand, chainOption ...chain.Option) (*chain.C } func main() { - pluginMap := map[string]hplugin.Plugin{ - "<%= Name %>": &plugin.InterfacePlugin{Impl: &app{}}, - } - hplugin.Serve(&hplugin.ServeConfig{ HandshakeConfig: plugin.HandshakeConfig(), - Plugins: pluginMap, + Plugins: map[string]hplugin.Plugin{ + "<%= Name %>": plugin.NewGRPC(&app{}), + }, + GRPCServer: hplugin.DefaultGRPCServer, }) } diff --git a/integration/plugin/plugin_test.go b/integration/plugin/plugin_test.go index 813af11180..9f0fe6268e 100644 --- a/integration/plugin/plugin_test.go +++ b/integration/plugin/plugin_test.go @@ -1,6 +1,7 @@ package plugin_test import ( + "path/filepath" "testing" "github.com/stretchr/testify/assert" @@ -14,11 +15,10 @@ import ( func TestAddRemovePlugin(t *testing.T) { var ( - require = require.New(t) - assert = assert.New(t) - env = envtest.New(t) - app = env.Scaffold("github.com/test/blog") - pluginRepo = "github.com/ignite/example-plugin" + require = require.New(t) + assert = assert.New(t) + env = envtest.New(t) + app = env.Scaffold("github.com/test/blog") assertPlugins = func(expectedLocalPlugins, expectedGlobalPlugins []pluginsconfig.Plugin) { localCfg, err := pluginsconfig.ParseDir(app.SourcePath()) @@ -36,7 +36,11 @@ func TestAddRemovePlugin(t *testing.T) { // no plugins expected assertPlugins(nil, nil) - env.Must(env.Exec("install plugin locally", + // Note: Originally plugin repo was "github.com/ignite/example-plugin" instead of a local one + pluginRepo, err := filepath.Abs("testdata/example-plugin") + require.NoError(err) + + env.Must(env.Exec("add plugin locally", step.NewSteps(step.New( step.Exec(envtest.IgniteApp, "app", "install", pluginRepo, "k1=v1", "k2=v2"), step.Workdir(app.SourcePath()), diff --git a/integration/plugin/testdata/example-plugin/go.mod b/integration/plugin/testdata/example-plugin/go.mod new file mode 100644 index 0000000000..70704d2477 --- /dev/null +++ b/integration/plugin/testdata/example-plugin/go.mod @@ -0,0 +1,82 @@ +module example-plugin + +go 1.20 + +require ( + github.com/hashicorp/go-plugin v1.4.9 + github.com/ignite/cli v0.27.1 +) + +require ( + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 // indirect + github.com/acomagu/bufpipe v1.0.4 // indirect + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/charmbracelet/lipgloss v0.6.0 // indirect + github.com/cloudflare/circl v1.3.3 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/fatih/color v1.15.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/go-git/gcfg v1.5.0 // indirect + github.com/go-git/go-billy/v5 v5.4.1 // indirect + github.com/go-git/go-git/v5 v5.6.1 // indirect + github.com/gobuffalo/flect v0.3.0 // indirect + github.com/gobuffalo/genny/v2 v2.1.0 // indirect + github.com/gobuffalo/github_flavored_markdown v1.1.3 // indirect + github.com/gobuffalo/helpers v0.6.7 // indirect + github.com/gobuffalo/logger v1.0.7 // indirect + github.com/gobuffalo/packd v1.0.2 // indirect + github.com/gobuffalo/plush/v4 v4.1.16 // indirect + github.com/gobuffalo/tags/v3 v3.1.4 // indirect + github.com/gobuffalo/validate/v3 v3.3.3 // indirect + github.com/gofrs/uuid v4.3.0+incompatible // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/hashicorp/go-hclog v1.2.0 // indirect + github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect + github.com/imdario/mergo v0.3.15 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/microcosm-cc/bluemonday v1.0.20 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/muesli/reflow v0.3.0 // indirect + github.com/muesli/termenv v0.15.1 // indirect + github.com/oklog/run v1.0.0 // indirect + github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/rivo/uniseg v0.4.4 // indirect + github.com/sergi/go-diff v1.3.1 // indirect + github.com/sirupsen/logrus v1.9.2 // indirect + github.com/skeema/knownhosts v1.1.1 // indirect + github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d // indirect + github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e // indirect + github.com/spf13/cobra v1.7.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + go.etcd.io/bbolt v1.3.7 // indirect + golang.org/x/crypto v0.9.0 // indirect + golang.org/x/exp v0.0.0-20230519143937-03e91628a987 // indirect + golang.org/x/mod v0.10.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sync v0.2.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/term v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/tools v0.9.1 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + google.golang.org/grpc v1.55.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) + +replace ( + github.com/ignite/cli => ../../../../ +) diff --git a/integration/plugin/testdata/example-plugin/go.sum b/integration/plugin/testdata/example-plugin/go.sum new file mode 100644 index 0000000000..56b88f4cac --- /dev/null +++ b/integration/plugin/testdata/example-plugin/go.sum @@ -0,0 +1,288 @@ +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= +github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 h1:ZK3C5DtzV2nVAQTx5S5jQvMeDqWtD1By5mOoyY/xJek= +github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE= +github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= +github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/charmbracelet/lipgloss v0.6.0 h1:1StyZB9vBSOyuZxQUcUwGr17JmojPNm87inij9N3wJY= +github.com/charmbracelet/lipgloss v0.6.0/go.mod h1:tHh2wr34xcHjC2HCXIlGSG1jaDF0S0atAUvBMP6Ppuk= +github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= +github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= +github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= +github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= +github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= +github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= +github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= +github.com/go-git/go-git-fixtures/v4 v4.3.1 h1:y5z6dd3qi8Hl+stezc8p3JxDkoTRqMAlKnXHuzrfjTQ= +github.com/go-git/go-git-fixtures/v4 v4.3.1/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo= +github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk= +github.com/go-git/go-git/v5 v5.6.1/go.mod h1:mvyoL6Unz0PiTQrGQfSfiLFhBH1c1e84ylC2MDs4ee8= +github.com/gobuffalo/flect v0.3.0 h1:erfPWM+K1rFNIQeRPdeEXxo8yFr/PO17lhRnS8FUrtk= +github.com/gobuffalo/flect v0.3.0/go.mod h1:5pf3aGnsvqvCj50AVni7mJJF8ICxGZ8HomberC3pXLE= +github.com/gobuffalo/genny/v2 v2.1.0 h1:cCRBbqzo3GfNvj3UetD16zRgUvWFEyyl0qTqquuIqOM= +github.com/gobuffalo/genny/v2 v2.1.0/go.mod h1:4yoTNk4bYuP3BMM6uQKYPvtP6WsXFGm2w2EFYZdRls8= +github.com/gobuffalo/github_flavored_markdown v1.1.3 h1:rSMPtx9ePkFB22vJ+dH+m/EUBS8doQ3S8LeEXcdwZHk= +github.com/gobuffalo/github_flavored_markdown v1.1.3/go.mod h1:IzgO5xS6hqkDmUh91BW/+Qxo/qYnvfzoz3A7uLkg77I= +github.com/gobuffalo/helpers v0.6.7 h1:C9CedoRSfgWg2ZoIkVXgjI5kgmSpL34Z3qdnzpfNVd8= +github.com/gobuffalo/helpers v0.6.7/go.mod h1:j0u1iC1VqlCaJEEVkZN8Ia3TEzfj/zoXANqyJExTMTA= +github.com/gobuffalo/logger v1.0.7 h1:LTLwWelETXDYyqF/ASf0nxaIcdEOIJNxRokPcfI/xbU= +github.com/gobuffalo/logger v1.0.7/go.mod h1:u40u6Bq3VVvaMcy5sRBclD8SXhBYPS0Qk95ubt+1xJM= +github.com/gobuffalo/packd v1.0.2 h1:Yg523YqnOxGIWCp69W12yYBKsoChwI7mtu6ceM9Bwfw= +github.com/gobuffalo/packd v1.0.2/go.mod h1:sUc61tDqGMXON80zpKGp92lDb86Km28jfvX7IAyxFT8= +github.com/gobuffalo/plush/v4 v4.1.16 h1:Y6jVVTLdg1BxRXDIbTJz+J8QRzEAtv5ZwYpGdIFR7VU= +github.com/gobuffalo/plush/v4 v4.1.16/go.mod h1:6t7swVsarJ8qSLw1qyAH/KbrcSTwdun2ASEQkOznakg= +github.com/gobuffalo/tags/v3 v3.1.4 h1:X/ydLLPhgXV4h04Hp2xlbI2oc5MDaa7eub6zw8oHjsM= +github.com/gobuffalo/tags/v3 v3.1.4/go.mod h1:ArRNo3ErlHO8BtdA0REaZxijuWnWzF6PUXngmMXd2I0= +github.com/gobuffalo/validate/v3 v3.3.3 h1:o7wkIGSvZBYBd6ChQoLxkz2y1pfmhbI4jNJYh6PuNJ4= +github.com/gobuffalo/validate/v3 v3.3.3/go.mod h1:YC7FsbJ/9hW/VjQdmXPvFqvRis4vrRYFxr69WiNZw6g= +github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc= +github.com/gofrs/uuid v4.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= +github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-plugin v1.4.9 h1:ESiK220/qE0aGxWdzKIvRH69iLiuN/PjoLTm69RoWtU= +github.com/hashicorp/go-plugin v1.4.9/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M= +github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/microcosm-cc/bluemonday v1.0.20 h1:flpzsq4KU3QIYAYGV/szUat7H+GPOXR0B2JU5A1Wp8Y= +github.com/microcosm-cc/bluemonday v1.0.20/go.mod h1:yfBmMi8mxvaZut3Yytv+jTXRY8mxyjJ0/kQBTElld50= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM= +github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ= +github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= +github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= +github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= +github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs= +github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y= +github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag= +github.com/skeema/knownhosts v1.1.1 h1:MTk78x9FPgDFVFkDLTrsnnfCJl7g1C/nnKvePgrIngE= +github.com/skeema/knownhosts v1.1.1/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d h1:yKm7XZV6j9Ev6lojP2XaIshpT4ymkqhMeSghO5Ps00E= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e h1:qpG93cPwA5f7s/ZPBJnGOYQNK/vKsaDaseuKT5Asee8= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +golang.org/x/arch v0.1.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/exp v0.0.0-20230519143937-03e91628a987 h1:3xJIFvzUFbu4ls0BTBYcgbCGhA63eAOEMxIHugyXJqA= +golang.org/x/exp v0.0.0-20230519143937-03e91628a987/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/integration/plugin/testdata/example-plugin/main.go b/integration/plugin/testdata/example-plugin/main.go new file mode 100644 index 0000000000..4a8b177bf4 --- /dev/null +++ b/integration/plugin/testdata/example-plugin/main.go @@ -0,0 +1,74 @@ +package main + +import ( + "context" + "fmt" + + hplugin "github.com/hashicorp/go-plugin" + + "github.com/ignite/cli/ignite/services/plugin" +) + +type p struct{} + +func (p) Manifest(context.Context) (*plugin.Manifest, error) { + return &plugin.Manifest{ + Name: "example-plugin", + Commands: []*plugin.Command{ + { + Use: "example-plugin", + Short: "Explain what the command is doing...", + Long: "Long description goes here...", + Flags: []*plugin.Flag{ + {Name: "my-flag", Type: plugin.FlagTypeString, Usage: "my flag description"}, + }, + PlaceCommandUnder: "ignite", + }, + }, + Hooks: []*plugin.Hook{}, + }, nil +} + +func (p) Execute(ctx context.Context, cmd *plugin.ExecutedCommand, api plugin.ClientAPI) error { + fmt.Printf("Hello I'm the example-plugin plugin\n") + fmt.Printf("My executed command: %q\n", cmd.Path) + fmt.Printf("My args: %v\n", cmd.Args) + + flags, err := cmd.NewFlags() + if err != nil { + return err + } + + myFlag, _ := flags.GetString("my-flag") + fmt.Printf("My flags: my-flag=%q\n", myFlag) + fmt.Printf("My config parameters: %v\n", cmd.With) + + fmt.Println(api.GetChainInfo(ctx)) + + return nil +} + +func (p) ExecuteHookPre(_ context.Context, h *plugin.ExecutedHook, _ plugin.ClientAPI) error { + fmt.Printf("Executing hook pre %q\n", h.Hook.GetName()) + return nil +} + +func (p) ExecuteHookPost(_ context.Context, h *plugin.ExecutedHook, _ plugin.ClientAPI) error { + fmt.Printf("Executing hook post %q\n", h.Hook.GetName()) + return nil +} + +func (p) ExecuteHookCleanUp(_ context.Context, h *plugin.ExecutedHook, _ plugin.ClientAPI) error { + fmt.Printf("Executing hook cleanup %q\n", h.Hook.GetName()) + return nil +} + +func main() { + hplugin.Serve(&hplugin.ServeConfig{ + HandshakeConfig: plugin.HandshakeConfig(), + Plugins: map[string]hplugin.Plugin{ + "example-plugin": plugin.NewGRPC(&p{}), + }, + GRPCServer: hplugin.DefaultGRPCServer, + }) +} diff --git a/proto/buf.gen.yaml b/proto/buf.gen.yaml new file mode 100644 index 0000000000..36d3d55811 --- /dev/null +++ b/proto/buf.gen.yaml @@ -0,0 +1,8 @@ +version: v1 +plugins: +- plugin: buf.build/protocolbuffers/go + out: . + opt: paths=source_relative +- plugin: buf.build/grpc/go + out: . + opt: paths=source_relative diff --git a/proto/buf.md b/proto/buf.md new file mode 100644 index 0000000000..00a7d287b3 --- /dev/null +++ b/proto/buf.md @@ -0,0 +1,3 @@ +# Protobufs + +This is the public protocol buffers API for [Ignite CLI](https://github.com/ignite/cli). diff --git a/proto/buf.yaml b/proto/buf.yaml new file mode 100644 index 0000000000..faea9af67b --- /dev/null +++ b/proto/buf.yaml @@ -0,0 +1,15 @@ +version: v1 +name: buf.build/ignitehq/cli +breaking: + use: + - FILE +lint: + use: + - DEFAULT + - FILE_LOWER_SNAKE_CASE + except: + - UNARY_RPC + - COMMENT_FIELD + - SERVICE_SUFFIX + - PACKAGE_VERSION_SUFFIX + - RPC_REQUEST_STANDARD_NAME diff --git a/proto/ignite/services/plugin/grpc/v1/client_api.proto b/proto/ignite/services/plugin/grpc/v1/client_api.proto new file mode 100644 index 0000000000..d7b76c7bc0 --- /dev/null +++ b/proto/ignite/services/plugin/grpc/v1/client_api.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +package ignite.services.plugin.grpc.v1; + +option go_package = "github.com/ignite/cli/ignite/services/plugin/grpc/v1"; + +message ChainInfo { + string chain_id = 1; + string app_path = 2; + string config_path = 3; + string rpc_address = 4; +} diff --git a/proto/ignite/services/plugin/grpc/v1/interface.proto b/proto/ignite/services/plugin/grpc/v1/interface.proto new file mode 100644 index 0000000000..5dcaef4209 --- /dev/null +++ b/proto/ignite/services/plugin/grpc/v1/interface.proto @@ -0,0 +1,147 @@ +syntax = "proto3"; + +package ignite.services.plugin.grpc.v1; + +option go_package = "github.com/ignite/cli/ignite/services/plugin/grpc/v1"; + +// ExecutedCommand represents a plugin command under execution. +message ExecutedCommand { + // Use is the one-line usage message. + string use = 1; + + // Path contains the command path, e.g. `ignite scaffold foo`. + string path = 2; + + // Args are the command arguments. + repeated string args = 3; + + // Full list of args taken from the command line. + repeated string os_args = 4; + + // With contains the plugin config parameters. + map with = 5; + + // Flags holds the list of command flags. + repeated Flag flags = 6; +} + +// ExecutedHook represents a plugin hook under execution. +message ExecutedHook { + // Hook is a copy of the original Hook defined in the Manifest. + Hook hook = 1; + + // ExecutedCommand gives access to the command attached by the hook. + ExecutedCommand executed_command = 2; +} + +// Manifest represents the plugin behavior. +message Manifest { + // Plugin name. + string name = 1; + + // Commands contains the commands that will be added to the list of ignite commands. + // Each commands are independent, for nested commands use the inner Commands field. + bool shared_host = 2; + + // Hooks contains the hooks that will be attached to the existing ignite commands. + repeated Command commands = 3; + + // Enables sharing a single plugin server across all running instances of a plugin. + // Useful if a plugin adds or extends long running commands. + // + // Example: if a plugin defines a hook on `ignite chain serve`, a plugin server is + // instanciated when the command is run. Now if you want to interact with that instance + // from commands defined in that plugin, you need to enable shared host, or else the + // commands will just instantiate separate plugin servers. + // + // When enabled, all plugins of the same path loaded from the same configuration will + // attach it's RPC client to a an existing RPC server. + // + // If a plugin instance has no other running plugin servers, it will create one and it + // will be the host. + repeated Hook hooks = 4; +} + +// Command represents a plugin command. +message Command { + // Use is the one-line usage message. + // + // Recommended syntax is as follow: + // [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required. + // ... indicates that you can specify multiple values for the previous argument. + // | indicates mutually exclusive information. You can use the argument to the left of the separator or the + // argument to the right of the separator. You cannot use both arguments in a single use of the command. + // { } delimits a set of mutually exclusive arguments when one of the arguments is required. If the arguments are + // optional, they are enclosed in brackets ([ ]). + // + // Example: add [-F file | -D dir]... [-f format] profile + string use = 1; + + // Aliases is an array of aliases that can be used instead of the first word in Use. + repeated string aliases = 2; + + // Short is the short description shown in the 'help' output. + string short = 3; + + // Long is the long message shown in the 'help ' output. + string long = 4; + + // Hidden defines, if this command is hidden and should NOT show up in the list of available commands. + bool hidden = 5; + + // Flags holds the list of command flags. + repeated Flag flags = 6; + + // Indicates where the command should be placed. + // For instance `ignite scaffold` will place the command at the `scaffold` command. + // An empty value is interpreted as `ignite` (==root). + string place_command_under = 7; + + // List of sub commands. + repeated Command commands = 8; +} + +// Flag represents of a command line flag. +message Flag { + // Type represents the flag type. + enum Type { + TYPE_FLAG_STRING_UNSPECIFIED = 0; + TYPE_FLAG_INT = 1; + TYPE_FLAG_UINT = 2; + TYPE_FLAG_INT64 = 3; + TYPE_FLAG_UINT64 = 4; + TYPE_FLAG_BOOL = 5; + TYPE_FLAG_STRING_SLICE = 6; + } + + // Name as it appears in the command line. + string name = 1; + + // One letter abbreviation of the flag. + string shorthand = 2; + + // Help message. + string usage = 3; + + // Default flag value. + string default_value = 4; + + // Flag type. + Type type = 5; + + // Flag value. + string value = 6; + + // Indicates wether or not the flag is propagated on children commands. + bool persistent = 7; +} + +// Hook represents a user defined action within a plugin. +message Hook { + // Identifies the hook for the client to invoke the correct hook. + // It must be unique. + string name = 1; + + // Indicates the command where to register the hooks. + string place_hook_on = 2; +} diff --git a/proto/ignite/services/plugin/grpc/v1/service.proto b/proto/ignite/services/plugin/grpc/v1/service.proto new file mode 100644 index 0000000000..e35d89f2f5 --- /dev/null +++ b/proto/ignite/services/plugin/grpc/v1/service.proto @@ -0,0 +1,84 @@ +syntax = "proto3"; + +package ignite.services.plugin.grpc.v1; + +import "ignite/services/plugin/grpc/v1/client_api.proto"; +import "ignite/services/plugin/grpc/v1/interface.proto"; + +option go_package = "github.com/ignite/cli/ignite/services/plugin/grpc/v1"; + +// InterfaceService defines the interface that must be implemented by all plugins. +service InterfaceService { + // Manifest declares the plugin's Command(s) and Hook(s). + rpc Manifest(ManifestRequest) returns (ManifestResponse); + + // Execute will be invoked by ignite when a plugin Command is executed. + // It is global for all commands declared in Manifest, if you have declared + // multiple commands, use cmd.Path to distinguish them. + rpc Execute(ExecuteRequest) returns (ExecuteResponse); + + // ExecuteHookPre is invoked by ignite when a command specified by the Hook + // path is invoked. + // It is global for all hooks declared in Manifest, if you have declared + // multiple hooks, use hook.Name to distinguish them. + rpc ExecuteHookPre(ExecuteHookPreRequest) returns (ExecuteHookPreResponse); + + // ExecuteHookPost is invoked by ignite when a command specified by the hook + // path is invoked. + // It is global for all hooks declared in Manifest, if you have declared + // multiple hooks, use hook.Name to distinguish them. + rpc ExecuteHookPost(ExecuteHookPostRequest) returns (ExecuteHookPostResponse); + + // ExecuteHookCleanUp is invoked by ignite when a command specified by the + // hook path is invoked. Unlike ExecuteHookPost, it is invoked regardless of + // execution status of the command and hooks. + // It is global for all hooks declared in Manifest, if you have declared + // multiple hooks, use hook.Name to distinguish them. + rpc ExecuteHookCleanUp(ExecuteHookCleanUpRequest) returns (ExecuteHookCleanUpResponse); +} + +message ManifestRequest {} + +message ManifestResponse { + Manifest manifest = 1; +} + +message ExecuteRequest { + ExecutedCommand cmd = 1; + uint32 client_api = 2; +} + +message ExecuteResponse {} + +message ExecuteHookPreRequest { + ExecutedHook hook = 1; + uint32 client_api = 2; +} + +message ExecuteHookPreResponse {} + +message ExecuteHookPostRequest { + ExecutedHook hook = 1; + uint32 client_api = 2; +} + +message ExecuteHookPostResponse {} + +message ExecuteHookCleanUpRequest { + ExecutedHook hook = 1; + uint32 client_api = 2; +} + +message ExecuteHookCleanUpResponse {} + +// ClientAPIService defines the interface that allows plugins to get chain app analysis info. +service ClientAPIService { + // GetChainInfo returns basic chain info for the configured app + rpc GetChainInfo(GetChainInfoRequest) returns (GetChainInfoResponse); +} + +message GetChainInfoRequest {} + +message GetChainInfoResponse { + ChainInfo chain_info = 1; +}