diff --git a/.circleci/config.yml b/.circleci/config.yml index eff1850ab..bb533b3d6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -85,22 +85,6 @@ jobs: - run: docker push mesg/core:$CIRCLE_TAG - run: docker push mesg/core:latest - "release_cli_dev": - <<: *run_on_docker - steps: - - checkout - - run: scripts/build-cli.sh "dev build `echo $CIRCLE_SHA1 | cut -c1-7`" - - run: go get -u github.com/tcnksm/ghr - - run: ghr -u mesg-foundation -r engine -delete -prerelease -n "Developer Release" -b "Warning - this is a developer release, use it only if you know what are doing. Make sure to pull the latest \`mesg/core:dev\` image. \`\`\`docker pull mesg/core:dev\`\`\`" release-dev ./bin - - "release_cli_prod": - <<: *run_on_docker - steps: - - checkout - - run: scripts/build-cli.sh $CIRCLE_TAG - - run: go get -u github.com/tcnksm/ghr - - run: ghr -u mesg-foundation -r engine -delete $CIRCLE_TAG ./bin - workflows: version: 2 @@ -141,9 +125,6 @@ workflows: requires: - "test" - "lint" - - "release_cli_dev": - requires: - - "publish_docker_dev" test_prod: jobs: @@ -183,11 +164,3 @@ workflows: only: /^v.*/ branches: ignore: /.*/ - - "release_cli_prod": - requires: - - "publish_docker_prod" - filters: - tags: - only: /^v.*/ - branches: - ignore: /.*/ diff --git a/commands/commands.go b/commands/commands.go deleted file mode 100644 index 4efe92597..000000000 --- a/commands/commands.go +++ /dev/null @@ -1,99 +0,0 @@ -package commands - -import ( - "io" - "io/ioutil" - "time" - - "github.com/mesg-foundation/core/commands/provider" - "github.com/mesg-foundation/core/container" - "github.com/mesg-foundation/core/protobuf/coreapi" - "github.com/mesg-foundation/core/utils/servicetemplate" - "github.com/spf13/cobra" -) - -// RootExecutor is an interface that handles core commands. -type RootExecutor interface { - Start() error - Stop() error - Status() (container.StatusType, error) - Logs() (io.ReadCloser, error) -} - -// ServiceExecutor is an interface that handles services commands. -type ServiceExecutor interface { - ServiceByID(id string) (*coreapi.Service, error) - ServiceDeleteAll(deleteData bool) error - ServiceDelete(deleteData bool, ids ...string) error - ServiceDeploy(path string, env map[string]string, statuses chan provider.DeployStatus) (sid string, hash string, validationError, err error) - ServiceListenEvents(id, eventFilter string) (chan *coreapi.EventData, chan error, error) - ServiceListenResults(id, taskFilter string, tagFilters []string) (chan *coreapi.ResultData, chan error, error) - ServiceLogs(id string, dependencies ...string) (logs []*provider.Log, closer func(), errC chan error, err error) - ServiceExecuteTask(id, taskKey, inputData string, tags []string) (string, error) - ServiceStart(id string) error - ServiceStop(id string) error - ServiceValidate(path string) (string, error) - ServiceGenerateDocs(path string) error - ServiceList() ([]*coreapi.Service, error) - ServiceInitTemplateList() ([]*servicetemplate.Template, error) - ServiceInitDownloadTemplate(t *servicetemplate.Template, dst string) error -} - -// MarketplaceExecutor is an interface that handles marketplace commands. -type MarketplaceExecutor interface { - UploadSource(path string) (deployment provider.MarketplaceDeployedSource, err error) - PreparePublishServiceVersion(service provider.MarketplaceManifestServiceData, from string) (provider.Transaction, error) - PublishPublishServiceVersion(signedTransaction string) (sid, versionHash, manifest, manifestProtocol string, err error) - PrepareCreateServiceOffer(sid string, price string, duration string, from string) (provider.Transaction, error) - PublishCreateServiceOffer(signedTransaction string) (sid, offerIndex, price, duration string, err error) - PreparePurchase(sid, offerIndex, from string) ([]provider.Transaction, error) - PublishPurchase(signedTransactions []string) (sid, offerIndex, purchaser, price, duration string, expire time.Time, err error) - GetService(sid string) (provider.MarketplaceService, error) -} - -// WalletExecutor is an interface that handles wallet commands. -type WalletExecutor interface { - List() ([]string, error) - Create(passphrase string) (string, error) - Delete(address string, passphrase string) (string, error) - Export(address string, passphrase string) (provider.WalletEncryptedKeyJSONV3, error) - Import(account provider.WalletEncryptedKeyJSONV3, passphrase string) (string, error) - ImportFromPrivateKey(privateKey string, passphrase string) (string, error) - Sign(address string, passphrase string, transaction provider.Transaction) (string, error) -} - -// Executor is an interface that keeps all commands interfaces. -type Executor interface { - RootExecutor - ServiceExecutor - MarketplaceExecutor - WalletExecutor -} - -// Build constructs root command and returns it. -func Build(e Executor) *cobra.Command { - return newRootCmd(e).cmd -} - -type baseCmd struct { - cmd *cobra.Command -} - -// newCommand set default options for given command. -func newCommand(c *cobra.Command) *cobra.Command { - c.DisableAutoGenTag = true - return c -} - -// discardOutput discards usage and error messages. -func (c *baseCmd) discardOutput() { - c.cmd.SetOutput(ioutil.Discard) -} - -// getFirstOrCurrentPath returns directory if args len is gt 0 or current directory. -func getFirstOrCurrentPath(args []string) string { - if len(args) > 0 { - return args[0] - } - return "./" -} diff --git a/commands/commands_test.go b/commands/commands_test.go deleted file mode 100644 index a6df36edc..000000000 --- a/commands/commands_test.go +++ /dev/null @@ -1,82 +0,0 @@ -package commands - -import ( - "bufio" - "io" - "os" - "strings" - "sync" - "testing" - - "github.com/mesg-foundation/core/commands/mocks" - "github.com/stretchr/testify/require" -) - -// captureStd is helper function that captures Stdout and Stderr and returns function -// that returns standard output and standard error as string. -func captureStd(t *testing.T) func() (stdout string, stderr string) { - var ( - bufout strings.Builder - buferr strings.Builder - wg sync.WaitGroup - - stdout = os.Stdout - stderr = os.Stderr - ) - - or, ow, err := os.Pipe() - require.NoError(t, err) - - er, ew, err := os.Pipe() - require.NoError(t, err) - - os.Stdout = ow - os.Stderr = ew - - wg.Add(1) - // copy out and err to buffers - go func() { - _, err := io.Copy(&bufout, or) - require.NoError(t, err) - or.Close() - - _, err = io.Copy(&buferr, er) - require.NoError(t, err) - er.Close() - - wg.Done() - }() - - return func() (string, string) { - // close writers and wait for copy to finish - ow.Close() - ew.Close() - wg.Wait() - - // set back oginal stdout and stderr - os.Stdout = stdout - os.Stderr = stderr - - // return stdout and stderr - return bufout.String(), buferr.String() - } -} - -// newMockExecutor returns an Executor mock for testing. -func newMockExecutor() *mocks.Executor { - return &mocks.Executor{} -} - -func TestBaseCommandCmd(t *testing.T) { - // NOTE: this test is only to satisfy structcheck - // as it doesn't handle embedded structs yet. - // It is still very usesful linter so - // DO NOT REMOVE this test - _ = baseCmd{}.cmd -} - -func readLine(t *testing.T, r *bufio.Reader) []byte { - line, _, err := r.ReadLine() - require.NoError(t, err) - return line -} diff --git a/commands/custom_flags.go b/commands/custom_flags.go deleted file mode 100644 index 46c1b2492..000000000 --- a/commands/custom_flags.go +++ /dev/null @@ -1,33 +0,0 @@ -package commands - -import ( - "fmt" - - "github.com/sirupsen/logrus" -) - -// logFormatValue represents log format flag value. -type logFormatValue string - -func (v *logFormatValue) Set(value string) error { - if value != "text" && value != "json" { - return fmt.Errorf("%s is not valid log format", value) - } - *v = logFormatValue(value) - return nil -} -func (v *logFormatValue) Type() string { return "string" } -func (v *logFormatValue) String() string { return string(*v) } - -// logLevelValue represents log level flag value. -type logLevelValue string - -func (v *logLevelValue) Set(value string) error { - if _, err := logrus.ParseLevel(value); err != nil { - return fmt.Errorf("%s is not valid log level", value) - } - *v = logLevelValue(value) - return nil -} -func (v *logLevelValue) Type() string { return "string" } -func (v *logLevelValue) String() string { return string(*v) } diff --git a/commands/custom_flags_test.go b/commands/custom_flags_test.go deleted file mode 100644 index 6dd631ab2..000000000 --- a/commands/custom_flags_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package commands - -import ( - "testing" - - "github.com/spf13/pflag" - "github.com/stretchr/testify/require" -) - -func TestLogFormatValue(t *testing.T) { - lfv := logFormatValue("") - require.Equal(t, lfv.Type(), "string") - - pflag.Var(&lfv, "test-log-format", "") - require.NoError(t, pflag.Set("test-log-format", "text")) - require.NoError(t, pflag.Set("test-log-format", "json")) - require.Error(t, pflag.Set("test-log-format", "unknown")) -} - -func TestLogLevelValue(t *testing.T) { - llv := logLevelValue("") - require.Equal(t, llv.Type(), "string") - - pflag.Var(&llv, "test-log-level", "") - require.NoError(t, pflag.Set("test-log-level", "debug")) - require.NoError(t, pflag.Set("test-log-level", "info")) - require.NoError(t, pflag.Set("test-log-level", "warn")) - require.NoError(t, pflag.Set("test-log-level", "error")) - require.NoError(t, pflag.Set("test-log-level", "fatal")) - require.NoError(t, pflag.Set("test-log-level", "panic")) - require.Error(t, pflag.Set("test-log-level", "unknown")) -} diff --git a/commands/logs.go b/commands/logs.go deleted file mode 100644 index 8c4e377e8..000000000 --- a/commands/logs.go +++ /dev/null @@ -1,48 +0,0 @@ -package commands - -import ( - "fmt" - "os" - - "github.com/docker/docker/pkg/stdcopy" - "github.com/mesg-foundation/core/container" - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" -) - -type logsCmd struct { - baseCmd - - e RootExecutor -} - -func newLogsCmd(e RootExecutor) *logsCmd { - c := &logsCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "logs", - Short: "Show the Core's logs", - RunE: c.runE, - }) - return c -} - -func (c *logsCmd) runE(cmd *cobra.Command, args []string) error { - status, err := c.e.Status() - if err != nil { - return err - } - - if status == container.STOPPED { - fmt.Printf("%s Core is stopped", pretty.WarnSign) - return nil - } - - reader, err := c.e.Logs() - if err != nil { - return err - } - defer reader.Close() - - _, err = stdcopy.StdCopy(os.Stdout, os.Stderr, reader) - return err -} diff --git a/commands/logs_test.go b/commands/logs_test.go deleted file mode 100644 index 2d6d8c5e3..000000000 --- a/commands/logs_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package commands - -import ( - "bytes" - "io/ioutil" - "testing" - - "github.com/docker/docker/pkg/stdcopy" - "github.com/mesg-foundation/core/container" - "github.com/stretchr/testify/require" -) - -func TestLogsCmdRunE(t *testing.T) { - var ( - m = newMockExecutor() - c = newLogsCmd(m) - closeStd = captureStd(t) - buf = new(bytes.Buffer) - msgout = []byte("core: 2018-01-01 log\n") - msgerr = []byte("core: 2018-01-01 errlog\n") - ) - - // create reader for docker stdcopy - wout := stdcopy.NewStdWriter(buf, stdcopy.Stdout) - wout.Write(msgout) - - werr := stdcopy.NewStdWriter(buf, stdcopy.Stderr) - werr.Write(msgerr) - - m.On("Status").Return(container.RUNNING, nil) - m.On("Logs").Return(ioutil.NopCloser(buf), nil) - c.cmd.Execute() - - m.AssertExpectations(t) - - stdout, stderr := closeStd() - require.Equal(t, string(msgout), stdout) - require.Equal(t, string(msgerr), stderr) -} diff --git a/commands/marketplace_create_offer.go b/commands/marketplace_create_offer.go deleted file mode 100644 index f64bb7688..000000000 --- a/commands/marketplace_create_offer.go +++ /dev/null @@ -1,90 +0,0 @@ -package commands - -import ( - "fmt" - - "github.com/mesg-foundation/core/commands/provider" - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" - survey "gopkg.in/AlecAivazis/survey.v1" -) - -type marketplaceCreateOfferCmd struct { - baseMarketplaceCmd - - price string // in MESG token - duration string - - e Executor -} - -func newMarketplaceCreateOfferCmd(e Executor) *marketplaceCreateOfferCmd { - c := &marketplaceCreateOfferCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "create-offer", - Short: "Create a new offer on a service on the MESG Marketplace", - Example: `mesg-core marketplace create-offer SID -mesg-core marketplace create-offer SID --price 10 --duration 3600`, - PreRunE: c.preRunE, - RunE: c.runE, - Args: cobra.MinimumNArgs(1), - }) - c.setupFlags() - c.cmd.Flags().StringVarP(&c.price, "price", "", c.price, "Price (in MESG token) of the offer to create") - c.cmd.Flags().StringVarP(&c.duration, "duration", "", c.duration, "Duration (in second) of the offer to create") - return c -} - -func (c *marketplaceCreateOfferCmd) preRunE(cmd *cobra.Command, args []string) error { - if err := c.askAccountAndPassphrase(); err != nil { - return err - } - - if c.price == "" { - if err := askInput("Enter the price (in MESG Token) of the offer", &c.price); err != nil { - return err - } - } - if c.duration == "" { - if err := askInput("Enter the duration (in second) of the offer", &c.duration); err != nil { - return err - } - } - - var confirmed bool - if err := survey.AskOne(&survey.Confirm{ - Message: fmt.Sprintf("Are you sure to create offer for service %q with a price of %s MESG Tokens and a duration of %s seconds?", args[0], c.price, c.duration), - }, &confirmed, nil); err != nil { - return err - } - if !confirmed { - return fmt.Errorf("cancelled") - } - - return nil -} - -func (c *marketplaceCreateOfferCmd) runE(cmd *cobra.Command, args []string) error { - var ( - tx provider.Transaction - signedTransaction string - err error - sid, offerIndex string - ) - pretty.Progress("Creating offer on the marketplace...", func() { - if tx, err = c.e.PrepareCreateServiceOffer(args[0], c.price, c.duration, c.account); err != nil { - return - } - if signedTransaction, err = c.e.Sign(c.account, c.passphrase, tx); err != nil { - return - } - sid, offerIndex, _, _, err = c.e.PublishCreateServiceOffer(signedTransaction) - }) - if err != nil { - return err - } - fmt.Printf("%s Offer created with success with index %q\n", pretty.SuccessSign, offerIndex) - fmt.Printf("%s See it on the marketplace: https://marketplace.mesg.com/services/%s#offers\n", pretty.SuccessSign, sid) - - return nil -} diff --git a/commands/marketplace_publish.go b/commands/marketplace_publish.go deleted file mode 100644 index c524a59b7..000000000 --- a/commands/marketplace_publish.go +++ /dev/null @@ -1,110 +0,0 @@ -package commands - -import ( - "fmt" - - "github.com/mesg-foundation/core/commands/provider" - "github.com/mesg-foundation/core/protobuf/coreapi" - "github.com/mesg-foundation/core/utils/pretty" - "github.com/mesg-foundation/core/utils/readme" - "github.com/spf13/cobra" - survey "gopkg.in/AlecAivazis/survey.v1" -) - -type marketplacePublishCmd struct { - baseMarketplaceCmd - - path string - service *coreapi.Service - - e Executor -} - -func newMarketplacePublishCmd(e Executor) *marketplacePublishCmd { - c := &marketplacePublishCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "publish", - Short: "Publish a service on the MESG Marketplace", - Example: `mesg-core marketplace publish PATH_TO_SERVICE`, - PreRunE: c.preRunE, - RunE: c.runE, - Args: cobra.MinimumNArgs(1), - }) - c.setupFlags() - return c -} - -func (c *marketplacePublishCmd) preRunE(cmd *cobra.Command, args []string) error { - if err := c.askAccountAndPassphrase(); err != nil { - return err - } - - c.path = getFirstOrCurrentPath(args) - - var err error - _, hash, err := deployService(c.e, c.path, map[string]string{}) - if err != nil { - return err - } - c.service, err = c.e.ServiceByID(hash) - if err != nil { - return err - } - fmt.Printf("%s Service deployed with sid %s and hash %s\n", pretty.SuccessSign, pretty.Success(c.service.Definition.Sid), pretty.Success(c.service.Definition.Hash)) - - var confirmed bool - if err := survey.AskOne(&survey.Confirm{ - Message: fmt.Sprintf("Are you sure to publish a new version of service %q from path %q using account %q?", c.service.Definition.Sid, c.path, c.account), - }, &confirmed, nil); err != nil { - return err - } - if !confirmed { - return fmt.Errorf("cancelled") - } - - return nil -} - -func (c *marketplacePublishCmd) runE(cmd *cobra.Command, args []string) error { - var ( - tx provider.Transaction - err error - deployment provider.MarketplaceDeployedSource - signedTransaction string - sid, versionHash string - ) - - pretty.Progress("Uploading service source code on the marketplace...", func() { - // TODO: add a progress for the upload - deployment, err = c.e.UploadSource(c.path) - }) - if err != nil { - return err - } - readme, err := readme.Lookup(c.path) - if err != nil { - return err - } - pretty.Progress("Publishing service on the marketplace...", func() { - if tx, err = c.e.PreparePublishServiceVersion(provider.MarketplaceManifestServiceData{ - Definition: c.service.Definition, - Readme: readme, - Deployment: deployment, - }, c.account); err != nil { - return - } - if signedTransaction, err = c.e.Sign(c.account, c.passphrase, tx); err != nil { - return - } - sid, versionHash, _, _, err = c.e.PublishPublishServiceVersion(signedTransaction) - }) - if err != nil { - return err - } - fmt.Printf("%s Service published with success with sid %q and marketplace hash %q\n", pretty.SuccessSign, sid, versionHash) - fmt.Printf("%s See it on the marketplace: https://marketplace.mesg.com/services/%s/%s\n", pretty.SuccessSign, sid, versionHash) - - fmt.Printf("%s To create a service offer, execute the command:\n\tmesg-core marketplace create-offer %s\n", pretty.SuccessSign, sid) - - return nil -} diff --git a/commands/marketplace_purchase.go b/commands/marketplace_purchase.go deleted file mode 100644 index e0f6216d7..000000000 --- a/commands/marketplace_purchase.go +++ /dev/null @@ -1,112 +0,0 @@ -package commands - -import ( - "fmt" - "strconv" - "time" - - "github.com/mesg-foundation/core/commands/provider" - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" - survey "gopkg.in/AlecAivazis/survey.v1" -) - -type marketplacePurchaseCmd struct { - baseMarketplaceCmd - - offerIndex string - - e Executor -} - -func newMarketplacePurchaseCmd(e Executor) *marketplacePurchaseCmd { - c := &marketplacePurchaseCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "purchase", - Short: "Purchase a service on the MESG Marketplace", - Example: `mesg-core marketplace purchase SID -mesg-core marketplace purchase SID --offer-index 1`, - PreRunE: c.preRunE, - RunE: c.runE, - Args: cobra.ExactArgs(1), - }) - c.setupFlags() - c.cmd.Flags().StringVarP(&c.offerIndex, "offer-index", "o", c.offerIndex, "Offer index to purchase") - return c -} - -func (c *marketplacePurchaseCmd) preRunE(cmd *cobra.Command, args []string) error { - var ( - service provider.MarketplaceService - err error - ) - - if err := c.askAccountAndPassphrase(); err != nil { - return err - } - - if c.offerIndex == "" { - // TODO: should display the list of offers and ask to select one - if err := askInput("Enter the offer index to purchase", &c.offerIndex); err != nil { - return err - } - } - - pretty.Progress("Getting offer data...", func() { - service, err = c.e.GetService(args[0]) - }) - if err != nil { - return err - } - offerIndex, err := strconv.Atoi(c.offerIndex) - if err != nil { - return err - } - if offerIndex < 0 || offerIndex >= len(service.Offers) { - return fmt.Errorf("offer with index %d doesn't exist", offerIndex) - } - offer := service.Offers[offerIndex] - - var confirmed bool - if err := survey.AskOne(&survey.Confirm{ - Message: fmt.Sprintf("Are you sure to purchase service %q for %s MESG Tokens and for a duration of %s seconds?", args[0], offer.Price, offer.Duration), - }, &confirmed, nil); err != nil { - return err - } - if !confirmed { - return fmt.Errorf("cancelled") - } - - return nil -} - -func (c *marketplacePurchaseCmd) runE(cmd *cobra.Command, args []string) error { - var ( - txs []provider.Transaction - signedTxs []string - signedTx string - err error - sid string - expire time.Time - ) - pretty.Progress("Purchasing offer on the marketplace...", func() { - txs, err = c.e.PreparePurchase(args[0], c.offerIndex, c.account) - if err != nil { - return - } - for _, tx := range txs { - signedTx, err = c.e.Sign(c.account, c.passphrase, tx) - if err != nil { - return - } - signedTxs = append(signedTxs, signedTx) - } - sid, _, _, _, _, expire, err = c.e.PublishPurchase(signedTxs) - }) - if err != nil { - return err - } - fmt.Printf("%s Offer of service %q purchased with success and will expire on %s\n", pretty.SuccessSign, sid, expire.Local()) - - return nil -} diff --git a/commands/marketplace_root.go b/commands/marketplace_root.go deleted file mode 100644 index f382a015e..000000000 --- a/commands/marketplace_root.go +++ /dev/null @@ -1,53 +0,0 @@ -package commands - -import ( - "github.com/spf13/cobra" -) - -type rootMarketplaceCmd struct { - baseCmd -} - -func newRootMarketplaceCmd(e Executor) *rootMarketplaceCmd { - c := &rootMarketplaceCmd{} - c.cmd = newCommand(&cobra.Command{ - Use: "marketplace", - Short: "Interact with the MESG Marketplace", - }) - - c.cmd.AddCommand( - newMarketplacePublishCmd(e).cmd, - newMarketplaceCreateOfferCmd(e).cmd, - newMarketplacePurchaseCmd(e).cmd, - ) - return c -} - -// baseMarketplaceCmd is basic command for marketplace subcommands -// that require passphrase. -type baseMarketplaceCmd struct { - baseCmd - account string - noPassphrase bool - passphrase string -} - -func (c *baseMarketplaceCmd) setupFlags() { - c.cmd.Flags().StringVarP(&c.account, "account", "a", c.account, "Account to use") - c.cmd.Flags().BoolVarP(&c.noPassphrase, "no-passphrase", "n", c.noPassphrase, "Leave passphrase empty") - c.cmd.Flags().StringVarP(&c.passphrase, "passphrase", "p", c.passphrase, "Passphrase to decrypt the account") -} - -func (c *baseMarketplaceCmd) askAccountAndPassphrase() error { - if c.account == "" { - if err := askInput("Enter the account to use", &c.account); err != nil { - return err - } - } - if !c.noPassphrase && c.passphrase == "" { - if err := askPass("Enter passphrase", &c.passphrase); err != nil { - return err - } - } - return nil -} diff --git a/commands/mocks/Executor.go b/commands/mocks/Executor.go deleted file mode 100644 index 370f75041..000000000 --- a/commands/mocks/Executor.go +++ /dev/null @@ -1,833 +0,0 @@ -// Code generated by mockery v1.0.0. DO NOT EDIT. - -package mocks - -import container "github.com/mesg-foundation/core/container" -import coreapi "github.com/mesg-foundation/core/protobuf/coreapi" -import io "io" -import mock "github.com/stretchr/testify/mock" -import provider "github.com/mesg-foundation/core/commands/provider" -import servicetemplate "github.com/mesg-foundation/core/utils/servicetemplate" -import time "time" - -// Executor is an autogenerated mock type for the Executor type -type Executor struct { - mock.Mock -} - -// Create provides a mock function with given fields: passphrase -func (_m *Executor) Create(passphrase string) (string, error) { - ret := _m.Called(passphrase) - - var r0 string - if rf, ok := ret.Get(0).(func(string) string); ok { - r0 = rf(passphrase) - } else { - r0 = ret.Get(0).(string) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(passphrase) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Delete provides a mock function with given fields: address, passphrase -func (_m *Executor) Delete(address string, passphrase string) (string, error) { - ret := _m.Called(address, passphrase) - - var r0 string - if rf, ok := ret.Get(0).(func(string, string) string); ok { - r0 = rf(address, passphrase) - } else { - r0 = ret.Get(0).(string) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(address, passphrase) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Export provides a mock function with given fields: address, passphrase -func (_m *Executor) Export(address string, passphrase string) (provider.WalletEncryptedKeyJSONV3, error) { - ret := _m.Called(address, passphrase) - - var r0 provider.WalletEncryptedKeyJSONV3 - if rf, ok := ret.Get(0).(func(string, string) provider.WalletEncryptedKeyJSONV3); ok { - r0 = rf(address, passphrase) - } else { - r0 = ret.Get(0).(provider.WalletEncryptedKeyJSONV3) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(address, passphrase) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetService provides a mock function with given fields: sid -func (_m *Executor) GetService(sid string) (provider.MarketplaceService, error) { - ret := _m.Called(sid) - - var r0 provider.MarketplaceService - if rf, ok := ret.Get(0).(func(string) provider.MarketplaceService); ok { - r0 = rf(sid) - } else { - r0 = ret.Get(0).(provider.MarketplaceService) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(sid) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Import provides a mock function with given fields: account, passphrase -func (_m *Executor) Import(account provider.WalletEncryptedKeyJSONV3, passphrase string) (string, error) { - ret := _m.Called(account, passphrase) - - var r0 string - if rf, ok := ret.Get(0).(func(provider.WalletEncryptedKeyJSONV3, string) string); ok { - r0 = rf(account, passphrase) - } else { - r0 = ret.Get(0).(string) - } - - var r1 error - if rf, ok := ret.Get(1).(func(provider.WalletEncryptedKeyJSONV3, string) error); ok { - r1 = rf(account, passphrase) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ImportFromPrivateKey provides a mock function with given fields: privateKey, passphrase -func (_m *Executor) ImportFromPrivateKey(privateKey string, passphrase string) (string, error) { - ret := _m.Called(privateKey, passphrase) - - var r0 string - if rf, ok := ret.Get(0).(func(string, string) string); ok { - r0 = rf(privateKey, passphrase) - } else { - r0 = ret.Get(0).(string) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(privateKey, passphrase) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// List provides a mock function with given fields: -func (_m *Executor) List() ([]string, error) { - ret := _m.Called() - - var r0 []string - if rf, ok := ret.Get(0).(func() []string); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]string) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Logs provides a mock function with given fields: -func (_m *Executor) Logs() (io.ReadCloser, error) { - ret := _m.Called() - - var r0 io.ReadCloser - if rf, ok := ret.Get(0).(func() io.ReadCloser); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(io.ReadCloser) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PrepareCreateServiceOffer provides a mock function with given fields: sid, price, duration, from -func (_m *Executor) PrepareCreateServiceOffer(sid string, price string, duration string, from string) (provider.Transaction, error) { - ret := _m.Called(sid, price, duration, from) - - var r0 provider.Transaction - if rf, ok := ret.Get(0).(func(string, string, string, string) provider.Transaction); ok { - r0 = rf(sid, price, duration, from) - } else { - r0 = ret.Get(0).(provider.Transaction) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string, string, string) error); ok { - r1 = rf(sid, price, duration, from) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PreparePublishServiceVersion provides a mock function with given fields: service, from -func (_m *Executor) PreparePublishServiceVersion(service provider.MarketplaceManifestServiceData, from string) (provider.Transaction, error) { - ret := _m.Called(service, from) - - var r0 provider.Transaction - if rf, ok := ret.Get(0).(func(provider.MarketplaceManifestServiceData, string) provider.Transaction); ok { - r0 = rf(service, from) - } else { - r0 = ret.Get(0).(provider.Transaction) - } - - var r1 error - if rf, ok := ret.Get(1).(func(provider.MarketplaceManifestServiceData, string) error); ok { - r1 = rf(service, from) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PreparePurchase provides a mock function with given fields: sid, offerIndex, from -func (_m *Executor) PreparePurchase(sid string, offerIndex string, from string) ([]provider.Transaction, error) { - ret := _m.Called(sid, offerIndex, from) - - var r0 []provider.Transaction - if rf, ok := ret.Get(0).(func(string, string, string) []provider.Transaction); ok { - r0 = rf(sid, offerIndex, from) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]provider.Transaction) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string, string) error); ok { - r1 = rf(sid, offerIndex, from) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PublishCreateServiceOffer provides a mock function with given fields: signedTransaction -func (_m *Executor) PublishCreateServiceOffer(signedTransaction string) (string, string, string, string, error) { - ret := _m.Called(signedTransaction) - - var r0 string - if rf, ok := ret.Get(0).(func(string) string); ok { - r0 = rf(signedTransaction) - } else { - r0 = ret.Get(0).(string) - } - - var r1 string - if rf, ok := ret.Get(1).(func(string) string); ok { - r1 = rf(signedTransaction) - } else { - r1 = ret.Get(1).(string) - } - - var r2 string - if rf, ok := ret.Get(2).(func(string) string); ok { - r2 = rf(signedTransaction) - } else { - r2 = ret.Get(2).(string) - } - - var r3 string - if rf, ok := ret.Get(3).(func(string) string); ok { - r3 = rf(signedTransaction) - } else { - r3 = ret.Get(3).(string) - } - - var r4 error - if rf, ok := ret.Get(4).(func(string) error); ok { - r4 = rf(signedTransaction) - } else { - r4 = ret.Error(4) - } - - return r0, r1, r2, r3, r4 -} - -// PublishPublishServiceVersion provides a mock function with given fields: signedTransaction -func (_m *Executor) PublishPublishServiceVersion(signedTransaction string) (string, string, string, string, error) { - ret := _m.Called(signedTransaction) - - var r0 string - if rf, ok := ret.Get(0).(func(string) string); ok { - r0 = rf(signedTransaction) - } else { - r0 = ret.Get(0).(string) - } - - var r1 string - if rf, ok := ret.Get(1).(func(string) string); ok { - r1 = rf(signedTransaction) - } else { - r1 = ret.Get(1).(string) - } - - var r2 string - if rf, ok := ret.Get(2).(func(string) string); ok { - r2 = rf(signedTransaction) - } else { - r2 = ret.Get(2).(string) - } - - var r3 string - if rf, ok := ret.Get(3).(func(string) string); ok { - r3 = rf(signedTransaction) - } else { - r3 = ret.Get(3).(string) - } - - var r4 error - if rf, ok := ret.Get(4).(func(string) error); ok { - r4 = rf(signedTransaction) - } else { - r4 = ret.Error(4) - } - - return r0, r1, r2, r3, r4 -} - -// PublishPurchase provides a mock function with given fields: signedTransactions -func (_m *Executor) PublishPurchase(signedTransactions []string) (string, string, string, string, string, time.Time, error) { - ret := _m.Called(signedTransactions) - - var r0 string - if rf, ok := ret.Get(0).(func([]string) string); ok { - r0 = rf(signedTransactions) - } else { - r0 = ret.Get(0).(string) - } - - var r1 string - if rf, ok := ret.Get(1).(func([]string) string); ok { - r1 = rf(signedTransactions) - } else { - r1 = ret.Get(1).(string) - } - - var r2 string - if rf, ok := ret.Get(2).(func([]string) string); ok { - r2 = rf(signedTransactions) - } else { - r2 = ret.Get(2).(string) - } - - var r3 string - if rf, ok := ret.Get(3).(func([]string) string); ok { - r3 = rf(signedTransactions) - } else { - r3 = ret.Get(3).(string) - } - - var r4 string - if rf, ok := ret.Get(4).(func([]string) string); ok { - r4 = rf(signedTransactions) - } else { - r4 = ret.Get(4).(string) - } - - var r5 time.Time - if rf, ok := ret.Get(5).(func([]string) time.Time); ok { - r5 = rf(signedTransactions) - } else { - r5 = ret.Get(5).(time.Time) - } - - var r6 error - if rf, ok := ret.Get(6).(func([]string) error); ok { - r6 = rf(signedTransactions) - } else { - r6 = ret.Error(6) - } - - return r0, r1, r2, r3, r4, r5, r6 -} - -// ServiceByID provides a mock function with given fields: id -func (_m *Executor) ServiceByID(id string) (*coreapi.Service, error) { - ret := _m.Called(id) - - var r0 *coreapi.Service - if rf, ok := ret.Get(0).(func(string) *coreapi.Service); ok { - r0 = rf(id) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*coreapi.Service) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(id) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ServiceDelete provides a mock function with given fields: deleteData, ids -func (_m *Executor) ServiceDelete(deleteData bool, ids ...string) error { - _va := make([]interface{}, len(ids)) - for _i := range ids { - _va[_i] = ids[_i] - } - var _ca []interface{} - _ca = append(_ca, deleteData) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 error - if rf, ok := ret.Get(0).(func(bool, ...string) error); ok { - r0 = rf(deleteData, ids...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ServiceDeleteAll provides a mock function with given fields: deleteData -func (_m *Executor) ServiceDeleteAll(deleteData bool) error { - ret := _m.Called(deleteData) - - var r0 error - if rf, ok := ret.Get(0).(func(bool) error); ok { - r0 = rf(deleteData) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ServiceDeploy provides a mock function with given fields: path, env, statuses -func (_m *Executor) ServiceDeploy(path string, env map[string]string, statuses chan provider.DeployStatus) (string, string, error, error) { - ret := _m.Called(path, env, statuses) - - var r0 string - if rf, ok := ret.Get(0).(func(string, map[string]string, chan provider.DeployStatus) string); ok { - r0 = rf(path, env, statuses) - } else { - r0 = ret.Get(0).(string) - } - - var r1 string - if rf, ok := ret.Get(1).(func(string, map[string]string, chan provider.DeployStatus) string); ok { - r1 = rf(path, env, statuses) - } else { - r1 = ret.Get(1).(string) - } - - var r2 error - if rf, ok := ret.Get(2).(func(string, map[string]string, chan provider.DeployStatus) error); ok { - r2 = rf(path, env, statuses) - } else { - r2 = ret.Error(2) - } - - var r3 error - if rf, ok := ret.Get(3).(func(string, map[string]string, chan provider.DeployStatus) error); ok { - r3 = rf(path, env, statuses) - } else { - r3 = ret.Error(3) - } - - return r0, r1, r2, r3 -} - -// ServiceExecuteTask provides a mock function with given fields: id, taskKey, inputData, tags -func (_m *Executor) ServiceExecuteTask(id string, taskKey string, inputData string, tags []string) (string, error) { - ret := _m.Called(id, taskKey, inputData, tags) - - var r0 string - if rf, ok := ret.Get(0).(func(string, string, string, []string) string); ok { - r0 = rf(id, taskKey, inputData, tags) - } else { - r0 = ret.Get(0).(string) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string, string, []string) error); ok { - r1 = rf(id, taskKey, inputData, tags) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ServiceGenerateDocs provides a mock function with given fields: path -func (_m *Executor) ServiceGenerateDocs(path string) error { - ret := _m.Called(path) - - var r0 error - if rf, ok := ret.Get(0).(func(string) error); ok { - r0 = rf(path) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ServiceInitDownloadTemplate provides a mock function with given fields: t, dst -func (_m *Executor) ServiceInitDownloadTemplate(t *servicetemplate.Template, dst string) error { - ret := _m.Called(t, dst) - - var r0 error - if rf, ok := ret.Get(0).(func(*servicetemplate.Template, string) error); ok { - r0 = rf(t, dst) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ServiceInitTemplateList provides a mock function with given fields: -func (_m *Executor) ServiceInitTemplateList() ([]*servicetemplate.Template, error) { - ret := _m.Called() - - var r0 []*servicetemplate.Template - if rf, ok := ret.Get(0).(func() []*servicetemplate.Template); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*servicetemplate.Template) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ServiceList provides a mock function with given fields: -func (_m *Executor) ServiceList() ([]*coreapi.Service, error) { - ret := _m.Called() - - var r0 []*coreapi.Service - if rf, ok := ret.Get(0).(func() []*coreapi.Service); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*coreapi.Service) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ServiceListenEvents provides a mock function with given fields: id, eventFilter -func (_m *Executor) ServiceListenEvents(id string, eventFilter string) (chan *coreapi.EventData, chan error, error) { - ret := _m.Called(id, eventFilter) - - var r0 chan *coreapi.EventData - if rf, ok := ret.Get(0).(func(string, string) chan *coreapi.EventData); ok { - r0 = rf(id, eventFilter) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(chan *coreapi.EventData) - } - } - - var r1 chan error - if rf, ok := ret.Get(1).(func(string, string) chan error); ok { - r1 = rf(id, eventFilter) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(chan error) - } - } - - var r2 error - if rf, ok := ret.Get(2).(func(string, string) error); ok { - r2 = rf(id, eventFilter) - } else { - r2 = ret.Error(2) - } - - return r0, r1, r2 -} - -// ServiceListenResults provides a mock function with given fields: id, taskFilter, tagFilters -func (_m *Executor) ServiceListenResults(id string, taskFilter string, tagFilters []string) (chan *coreapi.ResultData, chan error, error) { - ret := _m.Called(id, taskFilter, tagFilters) - - var r0 chan *coreapi.ResultData - if rf, ok := ret.Get(0).(func(string, string, []string) chan *coreapi.ResultData); ok { - r0 = rf(id, taskFilter, tagFilters) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(chan *coreapi.ResultData) - } - } - - var r1 chan error - if rf, ok := ret.Get(1).(func(string, string, []string) chan error); ok { - r1 = rf(id, taskFilter, tagFilters) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(chan error) - } - } - - var r2 error - if rf, ok := ret.Get(2).(func(string, string, []string) error); ok { - r2 = rf(id, taskFilter, tagFilters) - } else { - r2 = ret.Error(2) - } - - return r0, r1, r2 -} - -// ServiceLogs provides a mock function with given fields: id, dependencies -func (_m *Executor) ServiceLogs(id string, dependencies ...string) ([]*provider.Log, func(), chan error, error) { - _va := make([]interface{}, len(dependencies)) - for _i := range dependencies { - _va[_i] = dependencies[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 []*provider.Log - if rf, ok := ret.Get(0).(func(string, ...string) []*provider.Log); ok { - r0 = rf(id, dependencies...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*provider.Log) - } - } - - var r1 func() - if rf, ok := ret.Get(1).(func(string, ...string) func()); ok { - r1 = rf(id, dependencies...) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(func()) - } - } - - var r2 chan error - if rf, ok := ret.Get(2).(func(string, ...string) chan error); ok { - r2 = rf(id, dependencies...) - } else { - if ret.Get(2) != nil { - r2 = ret.Get(2).(chan error) - } - } - - var r3 error - if rf, ok := ret.Get(3).(func(string, ...string) error); ok { - r3 = rf(id, dependencies...) - } else { - r3 = ret.Error(3) - } - - return r0, r1, r2, r3 -} - -// ServiceStart provides a mock function with given fields: id -func (_m *Executor) ServiceStart(id string) error { - ret := _m.Called(id) - - var r0 error - if rf, ok := ret.Get(0).(func(string) error); ok { - r0 = rf(id) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ServiceStop provides a mock function with given fields: id -func (_m *Executor) ServiceStop(id string) error { - ret := _m.Called(id) - - var r0 error - if rf, ok := ret.Get(0).(func(string) error); ok { - r0 = rf(id) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ServiceValidate provides a mock function with given fields: path -func (_m *Executor) ServiceValidate(path string) (string, error) { - ret := _m.Called(path) - - var r0 string - if rf, ok := ret.Get(0).(func(string) string); ok { - r0 = rf(path) - } else { - r0 = ret.Get(0).(string) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(path) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Sign provides a mock function with given fields: address, passphrase, transaction -func (_m *Executor) Sign(address string, passphrase string, transaction provider.Transaction) (string, error) { - ret := _m.Called(address, passphrase, transaction) - - var r0 string - if rf, ok := ret.Get(0).(func(string, string, provider.Transaction) string); ok { - r0 = rf(address, passphrase, transaction) - } else { - r0 = ret.Get(0).(string) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string, provider.Transaction) error); ok { - r1 = rf(address, passphrase, transaction) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Start provides a mock function with given fields: -func (_m *Executor) Start() error { - ret := _m.Called() - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Status provides a mock function with given fields: -func (_m *Executor) Status() (container.StatusType, error) { - ret := _m.Called() - - var r0 container.StatusType - if rf, ok := ret.Get(0).(func() container.StatusType); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(container.StatusType) - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Stop provides a mock function with given fields: -func (_m *Executor) Stop() error { - ret := _m.Called() - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// UploadSource provides a mock function with given fields: path -func (_m *Executor) UploadSource(path string) (provider.MarketplaceDeployedSource, error) { - ret := _m.Called(path) - - var r0 provider.MarketplaceDeployedSource - if rf, ok := ret.Get(0).(func(string) provider.MarketplaceDeployedSource); ok { - r0 = rf(path) - } else { - r0 = ret.Get(0).(provider.MarketplaceDeployedSource) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(path) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} diff --git a/commands/provider/assets/readme_template.go b/commands/provider/assets/readme_template.go deleted file mode 100644 index a7eac7d91..000000000 --- a/commands/provider/assets/readme_template.go +++ /dev/null @@ -1,239 +0,0 @@ -// Code generated by go-bindata. (@generated) DO NOT EDIT. -// sources: -// commands/provider/assets/readme_template.md -package assets - -import ( - "bytes" - "compress/gzip" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindataFileInfo) Name() string { - return fi.name -} -func (fi bindataFileInfo) Size() int64 { - return fi.size -} -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi bindataFileInfo) IsDir() bool { - return false -} -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _commandsProviderAssetsReadme_templateMd = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x54\x4d\x6f\xeb\x2a\x10\xdd\xf3\x2b\x46\x75\x17\x76\x54\x3b\xfb\xe8\xbd\x55\x53\x3d\x55\x7d\x7d\x5d\x34\x9b\xa7\x28\x92\x89\x4d\x1c\x14\x07\x72\x0d\xee\x55\xe4\xfa\xbf\x5f\x0d\x60\x43\x3e\xfa\xb1\xe9\x26\x19\xce\xcc\xc0\x39\x1c\x0f\x11\x74\x5d\xf6\x1f\xdd\xb3\xbe\x87\xae\xe3\x1b\xc8\x5e\x79\xd9\xf7\xf1\xe3\x7c\x86\x19\xb3\x48\xba\x8e\x89\xb2\xef\x09\xe9\xba\x6c\xce\x54\xd1\xf0\x83\xe6\x52\x20\x12\xc1\xbd\x14\x9a\x09\xad\x08\x49\x61\xf9\x28\x94\xa6\x75\x4d\x31\xbd\x8a\xa3\x70\x99\x60\x7e\xce\x36\x5c\x70\x5c\xaa\x55\x1c\x05\xab\x84\x80\x3b\xff\xe1\x0d\x77\xeb\xfb\x14\x96\x36\x5c\xc5\x91\x0d\x92\xae\x6b\xa8\xa8\x18\xdc\xee\xd8\xf1\x0e\x6e\x19\xa2\x30\xfb\xdb\xf7\x10\x00\x80\x14\x96\x5d\x27\x1b\x97\x37\xe2\x4c\x47\xdf\xaf\xe2\xe8\x6a\x06\xde\x81\x8a\x62\x2b\x9b\x07\x51\xc8\x92\x79\xc5\x83\xf0\x81\xdb\x82\xaa\x9d\xa5\x66\xa2\x55\x1c\x99\xff\x73\x62\x9a\xaa\x9d\xe1\xe5\xea\x4f\x69\x61\xf6\x2a\xab\xd3\xc4\x97\xa4\x48\x04\xe1\xfd\x12\x12\x45\xf0\xfc\xf0\xfa\x0f\xdc\xcb\x86\x11\xb2\xd8\x72\x05\x8a\x35\x6f\xbc\x60\xd0\xb0\x5f\x2d\x6f\x98\x82\xe5\x58\xb1\x8a\xb7\x5a\x1f\xd4\x6c\x3a\xad\xb8\xde\xb6\xeb\xac\x90\xfb\xe9\x9e\xa9\x2a\xdd\xc8\x56\x94\x66\xcf\x69\x21\x1b\x96\x80\x96\xb0\x66\xc0\xed\x61\xac\x84\x0d\x6f\x94\xce\x08\xf9\x5f\xb6\x50\x50\x31\x64\xfc\xe9\xb0\x3e\x42\xd3\x0a\xc1\x45\x05\x7a\xcb\x60\x23\xeb\x5a\xfe\xc6\x55\x21\xf7\x7b\x2a\x4a\x90\x0d\x2c\x2d\x6a\x0a\x78\x20\x04\xaa\x96\x97\x01\xbd\x52\x16\x2a\x43\x62\x86\xa1\x49\x4e\xc3\xfa\x6c\xab\xf7\x75\x92\x11\x92\xe7\xf9\x9a\xaa\x2d\xc1\x1f\xf8\x2b\x2e\xda\xa6\x86\x74\xa3\x5e\xff\x85\x61\xab\x71\x17\xd7\x9f\x60\x8f\xb9\xb8\x39\x3b\xd4\xf2\x68\xb8\xb8\x3b\x23\x64\x21\xa1\x1c\x60\x7f\x97\x77\x50\x49\xbc\x91\x65\x08\xc2\x81\x56\x01\xe5\x3d\x6d\x76\x4c\x1f\x6a\x5a\x30\xcf\xdc\x95\xaa\xe9\x38\x57\x20\x85\x39\xd1\x9a\xf2\xec\x9b\x3e\xdf\x29\x01\xbc\xc1\xa2\xe6\xc5\xce\xb4\xaf\x5b\xad\xa5\x80\x9b\x8a\xe9\xe9\xba\x3d\x65\x7b\x93\xe1\x77\x12\x0c\x1a\x0e\x71\x38\x66\x11\xd8\x88\x7c\x3d\x5c\x11\x3e\x16\x57\x07\x8b\x10\x53\x04\x3b\x76\x9c\x41\xde\x75\x16\xcd\xf1\x2c\x57\x7c\xf6\x6c\x18\x0e\x43\x8a\x6a\xda\xf7\xef\x30\x99\xe0\x8e\x93\x09\x60\xf8\xc4\x8e\x2e\x5a\x1c\x0f\x03\x18\x6c\x82\x08\x79\x87\x34\x4d\xe1\xca\xaf\x17\x53\x52\x4d\x9f\x8c\x20\x8c\x50\xcf\xc5\xa9\x56\x13\xa6\x9d\x24\xd7\xd3\xf7\xe6\x58\x94\x33\x22\x79\x00\x64\xc8\xcc\x42\x56\x8e\x01\x5f\x0c\x3d\x5a\x63\x77\x2e\xdd\x22\x9f\x4c\x60\x9c\x5e\x5b\x77\x72\x21\x86\x71\x38\xdc\x67\xa3\x7e\xf2\xfa\x44\x60\x82\x73\xc3\x2e\x1e\x9d\xd1\xae\xf3\x07\x87\x10\x2c\xb9\x6a\x96\x29\xbd\xea\x95\xc9\x3c\x8a\x43\x6b\x3e\x9a\x08\xdf\x1e\x8c\x09\xf9\x21\xe3\x38\x6e\x6f\x9d\x33\xa1\xb1\xee\x84\x84\xf7\xce\x14\x38\x85\x43\x5f\xe0\x9e\x87\xf2\x10\xb9\xf0\xcf\xa2\xdf\x30\xd0\x16\x7e\xee\x60\x78\x6d\x2f\xad\xf6\xf7\xe6\x16\xc4\x4b\x95\x06\xb1\x5a\x6d\xec\xc5\x86\xad\x83\x9f\xb6\xc6\xe9\x1d\x9b\xd1\x2a\x5b\xed\x9d\x0d\x92\xd6\x5f\xd7\x7a\xe6\xf0\x0f\x59\xf8\x81\xae\x81\xc3\xd9\x00\x7e\xa4\x6a\xb4\x31\x14\x73\x02\x5d\x18\xe9\xe0\x6f\x38\x79\xed\x3e\xbc\x95\x9f\x0f\xe5\x9f\x00\x00\x00\xff\xff\xfc\x88\x00\xd2\x3b\x09\x00\x00") - -func commandsProviderAssetsReadme_templateMdBytes() ([]byte, error) { - return bindataRead( - _commandsProviderAssetsReadme_templateMd, - "commands/provider/assets/readme_template.md", - ) -} - -func commandsProviderAssetsReadme_templateMd() (*asset, error) { - bytes, err := commandsProviderAssetsReadme_templateMdBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "commands/provider/assets/readme_template.md", size: 2363, mode: os.FileMode(420), modTime: time.Unix(1557897272, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "commands/provider/assets/readme_template.md": commandsProviderAssetsReadme_templateMd, -} - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"} -// AssetDir("data/img") would return []string{"a.png", "b.png"} -// AssetDir("foo.txt") and AssetDir("notexist") would return an error -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - cannonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(cannonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} - -var _bintree = &bintree{nil, map[string]*bintree{ - "commands": &bintree{nil, map[string]*bintree{ - "provider": &bintree{nil, map[string]*bintree{ - "assets": &bintree{nil, map[string]*bintree{ - "readme_template.md": &bintree{commandsProviderAssetsReadme_templateMd, map[string]*bintree{}}, - }}, - }}, - }}, -}} - -// RestoreAsset restores an asset under the given directory -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) - if err != nil { - return err - } - return nil -} - -// RestoreAssets restores an asset under the given directory recursively -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - cannonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) -} diff --git a/commands/provider/assets/readme_template.md b/commands/provider/assets/readme_template.md deleted file mode 100644 index 97b2c2482..000000000 --- a/commands/provider/assets/readme_template.md +++ /dev/null @@ -1,70 +0,0 @@ -# {{.Name}} {{if .Sid}}(ID: {{.Sid}}){{end}} - -{{.Description}} - -# Contents - -- [Installation](#Installation) -- [Definitions](#Definitions) - {{if .Events}}- [Events](#Events){{range $key, $event := .Events}} - - [{{or $event.Name $key}}](#{{or $event.Name $key | anchorEncode}}){{end}}{{end}} - {{if .Tasks}}- [Tasks](#Tasks){{range $key, $task := .Tasks}} - - [{{or $task.Name $key}}](#{{or $task.Name $key | anchorEncode}}){{end}}{{end}} - -# Installation - -## MESG Core - -This service requires [MESG Core](https://github.com/mesg-foundation/core) to be installed first. - -You can install MESG Core by running the following command or [follow the installation guide](https://docs.mesg.com/guide/installation.html). - -```bash -bash <(curl -fsSL https://mesg.com/install) -``` - -## Deploy the service - -To deploy this service, go to [this service page](https://marketplace.mesg.com/services/{{.Sid}}) on the [MESG Marketplace](https://marketplace.mesg.com) and click the button "get/buy this service". - -# Definitions - -{{if .Events}}# Events -{{range $key, $event := .Events}} -## {{or $event.Name $key}} - -Event key: `{{$key}}` - -{{$event.Description}} - -{{if $event.Data}}| **Name** | **Key** | **Type** | **Description** | -| --- | --- | --- | --- | -{{range $dataKey, $data := $event.Data}}| **{{or $data.Name $dataKey}}** | `{{$dataKey}}` | `{{$data.Type}}` | {{if $data.Optional}}**`optional`** {{end}}{{$data.Description}} | -{{end}}{{end}}{{end}}{{end}} -{{if .Tasks}}# Tasks -{{range $key, $task := .Tasks}} -## {{or $task.Name $key}} - -Task key: `{{$key}}` - -{{$task.Description}} - -{{if $task.Inputs}}### Inputs - -| **Name** | **Key** | **Type** | **Description** | -| --- | --- | --- | --- | -{{range $inputKey, $input := $task.Inputs}}| **{{or $input.Name $inputKey}}** | `{{$inputKey}}` | `{{$input.Type}}` | {{if $input.Optional}}**`optional`** {{end}}{{$input.Description}} | -{{end}}{{end}} -{{if $task.Outputs}}### Outputs - -{{range $outputKey, $output := $task.Outputs}}#### {{or $output.Name $outputKey}} - -Output key: `{{$outputKey}}` - -{{$output.Description}} - -| **Name** | **Key** | **Type** | **Description** | -| --- | --- | --- | --- | -{{range $outputKey, $output := $output.Data}}| **{{or $output.Name $outputKey}}** | `{{$outputKey}}` | `{{$output.Type}}` | {{if $output.Optional}}**`optional`** {{end}}{{$output.Description}} | -{{end}} -{{end}}{{end}}{{end}}{{end}} diff --git a/commands/provider/client.go b/commands/provider/client.go deleted file mode 100644 index 8e48dee3b..000000000 --- a/commands/provider/client.go +++ /dev/null @@ -1,146 +0,0 @@ -package provider - -import ( - "context" - "encoding/json" - "errors" - "fmt" - - "github.com/mesg-foundation/core/protobuf/acknowledgement" - "github.com/mesg-foundation/core/protobuf/coreapi" - uuid "github.com/satori/go.uuid" -) - -// client is a wrapper for core client that -// sets up stream connection and provides more frienldy api. -type client struct { - coreapi.CoreClient -} - -// ListenEvent returns a channel with event data streaming. -func (c *client) ListenEvent(id, eventFilter string) (chan *coreapi.EventData, chan error, error) { - stream, err := c.CoreClient.ListenEvent(context.Background(), &coreapi.ListenEventRequest{ - ServiceID: id, - EventFilter: eventFilter, - }) - if err != nil { - return nil, nil, err - } - - resultC := make(chan *coreapi.EventData) - errC := make(chan error) - - go func() { - <-stream.Context().Done() - errC <- stream.Context().Err() - }() - go func() { - for { - if res, err := stream.Recv(); err != nil { - errC <- err - break - } else { - resultC <- res - } - } - }() - - if err := acknowledgement.WaitForStreamToBeReady(stream); err != nil { - return nil, nil, err - } - - return resultC, errC, nil -} - -// ListenResults returns a channel with event results streaming.. -func (c *client) ListenResult(id, taskFilter string, tagFilters []string) (chan *coreapi.ResultData, chan error, error) { - resultC := make(chan *coreapi.ResultData) - errC := make(chan error) - - stream, err := c.CoreClient.ListenResult(context.Background(), &coreapi.ListenResultRequest{ - ServiceID: id, - TaskFilter: taskFilter, - TagFilters: tagFilters, - }) - if err != nil { - return nil, nil, err - } - - go func() { - <-stream.Context().Done() - errC <- stream.Context().Err() - }() - go func() { - for { - if res, err := stream.Recv(); err != nil { - errC <- err - break - } else { - resultC <- res - } - } - }() - - if err := acknowledgement.WaitForStreamToBeReady(stream); err != nil { - return nil, nil, err - } - - return resultC, errC, nil -} - -// ExecuteTask executes task on given service. -func (c *client) ExecuteTask(id, taskKey, inputData string, tags []string) (string, error) { - result, err := c.CoreClient.ExecuteTask(context.Background(), &coreapi.ExecuteTaskRequest{ - ServiceID: id, - TaskKey: taskKey, - InputData: inputData, - ExecutionTags: tags, - }) - if err != nil { - return "", err - } - return result.ExecutionID, nil -} - -// ExecuteAndListen executes task and listens for it's results. -func (c *client) ExecuteAndListen(id, taskKey string, inputData interface{}) (*coreapi.ResultData, error) { - data, err := json.Marshal(inputData) - if err != nil { - return nil, err - } - - // TODO: the following ListenResult should be destroy after result is received - tags := []string{uuid.NewV4().String()} - resultC, errC, err := c.ListenResult(id, taskKey, tags) - if err != nil { - return nil, err - } - - if _, err := c.ExecuteTask(id, taskKey, string(data), tags); err != nil { - return nil, err - } - - select { - case r := <-resultC: - if r.Error != "" { - return nil, errors.New(r.Error) - } - return r, nil - case err := <-errC: - return nil, err - } -} - -// GetServiceHash returns the service hash of the corresponding service key -func (c *client) GetServiceHash(key string) (string, error) { - rep, err := c.Info(context.Background(), &coreapi.InfoRequest{}) - if err != nil { - return "", err - } - for _, service := range rep.Services { - if service.Key == key { - return service.Hash, nil - } - } - return "", fmt.Errorf("no service found with key %q", key) -} diff --git a/commands/provider/core_provider.go b/commands/provider/core_provider.go deleted file mode 100644 index 9b0146ffc..000000000 --- a/commands/provider/core_provider.go +++ /dev/null @@ -1,43 +0,0 @@ -package provider - -import ( - "io" - - "github.com/mesg-foundation/core/container" - "github.com/mesg-foundation/core/daemon" - "github.com/mesg-foundation/core/protobuf/coreapi" -) - -// CoreProvider is a struct that provides all methods required by core command. -type CoreProvider struct { - d daemon.Daemon - client coreapi.CoreClient -} - -// NewCoreProvider creates new CoreProvider. -func NewCoreProvider(client coreapi.CoreClient, d daemon.Daemon) *CoreProvider { - return &CoreProvider{ - client: client, - d: d, - } -} - -// Start starts core daemon. -func (p *CoreProvider) Start() error { - return p.d.Start() -} - -// Stop stops core daemon and all running services. -func (p *CoreProvider) Stop() error { - return p.d.Stop() -} - -// Status returns daemon status. -func (p *CoreProvider) Status() (container.StatusType, error) { - return p.d.Status() -} - -// Logs returns daemon logs reader. -func (p *CoreProvider) Logs() (io.ReadCloser, error) { - return p.d.Logs() -} diff --git a/commands/provider/marketplace_provider.go b/commands/provider/marketplace_provider.go deleted file mode 100644 index e47ef7dad..000000000 --- a/commands/provider/marketplace_provider.go +++ /dev/null @@ -1,145 +0,0 @@ -package provider - -import ( - "encoding/json" - "time" - - "github.com/docker/docker/pkg/archive" - "github.com/mesg-foundation/core/ipfs" - "github.com/mesg-foundation/core/protobuf/coreapi" -) - -// MarketplaceProvider is a struct that provides all methods required by service command. -type MarketplaceProvider struct { - client client -} - -// NewMarketplaceProvider creates new MarketplaceProvider. -func NewMarketplaceProvider(c coreapi.CoreClient) *MarketplaceProvider { - return &MarketplaceProvider{client: client{c}} -} - -// PreparePublishServiceVersion executes the create service version task -func (p *MarketplaceProvider) PreparePublishServiceVersion(service MarketplaceManifestServiceData, from string) (Transaction, error) { - input := marketplacePreparePublishServiceVersionTaskInputs{ - marketplacePrepareTaskInputs: marketplacePrepareTaskInputs{From: from}, - Service: service, - } - var output Transaction - return output, p.call("preparePublishServiceVersion", input, &output) -} - -// PublishPublishServiceVersion executes the task publish service version task -func (p *MarketplaceProvider) PublishPublishServiceVersion(signedTransaction string) (sid, versionHash, manifest, manifestProtocol string, err error) { - input := marketplacePublishTaskInputs{ - SignedTransaction: signedTransaction, - } - var o marketplacePublishPublishServiceVersionTaskOutputs - err = p.call("publishPublishServiceVersion", input, &o) - return o.Sid, o.VersionHash, o.Manifest, o.ManifestProtocol, err -} - -// PrepareCreateServiceOffer executes the create service offer task -func (p *MarketplaceProvider) PrepareCreateServiceOffer(sid string, price string, duration string, from string) (Transaction, error) { - input := marketplacePrepareCreateServiceOfferTaskInputs{ - marketplacePrepareTaskInputs: marketplacePrepareTaskInputs{From: from}, - Sid: sid, - Price: price, - Duration: duration, - } - var output Transaction - return output, p.call("prepareCreateServiceOffer", input, &output) -} - -// PublishCreateServiceOffer executes the task publish service offer task -func (p *MarketplaceProvider) PublishCreateServiceOffer(signedTransaction string) (sid, offerIndex, price, duration string, err error) { - input := marketplacePublishTaskInputs{ - SignedTransaction: signedTransaction, - } - var o marketplacePublishCreateServiceOfferTaskOutputs - err = p.call("publishCreateServiceOffer", input, &o) - return o.Sid, o.OfferIndex, o.Price, o.Duration, err -} - -// PreparePurchase executes the purchase task -func (p *MarketplaceProvider) PreparePurchase(sid, offerIndex, from string) ([]Transaction, error) { - input := marketplacePreparePurchaseTaskInputs{ - marketplacePrepareTaskInputs: marketplacePrepareTaskInputs{From: from}, - Sid: sid, - OfferIndex: offerIndex, - } - var output marketplacePreparePurchaseTaskOutputs - return output.Transactions, p.call("preparePurchase", input, &output) -} - -// PublishPurchase executes the task publish service version task -func (p *MarketplaceProvider) PublishPurchase(signedTransactions []string) (sid, offerIndex, purchaser, price, duration string, expire time.Time, err error) { - input := marketplacePublishPurchaseTaskInputs{ - SignedTransactions: signedTransactions, - } - var o marketplacePublishPurchaseTaskOutputs - err = p.call("publishPurchase", input, &o) - return o.Sid, o.OfferIndex, o.Purchaser, o.Price, o.Duration, o.Expire, err -} - -// GetService executes the task get service. -func (p *MarketplaceProvider) GetService(sid string) (MarketplaceService, error) { - input := marketplaceGetServiceTaskInputs{ - Sid: sid, - } - var output MarketplaceService - return output, p.call("getService", input, &output) -} - -// IsAuthorized executes the task IsAuthorized. -func (p *MarketplaceProvider) IsAuthorized(sid string, versionHash string, addresses []string) (bool, string, string, string, error) { - input := marketplaceIsAuthorizedInputs{ - VersionHash: versionHash, - Sid: sid, - Addresses: addresses, - } - var output marketplaceIsAuthorizedSuccessOutput - return output.Authorized, output.Sid, output.Source, output.Type, p.call("isAuthorized", input, &output) -} - -// UploadSource upload the tarball, and returns the address of the uploaded sources -func (p *MarketplaceProvider) UploadSource(path string) (MarketplaceDeployedSource, error) { - // upload service source to IPFS - tar, err := archive.TarWithOptions(path, &archive.TarOptions{ - Compression: archive.Gzip, - }) - if err != nil { - return MarketplaceDeployedSource{}, err - } - tarballResponse, err := ipfs.Add("tarball", tar) - if err != nil { - return MarketplaceDeployedSource{}, err - } - return MarketplaceDeployedSource{ - Type: marketplaceDeploymentType, - Source: tarballResponse.Hash, - }, nil -} - -func (p *MarketplaceProvider) call(task string, inputs interface{}, output interface{}) error { - serviceHash, err := p.client.GetServiceHash(marketplaceServiceKey) - if err != nil { - return err - } - r, err := p.client.ExecuteAndListen(serviceHash, task, &inputs) - if err != nil { - return err - } - return p.parseResult(r, &output) -} - -func (p *MarketplaceProvider) parseResult(r *coreapi.ResultData, output interface{}) error { - if r.Error != "" { - var outputError MarketplaceErrorOutput - if err := json.Unmarshal([]byte(r.Error), &outputError); err != nil { - return err - } - return outputError - } - return json.Unmarshal([]byte(r.OutputData), &output) -} diff --git a/commands/provider/marketplace_types.go b/commands/provider/marketplace_types.go deleted file mode 100644 index 9351ac1d6..000000000 --- a/commands/provider/marketplace_types.go +++ /dev/null @@ -1,153 +0,0 @@ -package provider - -import ( - "encoding/json" - "time" - - "github.com/mesg-foundation/core/protobuf/definition" -) - -const ( - // marketplaceDeploymentType is the type of deployment used for the service. - marketplaceDeploymentType = "ipfs" - - // marketplaceServiceKey is the key of the marketplace service. - marketplaceServiceKey = "marketplace" -) - -// MarketplaceErrorOutput is the output for any task that fails. -type MarketplaceErrorOutput struct { - Message string `json:"message"` - Code string `json:"code"` -} - -func (e MarketplaceErrorOutput) Error() string { - return e.Message -} - -// MarketplaceService is the success output of task service exist. -type MarketplaceService struct { - Sid string `json:"sid"` - Owner string `json:"owner"` - Versions []struct { - VersionHash string `json:"versionHash"` - Manifest string `json:"manifest"` - ManifestProtocol string `json:"manifestProtocol"` - ManifestData MarketplaceManifestData `json:"manifestData,omitempty"` - } `json:"versions"` - Offers []struct { - OfferIndex string `json:"offerIndex"` - Price string `json:"price"` - Duration string `json:"duration"` - Active bool `json:"active"` - } `json:"offers"` - Purchases []struct { - Purchaser string `json:"purchaser"` - Expire time.Time `json:"expire"` - } `json:"purchases"` -} - -// MarketplaceDeployedSource is the information related to a deployment -type MarketplaceDeployedSource struct { - Type string `json:"type"` - Source string `json:"source"` -} - -// MarketplaceManifestServiceData is the data present to the manifest and sent to create a new service's version -type MarketplaceManifestServiceData struct { - Definition *definition.Service `json:"definition"` - Readme string `json:"readme,omitempty"` - Deployment MarketplaceDeployedSource `json:"deployment"` -} - -// MarketplaceManifestData struct { -type MarketplaceManifestData struct { - Version string `json:"version"` - Service MarketplaceManifestServiceData `json:"service"` -} - -// UnmarshalJSON overrides the default one to allow parsing malformed manifest data without returning error to user. -func (d *MarketplaceManifestData) UnmarshalJSON(data []byte) error { - // the following temporary type prevents recursive cycling call when unmarshalling - type tempType MarketplaceManifestData - if err := json.Unmarshal(data, (*tempType)(d)); err != nil { - *d = MarketplaceManifestData{} - } - return nil -} - -type marketplacePrepareTaskInputs struct { - From string `json:"from"` - Gas string `json:"gas,omitempty"` - GasPrice string `json:"gasPrice,omitempty"` -} - -type marketplacePublishTaskInputs struct { - SignedTransaction string `json:"signedTransaction"` -} - -type marketplacePreparePublishServiceVersionTaskInputs struct { - marketplacePrepareTaskInputs - Service MarketplaceManifestServiceData `json:"service"` -} - -type marketplacePublishPublishServiceVersionTaskOutputs struct { - Sid string `json:"sid"` - VersionHash string `json:"versionHash"` - Manifest string `json:"manifest"` - ManifestProtocol string `json:"manifestProtocol"` -} - -type marketplacePrepareCreateServiceOfferTaskInputs struct { - marketplacePrepareTaskInputs - Sid string `json:"sid"` - Price string `json:"price"` - Duration string `json:"duration"` -} - -type marketplacePublishCreateServiceOfferTaskOutputs struct { - Sid string `json:"sid"` - OfferIndex string `json:"offerIndex"` - Price string `json:"price"` - Duration string `json:"duration"` -} - -type marketplacePreparePurchaseTaskInputs struct { - marketplacePrepareTaskInputs - Sid string `json:"sid"` - OfferIndex string `json:"offerIndex"` -} - -type marketplacePreparePurchaseTaskOutputs struct { - Transactions []Transaction `json:"transactions"` -} - -type marketplacePublishPurchaseTaskInputs struct { - SignedTransactions []string `json:"signedTransactions"` -} - -type marketplacePublishPurchaseTaskOutputs struct { - Sid string `json:"sid"` - OfferIndex string `json:"offerIndex"` - Purchaser string `json:"purchaser"` - Price string `json:"price"` - Duration string `json:"duration"` - Expire time.Time `json:"expire"` -} - -type marketplaceGetServiceTaskInputs struct { - Sid string `json:"sid"` -} - -type marketplaceIsAuthorizedInputs struct { - Sid string `json:"sid"` - VersionHash string `json:"versionHash"` - Addresses []string `json:"addresses"` -} - -type marketplaceIsAuthorizedSuccessOutput struct { - Authorized bool `json:"authorized"` - Sid string `json:"sid"` - Source string `json:"source"` - Type string `json:"type"` -} diff --git a/commands/provider/provider.go b/commands/provider/provider.go deleted file mode 100644 index cc143f9e8..000000000 --- a/commands/provider/provider.go +++ /dev/null @@ -1,26 +0,0 @@ -package provider - -import ( - "github.com/mesg-foundation/core/daemon" - "github.com/mesg-foundation/core/protobuf/coreapi" -) - -// Provider is a struct that provides all methods required by any command. -type Provider struct { - *CoreProvider - *ServiceProvider - *WalletProvider - *MarketplaceProvider -} - -// New creates Provider based on given CoreClient. -func New(c coreapi.CoreClient, d daemon.Daemon) *Provider { - wp := NewWalletProvider(c) - mp := NewMarketplaceProvider(c) - return &Provider{ - CoreProvider: NewCoreProvider(c, d), - ServiceProvider: NewServiceProvider(c, mp, wp), - WalletProvider: wp, - MarketplaceProvider: mp, - } -} diff --git a/commands/provider/service_deployer.go b/commands/provider/service_deployer.go deleted file mode 100644 index 6cdd1a608..000000000 --- a/commands/provider/service_deployer.go +++ /dev/null @@ -1,223 +0,0 @@ -package provider - -import ( - "context" - "errors" - "fmt" - "io" - "net/url" - "strings" - - "github.com/docker/cli/cli/command/image/build" - "github.com/docker/docker/pkg/archive" - "github.com/mesg-foundation/core/protobuf/coreapi" - validator "gopkg.in/go-playground/validator.v9" -) - -// StatusType indicates the type of status message. -type StatusType int - -const ( - _ StatusType = iota // skip zero value. - - // Running indicates that status message belongs to a continuous state. - Running - - // DonePositive indicates that status message belongs to a positive noncontinuous state. - DonePositive - - // DoneNegative indicates that status message belongs to a negative noncontinuous state. - DoneNegative -) - -// DeployStatus represents the deployment status. -type DeployStatus struct { - Message string - Type StatusType -} - -// deploymentResult keeps information about deployment result. -type deploymentResult struct { - sid string - hash string - err error - validationError error -} - -// ServiceDeploy deploys service from given path. -func (p *ServiceProvider) ServiceDeploy(path string, env map[string]string, statuses chan DeployStatus) (sid string, hash string, validationError, err error) { - stream, err := p.client.DeployService(context.Background()) - if err != nil { - return "", "", nil, err - } - - deployment := make(chan deploymentResult) - go func() { - <-stream.Context().Done() - deployment <- deploymentResult{err: stream.Context().Err()} - }() - go readDeployReply(stream, deployment, statuses) - - isURL := validator.New().Var(path, "url") - switch { - case strings.HasPrefix(path, "mesg:"): - err = p.deployServiceFromMarketplace(path, env, stream) - case isURL == nil: - err = stream.Send(&coreapi.DeployServiceRequest{ - Value: &coreapi.DeployServiceRequest_Url{Url: path}, - Env: env, - }) - default: - err = deployServiceSendServiceContext(path, env, stream) - } - if err != nil { - return "", "", nil, err - } - - if err := stream.CloseSend(); err != nil { - return "", "", nil, err - } - - result := <-deployment - close(statuses) - return result.sid, result.hash, result.validationError, result.err -} - -func (p *ServiceProvider) deployServiceFromMarketplace(u string, env map[string]string, stream coreapi.Core_DeployServiceClient) error { - - urlParsed, err := url.Parse(u) - if err != nil { - return err - } - path := strings.Split(strings.Trim(urlParsed.EscapedPath(), "/"), "/") - if urlParsed.Hostname() != "marketplace" || len(path) != 2 || path[0] != "service" || len(path[1]) == 0 { - return fmt.Errorf("marketplace url %s invalid", u) - } - - // Get ALL address from wallet - addresses, err := p.wp.List() - if err != nil { - return err - } - - // Check if one of them are is authorized - authorized, sid, source, sourceType, err := p.mp.IsAuthorized("", path[1], addresses) - if err != nil { - return err - } - - if !authorized { - return fmt.Errorf("you are not authorized to deploy this service. Did you purchase it?\nExecute the following command to purchase it:\n\tmesg-core marketplace purchase %s", sid) - } - - var url string - switch sourceType { - case "https", "http": - url = source - case "ipfs": - url = "http://ipfs.app.mesg.com:8080/ipfs/" + source - default: - return fmt.Errorf("unknown protocol %s", sourceType) - } - - return stream.Send(&coreapi.DeployServiceRequest{ - Value: &coreapi.DeployServiceRequest_Url{Url: url}, - Env: env, - }) -} - -func deployServiceSendServiceContext(path string, env map[string]string, stream coreapi.Core_DeployServiceClient) error { - excludes, err := build.ReadDockerignore(path) - if err != nil { - return err - } - - if err := build.ValidateContextDirectory(path, excludes); err != nil { - return fmt.Errorf("error checking context: %s", err) - } - - // And canonicalize dockerfile name to a platform-independent one - excludes = build.TrimBuildFilesFromExcludes(excludes, build.DefaultDockerfileName, false) - - archive, err := archive.TarWithOptions(path, &archive.TarOptions{ - Compression: archive.Gzip, - ExcludePatterns: excludes, - }) - if err != nil { - return err - } - - if len(env) > 0 { - if err := stream.Send(&coreapi.DeployServiceRequest{Env: env}); err != nil { - return err - } - } - - buf := make([]byte, 1024) - for { - n, err := archive.Read(buf) - if err == io.EOF { - break - } - if err != nil { - return err - } - - if err := stream.Send(&coreapi.DeployServiceRequest{ - Value: &coreapi.DeployServiceRequest_Chunk{Chunk: buf[:n]}, - }); err != nil { - return err - } - } - - return nil -} - -func readDeployReply(stream coreapi.Core_DeployServiceClient, deployment chan deploymentResult, - statuses chan DeployStatus) { - result := deploymentResult{} - - for { - message, err := stream.Recv() - if err != nil { - result.err = err - deployment <- result - return - } - - var ( - status = message.GetStatus() - service = message.GetService() - validationError = message.GetValidationError() - ) - - switch { - case status != nil: - s := DeployStatus{ - Message: status.Message, - } - - switch status.Type { - case coreapi.DeployServiceReply_Status_RUNNING: - s.Type = Running - case coreapi.DeployServiceReply_Status_DONE_POSITIVE: - s.Type = DonePositive - case coreapi.DeployServiceReply_Status_DONE_NEGATIVE: - s.Type = DoneNegative - } - - statuses <- s - - case service != nil: - result.sid = service.Sid - result.hash = service.Hash - deployment <- result - return - - case validationError != "": - result.validationError = errors.New(validationError) - deployment <- result - return - } - } -} diff --git a/commands/provider/service_provider.go b/commands/provider/service_provider.go deleted file mode 100644 index e76603250..000000000 --- a/commands/provider/service_provider.go +++ /dev/null @@ -1,287 +0,0 @@ -package provider - -import ( - "context" - "fmt" - "os" - "path/filepath" - "strings" - "sync" - "text/template" - - "github.com/mesg-foundation/core/commands/provider/assets" - "github.com/mesg-foundation/core/protobuf/acknowledgement" - "github.com/mesg-foundation/core/protobuf/coreapi" - "github.com/mesg-foundation/core/service" - "github.com/mesg-foundation/core/service/importer" - "github.com/mesg-foundation/core/utils/chunker" - "github.com/mesg-foundation/core/utils/pretty" - "github.com/mesg-foundation/core/utils/servicetemplate" - "github.com/mesg-foundation/core/x/xerrors" -) - -// ServiceProvider is a struct that provides all methods required by service command. -type ServiceProvider struct { - client client - mp *MarketplaceProvider - wp *WalletProvider -} - -// NewServiceProvider creates new ServiceProvider. -func NewServiceProvider(c coreapi.CoreClient, mp *MarketplaceProvider, wp *WalletProvider) *ServiceProvider { - return &ServiceProvider{ - client: client{c}, - mp: mp, - wp: wp, - } -} - -// ServiceByID finds service based on given id. -func (p *ServiceProvider) ServiceByID(id string) (*coreapi.Service, error) { - serviceReply, err := p.client.GetService(context.Background(), &coreapi.GetServiceRequest{ServiceID: id}) - if err != nil { - return nil, err - } - - return serviceReply.Service, nil -} - -// ServiceDeleteAll deletes all services. -func (p *ServiceProvider) ServiceDeleteAll(deleteData bool) error { - rep, err := p.client.ListServices(context.Background(), &coreapi.ListServicesRequest{}) - if err != nil { - return err - } - - var ( - errs xerrors.SyncErrors - wg sync.WaitGroup - ) - wg.Add(len(rep.Services)) - for _, s := range rep.Services { - go func(id string) { - _, err := p.client.DeleteService(context.Background(), &coreapi.DeleteServiceRequest{ - ServiceID: id, - DeleteData: deleteData, - }) - if err != nil { - errs.Append(err) - } - wg.Done() - }(s.Definition.Hash) - } - wg.Wait() - return errs.ErrorOrNil() -} - -// ServiceDelete deletes service with given ids. -func (p *ServiceProvider) ServiceDelete(deleteData bool, ids ...string) error { - var errs xerrors.Errors - for _, id := range ids { - if _, err := p.client.DeleteService(context.Background(), &coreapi.DeleteServiceRequest{ - ServiceID: id, - DeleteData: deleteData, - }); err != nil { - errs = append(errs, err) - } - } - return errs.ErrorOrNil() -} - -// ServiceListenEvents returns a channel with event data streaming.. -func (p *ServiceProvider) ServiceListenEvents(id, eventFilter string) (chan *coreapi.EventData, chan error, error) { - return p.client.ListenEvent(id, eventFilter) -} - -// ServiceListenResults returns a channel with event results streaming.. -func (p *ServiceProvider) ServiceListenResults(id, taskFilter string, tagFilters []string) (chan *coreapi.ResultData, chan error, error) { - return p.client.ListenResult(id, taskFilter, tagFilters) -} - -// ServiceExecuteTask executes task on given service. -func (p *ServiceProvider) ServiceExecuteTask(id, taskKey, inputData string, tags []string) (string, error) { - return p.client.ExecuteTask(id, taskKey, inputData, tags) -} - -// Log keeps dependency logs of service. -type Log struct { - Dependency string - Standard, Error *chunker.Stream -} - -// ServiceLogs returns logs reader for all service dependencies. -func (p *ServiceProvider) ServiceLogs(id string, dependencies ...string) (logs []*Log, close func(), errC chan error, err error) { - if len(dependencies) == 0 { - resp, err := p.client.GetService(context.Background(), &coreapi.GetServiceRequest{ - ServiceID: id, - }) - if err != nil { - return nil, nil, nil, err - } - dependencies = append(dependencies, service.MainServiceKey) - for _, dep := range resp.Service.Definition.Dependencies { - dependencies = append(dependencies, dep.Key) - } - } - - ctx, cancel := context.WithCancel(context.Background()) - - stream, err := p.client.ServiceLogs(ctx, &coreapi.ServiceLogsRequest{ - ServiceID: id, - Dependencies: dependencies, - }) - if err != nil { - cancel() - return nil, nil, nil, err - } - - for _, key := range dependencies { - log := &Log{ - Dependency: key, - Standard: chunker.NewStream(), - Error: chunker.NewStream(), - } - logs = append(logs, log) - } - - closer := func() { - cancel() - for _, log := range logs { - log.Standard.Close() - log.Error.Close() - } - } - - errC = make(chan error) - go func() { - <-stream.Context().Done() - errC <- stream.Context().Err() - }() - go p.listenServiceLogs(stream, logs, errC) - - if err := acknowledgement.WaitForStreamToBeReady(stream); err != nil { - closer() - return nil, nil, nil, err - } - - return logs, closer, errC, nil -} - -// listenServiceLogs listen gRPC stream to get service logs. -func (p *ServiceProvider) listenServiceLogs(stream coreapi.Core_ServiceLogsClient, logs []*Log, - errC chan error) { - for { - data, err := stream.Recv() - if err != nil { - errC <- err - return - } - - for _, log := range logs { - if log.Dependency == data.Dependency { - var out *chunker.Stream - switch data.Type { - case coreapi.LogData_Standard: - out = log.Standard - case coreapi.LogData_Error: - out = log.Error - } - out.Provide(data.Data) - } - } - } -} - -// ServiceStart starts a service. -func (p *ServiceProvider) ServiceStart(id string) error { - _, err := p.client.StartService(context.Background(), &coreapi.StartServiceRequest{ServiceID: id}) - return err -} - -// ServiceStop stops a service. -func (p *ServiceProvider) ServiceStop(id string) error { - _, err := p.client.StopService(context.Background(), &coreapi.StopServiceRequest{ServiceID: id}) - return err -} - -// ServiceValidate validates a service configuration and Dockerfile. -func (p *ServiceProvider) ServiceValidate(path string) (string, error) { - validation, err := importer.Validate(path) - if err != nil { - return "", err - } - - if !validation.ServiceFileExist { - return fmt.Sprintf("%s File 'mesg.yml' does not exist", pretty.FailSign), nil - } - - if len(validation.ServiceFileWarnings) > 0 { - var msg = fmt.Sprintf("%s File 'mesg.yml' is not valid. See documentation: https://docs.mesg.com/guide/service/service-file.html\n", pretty.FailSign) - for _, warning := range validation.ServiceFileWarnings { - msg += fmt.Sprintf("\t* %s\n", warning) - } - return msg, nil - } - - if !validation.DockerfileExist { - return fmt.Sprintf("%s Dockerfile does not exist", pretty.FailSign), nil - } - if !validation.IsValid() { - return fmt.Sprintf("%s Service is not valid", pretty.FailSign), nil - } - - return fmt.Sprintf(`%s Dockerfile exists -%s mesg.yml is valid -%s Service is valid`, pretty.SuccessSign, pretty.SuccessSign, pretty.SuccessSign), nil -} - -// ServiceGenerateDocs creates docs in given path. -func (p *ServiceProvider) ServiceGenerateDocs(path string) error { - readmePath := filepath.Join(path, "README.md") - service, err := importer.From(path) - if err != nil { - return err - } - - f, err := os.OpenFile(readmePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) - if err != nil { - return err - } - defer f.Close() - - readmeTemplate, err := assets.Asset("commands/provider/assets/readme_template.md") - if err != nil { - return err - } - - anchorEncode := func(a string) string { - a = strings.Replace(a, " ", "-", -1) - a = strings.Replace(a, "'", "", -1) - a = strings.ToLower(a) - return a - } - tpl, err := template.New("doc").Funcs(template.FuncMap{"anchorEncode": anchorEncode}).Parse(string(readmeTemplate)) - if err != nil { - return err - } - return tpl.Execute(f, service) -} - -// ServiceList lists all services. -func (p *ServiceProvider) ServiceList() ([]*coreapi.Service, error) { - reply, err := p.client.ListServices(context.Background(), &coreapi.ListServicesRequest{}) - if err != nil { - return nil, err - } - return reply.Services, nil -} - -// ServiceInitTemplateList downloads services templates list from awesome github repo. -func (p *ServiceProvider) ServiceInitTemplateList() ([]*servicetemplate.Template, error) { - return servicetemplate.List() -} - -// ServiceInitDownloadTemplate download given service template. -func (p *ServiceProvider) ServiceInitDownloadTemplate(t *servicetemplate.Template, dst string) error { - return servicetemplate.Download(t, dst) -} diff --git a/commands/provider/wallet_provider.go b/commands/provider/wallet_provider.go deleted file mode 100644 index 351492b5c..000000000 --- a/commands/provider/wallet_provider.go +++ /dev/null @@ -1,107 +0,0 @@ -package provider - -import ( - "encoding/json" - - "github.com/mesg-foundation/core/protobuf/coreapi" -) - -// WalletProvider is a struct that provides all methods required by wallet command. -type WalletProvider struct { - client client -} - -// NewWalletProvider creates new WalletProvider. -func NewWalletProvider(c coreapi.CoreClient) *WalletProvider { - return &WalletProvider{client: client{c}} -} - -// List return the accounts of this wallet -func (p *WalletProvider) List() ([]string, error) { - var output walletListOutputSuccess - return output.Addresses, p.call("list", nil, &output) -} - -// Create creates a new account in the wallet -func (p *WalletProvider) Create(passphrase string) (string, error) { - input := walletCreateInputs{ - Passphrase: passphrase, - } - var output walletCreateOutputSuccess - return output.Address, p.call("create", &input, &output) -} - -// Delete removes an account from the wallet -func (p *WalletProvider) Delete(address string, passphrase string) (string, error) { - input := walletDeleteInputs{ - Address: address, - Passphrase: passphrase, - } - var output walletDeleteOutputSuccess - return output.Address, p.call("delete", &input, &output) -} - -// Export exports an account -func (p *WalletProvider) Export(address string, passphrase string) (WalletEncryptedKeyJSONV3, error) { - input := walletExportInputs{ - Address: address, - Passphrase: passphrase, - } - var output WalletEncryptedKeyJSONV3 - return output, p.call("export", &input, &output) -} - -// Import imports an account into the wallet -func (p *WalletProvider) Import(account WalletEncryptedKeyJSONV3, passphrase string) (string, error) { - input := walletImportInputs{ - Account: account, - Passphrase: passphrase, - } - var output walletImportOutputSuccess - return output.Address, p.call("import", &input, &output) -} - -// ImportFromPrivateKey imports an account from a private key -func (p *WalletProvider) ImportFromPrivateKey(privateKey string, passphrase string) (string, error) { - input := walletImportFromPrivateKeyInputs{ - PrivateKey: privateKey, - Passphrase: passphrase, - } - var output walletImportOutputSuccess - return output.Address, p.call("importFromPrivateKey", &input, &output) - -} - -// Sign signs a transaction -func (p *WalletProvider) Sign(address string, passphrase string, transaction Transaction) (string, error) { - input := walletSignInputs{ - Address: address, - Passphrase: passphrase, - Transaction: transaction, - } - var output walletSignOutputSuccess - return output.SignedTransaction, p.call("sign", &input, &output) -} - -func (p *WalletProvider) call(task string, inputs interface{}, output interface{}) error { - serviceHash, err := p.client.GetServiceHash(walletServiceKey) - if err != nil { - return err - } - r, err := p.client.ExecuteAndListen(serviceHash, task, &inputs) - if err != nil { - return err - } - return p.parseResult(r, &output) -} - -func (p *WalletProvider) parseResult(r *coreapi.ResultData, output interface{}) error { - if r.Error != "" { - var outputError walletErrorOutput - if err := json.Unmarshal([]byte(r.Error), &outputError); err != nil { - return err - } - return outputError - } - return json.Unmarshal([]byte(r.OutputData), &output) -} diff --git a/commands/provider/wallet_types.go b/commands/provider/wallet_types.go deleted file mode 100644 index d68f19dd3..000000000 --- a/commands/provider/wallet_types.go +++ /dev/null @@ -1,94 +0,0 @@ -package provider - -const walletServiceKey = "ethwallet" - -// walletErrorOutput is the output for any task that fails. -type walletErrorOutput struct { - Message string `json:"message"` -} - -func (e walletErrorOutput) Error() string { - return e.Message -} - -type walletListOutputSuccess struct { - Addresses []string `json:"addresses"` -} - -type walletCreateInputs struct { - Passphrase string `json:"passphrase"` -} - -type walletCreateOutputSuccess struct { - Address string `json:"address"` -} - -type walletDeleteInputs struct { - Address string `json:"address"` - Passphrase string `json:"passphrase"` -} - -type walletDeleteOutputSuccess struct { - Address string `json:"address"` -} - -type walletExportInputs struct { - Address string `json:"address"` - Passphrase string `json:"passphrase"` -} - -type walletImportInputs struct { - Account WalletEncryptedKeyJSONV3 `json:"account"` - Passphrase string `json:"passphrase"` -} - -type walletImportFromPrivateKeyInputs struct { - PrivateKey string `json:"privateKey"` - Passphrase string `json:"passphrase"` -} - -type walletImportOutputSuccess struct { - Address string `json:"address"` -} - -type walletSignInputs struct { - Address string `json:"address"` - Passphrase string `json:"passphrase"` - Transaction Transaction `json:"transaction"` -} - -type walletSignOutputSuccess struct { - SignedTransaction string `json:"signedTransaction"` -} - -// WalletEncryptedKeyJSONV3 represents an Ethereum JSON v3 encrypted wallet -type WalletEncryptedKeyJSONV3 struct { - Address string `json:"address"` - Crypto interface{} `json:"crypto"` - ID string `json:"id"` - Version int `json:"version"` -} - -// Transaction represents created transaction. -type Transaction struct { - ChainID int64 `json:"chainID"` - Nonce uint64 `json:"nonce"` - To string `json:"to"` - Value string `json:"value"` - Gas uint64 `json:"gas"` - GasPrice string `json:"gasPrice"` - Data string `json:"data"` -} - -// TransactionReceipt is the success output of task send signed transaction. -type TransactionReceipt struct { - Receipt struct { - BlockNumber uint `json:"blockNumber"` - From string `json:"from"` - GasUsed uint `json:"gasUsed"` - Status bool `json:"status"` - To string `json:"to"` - TransactionHash string `json:"transactionHash"` - TransactionIndex uint `json:"transactionIndex"` - } `json:"receipt"` -} diff --git a/commands/root.go b/commands/root.go deleted file mode 100644 index 9966d132d..000000000 --- a/commands/root.go +++ /dev/null @@ -1,46 +0,0 @@ -package commands - -import ( - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" -) - -type rootCmd struct { - baseCmd - - noColor bool - noSpinner bool -} - -func newRootCmd(e Executor) *rootCmd { - c := &rootCmd{} - c.cmd = newCommand(&cobra.Command{ - Use: "mesg-core", - Short: "MESG Core", - PersistentPreRun: c.persistentPreRun, - SilenceUsage: true, - SilenceErrors: true, - }) - c.cmd.PersistentFlags().BoolVar(&c.noColor, "no-color", c.noColor, "disable colorized output") - c.cmd.PersistentFlags().BoolVar(&c.noSpinner, "no-spinner", c.noSpinner, "disable spinners") - - c.cmd.AddCommand( - newStartCmd(e).cmd, - newStatusCmd(e).cmd, - newStopCmd(e).cmd, - newLogsCmd(e).cmd, - newRootServiceCmd(e).cmd, - newRootWalletCmd(e).cmd, - newRootMarketplaceCmd(e).cmd, - ) - return c -} - -func (c *rootCmd) persistentPreRun(cmd *cobra.Command, args []string) { - if c.noColor { - pretty.DisableColor() - } - if c.noSpinner { - pretty.DisableSpinner() - } -} diff --git a/commands/root_test.go b/commands/root_test.go deleted file mode 100644 index 89a5da736..000000000 --- a/commands/root_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package commands - -import ( - "os" - "strings" - "testing" - - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" - "github.com/stretchr/testify/require" -) - -func findCommandChildByUsePrefix(root *cobra.Command, use string) bool { - for _, cmd := range root.Commands() { - if strings.HasPrefix(cmd.Use, use) { - return true - } - } - return false -} - -func TestMain(m *testing.M) { - pretty.DisableColor() - pretty.DisableSpinner() - os.Exit(m.Run()) -} - -func TestRootCmd(t *testing.T) { - cmd := newRootCmd(nil).cmd - for _, tt := range []struct { - use string - }{ - {"start"}, - {"status"}, - {"stop"}, - {"logs"}, - {"service"}, - } { - require.Truef(t, findCommandChildByUsePrefix(cmd, tt.use), "command %q not found", tt.use) - } -} - -func TestRootCmdFlags(t *testing.T) { - c := newRootCmd(nil) - - c.cmd.PersistentFlags().Set("no-color", "true") - require.True(t, c.noColor) - - c.cmd.PersistentFlags().Set("no-spinner", "true") - require.True(t, c.noSpinner) -} diff --git a/commands/service_delete.go b/commands/service_delete.go deleted file mode 100644 index 0f741f0c0..000000000 --- a/commands/service_delete.go +++ /dev/null @@ -1,135 +0,0 @@ -package commands - -import ( - "errors" - "fmt" - "os" - - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" - survey "gopkg.in/AlecAivazis/survey.v1" -) - -var ( - errConfirmationNeeded = errors.New("can't continue without confirmation") - errNoID = errors.New("at least one service id must be provided (or run with --all flag)") -) - -type serviceDeleteCmd struct { - baseCmd - - yes bool - all bool - keepData bool - - e ServiceExecutor -} - -func newServiceDeleteCmd(e ServiceExecutor) *serviceDeleteCmd { - c := &serviceDeleteCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "delete", - Short: "Delete one or many services", - Example: `mesg-core service delete SERVICE [SERVICE...] -mesg-core service delete --all`, - PreRunE: c.preRunE, - RunE: c.runE, - }) - c.cmd.Flags().BoolVarP(&c.yes, "yes", "y", c.yes, `Automatic "yes" to all prompts and run non-interactively`) - c.cmd.Flags().BoolVar(&c.all, "all", c.all, "Delete all services") - c.cmd.Flags().BoolVar(&c.keepData, "keep-data", c.keepData, "Do not delete services' persistent data") - return c -} - -func (c *serviceDeleteCmd) preRunE(cmd *cobra.Command, args []string) error { - if len(args) == 0 && !c.all { - return errNoID - } - - if c.yes { - return nil - } - - if err := c.confirmServiceDelete(); err != nil { - return err - } - - if !c.keepData { - if err := c.confirmDataDelete(); err != nil { - return err - } - } - - return nil -} - -// confirmServiceDelete prompts a confirmation dialog for deleting services. -func (c *serviceDeleteCmd) confirmServiceDelete() error { - var ( - confirmed bool - confirm = &survey.Confirm{ - Message: "Are you sure to delete service(s)?", - } - ) - - if c.all { - confirm.Message = "Are you sure to delete all services?" - } - - if err := survey.AskOne(confirm, &confirmed, nil); err != nil { - return err - } - - if !confirmed { - return errConfirmationNeeded - } - return nil -} - -// confirmServiceDelete prompts a confirmation dialog for deleting services' data. -func (c *serviceDeleteCmd) confirmDataDelete() error { - var deleteData bool - if err := survey.AskOne(&survey.Confirm{ - Message: "Are you sure to remove service(s)' persistent data as well?", - }, &deleteData, nil); err != nil { - return err - } - c.keepData = !deleteData - return nil -} - -func (c *serviceDeleteCmd) runE(cmd *cobra.Command, args []string) error { - var err error - if c.all { - pretty.Progress("Deleting all services...", func() { - err = c.e.ServiceDeleteAll(!c.keepData) - }) - if err != nil { - return err - } - fmt.Printf("%s all services are deleted\n", pretty.SuccessSign) - return nil - } - - exitWithError := false - for _, arg := range args { - // build function to avoid using arg inside progress - fn := func(id string) func() { - return func() { - err = c.e.ServiceDelete(!c.keepData, id) - } - }(arg) - pretty.Progress(fmt.Sprintf("Deleting service %q...", arg), fn) - if err != nil { - exitWithError = true - fmt.Fprintf(os.Stderr, "%s can't delete service %q: %s\n", pretty.FailSign, arg, err) - } else { - fmt.Printf("%s service %q deleted\n", pretty.SuccessSign, arg) - } - } - - if exitWithError { - return errors.New("there was a problem with deleting some services") - } - return nil -} diff --git a/commands/service_delete_test.go b/commands/service_delete_test.go deleted file mode 100644 index 3f05f382f..000000000 --- a/commands/service_delete_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package commands - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestServiceDeleteCmdFlags(t *testing.T) { - var ( - c = newServiceDeleteCmd(nil) - flags = c.cmd.Flags() - ) - - // check defaults. - require.False(t, c.yes) - require.False(t, c.all) - require.False(t, c.keepData) - - require.Equal(t, flags.ShorthandLookup("y"), flags.Lookup("yes")) - - flags.Set("yes", "true") - require.True(t, c.yes) - - flags.Set("all", "true") - require.True(t, c.all) - - flags.Set("keep-data", "true") - require.True(t, c.keepData) -} - -func TestServiceDeletePreRunE(t *testing.T) { - c := newServiceDeleteCmd(nil) - - c.discardOutput() - require.Equal(t, errNoID, c.preRunE(c.cmd, nil)) - - c.yes = true - c.all = true - require.NoError(t, c.preRunE(c.cmd, nil)) -} - -func TestServiceDeleteRunE(t *testing.T) { - var ( - m = newMockExecutor() - c = newServiceDeleteCmd(m) - ) - - tests := []struct { - all bool - keepData bool - arg string - }{ - {all: false, keepData: false, arg: "0"}, - {all: false, keepData: true, arg: "0"}, - {all: true, keepData: false}, - {all: true, keepData: true}, - } - - for _, tt := range tests { - c.all = tt.all - c.keepData = tt.keepData - - if tt.all { - m.On("ServiceDeleteAll", !tt.keepData).Once().Return(nil) - } else { - m.On("ServiceDelete", !tt.keepData, tt.arg).Once().Return(nil) - } - require.NoError(t, c.runE(c.cmd, []string{tt.arg})) - } - m.AssertExpectations(t) -} diff --git a/commands/service_deploy.go b/commands/service_deploy.go deleted file mode 100644 index 1e259ebe3..000000000 --- a/commands/service_deploy.go +++ /dev/null @@ -1,102 +0,0 @@ -package commands - -import ( - "errors" - "fmt" - "sync" - - "github.com/mesg-foundation/core/commands/provider" - "github.com/mesg-foundation/core/utils/pretty" - "github.com/mesg-foundation/core/x/xerrors" - "github.com/mesg-foundation/core/x/xpflag" - "github.com/spf13/cobra" -) - -type serviceDeployCmd struct { - baseCmd - - path string - env map[string]string - - e ServiceExecutor -} - -func newServiceDeployCmd(e ServiceExecutor) *serviceDeployCmd { - c := &serviceDeployCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "deploy", - Short: "Deploy a service", - Long: `Deploy a service. - -To get more information, see the [deploy page from the documentation](https://docs.mesg.com/guide/service/deploy-a-service.html)`, - Example: `mesg-core service deploy [PATH_TO_SERVICE|URL_TO_SERVICE]`, - PreRunE: c.preRunE, - RunE: c.runE, - Args: cobra.MaximumNArgs(1), - }) - c.cmd.Flags().Var(xpflag.NewStringToStringValue(&c.env, nil), "env", "set env defined in mesg.yml (configuration.env)") - return c -} - -func (c *serviceDeployCmd) preRunE(cmd *cobra.Command, args []string) error { - c.path = getFirstOrCurrentPath(args) - return nil -} - -func (c *serviceDeployCmd) runE(cmd *cobra.Command, args []string) error { - sid, hash, err := deployService(c.e, c.path, c.env) - if err != nil { - return err - } - fmt.Printf("%s Service deployed with sid %s and hash %s\n", pretty.SuccessSign, pretty.Success(sid), pretty.Success(hash)) - fmt.Printf("To start it, run the command:\n\tmesg-core service start %s\n", sid) - return nil -} - -func deployService(e ServiceExecutor, path string, env map[string]string) (string, string, error) { - var ( - statuses = make(chan provider.DeployStatus) - wg sync.WaitGroup - ) - - wg.Add(1) - go func() { - defer wg.Done() - printDeployStatuses(statuses) - }() - - sid, hash, validationError, err := e.ServiceDeploy(path, env, statuses) - if err != nil { - return "", "", err - } - wg.Wait() - - pretty.DestroySpinner() - if validationError != nil { - return "", "", xerrors.Errors{ - validationError, - errors.New("to get more information, run: mesg-core service validate"), - } - } - - return sid, hash, nil -} - -func printDeployStatuses(statuses chan provider.DeployStatus) { - for status := range statuses { - switch status.Type { - case provider.Running: - pretty.UseSpinner(status.Message) - default: - var sign string - switch status.Type { - case provider.DonePositive: - sign = pretty.SuccessSign - case provider.DoneNegative: - sign = pretty.FailSign - } - pretty.DestroySpinner() - fmt.Printf("%s %s\n", sign, status.Message) - } - } -} diff --git a/commands/service_deploy_test.go b/commands/service_deploy_test.go deleted file mode 100644 index 4e952d1e0..000000000 --- a/commands/service_deploy_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package commands - -import ( - "bufio" - "strings" - "testing" - - "github.com/mesg-foundation/core/commands/provider" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" -) - -func TestServiceDeployCmdFlags(t *testing.T) { - c := newServiceDeployCmd(nil) - - flags := c.cmd.Flags() - flags.Set("env", "a=1") - flags.Set("env", "b=2") - require.Equal(t, map[string]string{"a": "1", "b": "2"}, c.env) -} - -func TestServiceDeploy(t *testing.T) { - var ( - url = "1" - sid = "2" - hash = "3" - env = map[string]string{"A": "3", "B": "4"} - m = newMockExecutor() - c = newServiceDeployCmd(m) - serviceDeployParameters = []interface{}{ - url, - env, - mock.Anything, - } - serviceDeployRunFunction = func(args mock.Arguments) { - statuses := args.Get(2).(chan provider.DeployStatus) - statuses <- provider.DeployStatus{ - Message: "5", - Type: provider.DonePositive, - } - statuses <- provider.DeployStatus{ - Message: "6", - Type: provider.DoneNegative, - } - close(statuses) - } - ) - c.cmd.SetArgs([]string{url}) - c.env = env - - m.On("ServiceDeploy", serviceDeployParameters...).Return(sid, hash, nil, nil).Run(serviceDeployRunFunction) - - closeStd := captureStd(t) - c.cmd.Execute() - stdout, _ := closeStd() - r := bufio.NewReader(strings.NewReader(stdout)) - - require.Equal(t, "✔ 5", string(readLine(t, r))) - require.Equal(t, "⨯ 6", string(readLine(t, r))) - require.Equal(t, "✔ Service deployed with sid 2 and hash 3", string(readLine(t, r))) - require.Equal(t, "To start it, run the command:", string(readLine(t, r))) - require.Equal(t, " mesg-core service start 2", string(readLine(t, r))) - - m.AssertExpectations(t) -} diff --git a/commands/service_detail.go b/commands/service_detail.go deleted file mode 100644 index 4f2d3164c..000000000 --- a/commands/service_detail.go +++ /dev/null @@ -1,47 +0,0 @@ -package commands - -import ( - "encoding/json" - "fmt" - - "github.com/mesg-foundation/core/protobuf/coreapi" - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" -) - -type serviceDetailCmd struct { - baseCmd - e ServiceExecutor -} - -func newServiceDetailCmd(e ServiceExecutor) *serviceDetailCmd { - c := &serviceDetailCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "detail SERVICE", - Short: "Show details of a published service", - Args: cobra.ExactArgs(1), - Example: "mesg-core service detail SERVICE", - RunE: c.runE, - }) - return c -} - -func (c *serviceDetailCmd) runE(cmd *cobra.Command, args []string) error { - var ( - err error - service *coreapi.Service - ) - pretty.Progress("Loading the service...", func() { - service, err = c.e.ServiceByID(args[0]) - }) - if err != nil { - return err - } - // dump service definition. - bytes, err := json.Marshal(service) - if err != nil { - return err - } - fmt.Println(string(pretty.ColorizeJSON(pretty.FgCyan, nil, true, bytes))) - return nil -} diff --git a/commands/service_detail_test.go b/commands/service_detail_test.go deleted file mode 100644 index 55ee2b4ab..000000000 --- a/commands/service_detail_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package commands - -import ( - "bufio" - "encoding/json" - "strings" - "testing" - - "github.com/mesg-foundation/core/protobuf/coreapi" - "github.com/mesg-foundation/core/protobuf/definition" - "github.com/mesg-foundation/core/utils/pretty" - "github.com/stretchr/testify/require" -) - -func TestServiceDetail(t *testing.T) { - var ( - id = "1" - service = &coreapi.Service{Definition: &definition.Service{Hash: "2", Name: "3", Events: []*definition.Event{{Key: "4"}}}} - m = newMockExecutor() - c = newServiceDetailCmd(m) - ) - c.cmd.SetArgs([]string{id}) - - m.On("ServiceByID", id).Return(service, nil) - - closeStd := captureStd(t) - c.cmd.Execute() - stdout, _ := closeStd() - r := bufio.NewReader(strings.NewReader(stdout)) - - data, _ := json.Marshal(service) - - require.Equal(t, "Loading the service...", string(readLine(t, r))) - require.Equal(t, string(pretty.ColorizeJSON(pretty.FgCyan, nil, true, data)), - strings.TrimSpace(string(readLine(t, r)))) - - m.AssertExpectations(t) -} diff --git a/commands/service_dev.go b/commands/service_dev.go deleted file mode 100644 index 2eafbff0b..000000000 --- a/commands/service_dev.go +++ /dev/null @@ -1,129 +0,0 @@ -package commands - -import ( - "fmt" - "os" - - "github.com/mesg-foundation/core/utils/pretty" - "github.com/mesg-foundation/core/x/xpflag" - "github.com/mesg-foundation/core/x/xsignal" - "github.com/spf13/cobra" -) - -type serviceDevCmd struct { - baseCmd - - eventFilter string - taskFilter string - path string - env map[string]string - - e ServiceExecutor -} - -func newServiceDevCmd(e ServiceExecutor) *serviceDevCmd { - c := &serviceDevCmd{ - e: e, - eventFilter: "*", - } - - c.cmd = newCommand(&cobra.Command{ - Use: "dev", - Short: "Run your service in development mode", - Example: "mesg-core service dev PATH", - Args: cobra.MaximumNArgs(1), - PreRunE: c.preRunE, - RunE: c.runE, - }) - c.cmd.Flags().StringVarP(&c.eventFilter, "event-filter", "e", c.eventFilter, "Only log the data of the given event") - c.cmd.Flags().StringVarP(&c.taskFilter, "task-filter", "t", "", "Only log the result of the given task") - c.cmd.Flags().Var(xpflag.NewStringToStringValue(&c.env, nil), "env", "set env defined in mesg.yml (configuration.env)") - return c -} - -func (c *serviceDevCmd) preRunE(cmd *cobra.Command, args []string) error { - c.path = getFirstOrCurrentPath(args) - return nil -} - -func (c *serviceDevCmd) runE(cmd *cobra.Command, args []string) error { - sid, hash, err := deployService(c.e, c.path, c.env) - if err != nil { - return err - } - fmt.Printf("%s Service deployed with sid %s and hash %s\n", pretty.SuccessSign, pretty.Success(sid), pretty.Success(hash)) - - defer func() { - var err error - pretty.Progress("Removing the service...", func() { - err = c.e.ServiceDelete(false, hash) - }) - if err != nil { - fmt.Printf("%s Removing the service completed with an error: %s\n", pretty.FailSign, err) - } else { - fmt.Printf("%s Service removed\n", pretty.SuccessSign) - } - }() - - pretty.Progress("Starting the service...", func() { err = c.e.ServiceStart(hash) }) - if err != nil { - return err - } - fmt.Printf("%s Service started\n", pretty.SuccessSign) - - listenEventsC, eventsErrC, err := c.e.ServiceListenEvents(hash, c.eventFilter) - if err != nil { - return err - } - - listenResultsC, resultsErrC, err := c.e.ServiceListenResults(hash, c.taskFilter, nil) - if err != nil { - return err - } - - closer, logsErrC, err := showLogs(c.e, hash) - if err != nil { - return err - } - defer closer() - - abort := xsignal.WaitForInterrupt() - fmt.Println("Listening for results and events from the service...") - - for { - select { - case <-abort: - return nil - - case err := <-logsErrC: - return err - - case e := <-listenEventsC: - fmt.Printf("Receive event %s: %s\n", - pretty.Success(e.EventKey), - pretty.ColorizeJSON(pretty.FgCyan, nil, false, []byte(e.EventData)), - ) - - case err := <-eventsErrC: - fmt.Fprintf(os.Stderr, "%s Listening events error: %s\n", pretty.FailSign, err) - return nil - - case r := <-listenResultsC: - if r.Error != "" { - fmt.Printf("Receive execution error on %s task: %s\n", - pretty.Fail(r.TaskKey), - pretty.Fail(r.Error), - ) - } else { - fmt.Printf("Receive execution result on %s task: %s\n", - pretty.Success(r.TaskKey), - pretty.ColorizeJSON(pretty.FgCyan, nil, false, []byte(r.OutputData)), - ) - } - - case err := <-resultsErrC: - fmt.Fprintf(os.Stderr, "%s Listening results error: %s\n", pretty.FailSign, err) - return nil - } - } -} diff --git a/commands/service_dev_test.go b/commands/service_dev_test.go deleted file mode 100644 index f37957b83..000000000 --- a/commands/service_dev_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package commands - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestServiceDevCmdFlags(t *testing.T) { - c := newServiceDevCmd(nil) - - flags := c.cmd.Flags() - require.Equal(t, flags.ShorthandLookup("e"), flags.Lookup("event-filter")) - require.Equal(t, flags.ShorthandLookup("t"), flags.Lookup("task-filter")) - - flags.Set("event-filter", "ef") - require.Equal(t, "ef", c.eventFilter) - - flags.Set("task-filter", "tf") - require.Equal(t, "tf", c.taskFilter) -} diff --git a/commands/service_docs.go b/commands/service_docs.go deleted file mode 100644 index 8aa128714..000000000 --- a/commands/service_docs.go +++ /dev/null @@ -1,61 +0,0 @@ -package commands - -import ( - "errors" - "fmt" - "os" - "path/filepath" - - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" - survey "gopkg.in/AlecAivazis/survey.v1" -) - -type serviceDocsCmd struct { - baseCmd - - force bool - path string - - e ServiceExecutor -} - -func newServiceDocsCmd(e ServiceExecutor) *serviceDocsCmd { - c := &serviceDocsCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "gen-doc", - Short: "Generate the documentation for the service in a README.md file", - Example: `mesg-core service gen-doc -mesg-core service gen-doc ./PATH_TO_SERVICE -mesg-core service gen-doc --force`, - PreRunE: c.preRunE, - RunE: c.runE, - }) - c.cmd.Flags().BoolVarP(&c.force, "force", "f", c.force, "No confirmation. Will replace existing README.md file") - return c -} - -func (c *serviceDocsCmd) preRunE(cmd *cobra.Command, args []string) error { - c.path = getFirstOrCurrentPath(args) - readmePath := filepath.Join(c.path, "README.md") - if _, err := os.Stat(readmePath); !c.force && err == nil { - if err := survey.AskOne(&survey.Confirm{ - Message: "The file README.md already exists. Do you want to overwrite it?", - }, &c.force, nil); err != nil { - return err - } - if !c.force { - return errors.New("can't continue without confirmation") - } - } - return nil -} - -func (c *serviceDocsCmd) runE(cmd *cobra.Command, args []string) error { - if err := c.e.ServiceGenerateDocs(c.path); err != nil { - return err - } - - fmt.Printf("%s File README.md generated with success\n", pretty.SuccessSign) - return nil -} diff --git a/commands/service_execute.go b/commands/service_execute.go deleted file mode 100644 index 793b0c175..000000000 --- a/commands/service_execute.go +++ /dev/null @@ -1,195 +0,0 @@ -package commands - -import ( - "encoding/json" - "fmt" - - "github.com/mesg-foundation/core/protobuf/coreapi" - "github.com/mesg-foundation/core/protobuf/definition" - "github.com/mesg-foundation/core/utils/pretty" - casting "github.com/mesg-foundation/core/utils/servicecasting" - "github.com/mesg-foundation/core/x/xjson" - "github.com/mesg-foundation/core/x/xpflag" - "github.com/mesg-foundation/core/x/xstrings" - "github.com/pkg/errors" - uuid "github.com/satori/go.uuid" - "github.com/spf13/cobra" - survey "gopkg.in/AlecAivazis/survey.v1" -) - -type serviceExecuteCmd struct { - baseCmd - - executeData map[string]string - taskKey string - jsonFile string - - e ServiceExecutor -} - -func newServiceExecuteCmd(e ServiceExecutor) *serviceExecuteCmd { - c := &serviceExecuteCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "execute", - Short: "Execute a task of a service", - Example: `mesg-core service execute SERVICE`, - Args: cobra.ExactArgs(1), - PreRunE: c.preRunE, - RunE: c.runE, - }) - c.cmd.Flags().StringVarP(&c.taskKey, "task", "t", c.taskKey, "Run the given task") - c.cmd.Flags().VarP(xpflag.NewStringToStringValue(&c.executeData, nil), "data", "d", "data required to run the task") - c.cmd.Flags().StringVarP(&c.jsonFile, "json", "j", c.jsonFile, "Path to a JSON file containing the data required to run the task") - return c -} - -func (c *serviceExecuteCmd) preRunE(cmd *cobra.Command, args []string) error { - if cmd.Flag("data").Changed && cmd.Flag("json").Changed { - return errors.New("only one of '--data' or '--json' options can be specified") - } - return nil -} - -func (c *serviceExecuteCmd) runE(cmd *cobra.Command, args []string) error { - var ( - s *coreapi.Service - result *coreapi.ResultData - listenResultsC chan *coreapi.ResultData - inputData string - resultsErrC chan error - err error - ) - - pretty.Progress("Loading the service...", func() { - s, err = c.e.ServiceByID(args[0]) - }) - if err != nil { - return err - } - - if err = c.getTaskKey(s.Definition); err != nil { - return err - } - - inputData, err = c.getData(s.Definition) - if err != nil { - return err - } - pretty.Progress(fmt.Sprintf("Executing task %q...", c.taskKey), func() { - // Create an unique tag that will be used to listen to the result of this exact execution - tags := []string{uuid.NewV4().String()} - - listenResultsC, resultsErrC, err = c.e.ServiceListenResults(args[0], c.taskKey, tags) - if err != nil { - return - } - - _, err = c.e.ServiceExecuteTask(args[0], c.taskKey, inputData, tags) - }) - if err != nil { - return err - } - fmt.Printf("%s Task %q executed\n", pretty.SuccessSign, c.taskKey) - - pretty.Progress("Waiting for result...", func() { - select { - case result = <-listenResultsC: - case err = <-resultsErrC: - } - }) - if err != nil { - return err - } - if result.Error != "" { - fmt.Printf("%s Task %s failed with an error:\n%s\n", - pretty.FailSign, - pretty.Fail(result.TaskKey), - pretty.Fail(result.Error), - ) - } else { - fmt.Printf("%s Task %s succeed with output:\n%s\n", - pretty.SuccessSign, - pretty.Success(result.TaskKey), - pretty.ColorizeJSON(pretty.FgCyan, nil, false, []byte(result.OutputData)), - ) - } - return nil -} - -func (c *serviceExecuteCmd) getTaskKey(s *definition.Service) error { - keys := taskKeysFromService(s) - - if c.taskKey != "" { - if !xstrings.SliceContains(keys, c.taskKey) { - return fmt.Errorf("task %q does not exists on service", c.taskKey) - } - return nil - } - - if len(keys) == 1 { - c.taskKey = keys[0] - return nil - } - - if survey.AskOne(&survey.Select{ - Message: "Select the task to execute", - Options: keys, - }, &c.taskKey, nil) != nil { - return errors.New("no task to execute") - } - return nil -} - -func (c *serviceExecuteCmd) getData(s *definition.Service) (string, error) { - if c.jsonFile != "" { - return c.readFile() - } - - // see if task has no inputs. - noInput := false - for _, task := range s.Tasks { - if task.Key == c.taskKey { - if len(task.Inputs) == 0 { - noInput = true - } - break - } - } - - if noInput { - if len(c.executeData) > 0 { - return "", fmt.Errorf("task %q has no input but --data flag was supplied", c.taskKey) - } - return "{}", nil - } - - if c.executeData != nil { - castData, err := casting.TaskInputs(s, c.taskKey, c.executeData) - if err != nil { - return "", err - } - - b, err := json.Marshal(castData) - return string(b), err - } - - if c.jsonFile == "" { - if survey.AskOne(&survey.Input{Message: "Enter the filepath to the inputs"}, &c.jsonFile, nil) != nil { - return "", errors.New("no filepath given") - } - } - return c.readFile() -} - -func (c *serviceExecuteCmd) readFile() (string, error) { - content, err := xjson.ReadFile(c.jsonFile) - return string(content), err -} - -func taskKeysFromService(s *definition.Service) []string { - var taskKeys []string - for _, task := range s.Tasks { - taskKeys = append(taskKeys, task.Key) - } - return taskKeys -} diff --git a/commands/service_execute_test.go b/commands/service_execute_test.go deleted file mode 100644 index a3a93ab33..000000000 --- a/commands/service_execute_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package commands - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestServiceExecuteCmdFlags(t *testing.T) { - c := newServiceExecuteCmd(nil) - - flags := c.cmd.Flags() - require.Equal(t, flags.ShorthandLookup("t"), flags.Lookup("task")) - require.Equal(t, flags.ShorthandLookup("d"), flags.Lookup("data")) - require.Equal(t, flags.ShorthandLookup("j"), flags.Lookup("json")) - - flags.Set("task", "t") - require.Equal(t, "t", c.taskKey) - - flags.Set("data", "k=v") - require.Equal(t, map[string]string{"k": "v"}, c.executeData) - - flags.Set("json", "data.json") - require.Equal(t, "data.json", c.jsonFile) -} diff --git a/commands/service_init.go b/commands/service_init.go deleted file mode 100644 index b416fc1f3..000000000 --- a/commands/service_init.go +++ /dev/null @@ -1,125 +0,0 @@ -package commands - -import ( - "fmt" - "os" - - "github.com/mesg-foundation/core/utils/pretty" - "github.com/mesg-foundation/core/utils/servicetemplate" - "github.com/spf13/cobra" - survey "gopkg.in/AlecAivazis/survey.v1" -) - -type serviceInitCmd struct { - baseCmd - - templateURL string - templateName string - path string - - e ServiceExecutor -} - -// service template select options. -const ( - addMyOwn = "Add my own" - customURL = "Enter template URL" -) - -func newServiceInitCmd(e ServiceExecutor) *serviceInitCmd { - c := &serviceInitCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "init", - Short: "Initialize a service", - Long: `Initialize a service by creating a mesg.yml and Dockerfile in a dedicated directory. - -To get more information, see the page [service file from the documentation](https://docs.mesg.com/guide/service/service-file.html)`, - Example: `mesg-core service init -mesg-core service init ./PATH_TO_SERVICE -mesg-core service init --template TEMPLATE_URL`, - PreRunE: c.preRunE, - RunE: c.runE, - }) - c.cmd.Flags().StringVarP(&c.templateURL, "template", "t", c.templateURL, "Specify the template URL to use") - return c -} - -func (c *serviceInitCmd) preRunE(cmd *cobra.Command, args []string) error { - c.path = getFirstOrCurrentPath(args) - return c.getTemplateURL() -} - -func (c *serviceInitCmd) getTemplateURL() error { - if c.templateURL != "" { - c.templateName = c.templateURL - return nil - } - - // no template specify - download and select one - var ( - list []*servicetemplate.Template - err error - ) - pretty.Progress("Loading templates...", func() { - list, err = c.e.ServiceInitTemplateList() - }) - if err != nil { - return err - } - - var result string - if err := survey.AskOne(&survey.Select{ - Message: "Select a template to use", - Options: templatesToOptions(list), - }, &result, nil); err != nil { - return err - } - - if result == addMyOwn { - fmt.Println("You can create and add your own template to this list") - fmt.Println("Go to the Awesome Github to see how") - fmt.Println("https://github.com/mesg-foundation/awesome") - os.Exit(0) - } - - if result == customURL { - if err := survey.AskOne(&survey.Input{ - Message: "Enter template URL", - }, &c.templateURL, nil); err != nil { - return err - } - } - - for _, l := range list { - if result == l.String() { - c.templateURL = l.URL - c.templateName = l.Name - } - } - return nil -} - -func (c *serviceInitCmd) runE(cmd *cobra.Command, args []string) error { - var err error - pretty.Progress("Downloading template...", func() { - err = c.e.ServiceInitDownloadTemplate(&servicetemplate.Template{ - Name: c.templateName, - URL: c.templateURL, - }, c.path) - }) - if err != nil { - return err - } - fmt.Printf("%s Service initialized in %q\n", pretty.SuccessSign, c.path) - return nil -} - -func templatesToOptions(templates []*servicetemplate.Template) []string { - var options []string - for _, template := range templates { - options = append(options, template.String()) - } - options = append(options, customURL) - options = append(options, addMyOwn) - return options -} diff --git a/commands/service_init_test.go b/commands/service_init_test.go deleted file mode 100644 index 5a5f5fe75..000000000 --- a/commands/service_init_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package commands - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestServiceInitCmdFlags(t *testing.T) { - c := newServiceInitCmd(nil) - - flags := c.cmd.Flags() - require.Equal(t, flags.ShorthandLookup("t"), flags.Lookup("template")) - - flags.Set("template", "github.com/mesg-foundation/awesome") - require.Equal(t, "github.com/mesg-foundation/awesome", c.templateURL) -} diff --git a/commands/service_list.go b/commands/service_list.go deleted file mode 100644 index 89dfd9f12..000000000 --- a/commands/service_list.go +++ /dev/null @@ -1,57 +0,0 @@ -package commands - -import ( - "fmt" - "os" - "strings" - "text/tabwriter" - - "github.com/mesg-foundation/core/protobuf/coreapi" - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" -) - -type serviceListCmd struct { - baseCmd - - e ServiceExecutor -} - -// newServiceListCmd receives e to do API calls and w to output structured table logs. -func newServiceListCmd(e ServiceExecutor) *serviceListCmd { - c := &serviceListCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "list", - Short: "List all published services", - Long: `This command returns all published services with basic information. -Optionally, you can filter the services published by a specific developer: -To have more details, see the [detail command](mesg-core_service_detail.md).`, - Example: `mesg-core service list`, - Args: cobra.NoArgs, - RunE: c.runE, - }) - return c -} - -func (c *serviceListCmd) runE(cmd *cobra.Command, args []string) error { - var ( - services []*coreapi.Service - err error - ) - pretty.Progress("Listing services...", func() { - services, err = c.e.ServiceList() - }) - if err != nil { - return err - } - - w := tabwriter.NewWriter(os.Stdout, 0, 0, 4, ' ', 0) - - fmt.Fprintf(w, "HASH\tSID\tNAME\tSTATUS\t\n") - for _, s := range services { - service := s.Definition - status := strings.ToLower(s.Status.String()) - fmt.Fprintf(w, "%s\t%s\t%s\t%s\t\n", service.Hash, service.Sid, service.Name, status) - } - return w.Flush() -} diff --git a/commands/service_list_test.go b/commands/service_list_test.go deleted file mode 100644 index 7dc220c82..000000000 --- a/commands/service_list_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package commands - -import ( - "bufio" - "fmt" - "regexp" - "strings" - "testing" - - "github.com/mesg-foundation/core/protobuf/coreapi" - "github.com/mesg-foundation/core/protobuf/definition" - "github.com/stretchr/testify/require" -) - -func TestServiceList(t *testing.T) { - var ( - services = []*coreapi.Service{ - {Definition: &definition.Service{Hash: "1", Name: "a"}, Status: coreapi.Service_RUNNING}, - {Definition: &definition.Service{Hash: "2", Name: "b"}, Status: coreapi.Service_PARTIAL}, - } - m = newMockExecutor() - c = newServiceListCmd(m) - ) - - m.On("ServiceList").Return(services, nil) - - closeStd := captureStd(t) - c.cmd.Execute() - stdout, _ := closeStd() - r := bufio.NewReader(strings.NewReader(stdout)) - - for _, s := range []string{ - `Listing services\.\.\.`, - `HASH\s+SID\s+NAME\s+STATUS`, - } { - matched, err := regexp.Match(fmt.Sprintf(`^\s*%s\s*$`, s), readLine(t, r)) - require.NoError(t, err) - require.True(t, matched) - } - - for _, s := range services { - status := strings.ToLower(s.Status.String()) - pattern := fmt.Sprintf(`^\s*%s\s+%s\s+%s\s+%s\s*$`, s.Definition.Hash, s.Definition.Sid, s.Definition.Name, status) - matched, err := regexp.Match(pattern, readLine(t, r)) - require.NoError(t, err) - require.True(t, matched) - } -} diff --git a/commands/service_logs.go b/commands/service_logs.go deleted file mode 100644 index 1de719c94..000000000 --- a/commands/service_logs.go +++ /dev/null @@ -1,114 +0,0 @@ -package commands - -import ( - "fmt" - "io" - "os" - "strings" - - "github.com/mesg-foundation/core/commands/provider" - "github.com/mesg-foundation/core/service" - "github.com/mesg-foundation/core/utils/pretty" - "github.com/mesg-foundation/core/x/xsignal" - "github.com/mesg-foundation/core/x/xstrings" - "github.com/mesg-foundation/prefixer" - "github.com/spf13/cobra" -) - -type serviceLogsCmd struct { - baseCmd - - dependencies []string - - e ServiceExecutor -} - -func newServiceLogsCmd(e ServiceExecutor) *serviceLogsCmd { - c := &serviceLogsCmd{ - e: e, - } - - c.cmd = newCommand(&cobra.Command{ - Use: "logs", - Short: "Show logs of a service", - Example: `mesg-core service logs SERVICE -mesg-core service logs SERVICE --dependencies DEPENDENCY_NAME,DEPENDENCY_NAME,...`, - Args: cobra.ExactArgs(1), - RunE: c.runE, - }) - - c.cmd.Flags().StringArrayVarP(&c.dependencies, "dependencies", "d", c.dependencies, "Name of the dependency to show the logs from") - return c -} - -func (c *serviceLogsCmd) runE(cmd *cobra.Command, args []string) error { - closer, errC, err := showLogs(c.e, args[0], c.dependencies...) - if err != nil { - return err - } - defer closer() - - select { - case err := <-errC: - return err - case <-xsignal.WaitForInterrupt(): - return nil - } -} - -func showLogs(e ServiceExecutor, serviceID string, dependencies ...string) (closer func(), errC chan error, err error) { - var ( - logs []*provider.Log - ) - pretty.Progress("Loading logs...", func() { - logs, closer, errC, err = e.ServiceLogs(serviceID, dependencies...) - }) - if err != nil { - return nil, nil, err - } - - // if there was no dependencies copy all returned - // by service logs. - if len(dependencies) == 0 { - dependencies = append(dependencies, service.MainServiceKey) - for _, log := range logs { - dependencies = append(dependencies, log.Dependency) - } - } - - prefixes := dependencyPrefixes(dependencies) - - for _, log := range logs { - go prefixedCopy(os.Stdout, log.Standard, prefixes[log.Dependency]) - go prefixedCopy(os.Stderr, log.Error, prefixes[log.Dependency]) - } - - return closer, errC, nil -} - -// dependencyPrefixes returns colored dependency name prefixes. -func dependencyPrefixes(dependencies []string) map[string]string { - var ( - colors = pretty.FgColors() - prefixes = make(map[string]string, len(dependencies)) - ) - - max := xstrings.FindLongest(dependencies) - for i, dep := range dependencies { - c := colors[i%len(colors)] - prefixes[dep] = c.Sprintf("%s%s |", dep, strings.Repeat(" ", max-len(dep))) - } - - return prefixes -} - -// prefixedCopy copies src to dst by prefixing dependency key to each new line. -func prefixedCopy(dst io.Writer, src io.Reader, dep string) { - io.Copy(dst, prefixedReader(src, dep)) -} - -// prefixedReader wraps io.Reader by adding a prefix for each new line -// in the stream. -func prefixedReader(r io.Reader, prefix string) io.Reader { - return prefixer.New(r, fmt.Sprintf("%s ", prefix)) -} diff --git a/commands/service_logs_test.go b/commands/service_logs_test.go deleted file mode 100644 index 322714a1a..000000000 --- a/commands/service_logs_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package commands - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestServiceLogsCmdFlags(t *testing.T) { - c := newServiceLogsCmd(nil) - - flags := c.cmd.Flags() - require.Equal(t, flags.ShorthandLookup("d"), flags.Lookup("dependencies")) - - flags.Set("dependencies", "a") - flags.Set("dependencies", "b") - require.Equal(t, []string{"a", "b"}, c.dependencies) - -} diff --git a/commands/service_root.go b/commands/service_root.go deleted file mode 100644 index d9eda3482..000000000 --- a/commands/service_root.go +++ /dev/null @@ -1,33 +0,0 @@ -package commands - -import ( - "github.com/spf13/cobra" -) - -type rootServiceCmd struct { - baseCmd -} - -func newRootServiceCmd(e ServiceExecutor) *rootServiceCmd { - c := &rootServiceCmd{} - c.cmd = newCommand(&cobra.Command{ - Use: "service", - Short: "Manage services", - }) - - c.cmd.AddCommand( - newServiceDeployCmd(e).cmd, - newServiceValidateCmd(e).cmd, - newServiceStartCmd(e).cmd, - newServiceStopCmd(e).cmd, - newServiceDetailCmd(e).cmd, - newServiceListCmd(e).cmd, - newServiceInitCmd(e).cmd, - newServiceDeleteCmd(e).cmd, - newServiceLogsCmd(e).cmd, - newServiceDocsCmd(e).cmd, - newServiceDevCmd(e).cmd, - newServiceExecuteCmd(e).cmd, - ) - return c -} diff --git a/commands/service_start.go b/commands/service_start.go deleted file mode 100644 index 7b2f93776..000000000 --- a/commands/service_start.go +++ /dev/null @@ -1,48 +0,0 @@ -package commands - -import ( - "fmt" - - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" -) - -type serviceStartCmd struct { - baseCmd - - e ServiceExecutor -} - -func newServiceStartCmd(e ServiceExecutor) *serviceStartCmd { - c := &serviceStartCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "start SERVICE", - Short: "Start a service", - Long: "Start a service previously published services", - Example: `mesg-core service start SERVICE [SERVICE...]`, - RunE: c.runE, - Args: cobra.MinimumNArgs(1), - }) - return c -} - -func (c *serviceStartCmd) runE(cmd *cobra.Command, args []string) error { - for _, arg := range args { - var err error - // build function to avoid using arg inside progress - fn := func(serviceID string) func() { - return func() { - err = c.e.ServiceStart(serviceID) - } - }(arg) - pretty.Progress(fmt.Sprintf("Starting service %q...", arg), fn) - if err != nil { - return err - } - fmt.Printf("%s Service %q started\n", pretty.SuccessSign, arg) - if len(args) == 1 { - fmt.Printf("To see its logs, run the command:\n\tmesg-core service logs %s\n", arg) - } - } - return nil -} diff --git a/commands/service_stop.go b/commands/service_stop.go deleted file mode 100644 index 6e5556a85..000000000 --- a/commands/service_stop.go +++ /dev/null @@ -1,44 +0,0 @@ -package commands - -import ( - "fmt" - - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" -) - -type serviceStopCmd struct { - baseCmd - - e ServiceExecutor -} - -func newServiceStopCmd(e ServiceExecutor) *serviceStopCmd { - c := &serviceStopCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "stop SERVICE", - Short: "Stop a service", - Example: `mesg-core service stop SERVICE [SERVICE...]`, - RunE: c.runE, - Args: cobra.MinimumNArgs(1), - }) - return c -} - -func (c *serviceStopCmd) runE(cmd *cobra.Command, args []string) error { - for _, arg := range args { - var err error - // build function to avoid using arg inside progress - fn := func(serviceID string) func() { - return func() { - err = c.e.ServiceStop(serviceID) - } - }(arg) - pretty.Progress(fmt.Sprintf("Stopping service %q...", arg), fn) - if err != nil { - return err - } - fmt.Printf("%s Service %q stopped\n", pretty.SuccessSign, arg) - } - return nil -} diff --git a/commands/service_test.go b/commands/service_test.go deleted file mode 100644 index 4f27c5f31..000000000 --- a/commands/service_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package commands - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestRootServiceCmd(t *testing.T) { - cmd := newRootServiceCmd(nil).cmd - for _, tt := range []struct { - use string - }{ - {"deploy"}, - {"validate"}, - {"start"}, - {"stop"}, - {"detail"}, - {"list"}, - {"init"}, - {"delete"}, - {"logs"}, - {"gen-doc"}, - {"dev"}, - {"execute"}, - } { - require.Truef(t, findCommandChildByUsePrefix(cmd, tt.use), "command %q not found", tt.use) - } -} diff --git a/commands/service_validate.go b/commands/service_validate.go deleted file mode 100644 index de00e20c5..000000000 --- a/commands/service_validate.go +++ /dev/null @@ -1,46 +0,0 @@ -package commands - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -type serviceValidateCmd struct { - baseCmd - - path string - - e ServiceExecutor -} - -func newServiceValidateCmd(e ServiceExecutor) *serviceValidateCmd { - c := &serviceValidateCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "validate", - Short: "Validate a service file", - Long: `Validate a service file. Check the yml format and rules. - -All the definitions of the service file can be found in the page [Service File from the documentation](https://docs.mesg.com/guide/service/service-file.html).`, - Example: `mesg-core service validate -mesg-core service validate ./SERVICE_FOLDER`, - Args: cobra.MaximumNArgs(1), - PreRunE: c.preRunE, - RunE: c.runE, - }) - return c -} - -func (c *serviceValidateCmd) preRunE(cmd *cobra.Command, args []string) error { - c.path = getFirstOrCurrentPath(args) - return nil -} - -func (c *serviceValidateCmd) runE(cmd *cobra.Command, args []string) error { - msg, err := c.e.ServiceValidate(c.path) - if err != nil { - return err - } - fmt.Println(msg) - return nil -} diff --git a/commands/start.go b/commands/start.go deleted file mode 100644 index 9727e45ca..000000000 --- a/commands/start.go +++ /dev/null @@ -1,61 +0,0 @@ -package commands - -import ( - "fmt" - - "github.com/mesg-foundation/core/config" - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" -) - -type startCmd struct { - baseCmd - - lfv logFormatValue - llv logLevelValue - lfc bool - - e RootExecutor -} - -func newStartCmd(e RootExecutor) *startCmd { - c := &startCmd{ - lfv: logFormatValue("text"), - llv: logLevelValue("info"), - e: e, - } - c.cmd = newCommand(&cobra.Command{ - Use: "start", - Short: "Start the Core", - PreRunE: c.preRunE, - RunE: c.runE, - }) - - c.cmd.Flags().Var(&c.lfv, "log-format", "log format [text|json]") - c.cmd.Flags().Var(&c.llv, "log-level", "log level [debug|info|warn|error|fatal|panic]") - c.cmd.Flags().BoolVar(&c.lfc, "log-force-colors", false, "log force colors [false|true]") - return c -} - -func (c *startCmd) preRunE(cmd *cobra.Command, args []string) error { - cfg, err := config.Global() - if err != nil { - return err - } - - cfg.Log.Format = string(c.lfv) - cfg.Log.Level = string(c.llv) - cfg.Log.ForceColors = c.lfc - return nil -} - -func (c *startCmd) runE(cmd *cobra.Command, args []string) error { - var err error - pretty.Progress("Starting Core...", func() { err = c.e.Start() }) - if err != nil { - return err - } - - fmt.Printf("%s Core started\n", pretty.SuccessSign) - return nil -} diff --git a/commands/start_test.go b/commands/start_test.go deleted file mode 100644 index 44ffc4a6d..000000000 --- a/commands/start_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package commands - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestStartCmdRunE(t *testing.T) { - m := newMockExecutor() - c := newStartCmd(m) - - closeStd := captureStd(t) - - m.On("Start").Return(nil) - c.cmd.Execute() - - stdout, stderr := closeStd() - require.Contains(t, stdout, "Starting Core") - require.Contains(t, stdout, "Core started") - require.Empty(t, stderr) - - m.AssertExpectations(t) -} - -func TestStartCmdFlags(t *testing.T) { - c := newStartCmd(nil) - require.Equal(t, "text", c.lfv.String()) - require.Equal(t, "info", c.llv.String()) - require.Equal(t, false, c.lfc) - - require.NoError(t, c.cmd.Flags().Set("log-format", "json")) - require.Equal(t, "json", c.lfv.String()) - - require.NoError(t, c.cmd.Flags().Set("log-level", "debug")) - require.Equal(t, "debug", c.llv.String()) - - require.NoError(t, c.cmd.Flags().Set("log-force-colors", "true")) - require.Equal(t, true, c.lfc) -} diff --git a/commands/status.go b/commands/status.go deleted file mode 100644 index b024e6b34..000000000 --- a/commands/status.go +++ /dev/null @@ -1,39 +0,0 @@ -package commands - -import ( - "fmt" - - "github.com/mesg-foundation/core/container" - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" -) - -type statusCmd struct { - baseCmd - - e RootExecutor -} - -func newStatusCmd(e RootExecutor) *statusCmd { - c := &statusCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "status", - Short: "Get the Core's status", - RunE: c.runE, - }) - return c -} - -func (c *statusCmd) runE(cmd *cobra.Command, args []string) error { - status, err := c.e.Status() - if err != nil { - return err - } - - if status == container.RUNNING { - fmt.Printf("%s Core is running\n", pretty.SuccessSign) - } else { - fmt.Printf("%s Core is stopped\n", pretty.WarnSign) - } - return nil -} diff --git a/commands/status_test.go b/commands/status_test.go deleted file mode 100644 index 68025e1b0..000000000 --- a/commands/status_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package commands - -import ( - "testing" - - "github.com/mesg-foundation/core/container" -) - -func TestStatusCmdRunE(t *testing.T) { - m := newMockExecutor() - c := newStatusCmd(m) - - m.On("Status").Return(container.RUNNING, nil) - c.cmd.Execute() - - m.AssertExpectations(t) -} diff --git a/commands/stop.go b/commands/stop.go deleted file mode 100644 index 998f879d3..000000000 --- a/commands/stop.go +++ /dev/null @@ -1,33 +0,0 @@ -package commands - -import ( - "fmt" - - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" -) - -type stopCmd struct { - baseCmd - e RootExecutor -} - -func newStopCmd(e RootExecutor) *stopCmd { - c := &stopCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "stop", - Short: "Stop the Core", - RunE: c.runE, - }) - return c -} - -func (c *stopCmd) runE(cmd *cobra.Command, args []string) error { - var err error - pretty.Progress("Stopping Core...", func() { err = c.e.Stop() }) - if err != nil { - return err - } - fmt.Printf("%s Core stopped\n", pretty.SuccessSign) - return nil -} diff --git a/commands/stop_test.go b/commands/stop_test.go deleted file mode 100644 index eb4cce141..000000000 --- a/commands/stop_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package commands - -import "testing" - -func TestStopCmdRunE(t *testing.T) { - m := newMockExecutor() - c := newStopCmd(m) - - m.On("Stop").Return(nil) - c.cmd.Execute() - - m.AssertExpectations(t) -} diff --git a/commands/survey.go b/commands/survey.go deleted file mode 100644 index d6a3b75de..000000000 --- a/commands/survey.go +++ /dev/null @@ -1,21 +0,0 @@ -package commands - -import survey "gopkg.in/AlecAivazis/survey.v1" - -// askPass wraps survey.AskOne password. -func askPass(message string, response interface{}) error { - return survey.AskOne(&survey.Password{Message: message}, response, survey.MinLength(1)) -} - -// askInput wraps survey.AskOne input. -func askInput(message string, response interface{}) error { - return survey.AskOne(&survey.Input{Message: message}, response, survey.MinLength(1)) -} - -// askSelect wraps survey.AskOne select. -func askSelect(message string, options []string, response interface{}) error { - return survey.AskOne(&survey.Select{ - Message: message, - Options: options, - }, response, nil) -} diff --git a/commands/wallet_create.go b/commands/wallet_create.go deleted file mode 100644 index 5680dd7e6..000000000 --- a/commands/wallet_create.go +++ /dev/null @@ -1,43 +0,0 @@ -package commands - -import ( - "fmt" - - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" -) - -type walletCreateCmd struct { - baseWalletCmd - - e WalletExecutor -} - -func newWalletCreateCmd(e WalletExecutor) *walletCreateCmd { - c := &walletCreateCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "create", - Short: "Create a new account", - Long: "Create a new account with a passphrase", - Example: "mesg-core wallet create --no-passphrase", - PreRunE: c.preRunE, - RunE: c.runE, - }) - c.setupFlags() - return c -} - -func (c *walletCreateCmd) preRunE(cmd *cobra.Command, args []string) error { - return c.askPassphrase() -} - -func (c *walletCreateCmd) runE(cmd *cobra.Command, args []string) error { - address, err := c.e.Create(c.passphrase) - if err != nil { - return err - } - - fmt.Printf("NOTE: remember to save passphrase\n\n") - fmt.Printf("%s Account created with address %s\n", pretty.SuccessSign, pretty.Success(address)) - return nil -} diff --git a/commands/wallet_delete.go b/commands/wallet_delete.go deleted file mode 100644 index 8fac36499..000000000 --- a/commands/wallet_delete.go +++ /dev/null @@ -1,49 +0,0 @@ -package commands - -import ( - "fmt" - - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" -) - -type walletDeleteCmd struct { - baseWalletCmd - - account string - - e WalletExecutor -} - -func newWalletDeleteCmd(e WalletExecutor) *walletDeleteCmd { - c := &walletDeleteCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "delete", - Short: "Delete an account", - Long: "Delete an account from the wallet", - Example: "mesg-core wallet delete 0x0", - Args: cobra.ExactArgs(1), - PreRunE: c.preRunE, - RunE: c.runE, - }) - c.setupFlags() - return c -} - -func (c *walletDeleteCmd) preRunE(cmd *cobra.Command, args []string) error { - if err := c.askPassphrase(); err != nil { - return err - } - // TODO: if no account provided, the cli should ask to select one. - c.account = args[0] - return nil -} - -func (c *walletDeleteCmd) runE(cmd *cobra.Command, args []string) error { - account, err := c.e.Delete(c.account, c.passphrase) - if err != nil { - return err - } - fmt.Printf("%s Account %q deleted\n", pretty.SuccessSign, account) - return nil -} diff --git a/commands/wallet_export.go b/commands/wallet_export.go deleted file mode 100644 index 8c0531bd3..000000000 --- a/commands/wallet_export.go +++ /dev/null @@ -1,54 +0,0 @@ -package commands - -import ( - "encoding/json" - "fmt" - - "github.com/mesg-foundation/core/utils/pretty" - "github.com/spf13/cobra" -) - -type walletExportCmd struct { - baseWalletCmd - - address string - - e WalletExecutor -} - -func newWalletExportCmd(e WalletExecutor) *walletExportCmd { - c := &walletExportCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "export", - Short: "export an account", - Long: "export an existing account in order to backup it and import it in an other wallet", - Example: "mesg-core wallet export 0x0000000...00001", - Args: cobra.ExactArgs(1), - PreRunE: c.preRunE, - RunE: c.runE, - }) - c.setupFlags() - return c -} - -func (c *walletExportCmd) preRunE(cmd *cobra.Command, args []string) error { - if err := c.askPassphrase(); err != nil { - return err - } - // TODO: if no address provided, the cli should ask to select one. - c.address = args[0] - return nil -} - -func (c *walletExportCmd) runE(cmd *cobra.Command, args []string) error { - account, err := c.e.Export(c.address, c.passphrase) - if err != nil { - return err - } - b, err := json.Marshal(account) - if err != nil { - return err - } - fmt.Println(string(pretty.ColorizeJSON(pretty.FgCyan, nil, true, b))) - return nil -} diff --git a/commands/wallet_import.go b/commands/wallet_import.go deleted file mode 100644 index 74644b945..000000000 --- a/commands/wallet_import.go +++ /dev/null @@ -1,99 +0,0 @@ -package commands - -import ( - "encoding/json" - "fmt" - - "github.com/mesg-foundation/core/commands/provider" - "github.com/mesg-foundation/core/utils/pretty" - "github.com/mesg-foundation/core/x/xjson" - "github.com/spf13/cobra" -) - -type walletImportCmd struct { - baseWalletCmd - - privateKey string - jsonFile string - account provider.WalletEncryptedKeyJSONV3 - - e WalletExecutor -} - -func newWalletImportCmd(e WalletExecutor) *walletImportCmd { - c := &walletImportCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "import", - Short: "import an account", - Long: "import an account to wallet", - Example: "mesg-core wallet import", - PreRunE: c.preRunE, - RunE: c.runE, - }) - - c.setupFlags() - c.cmd.Flags().StringVarP(&c.privateKey, "private-key", "k", c.privateKey, "Private key to import") - c.cmd.Flags().StringVarP(&c.jsonFile, "json", "j", c.jsonFile, "Filepath to the JSON file to import") - return c -} - -func (c *walletImportCmd) preRunE(cmd *cobra.Command, args []string) error { - if c.jsonFile == "" && c.privateKey == "" { - if err := c.askImportType(); err != nil { - return err - } - } - if c.jsonFile != "" { - if err := c.readJSONFile(c.jsonFile); err != nil { - return err - } - } - return c.askPassphrase() -} - -func (c *walletImportCmd) askImportType() error { - importType := []string{ - "json file", - "private key", - } - var selectedImportType string - if err := askSelect("How to import the account:", importType, &selectedImportType); err != nil { - return err - } - if selectedImportType == importType[1] { - if err := askPass("Enter the private key to import", &c.privateKey); err != nil { - return err - } - } - if selectedImportType == importType[0] { - if err := askInput("Enter the path to the json file to import", &c.jsonFile); err != nil { - return err - } - } - return nil -} - -func (c *walletImportCmd) readJSONFile(jsonFile string) error { - content, err := xjson.ReadFile(jsonFile) - if err != nil { - return err - } - return json.Unmarshal(content, &c.account) -} - -func (c *walletImportCmd) runE(cmd *cobra.Command, args []string) error { - var ( - address string - err error - ) - if c.privateKey != "" { - address, err = c.e.ImportFromPrivateKey(c.privateKey, c.passphrase) - } else { - address, err = c.e.Import(c.account, c.passphrase) - } - if err != nil { - return err - } - fmt.Printf("%s Account imported with address %s\n", pretty.SuccessSign, address) - return nil -} diff --git a/commands/wallet_list.go b/commands/wallet_list.go deleted file mode 100644 index 36851dbe6..000000000 --- a/commands/wallet_list.go +++ /dev/null @@ -1,46 +0,0 @@ -package commands - -import ( - "fmt" - "os" - "text/tabwriter" - - "github.com/spf13/cobra" -) - -type walletListCmd struct { - baseCmd - - e WalletExecutor -} - -func newWalletListCmd(e WalletExecutor) *walletListCmd { - c := &walletListCmd{e: e} - c.cmd = newCommand(&cobra.Command{ - Use: "list", - Short: "list accounts", - Long: "list the addresses of existing accounts", - Example: "mesg-core wallet list", - RunE: c.runE, - }) - - return c -} - -func (c *walletListCmd) runE(cmd *cobra.Command, args []string) error { - accounts, err := c.e.List() - if err != nil { - return err - } - if len(accounts) == 0 { - fmt.Println("No account") - return nil - } - w := tabwriter.NewWriter(os.Stdout, 0, 0, 4, ' ', 0) - - fmt.Fprintf(w, "ID\tACCOUNT\t\n") - for i, account := range accounts { - fmt.Fprintf(w, "%d\t%s\t\n", i+1, account) - } - return w.Flush() -} diff --git a/commands/wallet_root.go b/commands/wallet_root.go deleted file mode 100644 index bf62ca595..000000000 --- a/commands/wallet_root.go +++ /dev/null @@ -1,48 +0,0 @@ -package commands - -import ( - "github.com/spf13/cobra" -) - -type rootWalletCmd struct { - baseCmd -} - -func newRootWalletCmd(e WalletExecutor) *rootWalletCmd { - c := &rootWalletCmd{} - c.cmd = newCommand(&cobra.Command{ - Use: "wallet", - Short: "Manage wallets", - }) - - c.cmd.AddCommand( - newWalletListCmd(e).cmd, - newWalletCreateCmd(e).cmd, - newWalletDeleteCmd(e).cmd, - newWalletExportCmd(e).cmd, - newWalletImportCmd(e).cmd, - ) - return c -} - -// baseWalletCmd is basic command for wallet subcommands -// that require passphrase. -type baseWalletCmd struct { - baseCmd - noPassphrase bool - passphrase string -} - -func (c *baseWalletCmd) setupFlags() { - c.cmd.Flags().BoolVarP(&c.noPassphrase, "no-passphrase", "n", c.noPassphrase, "Leave passphrase empty") - c.cmd.Flags().StringVarP(&c.passphrase, "passphrase", "p", c.passphrase, "Passphrase to encrypt the account") -} - -func (c *baseWalletCmd) askPassphrase() error { - if !c.noPassphrase && c.passphrase == "" { - if err := askPass("Enter passphrase", &c.passphrase); err != nil { - return err - } - } - return nil -} diff --git a/daemon/daemon.go b/daemon/daemon.go deleted file mode 100644 index 6ba2c12b3..000000000 --- a/daemon/daemon.go +++ /dev/null @@ -1,90 +0,0 @@ -package daemon - -import ( - "io" - "time" - - "github.com/mesg-foundation/core/config" - "github.com/mesg-foundation/core/container" - "github.com/mesg-foundation/core/x/xnet" - "github.com/mesg-foundation/core/x/xos" -) - -// Daemon is an interface that start, stop etc core as daemon. -type Daemon interface { - Start() error - Stop() error - Status() (container.StatusType, error) - Logs() (io.ReadCloser, error) -} - -// ContainerDaemon run core as container. -type ContainerDaemon struct { - c container.Container - cfg *config.Config -} - -// NewContainerDaemon creates new dameon that will be run in container. -func NewContainerDaemon(cfg *config.Config, c container.Container) *ContainerDaemon { - return &ContainerDaemon{ - c: c, - cfg: cfg, - } -} - -// Start starts the docker core. -func (d *ContainerDaemon) Start() error { - sharedNetworkID, err := d.c.SharedNetworkID() - if err != nil { - return err - } - _, err = d.c.StartService(d.buildServiceOptions(sharedNetworkID)) - return err -} - -// Stop stops the MESG Core docker container. -func (d *ContainerDaemon) Stop() error { - return d.c.StopService([]string{}) -} - -// Status returns the Status of the docker service of the daemon. -func (d *ContainerDaemon) Status() (container.StatusType, error) { - return d.c.Status([]string{}) -} - -// Logs returns the core's docker service logs. -func (d *ContainerDaemon) Logs() (io.ReadCloser, error) { - return d.c.ServiceLogs([]string{}) -} - -func (d *ContainerDaemon) buildServiceOptions(sharedNetworkID string) container.ServiceOptions { - _, port, _ := xnet.SplitHostPort(d.cfg.Server.Address) - stopGracePeriod := 60 * time.Second - return container.ServiceOptions{ - Namespace: []string{}, - Image: d.cfg.Core.Image, - Env: xos.EnvMapToSlice(d.cfg.DaemonEnv()), - Mounts: []container.Mount{ - { - Source: d.cfg.Docker.Socket, - Target: d.cfg.Docker.Socket, - Bind: true, - }, - { - Source: d.cfg.Core.Path, - Target: d.cfg.Docker.Core.Path, - Bind: true, - }, - }, - Ports: []container.Port{ - { - Target: uint32(port), - Published: uint32(port), - }, - }, - Networks: []container.Network{ - {ID: sharedNetworkID}, - }, - StopGracePeriod: &stopGracePeriod, - } -} diff --git a/daemon/daemon_test.go b/daemon/daemon_test.go deleted file mode 100644 index f2bdf9569..000000000 --- a/daemon/daemon_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package daemon - -import ( - "testing" - - "github.com/mesg-foundation/core/config" - "github.com/mesg-foundation/core/container" - "github.com/mesg-foundation/core/container/mocks" - "github.com/mesg-foundation/core/x/xnet" - "github.com/stretchr/testify/require" -) - -func TestStart(t *testing.T) { - cfg, _ := config.Global() - c := &mocks.Container{} - d := NewContainerDaemon(cfg, c) - - c.On("SharedNetworkID").Return("1", nil) - c.On("StartService", d.buildServiceOptions("1")).Return("1", nil) - require.NoError(t, d.Start()) - c.AssertExpectations(t) -} - -func TestStop(t *testing.T) { - cfg, _ := config.Global() - c := &mocks.Container{} - d := NewContainerDaemon(cfg, c) - - c.On("StopService", []string{}).Return(nil) - require.NoError(t, d.Stop()) - c.AssertExpectations(t) -} - -func TestStatus(t *testing.T) { - cfg, _ := config.Global() - c := &mocks.Container{} - d := NewContainerDaemon(cfg, c) - - c.On("Status", []string{}).Return(container.STOPPED, nil) - status, err := d.Status() - require.NoError(t, err) - require.Equal(t, container.STOPPED, status) - c.AssertExpectations(t) -} - -func TestLogs(t *testing.T) { - cfg, _ := config.Global() - c := &mocks.Container{} - d := NewContainerDaemon(cfg, c) - - c.On("ServiceLogs", []string{}).Return(nil, nil) - _, err := d.Logs() - require.NoError(t, err) - c.AssertExpectations(t) -} - -func TestBuildServiceOptions(t *testing.T) { - cfg, _ := config.Global() - c := &mocks.Container{} - d := NewContainerDaemon(cfg, c) - - spec := d.buildServiceOptions("") - require.Equal(t, []string{}, spec.Namespace) - // Make sure that the config directory is passed in parameter to write on the same folder - require.Contains(t, spec.Env, "MESG_LOG_LEVEL=info") - require.Contains(t, spec.Env, "MESG_LOG_FORMAT=text") - require.Contains(t, spec.Env, "MESG_CORE_PATH="+cfg.Docker.Core.Path) - // Ensure that the port is shared - _, port, _ := xnet.SplitHostPort(cfg.Server.Address) - require.Equal(t, spec.Ports[0].Published, uint32(port)) - require.Equal(t, spec.Ports[0].Target, uint32(port)) - // Ensure that the docker socket is shared in the core - require.Equal(t, spec.Mounts[0].Source, cfg.Docker.Socket) - require.Equal(t, spec.Mounts[0].Target, cfg.Docker.Socket) - require.True(t, spec.Mounts[0].Bind) - // Ensure that the host users folder is sync with the core - require.Equal(t, spec.Mounts[1].Source, cfg.Core.Path) - require.Equal(t, spec.Mounts[1].Target, cfg.Docker.Core.Path) - require.True(t, spec.Mounts[1].Bind) -} diff --git a/dev-cli b/dev-cli deleted file mode 100755 index ad0a92959..000000000 --- a/dev-cli +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -e - -VERSION="local" -LDFLAGS="-X 'github.com/mesg-foundation/core/version.Version=$VERSION'" - -go build -o ./bin/cli -ldflags="$LDFLAGS" interface/cli/main.go - -mesg_port=50052 -endpoint="localhost:$mesg_port" -if [[ $DOCKER_HOST != "" ]]; then - endpoint="$(docker-machine ip $(docker-machine active)):$mesg_port" -fi -MESG_CLIENT_ADDRESS=$endpoint ./bin/cli $@ diff --git a/dev-core b/dev-core index 9a26761d8..b3321bfba 100755 --- a/dev-core +++ b/dev-core @@ -10,7 +10,6 @@ LDFLAGS="-X 'github.com/mesg-foundation/core/version.Version=$VERSION'" LDFLAGS+=" -X 'github.com/mesg-foundation/core/config.EnvMarketplaceEndpoint=https://ropsten.infura.io/v3/6115ae2531f64c04a9a392cf500e5fbe'" LDFLAGS+=" -X 'github.com/mesg-foundation/core/config.EnvMarketplaceAddress=0xeCC1A867F871323350A1A89FcAf69629a2d5085e'" LDFLAGS+=" -X 'github.com/mesg-foundation/core/config.EnvMarketplaceToken=0x5861b3dc52339d4f976b7fa5d80db6cd6f477f1b'" -CLIFLAGS="" MESG_SERVICE_SERVER="core-service-server" function deleteServiceServer { @@ -42,9 +41,8 @@ docker service create -d \ --network core \ $MESG_SERVICE_SERVER -echo "compile cli and core" +echo "compile core" GOOS=linux GOARCH=amd64 go build -o ./bin/core -ldflags="$LDFLAGS" core/main.go -go build -o ./bin/cli -ldflags="$LDFLAGS" interface/cli/main.go CORE_SUM_PATH="./bin/.core.sum" touch "$CORE_SUM_PATH" @@ -78,18 +76,25 @@ if [[ ! $BINCACHED ]] || [[ ! $DOCKERCACHED ]]; then docker build -f Dockerfile.dev -t "mesg/core:$VERSION" . fi -./bin/cli stop +# docker service rm core trap onexit EXIT INT function onexit { - ./bin/cli stop deleteServiceServer + docker service rm core } -if [[ "$MESG_LOG_FORCECOLORS" = true ]]; then - CLIFLAGS+="--log-force-colors" +networkExists=$(docker network list -f name=^core$ -f driver=overlay -q) +if [ "$networkExists" == "" ]; then + docker network create --driver overlay core --label com.docker.stack.namespace=core fi - -./bin/cli start --log-level "$MESG_LOG_LEVEL" "$CLIFLAGS" -./bin/cli logs +docker service create \ + --name core \ + --tty \ + --label com.docker.stack.namespace=core --label com.docker.stack.image=mesg/core:$VERSION \ + --mount type=bind,source=/var/run/docker.sock,destination=/var/run/docker.sock --mount type=bind,source=$HOME/.mesg,destination=/mesg \ + --network core --publish 50052:50052 \ + mesg/core:$VERSION + +docker service logs --follow --raw core diff --git a/interface/cli/main.go b/interface/cli/main.go deleted file mode 100644 index 9e364ba94..000000000 --- a/interface/cli/main.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "fmt" - "os" - "time" - - "github.com/mesg-foundation/core/commands" - "github.com/mesg-foundation/core/commands/provider" - "github.com/mesg-foundation/core/config" - "github.com/mesg-foundation/core/container" - "github.com/mesg-foundation/core/daemon" - "github.com/mesg-foundation/core/protobuf/coreapi" - "github.com/mesg-foundation/core/utils/clierrors" - "github.com/mesg-foundation/core/utils/pretty" - "github.com/mesg-foundation/core/version" - "google.golang.org/grpc" - "google.golang.org/grpc/keepalive" -) - -func main() { - cfg, err := config.Global() - if err != nil { - fmt.Fprintf(os.Stderr, "%s\n", pretty.Fail(clierrors.ErrorMessage(err))) - os.Exit(1) - } - - // Keep alive prevents Docker network to drop TCP idle connections after 15 minutes. - // See: https://forum.mesg.com/t/solution-summary-for-docker-dropping-connections-after-15-min/246 - dialKeepaliveOpt := grpc.WithKeepaliveParams(keepalive.ClientParameters{ - Time: 5 * time.Minute, // 5 minutes because it's the minimun time of gRPC enforcement policy. - }) - connection, err := grpc.Dial(cfg.Client.Address, dialKeepaliveOpt, grpc.WithInsecure()) - if err != nil { - fmt.Fprintf(os.Stderr, "%s\n", pretty.Fail(clierrors.ErrorMessage(err))) - os.Exit(1) - } - - c, err := container.New() - if err != nil { - fmt.Fprintf(os.Stderr, "%s\n", pretty.Fail(clierrors.ErrorMessage(err))) - os.Exit(1) - } - - p := provider.New(coreapi.NewCoreClient(connection), daemon.NewContainerDaemon(cfg, c)) - cmd := commands.Build(p) - cmd.Version = version.Version - cmd.Short = cmd.Short + " " + version.Version - - if err := cmd.Execute(); err != nil { - fmt.Fprintf(os.Stderr, "%s\n", pretty.Fail(clierrors.ErrorMessage(err))) - os.Exit(1) - } -} diff --git a/ipfs/basic.go b/ipfs/basic.go deleted file mode 100644 index d7beb5218..000000000 --- a/ipfs/basic.go +++ /dev/null @@ -1,56 +0,0 @@ -package ipfs - -import ( - "bytes" - "context" - "encoding/json" - "io" - "mime/multipart" - "net/http" - "net/url" -) - -// AddResponse contains the response of adding a file. -type AddResponse struct { - Name string - Hash string - Bytes int64 - Size string -} - -// Add sends data from a reader to the ipfs node. -func (ipfs *IPFS) Add(name string, r io.Reader) (*AddResponse, error) { - b := new(bytes.Buffer) - w := multipart.NewWriter(b) - fw, err := w.CreateFormFile("file", name) - if err != nil { - return nil, err - } - if _, err = io.Copy(fw, r); err != nil { - return nil, err - } - w.Close() - - headers := http.Header{"Content-Type": []string{w.FormDataContentType()}} - resp, err := ipfs.post(context.Background(), "add", nil, headers, b) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var re AddResponse - if err := json.NewDecoder(resp.Body).Decode(&re); err != nil { - return nil, err - } - return &re, nil -} - -// Get retrives the file from the ipfs node. -func (ipfs *IPFS) Get(hash string) (io.Reader, error) { - query := url.Values{"arg": []string{hash}} - resp, err := ipfs.get(context.Background(), "get", query, nil) - if err != nil { - return nil, err - } - return resp.Body, nil -} diff --git a/ipfs/basic_test.go b/ipfs/basic_test.go deleted file mode 100644 index 816625639..000000000 --- a/ipfs/basic_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package ipfs - -import ( - "bytes" - "io/ioutil" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestAddURL(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assertMethodAndPath(t, r, http.MethodPost, "/add") - w.Write([]byte("{}")) - })) - defer ts.Close() - - _, err := NewClient(ts.URL).Add("", bytes.NewBuffer([]byte{'-'})) - assert.NoError(t, err) -} - -func TestAddBody(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - b, _ := ioutil.ReadAll(r.Body) - assert.Contains(t, string(b), "a-a") - w.Write([]byte("{}")) - })) - defer ts.Close() - - _, err := NewClient(ts.URL).Add("", bytes.NewBuffer([]byte("a-a"))) - assert.NoError(t, err) -} - -func TestGetURL(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assertMethodAndPath(t, r, http.MethodGet, "/get") - })) - defer ts.Close() - - _, err := NewClient(ts.URL).Get("") - assert.NoError(t, err) -} - -func TestGetQuery(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, "arg=Q", r.URL.RawQuery) - })) - defer ts.Close() - - _, err := NewClient(ts.URL).Get("Q") - assert.NoError(t, err) -} diff --git a/ipfs/client.go b/ipfs/client.go deleted file mode 100644 index 94aa52503..000000000 --- a/ipfs/client.go +++ /dev/null @@ -1,80 +0,0 @@ -// Package ipfs provides functions to handle ipfs public API. -package ipfs - -import ( - "context" - "fmt" - "io" - "net/http" - "net/url" - - "golang.org/x/net/context/ctxhttp" -) - -// DefaultEndpoint is endpoint used to access ipfs network. -const DefaultEndpoint = "http://ipfs.app.mesg.com:5001/api/v0" - -// DefaultClient is global client used for communication with ipfs network. -var DefaultClient = NewClient(DefaultEndpoint) - -// Add sends data from a reader to the ipfs node. -func Add(name string, r io.Reader) (*AddResponse, error) { return DefaultClient.Add(name, r) } - -// Get retrives the file from the ipfs node. -func Get(hash string) (io.Reader, error) { return DefaultClient.Get(hash) } - -// IPFS handles communication with ipfs network. -type IPFS struct { - client *http.Client - endpoint string -} - -// NewClient creates new IPFS client. -func NewClient(endpoint string) *IPFS { - return &IPFS{ - client: &http.Client{}, - endpoint: endpoint, - } -} - -// getAPIPath returns the versioned request path to call the api. -// It appends the query parameters to the path if they are not empty. -func (c *IPFS) getAPIPath(path string, query url.Values) string { - if query == nil { - return fmt.Sprintf("%s/%s", c.endpoint, path) - } - return fmt.Sprintf("%s/%s?%s", c.endpoint, path, query.Encode()) -} - -func (c *IPFS) get(ctx context.Context, path string, query url.Values, headers http.Header) (*http.Response, error) { - return c.do(ctx, http.MethodGet, path, query, headers, nil) -} - -func (c *IPFS) post(ctx context.Context, path string, query url.Values, headers http.Header, body io.Reader) (*http.Response, error) { - return c.do(ctx, http.MethodPost, path, query, headers, body) -} - -func (c *IPFS) do(ctx context.Context, method, path string, query url.Values, headers http.Header, body io.Reader) (*http.Response, error) { - fullPath := c.getAPIPath(path, query) - req, err := http.NewRequest(method, fullPath, body) - if err != nil { - return nil, fmt.Errorf("%s %s unknown error: %s", method, fullPath, err) - } - for key, value := range headers { - req.Header[key] = value - } - - resp, err := ctxhttp.Do(ctx, c.client, req) - if err != nil { - if err == context.DeadlineExceeded { - return nil, fmt.Errorf("%s %s i/o timeout", method, fullPath) - } - return nil, fmt.Errorf("%s %s unknown error: %s", method, fullPath, err) - } - - if resp.StatusCode != http.StatusOK { - resp.Body.Close() - return nil, fmt.Errorf("%s %s status not ok: %s", method, fullPath, resp.Status) - } - return resp, nil -} diff --git a/ipfs/client_test.go b/ipfs/client_test.go deleted file mode 100644 index 1cf1af4e2..000000000 --- a/ipfs/client_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package ipfs - -import ( - "context" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" -) - -// noop server and handler for testing -var ( - noopHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) - noopServer = httptest.NewServer(noopHandler) - - errorHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusInternalServerError) - }) - errorServer = httptest.NewServer(errorHandler) -) - -func assertMethodAndPath(t *testing.T, r *http.Request, method string, path string) { - assert.Equal(t, method, r.Method, "method not found") - assert.Containsf(t, r.URL.Path, path, "invalid url path") -} - -func TestResponseStatusNotOk(t *testing.T) { - _, err := NewClient(errorServer.URL).get(context.Background(), "/", nil, nil) - assert.Error(t, err) - assert.Contains(t, err.Error(), "status not ok") -} - -func TestDoInvalidMethod(t *testing.T) { - _, err := NewClient(noopServer.URL).do(context.Background(), "/", "/", nil, nil, nil) - assert.Error(t, err, "exptected invalid method error") -} - -func TestDoInvalidRequest(t *testing.T) { - _, err := NewClient("").do(context.Background(), "noop", "/", nil, nil, nil) - assert.Error(t, err, "exptected invalid method error") -} diff --git a/scripts/build-cli.sh b/scripts/build-cli.sh deleted file mode 100755 index 798f75e63..000000000 --- a/scripts/build-cli.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -e - -if [[ -z "$1" ]]; then - echo -e "cli version is not set, run:\n" - echo "$0 cli-version" - exit 1 -fi - -LDFLAGS="-X 'github.com/mesg-foundation/core/version.Version=$1'" -archs=(amd64 386) -oss=(linux darwin) - -for os in ${oss[*]}; do - for arch in ${archs[*]}; do - echo "Building $os $arch..." - GOOS=$os GOARCH=$arch go build -o "./bin/mesg-core-$os-$arch" -ldflags="$LDFLAGS" ./interface/cli - done -done diff --git a/scripts/build-mocks.sh b/scripts/build-mocks.sh index 58640bd70..97e8fc6df 100755 --- a/scripts/build-mocks.sh +++ b/scripts/build-mocks.sh @@ -11,6 +11,3 @@ mockery -name CommonAPIClient -dir ./internal/mocks -output ./utils/docker/mocks # generate mocks for database package. mockery -name=ServiceDB -dir ./database -output ./database/mocks - -# generate mocks for commands package. -mockery -name=Executor -dir ./commands -output ./commands/mocks diff --git a/scripts/generate-assets.sh b/scripts/generate-assets.sh deleted file mode 100755 index f600713ad..000000000 --- a/scripts/generate-assets.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -# make sure script is running inside mesg/tools container. -source $(dirname $0)/require-mesg-tools.sh - -go-bindata -o commands/provider/assets/readme_template.go -pkg assets ./commands/provider/assets/readme_template.md diff --git a/utils/clierrors/error.go b/utils/clierrors/error.go deleted file mode 100644 index 4940ad4da..000000000 --- a/utils/clierrors/error.go +++ /dev/null @@ -1,37 +0,0 @@ -package clierrors - -import ( - "fmt" - - "github.com/docker/docker/client" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -const ( - cannotReachTheCore = "Cannot reach the Core" - startCore = "Please start the core by running: mesg-core start" - cannotReachDocker = "Cannot reach Docker" - installDocker = "Please make sure Docker is running\nIf Docker is not installed on your machine you can install it here: https://store.docker.com/search?type=edition&offering=community" -) - -// ErrorMessage returns error description based on error type. -func ErrorMessage(err error) string { - switch { - case coreConnectionError(err): - return fmt.Sprintf("%s\n%s", cannotReachTheCore, startCore) - case dockerDaemonError(err): - return fmt.Sprintf("%s\n%s", cannotReachDocker, installDocker) - default: - return err.Error() - } -} - -func coreConnectionError(err error) bool { - s := status.Convert(err) - return s.Code() == codes.Unavailable -} - -func dockerDaemonError(err error) bool { - return client.IsErrConnectionFailed(err) -} diff --git a/utils/clierrors/error_test.go b/utils/clierrors/error_test.go deleted file mode 100644 index 979053cc3..000000000 --- a/utils/clierrors/error_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package clierrors - -import ( - "errors" - "testing" - - "github.com/docker/docker/client" - "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -var testCoreConnectionErr = status.Error(codes.Unavailable, "test") -var testDockerConnectionErr = client.ErrorConnectionFailed("test") - -func TestCoreConnectionError(t *testing.T) { - require.True(t, coreConnectionError(testCoreConnectionErr)) - require.False(t, coreConnectionError(nil)) - require.False(t, coreConnectionError(errors.New("test"))) -} - -func TestDockerDaemonError(t *testing.T) { - require.True(t, dockerDaemonError(testDockerConnectionErr)) - require.False(t, dockerDaemonError(nil)) - require.False(t, dockerDaemonError(errors.New("test"))) -} - -func TestErrorMessage(t *testing.T) { - require.Contains(t, ErrorMessage(testCoreConnectionErr), cannotReachTheCore) - require.Contains(t, ErrorMessage(testCoreConnectionErr), startCore) - - require.Contains(t, ErrorMessage(testDockerConnectionErr), cannotReachDocker) - require.Contains(t, ErrorMessage(testDockerConnectionErr), installDocker) - - require.Contains(t, ErrorMessage(errors.New("errorX")), "errorX") -} diff --git a/utils/pretty/pretty.go b/utils/pretty/pretty.go deleted file mode 100644 index 9c04d6c88..000000000 --- a/utils/pretty/pretty.go +++ /dev/null @@ -1,386 +0,0 @@ -package pretty - -import ( - "fmt" - "runtime" - "strings" - "time" - - "github.com/briandowns/spinner" - "github.com/fatih/color" - prettyjson "github.com/hokaccha/go-prettyjson" -) - -var ( - // spinnerCharset is the default animation. - spinnerCharset = spinner.CharSets[11] - - // spinnerDuration is the default duration for spinning. - spinnerDuration = 100 * time.Millisecond -) - -// pg is the default Pretty printer. -var pg = New() - -// Signs to print for success, warn and fail. -var ( - SuccessSign = pg.Success("✔") - WarnSign = pg.Warn("?") - FailSign = pg.Fail("⨯") -) - -// Predefined colors. -var ( - FgYellow = color.New(color.FgYellow) - FgBlue = color.New(color.FgBlue) - FgMagenta = color.New(color.FgMagenta) - FgCyan = color.New(color.FgCyan) - FgRed = color.New(color.FgRed) - FgGreen = color.New(color.FgGreen) - FgWhite = color.New(color.FgWhite) -) - -// Pretty handles pretty printing for terminal and string. -type Pretty struct { - noColor bool - noSpinner bool - - successColor *color.Color - warnColor *color.Color - failColor *color.Color - boldColor *color.Color - - *color.Color - - *spinner.Spinner - - *prettyjson.Formatter -} - -// New returns a new pretty object with all values set to default one. -func New() *Pretty { - return &Pretty{ - noColor: runtime.GOOS == "windows", - noSpinner: runtime.GOOS == "windows", - - successColor: color.New(color.FgGreen), - warnColor: color.New(color.FgYellow), - failColor: color.New(color.FgRed), - boldColor: color.New(color.Bold), - - Color: color.New(), - - Spinner: spinner.New(spinnerCharset, spinnerDuration), - - Formatter: prettyjson.NewFormatter(), - } -} - -// DisableColor disables the color output. -func (p *Pretty) DisableColor() { - p.noColor = true - p.successColor.DisableColor() - p.warnColor.DisableColor() - p.failColor.DisableColor() - p.boldColor.DisableColor() - p.Color.DisableColor() - - p.Formatter.DisabledColor = true -} - -// EnableColor enables the color output. -func (p *Pretty) EnableColor() { - // windows terminal dosen't support colors - if runtime.GOOS == "windows" { - return - } - - p.noColor = false - p.successColor.EnableColor() - p.warnColor.EnableColor() - p.failColor.EnableColor() - p.boldColor.EnableColor() - p.Color.EnableColor() - p.Formatter.DisabledColor = false -} - -// DisableSpinner disables the spinner. -func (p *Pretty) DisableSpinner() { - p.noSpinner = true -} - -// EnableSpinner enables the spinner. -func (p *Pretty) EnableSpinner() { - // windows terminal dosen't support spinner - if runtime.GOOS == "windows" { - return - } - - p.noSpinner = false -} - -// Success formats using the default formats for its operands and -// returns the resulting string with success color foreground. -// Spaces are added between operands when neither is a string. -func (p *Pretty) Success(msg string) string { - return p.successColor.Sprint(msg) -} - -// Successf formats according to a format specifier and -// returns the resulting string with success color foreground. -func (p *Pretty) Successf(format string, a ...interface{}) string { - return p.successColor.Sprintf(format, a...) -} - -// Successln formats using the default formats for its operands and -// returns the resulting string with success color foreground. -// Spaces are always added between operands and a newline is appended. -func (p *Pretty) Successln(a ...interface{}) string { - return p.successColor.Sprintln(a...) -} - -// Warn formats using the default formats for its operands and -// returns the resulting string with warn color foreground. -// Spaces are added between operands when neither is a string. -func (p *Pretty) Warn(msg string) string { - return p.warnColor.Sprint(msg) -} - -// Warnf formats according to a format specifier and -// returns the resulting string with warn color foreground. -func (p *Pretty) Warnf(format string, a ...interface{}) string { - return p.warnColor.Sprintf(format, a...) -} - -// Warnln formats using the default formats for its operands and -// returns the resulting string with warn color foreground. -// Spaces are always added between operands and a newline is appended. -func (p *Pretty) Warnln(a ...interface{}) string { - return p.warnColor.Sprintln(a...) -} - -// Fail formats using the default formats for its operands and -// returns the resulting string with fail color foreground. -// Spaces are added between operands when neither is a string. -func (p *Pretty) Fail(msg string) string { - return p.failColor.Sprint(msg) -} - -// Failf formats according to a format specifier and -// returns the resulting string with fail color foreground. -func (p *Pretty) Failf(format string, a ...interface{}) string { - return p.failColor.Sprintf(format, a...) -} - -// Failln formats using the default formats for its operands and -// returns the resulting string with fail color foreground. -// Spaces are always added between operands and a newline is appended. -func (p *Pretty) Failln(a ...interface{}) string { return p.failColor.Sprintln(a...) } - -// Bold formats using the default formats for its operands and -// returns the resulting bolded string. -// Spaces are added between operands when neither is a string. -func (p *Pretty) Bold(msg string) string { - return p.boldColor.Sprint(msg) -} - -// Boldf formats according to a format specifier and -// returns the resulting bolded string. -func (p *Pretty) Boldf(format string, a ...interface{}) string { - return p.boldColor.Sprintf(format, a...) -} - -// Boldln formats using the default formats for its operands and -// returns the resulting bolded string. -// Spaces are always added between operands and a newline is appended. -func (p *Pretty) Boldln(a ...interface{}) string { - return p.boldColor.Sprintln(a...) -} - -// Colorize formats using the default formats for its operands and -// returns the resulting string with given color. -// Spaces are added between operands when neither is a string. -func (p *Pretty) Colorize(c *color.Color, msg string) string { - if p.noColor { - return msg - } - return c.Sprint(msg) -} - -// ColorizeJSON colors keys and values of stringified JSON. On errors the original string is returned. -// If color is nil then key/value won't be colorize. -func (p *Pretty) ColorizeJSON(keyColor *color.Color, valueColor *color.Color, multiline bool, data []byte) []byte { - if p.noColor { - return data - } - - f := prettyjson.NewFormatter() - if !multiline { - f.Indent = 0 - f.Newline = "" - } - - f.KeyColor = keyColor - f.StringColor = valueColor - f.BoolColor = valueColor - f.NumberColor = valueColor - f.NullColor = valueColor - - out, err := f.Format(data) - if err != nil { - return data - } - return out -} - -// Progress prints spinner with the given message while calling fn function. -func (p *Pretty) Progress(message string, fn func()) { - if p.noSpinner { - fmt.Println(message) - fn() - return - } - - p.UseSpinner(message) - fn() - p.DestroySpinner() -} - -// UseSpinner uses spinner animation for message. -func (p *Pretty) UseSpinner(message string) { - p.Spinner.Suffix = " " + strings.TrimRight(message, "\n") - p.Spinner.Start() -} - -// DestroySpinner destroys spinner animation. -func (p *Pretty) DestroySpinner() { - p.Spinner.Stop() - p.Spinner.Suffix = "" -} - -// FgColors returns a slice with predefiend foreground color. -func (p *Pretty) FgColors() []*color.Color { - return []*color.Color{ - FgYellow, - FgBlue, - FgMagenta, - FgCyan, - FgWhite, - FgRed, - FgGreen, - } -} - -// Default returns the default Pretty printer. -func Default() *Pretty { return pg } - -// DisableColor disables the color output. -func DisableColor() { - pg.DisableColor() - SuccessSign = pg.Success("✔") - WarnSign = pg.Warn("?") - FailSign = pg.Fail("⨯") - - for _, c := range FgColors() { - c.DisableColor() - } -} - -// EnableColor enables the color output. -func EnableColor() { - pg.EnableColor() - SuccessSign = pg.Success("✔") - WarnSign = pg.Warn("?") - FailSign = pg.Fail("⨯") - - for _, c := range FgColors() { - c.EnableColor() - } -} - -// DisableSpinner disables the spinner. -func DisableSpinner() { pg.DisableSpinner() } - -// EnableSpinner enables the spinner. -func EnableSpinner() { pg.EnableSpinner() } - -// Success formats using the default formats for its operands and -// returns the resulting string with success color foreground. -// Spaces are added between operands when neither is a string. -func Success(msg string) string { return pg.Success(msg) } - -// Successf formats according to a format specifier and -// returns the resulting string with success color foreground. -func Successf(format string, a ...interface{}) string { return pg.Successf(format, a...) } - -// Successln formats using the default formats for its operands and -// returns the resulting string with success color foreground. -// Spaces are always added between operands and a newline is appended. -func Successln(a ...interface{}) string { return pg.Successln(a...) } - -// Warn formats using the default formats for its operands and -// returns the resulting string with warn color foreground. -// Spaces are added between operands when neither is a string. -func Warn(msg string) string { return pg.Warn(msg) } - -// Warnf formats according to a format specifier and -// returns the resulting string with warn color foreground. -func Warnf(format string, a ...interface{}) string { return pg.Warnf(format, a...) } - -// Warnln formats using the default formats for its operands and -// returns the resulting string with warn color foreground. -// Spaces are always added between operands and a newline is appended. -func Warnln(a ...interface{}) string { return pg.Warnln(a...) } - -// Fail formats using the default formats for its operands and -// returns the resulting string with fail color foreground. -// Spaces are added between operands when neither is a string. -func Fail(msg string) string { return pg.Fail(msg) } - -// Failf formats according to a format specifier and -// returns the resulting string with fail color foreground. -func Failf(format string, a ...interface{}) string { return pg.Failf(format, a...) } - -// Failln formats using the default formats for its operands and -// returns the resulting string with fail color foreground. -// Spaces are always added between operands and a newline is appended. -func Failln(a ...interface{}) string { return pg.Failln(a...) } - -// Bold formats using the default formats for its operands and -// returns the resulting bolded string. -// Spaces are added between operands when neither is a string. -func Bold(msg string) string { return pg.Bold(msg) } - -// Boldf formats according to a format specifier and -// returns the resulting bolded string. -func Boldf(format string, a ...interface{}) string { return pg.Boldf(format, a...) } - -// Boldln formats using the default formats for its operands and -// returns the resulting bolded string. -// Spaces are always added between operands and a newline is appended. -func Boldln(a ...interface{}) string { return pg.Boldln(a...) } - -// Colorize formats using the default formats for its operands and -// returns the resulting string with given color. -// Spaces are added between operands when neither is a string. -func Colorize(c *color.Color, msg string) string { return pg.Colorize(c, msg) } - -// Progress prints spinner with the given message while calling fn function. -func Progress(message string, fn func()) { pg.Progress(message, fn) } - -// UseSpinner uses spinner animation for message. -func UseSpinner(message string) { pg.UseSpinner(message) } - -// DestroySpinner destroys spinner animation. -func DestroySpinner() { pg.DestroySpinner() } - -// ColorizeJSON colors keys and values of stringified JSON. On errors the original string is returned. -// If color is nil then key/value won't be colorize. -func ColorizeJSON(keyColor *color.Color, valueColor *color.Color, multiline bool, data []byte) []byte { - return pg.ColorizeJSON(keyColor, valueColor, multiline, data) -} - -// FgColors returns a slice with predefiend foreground color. -func FgColors() []*color.Color { - return pg.FgColors() -} diff --git a/utils/readme/readme.go b/utils/readme/readme.go deleted file mode 100644 index 3eced7f44..000000000 --- a/utils/readme/readme.go +++ /dev/null @@ -1,27 +0,0 @@ -package readme - -import ( - "io/ioutil" - "path/filepath" - "regexp" -) - -var readmeRegexp = regexp.MustCompile(`(?i)^readme(\\.md)?`) - -// Lookup returns the content of a readme in a directory -func Lookup(path string) (string, error) { - files, err := ioutil.ReadDir(path) - if err != nil { - return "", err - } - - for _, file := range files { - if readmeRegexp.Match([]byte(file.Name())) { - readme, err := ioutil.ReadFile(filepath.Join(path, file.Name())) - if err == nil && len(readme) > 0 { - return string(readme), nil - } - } - } - return "", nil -} diff --git a/utils/readme/readme_test.go b/utils/readme/readme_test.go deleted file mode 100644 index 5d2df1022..000000000 --- a/utils/readme/readme_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package readme - -import ( - "io/ioutil" - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestLookupReadme(t *testing.T) { - tests := []struct { - file string - present bool - }{ - {file: "Readme", present: true}, - {file: "Readme.md", present: true}, - {file: "readme", present: true}, - {file: "readme.md", present: true}, - {file: "README", present: true}, - {file: "README.md", present: true}, - {file: "xxx.md", present: false}, - } - for _, test := range tests { - dir, err := ioutil.TempDir("./", "mesg") - require.NoError(t, err) - defer os.RemoveAll(dir) - err = ioutil.WriteFile(filepath.Join(dir, test.file), []byte("hello"), os.ModePerm) - require.NoError(t, err) - x, err := Lookup(dir) - require.NoError(t, err) - if test.present { - require.Equal(t, "hello", x) - } else { - require.Equal(t, "", x) - } - } -} diff --git a/utils/servicecasting/cast.go b/utils/servicecasting/cast.go deleted file mode 100644 index f837530d7..000000000 --- a/utils/servicecasting/cast.go +++ /dev/null @@ -1,112 +0,0 @@ -package casting - -import ( - "encoding/json" - "fmt" - "strconv" - "strings" - - "github.com/mesg-foundation/core/protobuf/definition" -) - -type caster func(value string) (interface{}, error) - -func castString(value string) (interface{}, error) { - return value, nil -} - -func castNumber(value string) (interface{}, error) { - i, err := strconv.ParseInt(value, 10, 64) - if err == nil { - return i, nil - } - f, err := strconv.ParseFloat(value, 64) - if err != nil { - return nil, fmt.Errorf("input %q is not a Number type", value) - } - return f, nil -} - -func castBoolean(value string) (interface{}, error) { - b, err := strconv.ParseBool(value) - if err != nil { - return nil, fmt.Errorf("input %q is not a Boolean type", value) - } - return b, nil -} - -func castObject(value string) (interface{}, error) { - var v interface{} - if err := json.Unmarshal([]byte(value), &v); err != nil { - return nil, fmt.Errorf("input %q is not a Object type", value) - } - return v, nil -} - -func castAny(value string) (interface{}, error) { - return value, nil -} - -var casters = map[string]caster{ - "String": castString, - "Number": castNumber, - "Boolean": castBoolean, - "Object": castObject, - "Any": castAny, -} - -// TaskInputs converts map[string]string to map[string]interface{} based on defined types in the service tasks map. -func TaskInputs(s *definition.Service, taskKey string, taskData map[string]string) (map[string]interface{}, error) { - for _, task := range s.Tasks { - if task.Key == taskKey { - m := make(map[string]interface{}, len(taskData)) - for key, value := range taskData { - param, err := findParam(task.Inputs, key) - if err != nil { - return nil, err - } - - newValue, err := taskInputs(value, param.Type, param.Repeated) - if err != nil { - return nil, fmt.Errorf("task %q - %s", taskKey, err) - } - if newValue != nil { - m[key] = newValue - } - } - return m, nil - } - } - return nil, fmt.Errorf("task %q does not exists", taskKey) -} - -// findParam return a param based on the key from a list of parameter -func findParam(parameters []*definition.Parameter, key string) (*definition.Parameter, error) { - for _, p := range parameters { - if p.Key == key { - return p, nil - } - } - return nil, fmt.Errorf("task input %q does not exists", key) -} - -// taskInputs converts single input based on its type. -func taskInputs(input, inputType string, repeated bool) (interface{}, error) { - c, ok := casters[inputType] - if !ok { - return nil, fmt.Errorf("input %q type %s - invalid type", input, inputType) - } - - if repeated { - var ret []interface{} - for _, value := range strings.Split(input, ",") { - v, err := c(value) - if err != nil { - return nil, fmt.Errorf("input %q - %s is not valid type of %s", input, value, inputType) - } - ret = append(ret, v) - } - return ret, nil - } - return c(input) -} diff --git a/utils/servicecasting/cast_test.go b/utils/servicecasting/cast_test.go deleted file mode 100644 index 4d23549fe..000000000 --- a/utils/servicecasting/cast_test.go +++ /dev/null @@ -1,127 +0,0 @@ -package casting - -import ( - "strings" - "testing" - - "github.com/mesg-foundation/core/protobuf/definition" - "github.com/stretchr/testify/require" -) - -func TestServiceCast(t *testing.T) { - var tests = []struct { - service *definition.Service - data map[string]string - expected map[string]interface{} - expectErr bool - }{ - { - createTestServcieWithInputs(nil), - map[string]string{}, - map[string]interface{}{}, - false, - }, - { - createTestServcieWithInputs(map[string]string{ - "a": "String", - "b": "Number", - "c": "Number", - "d": "Boolean", - "e": "repeated String", - "f": "repeated Number", - "g": "repeated Number", - "h": "repeated Boolean", - }), - map[string]string{ - "a": "_", - "b": "1", - "c": "1.1", - "d": "true", - "e": "a,b", - "f": "1,2", - "g": "1.1,2.2", - "h": "false,true", - }, - map[string]interface{}{ - "a": "_", - "b": int64(1), - "c": 1.1, - "d": true, - "e": []interface{}{"a", "b"}, - "f": []interface{}{int64(1), int64(2)}, - "g": []interface{}{1.1, 2.2}, - "h": []interface{}{false, true}, - }, - false, - }, - { - createTestServcieWithInputs(map[string]string{"a": "NoType"}), - map[string]string{"a": ""}, - map[string]interface{}{}, - true, - }, - { - createTestServcieWithInputs(map[string]string{"a": "repeated Number"}), - map[string]string{"a": "0,a"}, - map[string]interface{}{}, - true, - }, - { - createTestServcieWithInputs(map[string]string{"a": "String"}), - map[string]string{"b": "_"}, - map[string]interface{}{}, - true, - }, - { - createTestServcieWithInputs(map[string]string{"a": "Number"}), - map[string]string{"a": "_"}, - map[string]interface{}{}, - true, - }, - { - createTestServcieWithInputs(map[string]string{"a": "Boolean"}), - map[string]string{"a": "_"}, - map[string]interface{}{}, - true, - }, - { - createTestServcieWithInputs(map[string]string{"a": "Object"}), - map[string]string{"a": `{"b":1}`}, - map[string]interface{}{"a": map[string]interface{}{"b": float64(1)}}, - false, - }, - } - - for _, tt := range tests { - got, err := TaskInputs(tt.service, "test", tt.data) - if tt.expectErr { - require.Error(t, err) - } else { - require.NoError(t, err) - require.Len(t, tt.expected, len(got), "maps len are not equal") - require.Equal(t, tt.expected, got, "maps are not equal") - } - } - - // test if non-existing key returns error - _, err := TaskInputs(tests[0].service, "_", nil) - require.Error(t, err) -} - -// createTestServcieWithInputs creates test service with given inputs name and type under "test" task key. -func createTestServcieWithInputs(inputs map[string]string) *definition.Service { - s := &definition.Service{ - Tasks: []*definition.Task{ - {Key: "test"}, - }, - } - - for name, itype := range inputs { - s.Tasks[0].Inputs = append(s.Tasks[0].Inputs, &definition.Parameter{ - Key: name, - Repeated: strings.HasPrefix(itype, "repeated"), - Type: strings.TrimPrefix(itype, "repeated "), - }) - } - return s -} diff --git a/utils/servicetemplate/services.go b/utils/servicetemplate/services.go deleted file mode 100644 index 5670cead0..000000000 --- a/utils/servicetemplate/services.go +++ /dev/null @@ -1,60 +0,0 @@ -package servicetemplate - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "os" - "path/filepath" - - "github.com/mesg-foundation/core/x/xgit" - "github.com/mesg-foundation/core/x/xos" -) - -const templatesURL = "https://raw.githubusercontent.com/mesg-foundation/awesome/master/templates.json" - -// Template represents single entry on awesome github list. -type Template struct { - Name string - URL string -} - -func (s *Template) String() string { - return fmt.Sprintf("%s (%s)", s.Name, s.URL) -} - -// List returns all service templates from awesome github project. -func List() ([]*Template, error) { - resp, err := http.Get(templatesURL) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - var list []*Template - if err := json.Unmarshal(body, &list); err != nil { - return nil, err - } - return list, nil -} - -// Download download given template into dst directory. -func Download(t *Template, dst string) error { - path, err := ioutil.TempDir("", "mesg-") - if err != nil { - return err - } - defer os.RemoveAll(path) - - if err = xgit.Clone(t.URL, path); err != nil { - return err - } - - return xos.CopyDir(filepath.Join(path, "template"), dst) -} diff --git a/x/xjson/file.go b/x/xjson/file.go deleted file mode 100644 index 9b80772f3..000000000 --- a/x/xjson/file.go +++ /dev/null @@ -1,21 +0,0 @@ -package xjson - -import ( - "encoding/json" - "io/ioutil" -) - -// ReadFile reads the file named by filename and returns the contents. -// It returns error if file is not well formated json. -func ReadFile(filename string) ([]byte, error) { - content, err := ioutil.ReadFile(filename) - if err != nil { - return nil, err - } - - var raw json.RawMessage - if err := json.Unmarshal(content, &raw); err != nil { - return nil, err - } - return raw, nil -} diff --git a/x/xjson/file_test.go b/x/xjson/file_test.go deleted file mode 100644 index 1936cfdeb..000000000 --- a/x/xjson/file_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package xjson - -import ( - "encoding/json" - "io/ioutil" - "os" - "testing" -) - -const testfilenmae = "data.test" - -func TestReadFile(t *testing.T) { - if err := ioutil.WriteFile(testfilenmae, []byte("{}"), os.ModePerm); err != nil { - t.Fatalf("write error: %s", err) - } - defer os.Remove(testfilenmae) - - content, err := ReadFile(testfilenmae) - if err != nil { - t.Fatalf("read error: %s", err) - } - - if string(content) != "{}" { - t.Fatalf("invalid content - got: %s, want: {}", string(content)) - } -} - -func TestReadFileNoFile(t *testing.T) { - _, err := ReadFile("nodata.test") - if _, ok := err.(*os.PathError); !ok { - t.Fatalf("read expected os.PathError - got: %s", err) - } -} - -func TestReadFileInvalidJSON(t *testing.T) { - if err := ioutil.WriteFile(testfilenmae, []byte("{"), os.ModePerm); err != nil { - t.Fatalf("write error: %s", err) - } - defer os.Remove(testfilenmae) - - _, err := ReadFile(testfilenmae) - if _, ok := err.(*json.SyntaxError); !ok { - t.Fatalf("read expected json.SyntaxError - got: %s", err) - } -} diff --git a/x/xpflag/string_to_string.go b/x/xpflag/string_to_string.go deleted file mode 100644 index 0bab596dc..000000000 --- a/x/xpflag/string_to_string.go +++ /dev/null @@ -1,60 +0,0 @@ -package xpflag - -import ( - "bytes" - "fmt" - "strings" -) - -// StringToStringValue flag. -type StringToStringValue struct { - value *map[string]string - changed bool -} - -// NewStringToStringValue creates new flag with init map, default value. -func NewStringToStringValue(p *map[string]string, value map[string]string) *StringToStringValue { - s := new(StringToStringValue) - s.value = p - *s.value = value - return s -} - -// Set value in format: a=1,b=2 -func (s *StringToStringValue) Set(val string) error { - out := make(map[string]string) - kv := strings.SplitN(val, "=", 2) - if len(kv) != 2 { - return fmt.Errorf("%s must be formatted as key=value", val) - } - out[kv[0]] = kv[1] - if !s.changed { - *s.value = out - } else { - for k, v := range out { - (*s.value)[k] = v - } - } - s.changed = true - return nil -} - -// Type returns type of value. -func (s *StringToStringValue) Type() string { - return "key=value" -} - -func (s *StringToStringValue) String() string { - var buf bytes.Buffer - i := 0 - for k, v := range *s.value { - if i > 0 { - buf.WriteString(" ") - } - buf.WriteString(k) - buf.WriteRune('=') - buf.WriteString(v) - i++ - } - return buf.String() -} diff --git a/x/xpflag/string_to_string_test.go b/x/xpflag/string_to_string_test.go deleted file mode 100644 index d063573eb..000000000 --- a/x/xpflag/string_to_string_test.go +++ /dev/null @@ -1,147 +0,0 @@ -package xpflag - -import ( - "fmt" - "testing" - - "github.com/spf13/pflag" -) - -func setUpS2SFlagSet(s2sp *map[string]string) *pflag.FlagSet { - f := pflag.NewFlagSet("test", pflag.ContinueOnError) - f.Var(NewStringToStringValue(s2sp, nil), "s2s", "Command separated ls2st!") - return f -} -func setUpS2SFlagSetWithDefault(s2sp *map[string]string) *pflag.FlagSet { - f := pflag.NewFlagSet("test", pflag.ContinueOnError) - f.Var(NewStringToStringValue(s2sp, map[string]string{"a": "1", "b": "2"}), "s2s", "Command separated ls2st!") - return f -} -func createS2SFlag(vals map[string]string) []string { - var args []string - for k, v := range vals { - args = append(args, "--s2s="+k+"="+v) - } - return args -} -func TestEmptyS2S(t *testing.T) { - var s2s map[string]string - f := setUpS2SFlagSet(&s2s) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - s2sf := f.Lookup("s2s") - if f == nil { - t.Fatal("s2s flag not found") - } - getS2S, ok := s2sf.Value.(*StringToStringValue) - if !ok { - t.Fatal("s2s flag wrong value type") - } - if len(*getS2S.value) != 0 { - t.Fatalf("got s2s %v with len=%d but expected length=0", getS2S, len(*getS2S.value)) - } -} -func TestS2S(t *testing.T) { - var s2s map[string]string - f := setUpS2SFlagSet(&s2s) - vals := map[string]string{"a": "1", "b": "2", "d": "4", "c": "3"} - args := createS2SFlag(vals) - err := f.Parse(args) - if err != nil { - t.Fatal("expected no error; got", err) - } - - for k, v := range s2s { - if vals[k] != v { - t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v) - } - } - s2sf := f.Lookup("s2s") - if f == nil { - t.Fatal("s2s flag not found") - } - getS2S, ok := s2sf.Value.(*StringToStringValue) - if !ok { - t.Fatal("s2s flag wrong value type") - } - for k, v := range *getS2S.value { - if vals[k] != v { - t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v) - } - } -} -func TestS2SDefault(t *testing.T) { - var s2s map[string]string - f := setUpS2SFlagSetWithDefault(&s2s) - vals := map[string]string{"a": "1", "b": "2"} - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for k, v := range s2s { - if vals[k] != v { - t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v) - } - } - s2sf := f.Lookup("s2s") - if f == nil { - t.Fatal("s2s flag not found") - } - getS2S, ok := s2sf.Value.(*StringToStringValue) - if !ok { - t.Fatal("s2s flag wrong value type") - } - for k, v := range *getS2S.value { - if vals[k] != v { - t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v) - } - } -} -func TestS2SWithDefault(t *testing.T) { - var s2s map[string]string - f := setUpS2SFlagSetWithDefault(&s2s) - vals := map[string]string{"a": "1", "b": "2"} - args := createS2SFlag(vals) - err := f.Parse(args) - if err != nil { - t.Fatal("expected no error; got", err) - } - for k, v := range s2s { - if vals[k] != v { - t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v) - } - } - s2sf := f.Lookup("s2s") - if f == nil { - t.Fatal("s2s flag not found") - } - getS2S, ok := s2sf.Value.(*StringToStringValue) - if !ok { - t.Fatal("s2s flag wrong value type") - } - for k, v := range *getS2S.value { - if vals[k] != v { - t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v) - } - } -} -func TestS2SCalledTwice(t *testing.T) { - var s2s map[string]string - f := setUpS2SFlagSet(&s2s) - in := []string{"a=1", "b=3"} - expected := map[string]string{"a": "1", "b": "3"} - argfmt := "--s2s=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range s2s { - if expected[i] != v { - t.Fatalf("expected s2s[%s] to be %s but got: %s", i, expected[i], v) - } - } -}