yet another refactor of nodes, this time with better tests
authorsalimfadhley <sal@stodge.org>
Mon, 17 Jun 2013 23:44:26 +0000 (00:44 +0100)
committerSalim Fadhley <sal@stodge.org>
Sun, 23 Jun 2013 20:21:51 +0000 (21:21 +0100)
jenkinsapi/exceptions.py
jenkinsapi/jenkins.py
jenkinsapi/node.py
jenkinsapi/nodes.py
jenkinsapi/utils/requester.py
jenkinsapi_tests/systests/test_nodes.py
jenkinsapi_tests/unittests/test_node.py

index 04cf7cb..4cee5e8 100644 (file)
@@ -18,6 +18,11 @@ class UnknownView( KeyError, JenkinsAPIException):
     Jenkins does not recognize the view requested.
     """
 
+class UnknownNode( KeyError, JenkinsAPIException):
+    """
+    Jenkins does not recognize the node requested.
+    """
+
 class UnknownQueueItem( KeyError, JenkinsAPIException):
     """
     Jenkins does not recognize the requested queue item
index 54b2186..8f5afeb 100644 (file)
@@ -216,10 +216,6 @@ class Jenkins(JenkinsBase):
         str_view_name = str_view_url.split('/view/')[-1].replace('/', '')
         return View(str_view_url , str_view_name, jenkins_obj=self)
 
-    def get_nodes(self):
-        url = self.get_nodes_url()
-        return Nodes(url, self)
-
     def __getitem__(self, jobname):
         """
         Get a job by name
@@ -239,18 +235,9 @@ class Jenkins(JenkinsBase):
         """
         return jobname in self.get_jobs_list()
 
-    def get_node_dict(self):
-        """Get registered slave nodes on this instance"""
-        url = self.python_api_url(self.get_node_url())
-        node_dict = dict(self.get_data(url))
-        return dict(
-            (node['displayName'], self.python_api_url(self.get_node_url(node['displayName'])))
-                for node in node_dict['computer'])
-
     def get_node(self, nodename):
         """Get a node object for a specific node"""
-        node_url = self.get_node_url(nodename)
-        return Node(node_url, nodename, jenkins_obj=self)
+        return self.get_nodes()[nodename]
 
     def get_node_url(self, nodename=""):
         """Return the url for nodes"""
@@ -265,6 +252,10 @@ class Jenkins(JenkinsBase):
         queue_url = self.get_queue_url()
         return Queue(queue_url, self)
 
+    def get_nodes(self):
+        url = self.get_nodes_url()
+        return Nodes(url, self)
+
     def has_node(self, nodename):
         """
         Does a node by the name specified exist
@@ -272,7 +263,7 @@ class Jenkins(JenkinsBase):
         :return: boolean
         """
         self.poll()
-        return nodename in self.get_node_dict()
+        return nodename in self.get_nodes()
 
     def delete_node(self, nodename):
         """
index 59555f3..1fb9f48 100644 (file)
@@ -58,7 +58,6 @@ class Node(JenkinsBase):
                                 (self._data['offline'], self._data['temporarilyOffline']))
         elif self._data['offline'] and self._data['temporarilyOffline']:
             self.toggle_temporarily_offline()
-            self.poll()
             if self._data['offline']:
                 raise AssertionError("The node state is still offline, check client connection:" +
                                      " offline = %s , temporarilyOffline = %s" %
@@ -70,7 +69,6 @@ class Node(JenkinsBase):
         If after run node state has not been changed raise AssertionError.
         : param message: optional string explain why you are taking this node offline
         """
-        self.poll()
         if not self._data['offline']:
             self.toggle_temporarily_offline(message)
             self.poll()
