Explorar o código

Return BAD_NAME if getProcessInfo() can't resolve the name. Fixes #211

Mike Naberezny %!s(int64=12) %!d(string=hai) anos
pai
achega
c4e0c25925
Modificáronse 3 ficheiros con 68 adicións e 47 borrados
  1. 4 0
      CHANGES.txt
  2. 3 0
      supervisor/rpcinterface.py
  3. 61 47
      supervisor/tests/test_rpcinterfaces.py

+ 4 - 0
CHANGES.txt

@@ -20,6 +20,10 @@ Next release
 - Fixed a bug where supervisord would crash if the syslog handler was used
   and supervisord received SIGUSR2 (log reopen request).
 
+- Fixed an XML-RPC bug where calling supervisor.getProcessInfo() with a bad
+  name would cause a 500 Internal Server Error rather than the returning
+  a BAD_NAME fault.
+
 3.0b1 (2012-09-10)
 ------------------
 

+ 3 - 0
supervisor/rpcinterface.py

@@ -503,6 +503,9 @@ class SupervisorNamespaceRPCInterface:
 
         group, process = self._getGroupAndProcess(name)
 
+        if process is None:
+            raise RPCError(Faults.BAD_NAME, name)
+
         start = int(process.laststart)
         stop = int(process.laststop)
         now = int(time.time())

+ 61 - 47
supervisor/tests/test_rpcinterfaces.py

@@ -57,7 +57,7 @@ class MainXMLRPCInterfaceTests(TestBase):
                              'dummy.hello', [1])
         self.assertEqual(xmlrpc.traverse(
             interface, 'dummy.hello', []), 'Hello!')
-            
+
 class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
     def _getTargetClass(self):
         from supervisor import rpcinterface
@@ -97,7 +97,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         from supervisor import options
         self.assertEqual(version, options.VERSION)
         self.assertEqual(interface.update_text, 'getSupervisorVersion')
-        
+
 
     def test_getIdentification(self):
         supervisord = DummySupervisor()
@@ -439,7 +439,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         time.sleep(.1)
         from supervisor import xmlrpc
         self._assertRPCError(xmlrpc.Faults.ABNORMAL_TERMINATION, callback)
-    
+
     def test_startProcess_abormal_term_startsecs_exceeded(self):
         options = DummyOptions()
         pconfig = DummyPConfig(options, 'foo', __file__, autostart=False,
@@ -876,7 +876,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
                    'start':start,
                    'stop':stop,
                    'now':_NOW}
-        
+
         description = interface._interpretProcessInfo(running)
         self.assertEqual(description, 'pid 1, uptime 0:01:40')
 
@@ -887,7 +887,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
                  'stop':stop,
                  'now':_NOW,
                  'spawnerr':'Hosed'}
-                 
+
         description = interface._interpretProcessInfo(fatal)
         self.assertEqual(description, 'Hosed')
 
@@ -898,10 +898,10 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
                   'stop':stop,
                   'now':_NOW,
                   'spawnerr':'',}
-                 
+
         description = interface._interpretProcessInfo(fatal2)
         self.assertEqual(description, 'unknown error (try "tail fatal")')
