]> scripts.mit.edu Git - wizard.git/blobdiff - wizard/deploy.py
Fix entry point name in deploy.web.
[wizard.git] / wizard / deploy.py
index 4fdff7d5dde202d63fcfbc4fa769ebd6f4425eb1..b1e8e6a9d55d9663f9a2e7857056f180754de461 100644 (file)
@@ -14,9 +14,11 @@ import time
 import traceback
 import shutil
 import errno
 import traceback
 import shutil
 import errno
+import pkg_resources
+import urlparse
 
 import wizard
 
 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 --
 
 
 ## -- 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:
             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
             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
 
         # 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
 ## -- Model Objects --
 
 @decorator.decorator
@@ -101,6 +135,7 @@ class Deployment(object):
         self._old_log = None
         self._dsn = None
         self._url = None
         self._old_log = None
         self._dsn = None
         self._url = None
+        self._urlGen = None
     def invalidateCache(self):
         """
         Invalidates all cached variables.  This currently applies to
     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)
             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):
         """
 
     def verifyTag(self, srv_path):
         """
@@ -297,16 +334,23 @@ class Deployment(object):
     @property
     def url(self):
         """The :class:`urlparse.ParseResult` for this deployment."""
     @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
         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.
         """
     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):
         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)
         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):
         """
     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.
     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):
 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 """
 
     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."""
 
 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."""
 
 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):
 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."""
 on the application.  You can specify this manually using
 the WIZARD_WEB_HOST and WIZARD_WEB_PATH environment
 variables."""
-