github.com/greenboxal/deis@v1.12.1/client/deis.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"os/exec"
     7  	"strings"
     8  	"syscall"
     9  
    10  	"github.com/deis/deis/client/parser"
    11  	"github.com/deis/deis/version"
    12  	docopt "github.com/docopt/docopt-go"
    13  )
    14  
    15  // main exits with the return value of Command(os.Args[1:]), deferring all logic to
    16  // a func we can test.
    17  func main() {
    18  	os.Exit(Command(os.Args[1:]))
    19  }
    20  
    21  // Command routes deis commands to their proper parser.
    22  func Command(argv []string) int {
    23  	usage := `
    24  The Deis command-line client issues API calls to a Deis controller.
    25  
    26  Usage: deis <command> [<args>...]
    27  
    28  Auth commands::
    29  
    30    register      register a new user with a controller
    31    login         login to a controller
    32    logout        logout from the current controller
    33  
    34  Subcommands, use 'deis help [subcommand]' to learn more::
    35  
    36    apps          manage applications used to provide services
    37    ps            manage processes inside an app container
    38    config        manage environment variables that define app config
    39    domains       manage and assign domain names to your applications
    40    builds        manage builds created using 'git push'
    41    limits        manage resource limits for your application
    42    tags          manage tags for application containers
    43    releases      manage releases of an application
    44    certs         manage SSL endpoints for an app
    45  
    46    keys          manage ssh keys used for 'git push' deployments
    47    perms         manage permissions for applications
    48    git           manage git for applications
    49    users         manage users
    50  
    51  Shortcut commands, use 'deis shortcuts' to see all::
    52  
    53    create        create a new application
    54    scale         scale processes by type (web=2, worker=1)
    55    info          view information about the current app
    56    open          open a URL to the app in a browser
    57    logs          view aggregated log info for the app
    58    run           run a command in an ephemeral app container
    59    destroy       destroy an application
    60    pull          imports an image and deploys as a new release
    61  
    62  Use 'git push deis master' to deploy to an application.
    63  `
    64  	// Reorganize some command line flags and commands.
    65  	command, argv := parseArgs(argv)
    66  	// Give docopt an optional final false arg so it doesn't call os.Exit().
    67  	_, err := docopt.Parse(usage, []string{command}, false, version.Version, true, false)
    68  
    69  	if err != nil {
    70  		fmt.Fprintln(os.Stderr, err)
    71  		return 1
    72  	}
    73  
    74  	if len(argv) == 0 {
    75  		fmt.Fprintln(os.Stderr, "Usage: deis <command> [<args>...]")
    76  		return 1
    77  	}
    78  
    79  	// Dispatch the command, passing the argv through so subcommands can
    80  	// re-parse it according to their usage strings.
    81  	switch command {
    82  	case "auth":
    83  		err = parser.Auth(argv)
    84  	case "ps":
    85  		err = parser.Ps(argv)
    86  	case "apps":
    87  		err = parser.Apps(argv)
    88  	case "config":
    89  		err = parser.Config(argv)
    90  	case "domains":
    91  		err = parser.Domains(argv)
    92  	case "builds":
    93  		err = parser.Builds(argv)
    94  	case "limits":
    95  		err = parser.Limits(argv)
    96  	case "tags":
    97  		err = parser.Tags(argv)
    98  	case "releases":
    99  		err = parser.Releases(argv)
   100  	case "certs":
   101  		err = parser.Certs(argv)
   102  	case "keys":
   103  		err = parser.Keys(argv)
   104  	case "perms":
   105  		err = parser.Perms(argv)
   106  	case "git":
   107  		err = parser.Git(argv)
   108  	case "users":
   109  		err = parser.Users(argv)
   110  	case "help":
   111  		fmt.Print(usage)
   112  		return 0
   113  	case "--version":
   114  		return 0
   115  	default:
   116  		env := os.Environ()
   117  		extCmd := "deis-" + command
   118  
   119  		binary, err := exec.LookPath(extCmd)
   120  		if err != nil {
   121  			parser.PrintUsage()
   122  			return 1
   123  		}
   124  
   125  		cmdArgv := []string{extCmd}
   126  
   127  		cmdSplit := strings.Split(argv[0], command+":")
   128  
   129  		if len(cmdSplit) > 1 {
   130  			argv[0] = cmdSplit[1]
   131  		}
   132  
   133  		cmdArgv = append(cmdArgv, argv...)
   134  
   135  		err = syscall.Exec(binary, cmdArgv, env)
   136  		if err != nil {
   137  			parser.PrintUsage()
   138  			return 1
   139  		}
   140  	}
   141  	if err != nil {
   142  		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
   143  		return 1
   144  	}
   145  	return 0
   146  }
   147  
   148  // parseArgs returns the provided args with "--help" as the last arg if need be,
   149  // expands shortcuts and formats commands to be properly routed.
   150  func parseArgs(argv []string) (string, []string) {
   151  	if len(argv) == 1 {
   152  		// rearrange "deis --help" as "deis help"
   153  		if argv[0] == "--help" || argv[0] == "-h" {
   154  			argv[0] = "help"
   155  		}
   156  	}
   157  
   158  	if len(argv) >= 2 {
   159  		// Rearrange "deis help <command>" to "deis <command> --help".
   160  		if argv[0] == "help" || argv[0] == "--help" || argv[0] == "-h" {
   161  			argv = append(argv[1:], "--help")
   162  		}
   163  	}
   164  
   165  	if len(argv) > 0 {
   166  		argv[0] = replaceShortcut(argv[0])
   167  
   168  		index := strings.Index(argv[0], ":")
   169  
   170  		if index != -1 {
   171  			command := argv[0]
   172  			return command[:index], argv
   173  		}
   174  
   175  		return argv[0], argv
   176  	}
   177  
   178  	return "", argv
   179  }
   180  
   181  func replaceShortcut(command string) string {
   182  	shortcuts := map[string]string{
   183  		"create":         "apps:create",
   184  		"destroy":        "apps:destroy",
   185  		"info":           "apps:info",
   186  		"login":          "auth:login",
   187  		"logout":         "auth:logout",
   188  		"logs":           "apps:logs",
   189  		"open":           "apps:open",
   190  		"passwd":         "auth:passwd",
   191  		"pull":           "builds:create",
   192  		"register":       "auth:register",
   193  		"rollback":       "releases:rollback",
   194  		"run":            "apps:run",
   195  		"scale":          "ps:scale",
   196  		"sharing":        "perms:list",
   197  		"sharing:list":   "perms:list",
   198  		"sharing:add":    "perms:create",
   199  		"sharing:remove": "perms:delete",
   200  		"whoami":         "auth:whoami",
   201  	}
   202  
   203  	expandedCommand := shortcuts[command]
   204  	if expandedCommand == "" {
   205  		return command
   206  	}
   207  
   208  	return expandedCommand
   209  }