-        
+
         stopped = {'name':'stopped',
                    'pid':3,
                    'state':ProcessStates.STOPPED,
@@ -914,7 +914,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         from datetime import datetime
         stoptime = datetime(*time.localtime(stop)[:7])
         self.assertEqual(description, stoptime.strftime(_TIMEFORMAT))
-        
+
         stopped2 = {'name':'stopped',
                    'pid':3,
                    'state':ProcessStates.STOPPED,
@@ -925,7 +925,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
 
         description = interface._interpretProcessInfo(stopped2)
         self.assertEqual(description, 'Not started')
-                   
+
 
     def test_getProcessInfo(self):
         from supervisor.process import ProcessStates
@@ -976,6 +976,20 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         self.assertEqual(data['logfile'], '')
         self.assertEqual(data['stdout_logfile'], '')
 
+    def test_getProcessInfo_bad_name(self):
+        from supervisor import xmlrpc
+        supervisord = DummySupervisor()
+        interface = self._makeOne(supervisord)
+        self._assertRPCError(xmlrpc.Faults.BAD_NAME,
+                             interface.getProcessInfo, 'nonexistant')
+
+    def test_getProcessInfo_bad_name_group_only(self):
+        from supervisor import xmlrpc
+        supervisord = DummySupervisor()
+        interface = self._makeOne(supervisord)
+        self._assertRPCError(xmlrpc.Faults.BAD_NAME,
+                             interface.getProcessInfo, 'grouponly:')
+
     def test_getAllProcessInfo(self):
         from supervisor.process import ProcessStates
         options = DummyOptions()
@@ -1036,10 +1050,10 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         self.assertEqual(p2info['exitstatus'], 0)
         self.assertEqual(p2info['spawnerr'], '')
         self.assertEqual(p1info['group'], 'gname')
-        
+
         from datetime import datetime
         starttime = datetime(*time.localtime(process2.laststart)[:7])
-        self.assertEqual(p2info['description'], 
+        self.assertEqual(p2info['description'],
                             starttime.strftime(_TIMEFORMAT))
 
     def test_readProcessStdoutLog_unreadable(self):
@@ -1172,7 +1186,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         from supervisor import xmlrpc
         supervisord = DummySupervisor()
         interface = self._makeOne(supervisord)
-        self._assertRPCError(xmlrpc.Faults.BAD_NAME, 
+        self._assertRPCError(xmlrpc.Faults.BAD_NAME,
                              interface.tailProcessStdoutLog, 'BAD_NAME', 0, 10)
 
     def test_tailProcessStdoutLog_all(self):
@@ -1189,9 +1203,9 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
             f = open(logfile, 'w+')
             f.write(letters)
             f.close()
-            
-            data, offset, overflow = interface.tailProcessStdoutLog('foo', 
-                                                        offset=0, 
+
+            data, offset, overflow = interface.tailProcessStdoutLog('foo',
+                                                        offset=0,
                                                         length=len(letters))
             self.assertEqual(interface.update_text, 'tailProcessStdoutLog')
             self.assertEqual(overflow, False)
@@ -1216,8 +1230,8 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
             f.close()
 
             # offset==logsize
-            data, offset, overflow = interface.tailProcessStdoutLog('foo', 
-                                                        offset=len(letters), 
+            data, offset, overflow = interface.tailProcessStdoutLog('foo',
+                                                        offset=len(letters),
                                                         length=100)
             self.assertEqual(interface.update_text, 'tailProcessStdoutLog')
             self.assertEqual(overflow, False)
@@ -1225,8 +1239,8 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
             self.assertEqual(data, '')
 
             # offset > logsize
-            data, offset, overflow = interface.tailProcessStdoutLog('foo', 
-                                                        offset=len(letters)+5, 
+            data, offset, overflow = interface.tailProcessStdoutLog('foo',
+                                                        offset=len(letters)+5,
                                                         length=100)
             self.assertEqual(interface.update_text, 'tailProcessStdoutLog')
             self.assertEqual(overflow, False)
@@ -1250,7 +1264,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
             f.write(letters)
             f.close()
 
-            data, offset, overflow = interface.tailProcessStdoutLog('foo', 
+            data, offset, overflow = interface.tailProcessStdoutLog('foo',
                                                         offset=0, length=5)
             self.assertEqual(interface.update_text, 'tailProcessStdoutLog')
             self.assertEqual(overflow, True)
@@ -1258,7 +1272,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
             self.assertEqual(data, letters[-5:])
         finally:
             os.remove(logfile)
-    
+
     def test_tailProcessStdoutLog_unreadable(self):
         # test nothing is returned if the log doesn't exist yet
         options = DummyOptions()
@@ -1266,8 +1280,8 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
                                stdout_logfile='/tmp/fooooooo')
         supervisord = PopulatedDummySupervisor(options, 'foo', pconfig)
         interface = self._makeOne(supervisord)
-                
-        data, offset, overflow = interface.tailProcessStdoutLog('foo', 
+
+        data, offset, overflow = interface.tailProcessStdoutLog('foo',
                                                     offset=0, length=100)
         self.assertEqual(interface.update_text, 'tailProcessStdoutLog')
         self.assertEqual(overflow, False)
@@ -1286,7 +1300,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         from supervisor import xmlrpc
         supervisord = DummySupervisor()
         interface = self._makeOne(supervisord)
-        self._assertRPCError(xmlrpc.Faults.BAD_NAME, 
+        self._assertRPCError(xmlrpc.Faults.BAD_NAME,
                              interface.tailProcessStderrLog, 'BAD_NAME', 0, 10)
 
     def test_tailProcessStderrLog_all(self):
@@ -1303,9 +1317,9 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
             f = open(logfile, 'w+')
             f.write(letters)
             f.close()
-            
-            data, offset, overflow = interface.tailProcessStderrLog('foo', 
-                                                        offset=0, 
+
+            data, offset, overflow = interface.tailProcessStderrLog('foo',
+                                                        offset=0,
                                                         length=len(letters))
             self.assertEqual(interface.update_text, 'tailProcessStderrLog')
             self.assertEqual(overflow, False)
@@ -1330,8 +1344,8 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
             f.close()
 
             # offset==logsize
-            data, offset, overflow = interface.tailProcessStderrLog('foo', 
-                                                        offset=len(letters), 
+            data, offset, overflow = interface.tailProcessStderrLog('foo',
+                                                        offset=len(letters),
                                                         length=100)
             self.assertEqual(interface.update_text, 'tailProcessStderrLog')
             self.assertEqual(overflow, False)
@@ -1339,8 +1353,8 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
             self.assertEqual(data, '')
 
             # offset > logsize
-            data, offset, overflow = interface.tailProcessStderrLog('foo', 
-                                                        offset=len(letters)+5, 
+            data, offset, overflow = interface.tailProcessStderrLog('foo',
+                                                        offset=len(letters)+5,
                                                         length=100)
             self.assertEqual(interface.update_text, 'tailProcessStderrLog')
             self.assertEqual(overflow, False)
@@ -1364,7 +1378,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
             f.write(letters)
             f.close()
 
-            data, offset, overflow = interface.tailProcessStderrLog('foo', 
+            data, offset, overflow = interface.tailProcessStderrLog('foo',
                                                         offset=0, length=5)
             self.assertEqual(interface.update_text, 'tailProcessStderrLog')
             self.assertEqual(overflow, True)
@@ -1372,7 +1386,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
             self.assertEqual(data, letters[-5:])
         finally:
             os.remove(logfile)
-    
+
     def test_tailProcessStderrLog_unreadable(self):
         # test nothing is returned if the log doesn't exist yet
         options = DummyOptions()
@@ -1380,8 +1394,8 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
                                stderr_logfile='/tmp/fooooooo')
         supervisord = PopulatedDummySupervisor(options, 'foo', pconfig)
         interface = self._makeOne(supervisord)
-                
-        data, offset, overflow = interface.tailProcessStderrLog('foo', 
+
+        data, offset, overflow = interface.tailProcessStderrLog('foo',
                                                     offset=0, length=100)
         self.assertEqual(interface.update_text, 'tailProcessStderrLog')
         self.assertEqual(overflow, False)
@@ -1418,7 +1432,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         supervisord = DummySupervisor(process_groups={'foo':pgroup})
         interface = self._makeOne(supervisord)
         self.assertRaises(xmlrpc.RPCError, interface.clearProcessLogs, 'foo')
-        
+
     def test_clearProcessLogAliasedTo_clearProcessLogs(self):
         options = DummyOptions()
         pconfig = DummyPConfig(options, 'foo', '/bin/foo')
@@ -1491,7 +1505,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         self._assertRPCError(xmlrpc.Faults.INCORRECT_PARAMETERS,
                              interface.sendProcessStdin,
                              'process1', thing_not_chars)
-    
+
     def test_sendProcessStdin_raises_bad_name_when_no_process(self):
         options = DummyOptions()
         supervisord = PopulatedDummySupervisor(options, 'foo')
@@ -1523,7 +1537,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         self._assertRPCError(xmlrpc.Faults.NOT_RUNNING,
                              interface.sendProcessStdin,
                              'process1', 'chars for stdin')
-        
+
     def test_sendProcessStdin_raises_no_file_when_write_raises_epipe(self):
         options = DummyOptions()
         pconfig1 = DummyPConfig(options, 'process1', 'foo')
@@ -1568,7 +1582,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         L = []
         def callback(event):
             L.append(event)
-        
+
         try:
             events.callbacks[:] = [(events.RemoteCommunicationEvent, callback)]
             result = interface.sendRemoteCommEvent('foo', 'bar')
@@ -1578,7 +1592,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
 
         self.assertTrue(result)
         self.assertEqual(len(L), 1)
-        event = L[0]                                     
+        event = L[0]
         self.assertEqual(event.type, 'foo')
         self.assertEqual(event.data, 'bar')
 
@@ -1591,7 +1605,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         L = []
         def callback(event):
             L.append(event)
-        
+
         try:
             events.callbacks[:] = [(events.RemoteCommunicationEvent, callback)]
             result = interface.sendRemoteCommEvent(u'fi\xed once', u'fi\xed twice')
@@ -1601,10 +1615,10 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
 
         self.assertTrue(result)
         self.assertEqual(len(L), 1)
-        event = L[0]                                     
+        event = L[0]
         self.assertEqual(event.type, 'fi\xc3\xad once')
         self.assertEqual(event.data, 'fi\xc3\xad twice')
-        
+
 
 class SystemNamespaceXMLRPCInterfaceTests(TestBase):
     def _getTargetClass(self):
@@ -1719,7 +1733,7 @@ class SystemNamespaceXMLRPCInterfaceTests(TestBase):
                 self.failUnless(type(doctext) == type(''), doctext)
 
             # result tokens
-            
+
             if len(rlines) > 1:
                 raise AssertionError(
                     'Duplicate @return values in docs for %s' % k)
@@ -1753,20 +1767,20 @@ class SystemNamespaceXMLRPCInterfaceTests(TestBase):
         from supervisor import xmlrpc
         interface = self._makeOne()
         callback = interface.multicall([
-            {'methodName': 'system.multicall', 'params': []},        
+            {'methodName': 'system.multicall', 'params': []},
         ])
 
         from supervisor import http
         result = http.NOT_DONE_YET
         while result is http.NOT_DONE_YET:
             result = callback()
-        
+
         code = xmlrpc.Faults.INCORRECT_PARAMETERS
         desc = xmlrpc.getFaultDescription(code)
         recursion_fault = {'faultCode': code, 'faultString': desc}
 
         self.assertEqual(result, [recursion_fault])
-        
+
     def test_multicall_nested_callback(self):
         interface = self._makeOne()
         callback = interface.multicall([