X-Git-Url: https://scripts.mit.edu/gitweb/wizard.git/blobdiff_plain/935e6c4b0f4ecb9e55ceac39ebd6f3885a90a218..d53c7c953a65d6e57cd0031cadfc1636e64fddb0:/wizard/deploy.py diff --git a/wizard/deploy.py b/wizard/deploy.py index 4fdff7d..b1e8e6a 100644 --- a/wizard/deploy.py +++ b/wizard/deploy.py @@ -14,9 +14,11 @@ import time import traceback import shutil import errno +import pkg_resources +import urlparse import wizard -from wizard import app, git, old_log, scripts, shell, sql, util +from wizard import app, git, old_log, shell, sql, util ## -- Global Functions -- @@ -53,6 +55,11 @@ def parse_install_lines(show, versions_store, yield_errors = False, user = None) d = Deployment.parse(line) name = d.application.name except app.NoSuchApplication as e: + if not e.location: + try: + e.location = line.split(':')[0] + except IndexError: + e.location = line if yield_errors: yield e continue @@ -68,6 +75,33 @@ def parse_install_lines(show, versions_store, yield_errors = False, user = None) # yield yield d +def web(dir, url=None): + """ + Attempts to determine the URL a directory would be web-accessible at. + If ``url`` is specified, automatically use it. Returns a generator whic + produces a list of candidate urls. + """ + if url: + yield url + return + + for entry in pkg_resources.iter_entry_points("wizard.deploy.web"): + f = entry.load() + for r in f(dir): + if isinstance(r, str): + r = urlparse.urlparse(r) + yield r + + # try the environment + host = os.getenv("WIZARD_WEB_HOST") + path = os.getenv("WIZARD_WEB_PATH") + if host is not None and path is not None: + yield urlparse.ParseResult( + "http", + host, + path.rstrip('/'), + "", "", "") + ## -- Model Objects -- @decorator.decorator @@ -101,6 +135,7 @@ class Deployment(object): self._old_log = None self._dsn = None self._url = None + self._urlGen = None def invalidateCache(self): """ Invalidates all cached variables. This currently applies to @@ -143,6 +178,8 @@ class Deployment(object): elif not has_git and not has_scripts: if os.path.isfile(".scripts-version"): raise NotMigratedError(self.location) + else: + raise NotAutoinstallError(self.location) def verifyTag(self, srv_path): """ @@ -297,16 +334,23 @@ class Deployment(object): @property def url(self): """The :class:`urlparse.ParseResult` for this deployment.""" - if not self._url: - self._url = scripts.fill_url(self.location, self.application.url(self)) - if not self._url: - raise UnknownWebPath + if not self._urlGen: + self._urlGen = web(self.location, self.application.url(self)) + self.nextUrl() return self._url + def nextUrl(self): + """""" + try: + self._url = self._urlGen.next() # pylint: disable-msg=E1101 + return self._url + except StopIteration: + raise UnknownWebPath def enableOldStyleUrls(self): """ Switches to using http://user.scripts.mit.edu/~user/app URLs. No effect if they have an explicit .scripts/url override. """ + # XXX: This is pretty scripts specific self._url = scripts.fill_url(self.location, self.application.url(self), old_style = True) @staticmethod def parse(line): @@ -403,12 +447,26 @@ class ProductionCopy(Deployment): this application uses. """ self.application.remove(self, options) + def verifyDatabase(self): + """ + Checks if the autoinstall has a properly configured database. + """ + if not self.application.checkDatabase(self): + raise DatabaseVerificationError def verifyWeb(self): """ - Checks if the autoinstall is viewable from the web. + Checks if the autoinstall is viewable from the web. If you do not run + this, there is no guarantee that the url returned by this application + is the correct one. """ - if not self.application.checkWeb(self): - raise WebVerificationError + while True: + if not self.application.checkWeb(self): + try: + self.nextUrl() + except UnknownWebPath: + raise WebVerificationError + else: + break def fetch(self, path, post=None): """ Performs a HTTP request on the website. @@ -518,17 +576,21 @@ ERROR: Directory contains a .scripts directory, but not a .git directory.""" class NotAutoinstallError(Error): - """The directory was not an autoinstall, due to missing .scripts-version file.""" - #: Directory in question + """Application is not an autoinstall.""" + #: Directory of the not autoinstall dir = None def __init__(self, dir): self.dir = dir def __str__(self): return """ -ERROR: Could not find .scripts-version file. Are you sure -this is an autoinstalled application? -""" +ERROR: The directory + + %s + +does not appear to be an autoinstall. If you are in a +subdirectory of an autoinstall, you need to use the root +directory for the autoinstall.""" % self.dir class NoTagError(Error): """Deployment has a tag that does not have an equivalent in upstream repository.""" @@ -621,6 +683,15 @@ web. This may indicate that the website is behind authentication on the htaccess level. You can find the contents of the page from the debug backtraces.""" +class DatabaseVerificationError(Error): + """Could not access the database""" + def __str__(self): + return """ + +ERROR: We were not able to access the database for +this application; this probably means that your database +configuration is misconfigured.""" + class UnknownWebPath(Error): """Could not determine application's web path.""" def __str__(self): @@ -631,4 +702,3 @@ host and path were in order to perform a web request on the application. You can specify this manually using the WIZARD_WEB_HOST and WIZARD_WEB_PATH environment variables.""" -