@@ -92,11 +92,30 @@ def __init__(self):
9292 self .cookies .clear_expired_cookies ()
9393 self .cookies .save ()
9494
95+ @property
96+ def app (self ):
97+ """Retrieve the application's name."""
98+ try :
99+ return self ._get_name_from_git_remote (self .git_root ())
100+ except EnvironmentError :
101+ return os .path .basename (os .getcwd ())
102+
103+ def is_git_app (self ):
104+ """Determines if this app is a git repository. This is important in special cases
105+ where we need to know whether or not we should use Deis' automatic app name
106+ generator, for example.
107+ """
108+ try :
109+ self .git_root ()
110+ return True
111+ except EnvironmentError :
112+ return False
113+
95114 def git_root (self ):
96115 """
97- Return the absolute path from the git repository root
116+ Returns the absolute path from the git repository root.
98117
99- If no git repository exists, raise an EnvironmentError
118+ If no git repository exists, raises an EnvironmentError.
100119 """
101120 try :
102121 git_root = subprocess .check_output (
@@ -106,15 +125,13 @@ def git_root(self):
106125 raise EnvironmentError ('Current directory is not a git repository' )
107126 return git_root
108127
109- def get_app (self ):
128+ def _get_name_from_git_remote (self , git_root ):
110129 """
111- Return the application name for the current directory
130+ Retrieves the application name from a git repository root.
112131
113132 The application is determined by parsing `git remote -v` output.
114- If no application is found, raise an EnvironmentError.
133+ If no application is found, raises an EnvironmentError.
115134 """
116- git_root = self .git_root ()
117- # try to match a deis remote
118135 remotes = subprocess .check_output (['git' , 'remote' , '-v' ],
119136 cwd = git_root )
120137 m = re .search (r'^deis\W+(?P<url>\S+)\W+\(' , remotes , re .MULTILINE )
@@ -127,8 +144,6 @@ def get_app(self):
127144 raise EnvironmentError ("Could not parse: {url}" .format (** locals ()))
128145 return m .groupdict ()['app' ]
129146
130- app = property (get_app )
131-
132147 def request (self , * args , ** kwargs ):
133148 """
134149 Issue an HTTP request with proper cookie handling including
@@ -391,19 +406,13 @@ def apps_create(self, args):
391406 --cluster=CLUSTER target cluster to host application [default: dev]
392407 --no-remote do not create a 'deis' git remote
393408 """
394- try :
395- self ._session .git_root () # check for a git repository
396- except EnvironmentError :
397- print ('No git repository found, use `git init` to create one' )
398- sys .exit (1 )
399- try :
400- self ._session .get_app ()
401- print ('Deis remote already exists' )
402- sys .exit (1 )
403- except EnvironmentError :
404- pass
405409 body = {}
406- app_name = args .get ('<id>' )
410+ app_name = None
411+ if not self ._session .is_git_app ():
412+ app_name = self ._session .app
413+ # prevent app name from being reset to None
414+ if args .get ('<id>' ):
415+ app_name = args .get ('<id>' )
407416 if app_name :
408417 body .update ({'id' : app_name })
409418 cluster = args .get ('--cluster' )
@@ -423,8 +432,11 @@ def apps_create(self, args):
423432 data = response .json ()
424433 app_id = data ['id' ]
425434 print ("done, created {}" .format (app_id ))
426- # add a git remote
427- # TODO: retrieve the hostname from service discovery
435+ # set a git remote if necessary
436+ try :
437+ self ._session .git_root ()
438+ except EnvironmentError :
439+ return
428440 hostname = urlparse .urlparse (self ._settings ['controller' ]).netloc .split (':' )[0 ]
429441 git_remote = "ssh://git@{hostname}:2222/{app_id}.git" .format (** locals ())
430442 if args .get ('--no-remote' ):
@@ -476,9 +488,9 @@ def apps_destroy(self, args):
476488 if response .status_code in (requests .codes .no_content , # @UndefinedVariable
477489 requests .codes .not_found ): # @UndefinedVariable
478490 print ('done in {}s' .format (int (time .time () - before )))
479- # If the requested app is in the current dir, delete the git remote
480491 try :
481- if app == self ._session .app :
492+ # If the requested app is a heroku app, delete the git remote
493+ if self ._session .is_git_app ():
482494 subprocess .check_call (
483495 ['git' , 'remote' , 'rm' , 'deis' ],
484496 stdout = subprocess .PIPE , stderr = subprocess .PIPE )
@@ -729,9 +741,19 @@ def builds(self, args):
729741
730742 def builds_create (self , args ):
731743 """
732- Create a new build of an application
744+ Creates a new build of an application. Imports an <image> and deploys it to Deis
745+ as a new release.
733746
734747 Usage: deis builds:create <image> [--app=<app>]
748+
749+ Arguments:
750+ <image>
751+ A fully-qualified docker image, either from DockerHub (e.g. deis/example-go)
752+ or from an in-house registry (e.g. myregistry.example.com:5000/example-go).
753+
754+ Options:
755+ --app=<app>
756+ The uniquely identifiable name for the application.
735757 """
736758 app = args .get ('--app' )
737759 if not app :
@@ -1178,12 +1200,13 @@ def ps_scale(self, args):
11781200 """
11791201 app = args .get ('--app' )
11801202 if not app :
1181- app = self ._session .get_app ()
1203+ app = self ._session .app
11821204 body = {}
11831205 for type_num in args .get ('<type=num>' ):
11841206 typ , count = type_num .split ('=' )
11851207 body .update ({typ : int (count )})
1186- print ('Scaling processes... but first, coffee!' )
1208+ sys .stdout .write ('Scaling processes... but first, coffee!\n ' )
1209+ sys .stdout .flush ()
11871210 try :
11881211 progress = TextProgress ()
11891212 progress .start ()
@@ -1195,7 +1218,7 @@ def ps_scale(self, args):
11951218 progress .cancel ()
11961219 progress .join ()
11971220 if response .status_code == requests .codes .no_content : # @UndefinedVariable
1198- print ('done in {}s\n ' .format (int (time .time () - before )))
1221+ print ('done in {}s' .format (int (time .time () - before )))
11991222 self .ps_list ({}, app )
12001223 else :
12011224 raise ResponseError (response )
@@ -1449,7 +1472,7 @@ def releases_list(self, args):
14491472 data = response .json ()
14501473 for item in data ['results' ]:
14511474 item ['created' ] = readable_datetime (item ['created' ])
1452- print ("v{version:<6} {created:<33 } {summary}" .format (** item ))
1475+ print ("v{version:<6} {created:<24 } {summary}" .format (** item ))
14531476 else :
14541477 raise ResponseError (response )
14551478
@@ -1470,9 +1493,18 @@ def releases_rollback(self, args):
14701493 else :
14711494 body = {}
14721495 url = "/api/apps/{app}/releases/rollback" .format (** locals ())
1473- response = self ._dispatch ('post' , url , json .dumps (body ))
1474- if response .status_code == requests .codes .created :
1475- print (response .json ())
1496+ sys .stdout .write ('Rolling back to v{version}... ' .format (** locals ()))
1497+ sys .stdout .flush ()
1498+ try :
1499+ progress = TextProgress ()
1500+ progress .start ()
1501+ response = self ._dispatch ('post' , url , json .dumps (body ))
1502+ finally :
1503+ progress .cancel ()
1504+ progress .join ()
1505+ if response .status_code == requests .codes .created : # @UndefinedVariable
1506+ new_version = response .json ()['version' ]
1507+ print ("done, v{}" .format (new_version ))
14761508 else :
14771509 raise ResponseError (response )
14781510
@@ -1499,6 +1531,7 @@ def shortcuts(self, args):
14991531 ('register' , 'auth:register' ),
15001532 ('login' , 'auth:login' ),
15011533 ('logout' , 'auth:logout' ),
1534+ ('pull' , 'builds:create' ),
15021535 ('scale' , 'ps:scale' ),
15031536 ('rollback' , 'releases:rollback' ),
15041537 ('sharing' , 'perms:list' ),
0 commit comments