@@ -87,7 +85,8 @@ class Node(JenkinsBase):
         """
         initial_state = self.is_temporarily_offline()
         url = self.baseurl + "/toggleOffline?offlineMessage=" + urllib.quote(message)
-        html_result = self.hit_url(url)
+        html_result = self.jenkins.requester.get_and_confirm_status(url)
+        self.poll()
         log.debug(html_result)
         if initial_state == self.is_temporarily_offline():
             raise AssertionError("The node state has not changed: temporarilyOffline = %s" % state)
index 5c93647..d6001cc 100644 (file)
@@ -1,5 +1,6 @@
 import logging
 from jenkinsapi.node import Node
+from jenkinsapi.exceptions import UnknownNode
 from jenkinsapi.jenkinsbase import JenkinsBase
 
 log = logging.getLogger(__name__)
@@ -16,19 +17,36 @@ class Nodes(JenkinsBase):
         self.jenkins = jenkins_obj
         JenkinsBase.__init__(self, baseurl)
 
+    def get_jenkins_obj(self):
+        return self.jenkins
+
     def __str__(self):
         return 'Nodes @ %s' % self.baseurl
 
+    def __contains__(self, node_name):
+        return node_name in self.keys()
+
+    def iterkeys(self):
+        for item in self._data['computer']:
+            yield item['displayName']
+
+    def keys(self):
+        return list(self.iterkeys())
+
     def iteritems(self):
         for item in self._data['computer']:
             nodename = item['displayName']
-            if nodename == 'master':
+            if nodename.lower() == 'master':
                 nodeurl = '%s/(%s)' % (self.baseurl, nodename)
             else:
                 nodeurl = '%s/%s' % (self.baseurl, nodename)
-            yield item['displayName'], Node(nodeurl, nodename, self.jenkins)
+            try:
+                yield item['displayName'], Node(nodeurl, nodename, self.jenkins)
+            except Exception:
+                import ipdb; ipdb.set_trace()
 
     def __getitem__(self, nodename):
         for k, v in self.iteritems():
             if k == nodename:
                 return v
+        raise UnknownNode(nodename)
index 3f9a002..c0eb23d 100644 (file)
@@ -45,6 +45,7 @@ class Requester(object):
         requestKwargs = self.get_request_dict(url, params, None, headers)
         return requests.get(url, **requestKwargs)
 
+
     def post_url(self, url, params=None, data=None, headers=None):
         requestKwargs = self.get_request_dict(url, params, data, headers)
         return requests.post(url, **requestKwargs)
index 4fb3b90..e485e9f 100644 (file)
@@ -11,17 +11,37 @@ log = logging.getLogger(__name__)
 
 
 class TestNodes(BaseSystemTest):
+
     def test_invoke_job_parameterized(self):
         node_name = random_string()
-        J = Jenkins('http://localhost:8080')
-        J.create_node(node_name)
-        self.assertTrue(J.has_node(node_name))
+        self.jenkins.create_node(node_name)
+        self.assertTrue(self.jenkins.has_node(node_name))
+
+        N = self.jenkins.get_node(node_name)
+        self.assertEquals(N.baseurl, self.jenkins.get_node_url(node_name))
+
+        self.jenkins.delete_node(node_name)
+        self.assertFalse(self.jenkins.has_node(node_name))
+
+    def test_online_offline(self):
+        """
+        Can we flip the online / offline state of the master node.
+        """
+        # Master node name should be case insensitive
+        #mn0 = self.jenkins.get_node('MaStEr')
+        mn = self.jenkins.get_node('master')
+        #self.assertEquals(mn, mn0)
+
+        mn.set_online() # It should already be online, hence no-op
+        self.assertTrue(mn.is_online())
+
+        mn.set_offline() # We switch that suckah off
+        mn.set_offline() # This should be a no-op
+        self.assertFalse(mn.is_online())
 
-        N = J.get_node(node_name)
-        self.assertEquals(N.baseurl, J.get_node_url(node_name))
+        mn.set_online() # Switch it back on
+        self.assertTrue(mn.is_online())
 
-        J.delete_node(node_name)
-        self.assertFalse(J.has_node(node_name))
 
 if __name__ == '__main__':
     logging.basicConfig()
index fefd4e5..e595838 100644 (file)
@@ -48,4 +48,9 @@ class TestNode(unittest.TestCase):
         with self.assertRaises(AttributeError):
             self.n.id()
 
+    def test_online(self):
+        return assertEquals(self.n, True)
+
+
+
         self.assertEquals(self.n.name, 'bobnit')