diff --git a/CHANGELOG.md b/CHANGELOG.md index a5814e7..d737c3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## 1.7.0 (14.01.2021) +- features + - add magento command (bin/magento) + - add magerun2 command + ## 1.6.3 (13.01.2021) - bugfix - remove jumper before install it diff --git a/Readme.md b/Readme.md index 408fc16..d11dcfc 100644 --- a/Readme.md +++ b/Readme.md @@ -1,12 +1,12 @@ # JUMPER -This tool has been created for helping developers out with daily docker routines. Once you configured the jumper file for a project, you can call easily run basic docker commands for any registered project and jump into main docker container using just `jumper b`. +This tool has been created for helping developers out with daily docker routines. Once you configured the jumper file for a project, you can call easily run basic docker commands for any registered project and jump into main docker container using just `jumper sh`. I was inspired by [Mark's Shust](https://github.com/markshust/docker-magento) solutution for M2. Many thanks to Mark from my side for his ideas. [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/asannikov/jumper/blob/master/LICENSE) [![Build Status](https://travis-ci.com/asannikov/jumper.svg?branch=master)](https://travis-ci.com/asannikov/jumper) -[![Release](https://img.shields.io/badge/release-1.6.3-brightgreen.svg)](https://github.com/asannikov/jumper/releases/tag/v1.6.3) +[![Release](https://img.shields.io/badge/release-1.6.3-brightgreen.svg)](https://github.com/asannikov/jumper/releases/tag/v1.7.0) It was not tested on Windows. @@ -102,7 +102,7 @@ Every stable release has attached sources for "linux/amd64", "linux/386", "darwi For example: ``` -https://github.com/asannikov/jumper/releases/tag/v1.6.3 +https://github.com/asannikov/jumper/releases/tag/v1.7.0 ``` Find related source there and download it. Now you can place use source at any place you want on your machine or make it global in a standard way. @@ -149,14 +149,14 @@ implemented commands: # Project config example - jumper.json ``` { - "name": "Project Name", - "main_container": "php_container", - "start_command": "docker-compose up -d", - "path": "/var/www/src", - "xdebug_location": "local", - "xdebug_path_cli": "/path/to/project/config/xdebug_cli.ini", - "xdebug_path_fpm": "/path/to/project/config/xdebug_fpm.ini", - "shell": "bash" + "name": "Project Name", + "main_container": "php_container", // container, where mostly you are working + "start_command": "docker-compose up -d", // standard project run + "path": "/var/www/src", // path to mounted project + "xdebug_location": "local", // Possible values: local and docker. Jumper will look for the xdebug file locally if was set "local" + "xdebug_path_cli": "/path/to/project/config/xdebug_cli.ini", // absolute path to xdebug config locally or in docker + "xdebug_path_fpm": "/path/to/project/config/xdebug_fpm.ini", // absolute path to xdebug config locally or in docker + "shell": "bash" // shell by default } ``` diff --git a/app/bash/bash.go b/app/bash/bash.go index 54c9d5c..00eb706 100644 --- a/app/bash/bash.go +++ b/app/bash/bash.go @@ -9,9 +9,13 @@ import ( "strings" ) +// Bash is an object for working with Cli +type Bash struct { +} + // GetCommandLocation get command locaton in docker container // Use it for detect commad location in related container -func GetCommandLocation() func(string, string) (string, error) { +func (b Bash) GetCommandLocation() func(string, string) (string, error) { return func(containerName string, command string) (string, error) { if len(containerName) == 0 { return "", errors.New("Container is not defined") diff --git a/app/command/magento.go b/app/command/magento.go new file mode 100644 index 0000000..c206a33 --- /dev/null +++ b/app/command/magento.go @@ -0,0 +1,189 @@ +package command + +import ( + "bufio" + "errors" + "fmt" + "io" + "os" + "os/exec" + "strings" + + "github.com/urfave/cli/v2" +) + +type magentoGlobalConfig interface { + SaveContainerNameToProjectConfig(string) error + GetProjectMainContainer() string + SaveDockerProjectPath(string) error + GetProjectDockerPath() string +} + +type magentoDialog interface { + SetMainContaner([]string) (int, string, error) + DockerProjectPath(string) (string, error) +} + +type magentoBash interface { + GetCommandLocation() func(string, string) (string, error) +} + +// CallMagentoCommand runs copyright dialog +func CallMagentoCommand(initf func(bool) string, cfg magentoGlobalConfig, d magentoDialog, clist containerlist, bash magentoBash) *cli.Command { + return &cli.Command{ + Name: "magento", + Aliases: []string{"m"}, + Subcommands: []*cli.Command{ + { + Name: "bin/magento", + Aliases: []string{"bm"}, + Action: func(c *cli.Context) error { + initf(true) + + var err error + var cl []string + + if cl, err = clist.GetContainerList(); err != nil { + return err + } + + if err = defineProjectMainContainer(cfg, d, cl); err != nil { + return err + } + + if err = defineProjectDockerPath(cfg, d, "/var/www/html/"); err != nil { + return err + } + + paths := []string{ + "bin/magento", + "html/bin/magento", + "source/bin/magento", + "src/bin/magento", + } + + var magentoBinSource string + var status bool + for _, path := range paths { + p := strings.TrimRight(cfg.GetProjectDockerPath(), string(os.PathSeparator)) + string(os.PathSeparator) + path + + if status, err = checkMagentoBin(cfg.GetProjectMainContainer(), p); err != nil { + return err + } + + if status { + magentoBinSource = p + break + } + } + + if magentoBinSource == "" { + return fmt.Errorf("Cannot find magento root folder. Searched for: %s", paths) + } + + var args []string + + args = append(args, []string{"exec", "-it", cfg.GetProjectMainContainer(), magentoBinSource}...) + args = append(args, c.Args().Slice()...) + + cmd := exec.Command("docker", args...) + + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + fmt.Printf("\ncommand: %s\n\n", "docker "+strings.Join(args, " ")) + + return cmd.Run() + }, + }, + { + Name: "magerun", + Aliases: []string{"mr"}, + Action: func(c *cli.Context) error { + initf(true) + + var err error + var cl []string + + if cl, err = clist.GetContainerList(); err != nil { + return err + } + + if err = defineProjectMainContainer(cfg, d, cl); err != nil { + return err + } + + b := bash.GetCommandLocation() + + var mrPath string + + if mrPath, err = b(cfg.GetProjectMainContainer(), "n98-magerun2.phar"); err != nil { + return err + } + + var args []string + + args = append(args, []string{"exec", "-it", cfg.GetProjectMainContainer(), mrPath}...) + args = append(args, c.Args().Slice()...) + + cmd := exec.Command("docker", args...) + + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + fmt.Printf("\ncommand: %s\n\n", "docker "+strings.Join(args, " ")) + + return cmd.Run() + }, + }, + }, + } +} + +func checkMagentoBin(containerName string, magentoBin string) (bool, error) { + if len(containerName) == 0 { + return false, errors.New("Container is not defined") + } + + if len(magentoBin) == 0 { + return false, errors.New("bin/magento is not defined") + } + + var args = []string{"exec", "-i", containerName, "sh"} + + cmd := exec.Command("docker", args...) + + r, w := io.Pipe() + + cmd.Stdout = w + cmd.Stderr = w + + var stdin io.WriteCloser + var err error + + if stdin, err = cmd.StdinPipe(); err != nil { + return false, fmt.Errorf("error when piping stdin: %w", err) + } + + defer stdin.Close() + + scanMergedOut := bufio.NewScanner(r) + + fmt.Fprintln(stdin, `[ -f "`+magentoBin+`" ] && echo "yes" || echo "no"`) + + if err = cmd.Start(); err != nil { + return false, fmt.Errorf("Cannot start command: %w", err) + } + + if !scanMergedOut.Scan() { + return false, errors.New("nothing found in Scanner output") + } + + if scanMergedOut.Err() != nil { + return false, fmt.Errorf("error while reading scanMergedOut: %s", scanMergedOut.Err()) + } + + return strings.Trim(string(scanMergedOut.Bytes()), " ") == "yes", nil +} diff --git a/app/commands.go b/app/commands.go index df5ca08..8fdf6a8 100644 --- a/app/commands.go +++ b/app/commands.go @@ -13,7 +13,9 @@ import ( func commandList(c *config.Config, d *dialog.Dialog, initf func(bool) string) []*cli.Command { - getCommandLocationF := bash.GetCommandLocation() + b := bash.Bash{} + + getCommandLocationF := b.GetCommandLocation() dck := docker.GetDockerInstance() @@ -83,5 +85,6 @@ func commandList(c *config.Config, d *dialog.Dialog, initf func(bool) string) [] command.ShellCommand(initf, c, d), // docker pull https://docs.docker.com/engine/api/sdk/examples/ + command.CallMagentoCommand(initf, c, d, dockerDialog, b), } } diff --git a/main.go b/main.go index f2b13fa..639707e 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,7 @@ import ( "github.com/urfave/cli/v2" ) -const version = "1.6.3" +const version = "1.7.0" func main() {