aboutsummaryrefslogtreecommitdiffstats
path: root/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/baseweb.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/baseweb.py')
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/baseweb.py607
1 files changed, 0 insertions, 607 deletions
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/baseweb.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/baseweb.py
deleted file mode 100644
index 9fe5e7fc..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/baseweb.py
+++ /dev/null
@@ -1,607 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-import os, weakref
-
-from zope.interface import implements
-from twisted.python import log
-from twisted.application import strports, service
-from twisted.internet import defer
-from twisted.web import server, distrib, static
-from twisted.spread import pb
-from twisted.web.util import Redirect
-from buildbot import config
-from buildbot.interfaces import IStatusReceiver
-from buildbot.status.web.base import StaticFile, createJinjaEnv
-from buildbot.status.web.feeds import Rss20StatusResource, \
- Atom10StatusResource
-from buildbot.status.web.waterfall import WaterfallStatusResource
-from buildbot.status.web.console import ConsoleStatusResource
-from buildbot.status.web.olpb import OneLinePerBuild
-from buildbot.status.web.grid import GridStatusResource
-from buildbot.status.web.grid import TransposedGridStatusResource
-from buildbot.status.web.changes import ChangesResource
-from buildbot.status.web.builder import BuildersResource
-from buildbot.status.web.buildstatus import BuildStatusStatusResource
-from buildbot.status.web.slaves import BuildSlavesResource
-from buildbot.status.web.status_json import JsonStatusResource
-from buildbot.status.web.about import AboutBuildbot
-from buildbot.status.web.authz import Authz
-from buildbot.status.web.auth import AuthFailResource,AuthzFailResource, LoginResource, LogoutResource
-from buildbot.status.web.root import RootPage
-from buildbot.status.web.users import UsersResource
-from buildbot.status.web.change_hook import ChangeHookResource
-from twisted.cred.portal import IRealm, Portal
-from twisted.cred import strcred
-from twisted.cred.checkers import ICredentialsChecker
-from twisted.cred.credentials import IUsernamePassword
-from twisted.web import resource, guard
-
-# this class contains the WebStatus class. Basic utilities are in base.py,
-# and specific pages are each in their own module.
-
-class WebStatus(service.MultiService):
- implements(IStatusReceiver)
- # TODO: IStatusReceiver is really about things which subscribe to hear
- # about buildbot events. We need a different interface (perhaps a parent
- # of IStatusReceiver) for status targets that don't subscribe, like the
- # WebStatus class. buildbot.master.BuildMaster.loadConfig:737 asserts
- # that everything in c['status'] provides IStatusReceiver, but really it
- # should check that they provide IStatusTarget instead.
-
- """
- The webserver provided by this class has the following resources:
-
- /waterfall : the big time-oriented 'waterfall' display, with links
- to individual changes, builders, builds, steps, and logs.
- A number of query-arguments can be added to influence
- the display.
- /rss : a rss feed summarizing all failed builds. The same
- query-arguments used by 'waterfall' can be added to
- influence the feed output.
- /atom : an atom feed summarizing all failed builds. The same
- query-arguments used by 'waterfall' can be added to
- influence the feed output.
- /grid : another summary display that shows a grid of builds, with
- sourcestamps on the x axis, and builders on the y. Query
- arguments similar to those for the waterfall can be added.
- /tgrid : similar to the grid display, but the commits are down the
- left side, and the build hosts are across the top.
- /builders/BUILDERNAME: a page summarizing the builder. This includes
- references to the Schedulers that feed it,
- any builds currently in the queue, which
- buildslaves are designated or attached, and a
- summary of the build process it uses.
- /builders/BUILDERNAME/builds/NUM: a page describing a single Build
- /builders/BUILDERNAME/builds/NUM/steps/STEPNAME: describes a single step
- /builders/BUILDERNAME/builds/NUM/steps/STEPNAME/logs/LOGNAME: a StatusLog
- /builders/_all/{force,stop}: force a build/stop building on all builders.
- /buildstatus?builder=...&number=...: an embedded iframe for the console
- /changes : summarize all ChangeSources
- /changes/CHANGENUM: a page describing a single Change
- /buildslaves : list all BuildSlaves
- /buildslaves/SLAVENAME : describe a single BuildSlave
- /one_line_per_build : summarize the last few builds, one line each
- /one_line_per_build/BUILDERNAME : same, but only for a single builder
- /about : describe this buildmaster (Buildbot and support library versions)
- /change_hook[/DIALECT] : accepts changes from external sources, optionally
- choosing the dialect that will be permitted
- (i.e. github format, etc..)
-
- and more! see the manual.
-
-
- All URLs for pages which are not defined here are used to look
- for files in PUBLIC_HTML, which defaults to BASEDIR/public_html.
- This means that /robots.txt or /favicon.ico can be placed in
- that directory
-
- This webserver uses the jinja2 template system to generate the web pages
- (see http://jinja.pocoo.org/2/) and by default loads pages from the
- buildbot.status.web.templates package. Any file here can be overridden by placing
- a corresponding file in the master's 'templates' directory.
-
- The main customization points are layout.html which loads style sheet
- (css) and provides header and footer content, and root.html, which
- generates the root page.
-
- All of the resources provided by this service use relative URLs to reach
- each other. The only absolute links are the c['titleURL'] links at the
- top and bottom of the page, and the buildbot home-page link at the
- bottom.
-
- Buildbot uses some generic classes to identify the type of object, and
- some more specific classes for the various kinds of those types. It does
- this by specifying both in the class attributes where applicable,
- separated by a space. It is important that in your CSS you declare the
- more generic class styles above the more specific ones. For example,
- first define a style for .Event, and below that for .SUCCESS
-
- The following CSS class names are used:
- - Activity, Event, BuildStep, LastBuild: general classes
- - waiting, interlocked, building, offline, idle: Activity states
- - start, running, success, failure, warnings, skipped, exception:
- LastBuild and BuildStep states
- - Change: box with change
- - Builder: box for builder name (at top)
- - Project
- - Time
-
- """
-
- # we are not a ComparableMixin, and therefore the webserver will be
- # rebuilt every time we reconfig. This is because WebStatus.putChild()
- # makes it too difficult to tell whether two instances are the same or
- # not (we'd have to do a recursive traversal of all children to discover
- # all the changes).
-
- def __init__(self, http_port=None, distrib_port=None, allowForce=None,
- public_html="public_html", site=None, numbuilds=20,
- num_events=200, num_events_max=None, auth=None,
- order_console_by_time=False, changecommentlink=None,
- revlink=None, projects=None, repositories=None,
- authz=None, logRotateLength=None, maxRotatedFiles=None,
- change_hook_dialects = {}, provide_feeds=None, jinja_loaders=None,
- change_hook_auth=None):
- """Run a web server that provides Buildbot status.
-
- @type http_port: int or L{twisted.application.strports} string
- @param http_port: a strports specification describing which port the
- buildbot should use for its web server, with the
- Waterfall display as the root page. For backwards
- compatibility this can also be an int. Use
- 'tcp:8000' to listen on that port, or
- 'tcp:12345:interface=127.0.0.1' if you only want
- local processes to connect to it (perhaps because
- you are using an HTTP reverse proxy to make the
- buildbot available to the outside world, and do not
- want to make the raw port visible).
-
- @type distrib_port: int or L{twisted.application.strports} string
- @param distrib_port: Use this if you want to publish the Waterfall
- page using web.distrib instead. The most common
- case is to provide a string that is an absolute
- pathname to the unix socket on which the
- publisher should listen
- (C{os.path.expanduser(~/.twistd-web-pb)} will
- match the default settings of a standard
- twisted.web 'personal web server'). Another
- possibility is to pass an integer, which means
- the publisher should listen on a TCP socket,
- allowing the web server to be on a different
- machine entirely. Both forms are provided for
- backwards compatibility; the preferred form is a
- strports specification like
- 'unix:/home/buildbot/.twistd-web-pb'. Providing
- a non-absolute pathname will probably confuse
- the strports parser.
-
- @param allowForce: deprecated; use authz instead
- @param auth: deprecated; use with authz
-
- @param authz: a buildbot.status.web.authz.Authz instance giving the authorization
- parameters for this view
-
- @param public_html: the path to the public_html directory for this display,
- either absolute or relative to the basedir. The default
- is 'public_html', which selects BASEDIR/public_html.
-
- @type site: None or L{twisted.web.server.Site}
- @param site: Use this if you want to define your own object instead of
- using the default.`
-
- @type numbuilds: int
- @param numbuilds: Default number of entries in lists at the /one_line_per_build
- and /builders/FOO URLs. This default can be overriden both programatically ---
- by passing the equally named argument to constructors of OneLinePerBuildOneBuilder
- and OneLinePerBuild --- and via the UI, by tacking ?numbuilds=xy onto the URL.
-
- @type num_events: int
- @param num_events: Default number of events to show in the waterfall.
-
- @type num_events_max: int
- @param num_events_max: The maximum number of events that are allowed to be
- shown in the waterfall. The default value of C{None} will disable this
- check
-
- @type auth: a L{status.web.auth.IAuth} or C{None}
- @param auth: an object that performs authentication to restrict access
- to the C{allowForce} features. Ignored if C{allowForce}
- is not C{True}. If C{auth} is C{None}, people can force or
- stop builds without auth.
-
- @type order_console_by_time: bool
- @param order_console_by_time: Whether to order changes (commits) in the console
- view according to the time they were created (for VCS like Git) or
- according to their integer revision numbers (for VCS like SVN).
-
- @type changecommentlink: callable, dict, tuple (2 or 3 strings) or C{None}
- @param changecommentlink: adds links to ticket/bug ids in change comments,
- see buildbot.status.web.base.changecommentlink for details
-
- @type revlink: callable, dict, string or C{None}
- @param revlink: decorations revision ids with links to a web-view,
- see buildbot.status.web.base.revlink for details
-
- @type projects: callable, dict or c{None}
- @param projects: maps project identifiers to URLs, so that any project listed
- is automatically decorated with a link to it's front page.
- see buildbot.status.web.base.dictlink for details
-
- @type repositories: callable, dict or c{None}
- @param repositories: maps repository identifiers to URLs, so that any project listed
- is automatically decorated with a link to it's web view.
- see buildbot.status.web.base.dictlink for details
-
- @type logRotateLength: None or int
- @param logRotateLength: file size at which the http.log is rotated/reset.
- If not set, the value set in the buildbot.tac will be used,
- falling back to the BuildMaster's default value (1 Mb).
-
- @type maxRotatedFiles: None or int
- @param maxRotatedFiles: number of old http.log files to keep during log rotation.
- If not set, the value set in the buildbot.tac will be used,
- falling back to the BuildMaster's default value (10 files).
-
- @type change_hook_dialects: None or dict
- @param change_hook_dialects: If empty, disables change_hook support, otherwise
- whitelists valid dialects. In the format of
- {"dialect1": "Option1", "dialect2", None}
- Where the values are options that will be passed
- to the dialect
-
- To enable the DEFAULT handler, use a key of DEFAULT
-
-
-
-
- @type provide_feeds: None or list
- @param provide_feeds: If empty, provides atom, json, and rss feeds.
- Otherwise, a dictionary of strings of
- the type of feeds provided. Current
- possibilities are "atom", "json", and "rss"
-
- @type jinja_loaders: None or list
- @param jinja_loaders: If not empty, a list of additional Jinja2 loader
- objects to search for templates.
- """
-
- service.MultiService.__init__(self)
- if type(http_port) is int:
- http_port = "tcp:%d" % http_port
- self.http_port = http_port
- if distrib_port is not None:
- if type(distrib_port) is int:
- distrib_port = "tcp:%d" % distrib_port
- if distrib_port[0] in "/~.": # pathnames
- distrib_port = "unix:%s" % distrib_port
- self.distrib_port = distrib_port
- self.num_events = num_events
- if num_events_max:
- if num_events_max < num_events:
- config.error(
- "num_events_max must be greater than num_events")
- self.num_events_max = num_events_max
- self.public_html = public_html
-
- # make up an authz if allowForce was given
- if authz:
- if allowForce is not None:
- config.error(
- "cannot use both allowForce and authz parameters")
- if auth:
- config.error(
- "cannot use both auth and authz parameters (pass " +
- "auth as an Authz parameter)")
- else:
- # invent an authz
- if allowForce and auth:
- authz = Authz(auth=auth, default_action="auth")
- elif allowForce:
- authz = Authz(default_action=True)
- else:
- if auth:
- log.msg("Warning: Ignoring authentication. Search for 'authorization'"
- " in the manual")
- authz = Authz() # no authorization for anything
-
- self.authz = authz
-
- # check for correctness of HTTP auth parameters
- if change_hook_auth is not None:
- self.change_hook_auth = []
- for checker in change_hook_auth:
- if isinstance(checker, str):
- try:
- checker = strcred.makeChecker(checker)
- except Exception, error:
- config.error("Invalid change_hook checker description: %s" % (error,))
- continue
- elif not ICredentialsChecker.providedBy(checker):
- config.error("change_hook checker doesn't provide ICredentialChecker: %r" % (checker,))
- continue
-
- if IUsernamePassword not in checker.credentialInterfaces:
- config.error("change_hook checker doesn't support IUsernamePassword: %r" % (checker,))
- continue
-
- self.change_hook_auth.append(checker)
- else:
- self.change_hook_auth = None
-
- self.orderConsoleByTime = order_console_by_time
-
- # If we were given a site object, go ahead and use it. (if not, we add one later)
- self.site = site
-
- # keep track of our child services
- self.http_svc = None
- self.distrib_svc = None
-
- # store the log settings until we create the site object
- self.logRotateLength = logRotateLength
- self.maxRotatedFiles = maxRotatedFiles
-
- # create the web site page structure
- self.childrenToBeAdded = {}
- self.setupUsualPages(numbuilds=numbuilds, num_events=num_events,
- num_events_max=num_events_max)
-
- self.revlink = revlink
- self.changecommentlink = changecommentlink
- self.repositories = repositories
- self.projects = projects
-
- # keep track of cached connections so we can break them when we shut
- # down. See ticket #102 for more details.
- self.channels = weakref.WeakKeyDictionary()
-
- # do we want to allow change_hook
- self.change_hook_dialects = {}
- if change_hook_dialects:
- self.change_hook_dialects = change_hook_dialects
- resource_obj = ChangeHookResource(dialects=self.change_hook_dialects)
- if self.change_hook_auth is not None:
- resource_obj = self.setupProtectedResource(
- resource_obj, self.change_hook_auth)
- self.putChild("change_hook", resource_obj)
-
- # Set default feeds
- if provide_feeds is None:
- self.provide_feeds = ["atom", "json", "rss"]
- else:
- self.provide_feeds = provide_feeds
-
- self.jinja_loaders = jinja_loaders
-
- def setupProtectedResource(self, resource_obj, checkers):
- class SimpleRealm(object):
- """
- A realm which gives out L{ChangeHookResource} instances for authenticated
- users.
- """
- implements(IRealm)
-
- def requestAvatar(self, avatarId, mind, *interfaces):
- if resource.IResource in interfaces:
- return (resource.IResource, resource_obj, lambda: None)
- raise NotImplementedError()
-
- portal = Portal(SimpleRealm(), checkers)
- credentialFactory = guard.BasicCredentialFactory('Protected area')
- wrapper = guard.HTTPAuthSessionWrapper(portal, [credentialFactory])
- return wrapper
-
- def setupUsualPages(self, numbuilds, num_events, num_events_max):
- #self.putChild("", IndexOrWaterfallRedirection())
- self.putChild("waterfall", WaterfallStatusResource(num_events=num_events,
- num_events_max=num_events_max))
- self.putChild("grid", GridStatusResource())
- self.putChild("console", ConsoleStatusResource(
- orderByTime=self.orderConsoleByTime))
- self.putChild("tgrid", TransposedGridStatusResource())
- self.putChild("builders", BuildersResource(numbuilds=numbuilds)) # has builds/steps/logs
- self.putChild("one_box_per_builder", Redirect("builders"))
- self.putChild("changes", ChangesResource())
- self.putChild("buildslaves", BuildSlavesResource())
- self.putChild("buildstatus", BuildStatusStatusResource())
- self.putChild("one_line_per_build",
- OneLinePerBuild(numbuilds=numbuilds))
- self.putChild("about", AboutBuildbot())
- self.putChild("authfail", AuthFailResource())
- self.putChild("authzfail", AuthzFailResource())
- self.putChild("users", UsersResource())
- self.putChild("login", LoginResource())
- self.putChild("logout", LogoutResource())
-
- def __repr__(self):
- if self.http_port is None:
- return "<WebStatus on path %s at %s>" % (self.distrib_port,
- hex(id(self)))
- if self.distrib_port is None:
- return "<WebStatus on port %s at %s>" % (self.http_port,
- hex(id(self)))
- return ("<WebStatus on port %s and path %s at %s>" %
- (self.http_port, self.distrib_port, hex(id(self))))
-
- def setServiceParent(self, parent):
- # this class keeps a *separate* link to the buildmaster, rather than
- # just using self.parent, so that when we are "disowned" (and thus
- # parent=None), any remaining HTTP clients of this WebStatus will still
- # be able to get reasonable results.
- self.master = parent.master
-
- # set master in IAuth instance
- if self.authz.auth:
- self.authz.auth.master = self.master
-
- def either(a,b): # a if a else b for py2.4
- if a:
- return a
- else:
- return b
-
- rotateLength = either(self.logRotateLength, self.master.log_rotation.rotateLength)
- maxRotatedFiles = either(self.maxRotatedFiles, self.master.log_rotation.maxRotatedFiles)
-
- # Set up the jinja templating engine.
- if self.revlink:
- revlink = self.revlink
- else:
- revlink = self.master.config.revlink
- self.templates = createJinjaEnv(revlink, self.changecommentlink,
- self.repositories, self.projects, self.jinja_loaders)
-
- if not self.site:
-
- class RotateLogSite(server.Site):
- def _openLogFile(self, path):
- try:
- from twisted.python.logfile import LogFile
- log.msg("Setting up http.log rotating %s files of %s bytes each" %
- (maxRotatedFiles, rotateLength))
- if hasattr(LogFile, "fromFullPath"): # not present in Twisted-2.5.0
- return LogFile.fromFullPath(path, rotateLength=rotateLength, maxRotatedFiles=maxRotatedFiles)
- else:
- log.msg("WebStatus: rotated http logs are not supported on this version of Twisted")
- except ImportError, e:
- log.msg("WebStatus: Unable to set up rotating http.log: %s" % e)
-
- # if all else fails, just call the parent method
- return server.Site._openLogFile(self, path)
-
- # this will be replaced once we've been attached to a parent (and
- # thus have a basedir and can reference BASEDIR)
- root = static.Data("placeholder", "text/plain")
- httplog = os.path.abspath(os.path.join(self.master.basedir, "http.log"))
- self.site = RotateLogSite(root, logPath=httplog)
-
- # the following items are accessed by HtmlResource when it renders
- # each page.
- self.site.buildbot_service = self
-
- if self.http_port is not None:
- self.http_svc = s = strports.service(self.http_port, self.site)
- s.setServiceParent(self)
- if self.distrib_port is not None:
- f = pb.PBServerFactory(distrib.ResourcePublisher(self.site))
- self.distrib_svc = s = strports.service(self.distrib_port, f)
- s.setServiceParent(self)
-
- self.setupSite()
-
- service.MultiService.setServiceParent(self, parent)
-
- def setupSite(self):
- # this is responsible for creating the root resource. It isn't done
- # at __init__ time because we need to reference the parent's basedir.
- htmldir = os.path.abspath(os.path.join(self.master.basedir, self.public_html))
- if os.path.isdir(htmldir):
- log.msg("WebStatus using (%s)" % htmldir)
- else:
- log.msg("WebStatus: warning: %s is missing. Do you need to run"
- " 'buildbot upgrade-master' on this buildmaster?" % htmldir)
- # all static pages will get a 404 until upgrade-master is used to
- # populate this directory. Create the directory, though, since
- # otherwise we get internal server errors instead of 404s.
- os.mkdir(htmldir)
-
- root = StaticFile(htmldir)
- root_page = RootPage()
- root.putChild("", root_page)
- root.putChild("shutdown", root_page)
- root.putChild("cancel_shutdown", root_page)
-
- for name, child_resource in self.childrenToBeAdded.iteritems():
- root.putChild(name, child_resource)
-
- status = self.getStatus()
- if "rss" in self.provide_feeds:
- root.putChild("rss", Rss20StatusResource(status))
- if "atom" in self.provide_feeds:
- root.putChild("atom", Atom10StatusResource(status))
- if "json" in self.provide_feeds:
- root.putChild("json", JsonStatusResource(status))
-
- self.site.resource = root
-
- def putChild(self, name, child_resource):
- """This behaves a lot like root.putChild() . """
- self.childrenToBeAdded[name] = child_resource
-
- def registerChannel(self, channel):
- self.channels[channel] = 1 # weakrefs
-
- @defer.inlineCallbacks
- def stopService(self):
- for channel in self.channels:
- try:
- channel.transport.loseConnection()
- except:
- log.msg("WebStatus.stopService: error while disconnecting"
- " leftover clients")
- log.err()
- yield service.MultiService.stopService(self)
-
- # having shut them down, now remove our child services so they don't
- # start up again if we're re-started
- if self.http_svc:
- yield self.http_svc.disownServiceParent()
- self.http_svc = None
- if self.distrib_svc:
- yield self.distrib_svc.disownServiceParent()
- self.distrib_svc = None
-
- def getStatus(self):
- return self.master.getStatus()
-
- def getChangeSvc(self):
- return self.master.change_svc
-
- def getPortnum(self):
- # this is for the benefit of unit tests
- s = list(self)[0]
- return s._port.getHost().port
-
- # What happened to getControl?!
- #
- # instead of passing control objects all over the place in the web
- # code, at the few places where a control instance is required we
- # find the requisite object manually, starting at the buildmaster.
- # This is in preparation for removal of the IControl hierarchy
- # entirely.
-
- def checkConfig(self, otherStatusReceivers):
- duplicate_webstatus=0
- for osr in otherStatusReceivers:
- if isinstance(osr,WebStatus):
- if osr is self:
- continue
- # compare against myself and complain if the settings conflict
- if self.http_port == osr.http_port:
- if duplicate_webstatus == 0:
- duplicate_webstatus = 2
- else:
- duplicate_webstatus += 1
-
- if duplicate_webstatus:
- config.error(
- "%d Webstatus objects have same port: %s"
- % (duplicate_webstatus, self.http_port),
- )
-
-# resources can get access to the IStatus by calling
-# request.site.buildbot_service.getStatus()