buildbot / buildbot

@@ -0,0 +1,138 @@
Loading
1 +
# This file is part of Buildbot.  Buildbot is free software: you can
2 +
# redistribute it and/or modify it under the terms of the GNU General Public
3 +
# License as published by the Free Software Foundation, version 2.
4 +
#
5 +
# This program is distributed in the hope that it will be useful, but WITHOUT
6 +
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7 +
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
8 +
# details.
9 +
#
10 +
# You should have received a copy of the GNU General Public License along with
11 +
# this program; if not, write to the Free Software Foundation, Inc., 51
12 +
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
13 +
#
14 +
# Copyright Buildbot Team Members
15 +
16 +
17 +
from twisted.application import strports
18 +
from twisted.internet import defer
19 +
from twisted.python import log
20 +
21 +
from buildbot.util import service
22 +
23 +
24 +
class BaseManager(service.AsyncMultiService):
25 +
    """
26 +
    A centralized manager for connection ports and authentication on them.
27 +
    Allows various pieces of code to request a (port, username) combo, along
28 +
    with a password and a connection factory.
29 +
    """
30 +
    def __init__(self, name):
31 +
        super().__init__()
32 +
        self.setName(name)
33 +
        self.dispatchers = {}
34 +
35 +
    @defer.inlineCallbacks
36 +
    def register(self, portstr, username, password, pfactory):
37 +
        """
38 +
        Register a connection code to be executed after a user with its USERNAME/PASSWORD
39 +
        was authenticated and a valid high level connection can be established on a PORTSTR.
40 +
        Returns a Registration object which can be used to unregister later.
41 +
        """
42 +
        # do some basic normalization of portstrs
43 +
        if isinstance(portstr, type(0)) or ':' not in portstr:
44 +
            portstr = "tcp:{}".format(portstr)
45 +
46 +
        reg = Registration(self, portstr, username)
47 +
48 +
        if portstr not in self.dispatchers:
49 +
            disp = self.dispatchers[portstr] = self.dispatcher_class(portstr)
50 +
            yield disp.setServiceParent(self)
51 +
        else:
52 +
            disp = self.dispatchers[portstr]
53 +
54 +
        disp.register(username, password, pfactory)
55 +
56 +
        return reg
57 +
58 +
    @defer.inlineCallbacks
59 +
    def _unregister(self, registration):
60 +
        disp = self.dispatchers[registration.portstr]
61 +
        disp.unregister(registration.username)
62 +
        registration.username = None
63 +
        if not disp.users:
64 +
            del self.dispatchers[registration.portstr]
65 +
            yield disp.disownServiceParent()
66 +
67 +
68 +
class Registration:
69 +
70 +
    def __init__(self, manager, portstr, username):
71 +
        self.portstr = portstr
72 +
        "portstr this registration is active on"
73 +
        self.username = username
74 +
        "username of this registration"
75 +
        self.manager = manager
76 +
77 +
    def __repr__(self):
78 +
        return "<base.Registration for {} on {}>".format(self.username, self.portstr)
79 +
80 +
    def unregister(self):
81 +
        """
82 +
        Unregister this registration, removing the username from the port, and
83 +
        closing the port if there are no more users left.  Returns a Deferred.
84 +
        """
85 +
        return self.manager._unregister(self)
86 +
87 +
    def getPort(self):
88 +
        """
89 +
        Helper method for testing; returns the TCP port used for this
90 +
        registration, even if it was specified as 0 and thus allocated by the
91 +
        OS.
92 +
        """
93 +
        disp = self.manager.dispatchers[self.portstr]
94 +
        return disp.port.getHost().port
95 +
96 +
97 +
class BaseDispatcher(service.AsyncService):
98 +
    debug = False
99 +
100 +
    def __init__(self, portstr):
101 +
        self.portstr = portstr
102 +
        self.users = {}
103 +
        self.port = None
104 +
105 +
    def __repr__(self):
106 +
        return "<base.BaseDispatcher for {} on {}>".format(", ".join(list(self.users)),
107 +
                                                           self.portstr)
108 +
109 +
    def start_listening_port(self):
110 +
        return strports.listen(self.portstr, self.serverFactory)
111 +
112 +
    def startService(self):
113 +
        assert not self.port
114 +
        self.port = self.start_listening_port()
115 +
116 +
        return super().startService()
117 +
118 +
    @defer.inlineCallbacks
119 +
    def stopService(self):
120 +
        # stop listening on the port when shut down
121 +
        assert self.port
122 +
        port, self.port = self.port, None
123 +
        yield port.stopListening()
124 +
        yield super().stopService()
125 +
126 +
    def register(self, username, password, pfactory):
127 +
        if self.debug:
128 +
            log.msg("registering username '{}' on port {}: {}".format(username, self.portstr,
129 +
                                                                      pfactory))
130 +
        if username in self.users:
131 +
            raise KeyError("username '{}' is already registered on port {}".format(username,
132 +
                                                                                   self.portstr))
133 +
        self.users[username] = (password, pfactory)
134 +
135 +
    def unregister(self, username):
136 +
        if self.debug:
137 +
            log.msg("unregistering username '{}' on port {}".format(username, self.portstr))
138 +
        del self.users[username]

@@ -14,7 +14,6 @@
Loading
14 14
# Copyright Buildbot Team Members
15 15
16 16
17 -
from twisted.application import strports
18 17
from twisted.cred import checkers
19 18
from twisted.cred import credentials
20 19
from twisted.cred import error
@@ -26,137 +25,25 @@
Loading
26 25
27 26
from buildbot.process.properties import Properties
28 27
from buildbot.util import bytes2unicode
29 -
from buildbot.util import service
30 28
from buildbot.util import unicode2bytes
31 29
from buildbot.util.eventual import eventually
32 -
33 -
debug = False
34 -
35 -
36 -
class PBManager(service.AsyncMultiService):
37 -
38 -
    """
39 -
    A centralized manager for PB ports and authentication on them.
40 -
41 -
    Allows various pieces of code to request a (port, username) combo, along
42 -
    with a password and a perspective factory.
43 -
    """
