github.com/naphatkrit/deis@v1.12.3/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 }