44 -
45 -
    def __init__(self):
46 -
        super().__init__()
47 -
        self.setName('pbmanager')
48 -
        self.dispatchers = {}
49 -
50 -
    @defer.inlineCallbacks
51 -
    def register(self, portstr, username, password, pfactory):
52 -
        """
53 -
        Register a perspective factory PFACTORY to be executed when a PB
54 -
        connection arrives on PORTSTR with USERNAME/PASSWORD.  Returns a
55 -
        Registration object which can be used to unregister later.
56 -
        """
57 -
        # do some basic normalization of portstrs
58 -
        if isinstance(portstr, type(0)) or ':' not in portstr:
59 -
            portstr = "tcp:{}".format(portstr)
60 -
61 -
        reg = Registration(self, portstr, username)
62 -
63 -
        if portstr not in self.dispatchers:
64 -
            disp = self.dispatchers[portstr] = Dispatcher(portstr)
65 -
            yield disp.setServiceParent(self)
66 -
        else:
67 -
            disp = self.dispatchers[portstr]
68 -
69 -
        disp.register(username, password, pfactory)
70 -
71 -
        return reg
72 -
73 -
    @defer.inlineCallbacks
74 -
    def _unregister(self, registration):
75 -
        disp = self.dispatchers[registration.portstr]
76 -
        disp.unregister(registration.username)
77 -
        registration.username = None
78 -
        if not disp.users:
79 -
            del self.dispatchers[registration.portstr]
80 -
            yield disp.disownServiceParent()
81 -
82 -
83 -
class Registration:
84 -
85 -
    def __init__(self, pbmanager, portstr, username):
86 -
        self.portstr = portstr
87 -
        "portstr this registration is active on"
88 -
        self.username = username
89 -
        "username of this registration"
90 -
91 -
        self.pbmanager = pbmanager
92 -
93 -
    def __repr__(self):
94 -
        return "<pbmanager.Registration for {} on {}>".format(self.username, self.portstr)
95 -
96 -
    def unregister(self):
97 -
        """
98 -
        Unregister this registration, removing the username from the port, and
99 -
        closing the port if there are no more users left.  Returns a Deferred.
100 -
        """
101 -
        return self.pbmanager._unregister(self)
102 -
103 -
    def getPort(self):
104 -
        """
105 -
        Helper method for testing; returns the TCP port used for this
106 -
        registration, even if it was specified as 0 and thus allocated by the
107 -
        OS.
108 -
        """
109 -
        disp = self.pbmanager.dispatchers[self.portstr]
110 -
        return disp.port.getHost().port
30 +
from buildbot.worker.protocols.manager.base import BaseDispatcher
31 +
from buildbot.worker.protocols.manager.base import BaseManager
111 32
112 33
113 34
@implementer(portal.IRealm, checkers.ICredentialsChecker)
114 -
class Dispatcher(service.AsyncService):
35 +
class Dispatcher(BaseDispatcher):
115 36
116 37
    credentialInterfaces = [credentials.IUsernamePassword,
117 38
                            credentials.IUsernameHashedPassword]
118 39
119 40
    def __init__(self, portstr):
120 -
        self.portstr = portstr
121 -
        self.users = {}
122 -
41 +
        super().__init__(portstr)
123 42
        # there's lots of stuff to set up for a PB connection!
124 43
        self.portal = portal.Portal(self)
125 44
        self.portal.registerChecker(self)
126 45
        self.serverFactory = pb.PBServerFactory(self.portal)
127 46
        self.serverFactory.unsafeTracebacks = True
128 -
        self.port = None
129 -
130 -
    def __repr__(self):
131 -
        return "<pbmanager.Dispatcher for {} on {}>".format(", ".join(list(self.users)),
132 -
                                                            self.portstr)
133 -
134 -
    def startService(self):
135 -
        assert not self.port
136 -
        self.port = strports.listen(self.portstr, self.serverFactory)
137 -
        return super().startService()
138 -
139 -
    @defer.inlineCallbacks
140 -
    def stopService(self):
141 -
        # stop listening on the port when shut down
142 -
        assert self.port
143 -
        port, self.port = self.port, None
144 -
        yield port.stopListening()
145 -
        yield super().stopService()
146 -
147 -
    def register(self, username, password, pfactory):
148 -
        if debug:
149 -
            log.msg("registering username '{}' on pb port {}: {}".format(username, self.portstr,
150 -
                                                                         pfactory))
151 -
        if username in self.users:
152 -
            raise KeyError("username '{}' is already registered on PB port {}".format(username,
153 -
                                                                                      self.portstr))
154 -
        self.users[username] = (password, pfactory)
155 -
156 -
    def unregister(self, username):
157 -
        if debug:
158 -
            log.msg("unregistering username '{}' on pb port {}".format(username, self.portstr))
159 -
        del self.users[username]
160 47
161 48
    # IRealm
162 49
@@ -200,3 +87,10 @@
Loading
200 87
            # brake the callback stack by returning to the reactor
201 88
            # before waking up other waiters
202 89
            eventually(self.master.initLock.release)
90 +
91 +
92 +
class PBManager(BaseManager):
93 +
    def __init__(self):
94 +
        super().__init__('pbmanager')
95 +
96 +
    dispatcher_class = Dispatcher
Files Coverage
master/buildbot 92.33%
worker/buildbot_worker 85.68%
Project Totals (335 files) 91.92%
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading