Exemplo n.º 1
0
    def test_initialization_sets_up_default_client_correctly(self):
        nt.assert_equal(self.token, self.client.token)
        nt.assert_dict_contains_subset(
            {
                'X-Rundeck-Auth-Token': self.token,
                'User-Agent': 'PyRundeck v ' + __version__
            }, self.client.client_args['headers'])

        new_client = RundeckApiClient(
            self.token,
            config.root_url,
            client_args={'headers': {
                'User-Agent': 'dummy agent string'
            }})
        nt.assert_equal(self.token, new_client.token)
        nt.assert_dict_contains_subset(
            {
                'X-Rundeck-Auth-Token': self.token,
                'User-Agent': 'dummy agent string'
            }, new_client.client_args['headers'])

        newest_client = RundeckApiClient(
            self.token,
            config.root_url,
            client_args={'headers': {
                'bogus_header': 'bogus_value'
            }})

        nt.assert_dict_contains_subset(
            {
                'X-Rundeck-Auth-Token': self.token,
                'User-Agent': 'PyRundeck v ' + __version__
            }, newest_client.client_args['headers'])

        nt.assert_equal(self.token, newest_client.token)
Exemplo n.º 2
0
    def setup(self):
        self.token = 'dummy token'
        self.client = RundeckApiClient(self.token, config.root_url)

        class Object(object):
            pass

        self.resp = Object()  # Dummy response object
        self.resp.status_code = 200
        self.resp.text = """<test_xml attribute="foo">
Exemplo n.º 3
0
    def setup(self):
        self.token = 'dummy token'
        self.client = RundeckApiClient(self.token, config.root_url)

        class Object(object):
            pass

        self.resp = Object()  # Dummy response object
        self.resp.status_code = 200
        self.resp.text = """<test_xml attribute="foo">
Exemplo n.º 4
0
    def test_perform_request_calls_request_correctly_with_https(
            self, mock_request):
        mock_request.return_value = self.resp

        https_url = 'https://rundeck.example.com'

        client = RundeckApiClient(self.token, https_url)
        client._perform_request(https_url)

        args, kwargs = mock_request.call_args
        nt.assert_dict_contains_subset({'verify': True}, kwargs)

        path_to_pem = '/path/to/pem/file'
        other_client = RundeckApiClient(self.token,
                                        https_url,
                                        pem_file_path=path_to_pem)
        other_client._perform_request(https_url)
        args, kwargs = mock_request.call_args

        nt.assert_dict_contains_subset({'verify': path_to_pem}, kwargs)
Exemplo n.º 5
0
    def test_perform_request_calls_request_correctly_with_https(self,
                                                                mock_request):
        mock_request.return_value = self.resp

        https_url = 'https://rundeck.example.com'

        client = RundeckApiClient(self.token, https_url)
        client._perform_request(https_url)

        args, kwargs = mock_request.call_args
        nt.assert_dict_contains_subset({'verify': True}, kwargs)

        path_to_pem = '/path/to/pem/file'
        other_client = RundeckApiClient(self.token, https_url,
                                        pem_file_path=path_to_pem)
        other_client._perform_request(https_url)
        args, kwargs = mock_request.call_args

        nt.assert_dict_contains_subset({'verify': path_to_pem}, kwargs)
Exemplo n.º 6
0
class TestEndpoints(object):
    def __init__(self):
        self.root_url = 'http://www.example.com'
        self.xml_str = ('<result success="true" apiversion="13">'
                        '<jobs count="3">'
                        '<job id="3b8a86d5-4fc3-4cc1-95a2-8b51421c2069">'
                        '<name>job_with_args</name>'
                        '<group/>'
                        '<project>API_client_development</project>'
                        '<description/>'
                        '</job>'
                        '<job id="78f491e7-714f-44c6-bddb-8b3b3a961ace">'
                        '<name>test_job_1</name>'
                        '<group/>'
                        '<project>API_client_development</project>'
                        '<description/>'
                        '</job>'
                        '<job id="b07b05b0-0a37-4f88-8a51-4bee77ceefb4">'
                        '<name>test_job_2</name>'
                        '<group/>'
                        '<project>API_client_development</project>'
                        '<description/>'
                        '</job>'
                        '</jobs>'
                        '</result>')
        self.xml_tree = etree.fromstring(self.xml_str)
        self.native_result = {
            'apiversion': '13',
            'jobs': {
                'count': 3,
                'list': [
                    {
                        'description': '',
                        'group': '',
                        'id': '3b8a86d5-4fc3-4cc1-95a2-8b51421c2069',
                        'name': 'job_with_args',
                        'project': 'API_client_development'
                    },
                    {
                        'description': '',
                        'group': '',
                        'id': '78f491e7-714f-44c6-bddb-8b3b3a961ace',
                        'name': 'test_job_1',
                        'project': 'API_client_development'
                    },
                    {
                        'description': '',
                        'group': '',
                        'id': 'b07b05b0-0a37-4f88-8a51-4bee77ceefb4',
                        'name': 'test_job_2',
                        'project': 'API_client_development'
                    }
                ]
            },
            'success': 'true'
        }
        self.return_status = 200

    def setup(self):
        self.client = RundeckApiClient('mock_token', self.root_url)

    # Tests for RundeckApiClient.import_job
    @patch('pyrundeck.RundeckApiClient.post')
    def test_import_job_xml(self, mock_post):
        mock_post.return_value = (self.return_status, self.xml_tree)
        actual_url = '{}/api/1/jobs/import'.format(self.root_url)

        status, res = self.client.import_job(native=False,
                                             xmlBatch='mock xmlBatch')

        mock_post.assert_called_once_with(actual_url,
                                          {'xmlBatch': 'mock xmlBatch'})
        nt.assert_equal(status, self.return_status)
        nt.assert_true(element_equality(res, self.xml_tree))

    @patch('pyrundeck.RundeckApiClient.post')
    def test_import_job_native(self, mock_post):
        mock_post.return_value = (self.return_status, self.xml_tree)
        actual_url = '{}/api/1/jobs/import'.format(self.root_url)

        status, res = self.client.import_job(xmlBatch='mock xmlBatch')

        mock_post.assert_called_once_with(actual_url,
                                          {'xmlBatch': 'mock xmlBatch'})
        nt.assert_equal(status, self.return_status)
        nt.assert_equal(res, self.native_result)

    # Tests for RundeckApiClient.export_jobs
    @patch('pyrundeck.RundeckApiClient.get')
    def test_export_jobs_xml(self, mock_get):
        mock_get.return_value = (self.return_status, self.xml_tree)
        actual_url = '{}/api/1/jobs/export'.format(self.root_url)

        status, res = self.client.export_jobs(native=False)

        mock_get.assert_called_once_with(actual_url, {})
        nt.assert_equal(status, self.return_status)
        nt.assert_true(element_equality(res, self.xml_tree))

    @patch('pyrundeck.RundeckApiClient.get')
    def test_export_jobs_native(self, mock_get):
        mock_get.return_value = (self.return_status, self.xml_tree)
        actual_url = '{}/api/1/jobs/export'.format(self.root_url)

        status, res = self.client.export_jobs()

        mock_get.assert_called_once_with(actual_url, {})
        nt.assert_equal(status, self.return_status)
        nt.assert_equal(res, self.native_result)

    # Tests for RundeckApiClient.list_jobs
    @patch('pyrundeck.RundeckApiClient.get')
    def test_list_jobs_xml(self, mock_get):
        mock_get.return_value = (self.return_status, self.xml_tree)
        actual_url = '{}/api/1/jobs'.format(self.root_url)

        status, res = self.client.list_jobs(native=False,
                                            project='mock project arg')

        mock_get.assert_called_once_with(actual_url,
                                         {'project': 'mock project arg'})
        nt.assert_equal(status, self.return_status)
        nt.assert_true(element_equality(res, self.xml_tree))

    @patch('pyrundeck.RundeckApiClient.get')
    def test_list_jobs_native(self, mock_get):
        mock_get.return_value = (self.return_status, self.xml_tree)
        actual_url = '{}/api/1/jobs'.format(self.root_url)

        status, res = self.client.list_jobs(project='mock project arg')

        mock_get.assert_called_once_with(actual_url,
                                         {'project': 'mock project arg'})
        nt.assert_equal(status, self.return_status)
        nt.assert_equal(res, self.native_result)

    # Tests for RundeckApiClient.run_job
    @patch('pyrundeck.RundeckApiClient.get')
    def test_run_job_xml(self, mock_get):
        mock_get.return_value = (self.return_status, self.xml_tree)
        job_id = 'mock id'
        actual_url = '{}/api/1/job/{}/run'.format(self.root_url, job_id)

        status, res = self.client.run_job(native=False, id=job_id)

        mock_get.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_true(element_equality(res, self.xml_tree))

    @patch('pyrundeck.RundeckApiClient.get')
    def test_run_job_native(self, mock_get):
        mock_get.return_value = (self.return_status, self.xml_tree)
        job_id = 'mock id'
        actual_url = '{}/api/1/job/{}/run'.format(self.root_url, job_id)

        status, res = self.client.run_job(id=job_id)
        mock_get.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_equal(res, self.native_result)

    @raises(RundeckException)
    def test_run_job_raises_if_no_id(self):
        self.client.run_job()

    # Tests for RundeckApiClient.execution_info
    @patch('pyrundeck.RundeckApiClient.get')
    def test_execution_info_xml(self, mock_get):
        mock_get.return_value = (self.return_status, self.xml_tree)
        execution_id = 'mock id'
        actual_url = '{}/api/1/execution/{}'.format(self.root_url,
                                                    execution_id)

        status, res = self.client.execution_info(native=False, id=execution_id)

        mock_get.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_true(element_equality(res, self.xml_tree))

    @patch('pyrundeck.RundeckApiClient.get')
    def test_execution_info_native(self, mock_get):
        mock_get.return_value = (self.return_status, self.xml_tree)
        execution_id = 'mock id'
        actual_url = '{}/api/1/execution/{}'.format(self.root_url,
                                                    execution_id)

        status, res = self.client.execution_info(id=execution_id)

        mock_get.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_equal(res, self.native_result)

    @raises(RundeckException)
    def test_execution_info_raises_if_no_id(self):
        self.client.execution_info()

    # Tests for RundeckApiClient.delete_job
    @patch('pyrundeck.RundeckApiClient.delete')
    def test_delete(self, mock_delete):
        mock_delete.return_value = (self.return_status, '')
        job_id = 'mock id'
        actual_url = '{}/api/1/job/{}'.format(self.root_url,
                                              job_id)

        status, res = self.client.delete_job(id=job_id)

        mock_delete.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_equal('', res)

    @raises(RundeckException)
    def test_delete_raises_if_no_id(self):
        self.client.delete_job()

    # Tests for RundeckApiClient.job_executions_info
    @patch('pyrundeck.RundeckApiClient.get')
    def test_job_executions_info_xml(self, mock_get):
        mock_get.return_value = (self.return_status, self.xml_tree)
        job_id = 'mock id'
        actual_url = '{}/api/1/job/{}/executions'.format(self.root_url,
                                                         job_id)

        status, res = self.client.job_executions_info(native=False, id=job_id)

        mock_get.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_true(element_equality(res, self.xml_tree))

    @patch('pyrundeck.RundeckApiClient.get')
    def test_job_executions_info_native(self, mock_get):
        mock_get.return_value = (self.return_status, self.xml_tree)
        job_id = 'mock id'
        actual_url = '{}/api/1/job/{}/executions'.format(self.root_url,
                                                         job_id)

        status, res = self.client.job_executions_info(id=job_id)

        mock_get.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_equal(res, self.native_result)

    @raises(RundeckException)
    def test_job_executions_info_raises_if_no_id(self):
        self.client.job_executions_info()

    # Tests for RundeckApiClient.running_executions
    @patch('pyrundeck.RundeckApiClient.post')
    def test_running_executions_xml(self, mock_post):
        mock_post.return_value = (self.return_status, self.xml_tree)
        actual_url = '{}/api/1/executions/running'.format(self.root_url)

        status, res = self.client.running_executions(native=False)

        mock_post.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_true(element_equality(res, self.xml_tree))

    @patch('pyrundeck.RundeckApiClient.post')
    def test_running_executions_native(self, mock_post):
        mock_post.return_value = (self.return_status, self.xml_tree)
        actual_url = '{}/api/1/executions/running'.format(self.root_url)

        status, res = self.client.running_executions()

        mock_post.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_equal(res, self.native_result)

    # Tests for RundeckApiClient.system_info
    @patch('pyrundeck.RundeckApiClient.get')
    def test_system_info_xml(self, mock_get):
        mock_get.return_value = (self.return_status, self.xml_tree)
        actual_url = '{}/api/1/system/info'.format(self.root_url)

        status, res = self.client.system_info(native=False)

        mock_get.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_true(element_equality(res, self.xml_tree))

    @patch('pyrundeck.RundeckApiClient.get')
    def test_system_info_native(self, mock_get):
        mock_get.return_value = (self.return_status, self.xml_tree)
        actual_url = '{}/api/1/system/info'.format(self.root_url)

        status, res = self.client.system_info()

        mock_get.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_equal(res, self.native_result)

    # Tests for RundeckApiClient.job_definition
    @patch('pyrundeck.RundeckApiClient.get')
    def test_job_definition_xml(self, mock_get):
        mock_get.return_value = (self.return_status, self.xml_tree)
        job_id = 'mock id'
        actual_url = '{}/api/1/job/{}'.format(self.root_url, job_id)

        status, res = self.client.job_definition(native=False,
                                                 id=job_id)

        mock_get.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_true(element_equality(res, self.xml_tree))

    @patch('pyrundeck.RundeckApiClient.get')
    def test_job_definition_native(self, mock_get):
        mock_get.return_value = (self.return_status, self.xml_tree)
        job_id = 'mock id'
        actual_url = '{}/api/1/job/{}'.format(self.root_url, job_id)

        status, res = self.client.job_definition(id=job_id)

        mock_get.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_equal(res, self.native_result)

    @raises(RundeckException)
    def test_job_definition_raises_if_no_id(self):
        self.client.job_definition()

    # Tests for RundeckApiClient.bulk_job_delete
    @patch('pyrundeck.RundeckApiClient.delete')
    def test_bulk_job_delete_xml(self, mock_delete):
        mock_delete.return_value = (self.return_status, self.xml_tree)
        actual_url = '{}/api/5/jobs/delete'.format(self.root_url)

        status, res = self.client.bulk_job_delete(native=False)

        mock_delete.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_true(element_equality(res, self.xml_tree))

    @patch('pyrundeck.RundeckApiClient.delete')
    def test_bulk_job_delete_native(self, mock_delete):
        mock_delete.return_value = (self.return_status, self.xml_tree)
        actual_url = '{}/api/5/jobs/delete'.format(self.root_url)

        status, res = self.client.bulk_job_delete()

        mock_delete.assert_called_once_with(actual_url, {})

        nt.assert_equal(status, self.return_status)
        nt.assert_equal(res, self.native_result)
Exemplo n.º 7
0
 def setup(self):
     self.client = RundeckApiClient('mock_token', self.root_url)
Exemplo n.º 8
0
    def test_initialization_strips_final_slash_from_url(self):
        url = 'http://rundeck.example.com/'
        client = RundeckApiClient(self.token, url)

        nt.assert_equal(client.root_url, url[:-1])
Exemplo n.º 9
0
class TestCoreRundeckAPIClient:
    def setup(self):
        self.token = 'dummy token'
        self.client = RundeckApiClient(self.token, config.root_url)

        class Object(object):
            pass

        self.resp = Object()  # Dummy response object
        self.resp.status_code = 200
        self.resp.text = """<test_xml attribute="foo">
  <element other_attribute="lala">Text</element>
  <element>Other Text</element>
</test_xml>
"""

    def test_initialization_sets_up_default_client_correctly(self):
        nt.assert_equal(self.token, self.client.token)
        nt.assert_dict_contains_subset(
            {
                'X-Rundeck-Auth-Token': self.token,
                'User-Agent': 'PyRundeck v ' + __version__
            }, self.client.client_args['headers'])

        new_client = RundeckApiClient(
            self.token,
            config.root_url,
            client_args={'headers': {
                'User-Agent': 'dummy agent string'
            }})
        nt.assert_equal(self.token, new_client.token)
        nt.assert_dict_contains_subset(
            {
                'X-Rundeck-Auth-Token': self.token,
                'User-Agent': 'dummy agent string'
            }, new_client.client_args['headers'])

        newest_client = RundeckApiClient(
            self.token,
            config.root_url,
            client_args={'headers': {
                'bogus_header': 'bogus_value'
            }})

        nt.assert_dict_contains_subset(
            {
                'X-Rundeck-Auth-Token': self.token,
                'User-Agent': 'PyRundeck v ' + __version__
            }, newest_client.client_args['headers'])

        nt.assert_equal(self.token, newest_client.token)

    def test_initialization_strips_final_slash_from_url(self):
        url = 'http://rundeck.example.com/'
        client = RundeckApiClient(self.token, url)

        nt.assert_equal(client.root_url, url[:-1])

    @patch('pyrundeck.RundeckApiClient._perform_request')
    def test_get_method_correctly_calls_perform(self, mock_perform):
        url = 'https://rundeck.example.com/api/13/foo'
        params = {'a': 'b', 'c': 'd'}
        self.client.get(url, params=params)
        mock_perform.assert_called_once_with(url, params=params, method='GET')

    @patch('pyrundeck.RundeckApiClient._perform_request')
    def test_post_method_correctly_calls_perform(self, mock_perform):
        url = 'https://rundeck.example.com/api/13/foo'
        params = {'a': 'b', 'c': 'd'}
        self.client.post(url, params=params)
        mock_perform.assert_called_once_with(url, params=params, method='POST')

    @patch('pyrundeck.RundeckApiClient._perform_request')
    def test_delete_method_correctly_calls_perform(self, mock_perform):
        url = 'https://rundeck.example.com/api/13/foo'
        params = {'a': 'b', 'c': 'd'}
        self.client.delete(url, params=params)
        mock_perform.assert_called_once_with(url,
                                             params=params,
                                             method='DELETE')

    @patch('pyrundeck.RundeckApiClient._perform_request')
    def test_all_methods_return_correctly_perform_request_result(
            self, mock_perform):
        ret = 'mock_perform_value'
        mock_perform.return_value = ret
        res1 = self.client.get('foo')
        nt.assert_equal(res1, ret)

        res2 = self.client.post('foo')
        nt.assert_equal(res2, ret)

        res3 = self.client.delete('foo')
        nt.assert_equal(res3, ret)

    @patch('requests.request')
    def test_perform_request_called_correctly_for_get_method(
            self, mock_request):
        url = 'https://rundeck.example.com/api/13/test_endpoint'
        mock_request.return_value = self.resp

        self.client._perform_request(url)
        args = mock_request.call_args
        nt.assert_equal(2, len(args))
        nt.assert_equal((
            'GET',
            url,
        ), args[0])
        nt.assert_in('headers', args[1])
        headers = args[1]['headers']
        nt.assert_dict_contains_subset(
            {
                'X-Rundeck-Auth-Token': self.token,
                'User-Agent': 'PyRundeck v ' + __version__
            }, headers)

    @patch('requests.request')
    def test_perform_requests_called_correctly_for_post_method(
            self, mock_request):
        url = 'https://rundeck.example.com/api/13/test_endpoint'
        mock_request.return_value = self.resp

        self.client._perform_request(url,
                                     method='POST',
                                     params={'xmlBatch': '123\n456'})

        args = mock_request.call_args
        nt.assert_equal(2, len(args))
        nt.assert_equal((
            'POST',
            url,
        ), args[0])
        nt.assert_in('headers', args[1])
        nt.assert_in('data', args[1])
        headers = args[1]['headers']
        nt.assert_dict_contains_subset(
            {
                'X-Rundeck-Auth-Token': self.token,
                'User-Agent': 'PyRundeck v ' + __version__
            }, headers)
        data = args[1]['data']
        nt.assert_dict_contains_subset({'xmlBatch': '123\n456'}, data)

    @patch('requests.request')
    def test_perform_request_returns_correctly_for_get_method(self, mock_get):
        mock_get.return_value = self.resp

        url = 'https://rundeck.example.com/api/13/test_endpoint'
        status, data = self.client._perform_request(url)
        nt.assert_equal(200, status)
        nt.assert_equal(
            self.resp.text,
            etree.tostring(data, pretty_print=True).decode('utf-8'))

    @patch('requests.request')
    def test_perform_request_calls_request_correctly_with_https(
            self, mock_request):
        mock_request.return_value = self.resp

        https_url = 'https://rundeck.example.com'

        client = RundeckApiClient(self.token, https_url)
        client._perform_request(https_url)

        args, kwargs = mock_request.call_args
        nt.assert_dict_contains_subset({'verify': True}, kwargs)

        path_to_pem = '/path/to/pem/file'
        other_client = RundeckApiClient(self.token,
                                        https_url,
                                        pem_file_path=path_to_pem)
        other_client._perform_request(https_url)
        args, kwargs = mock_request.call_args

        nt.assert_dict_contains_subset({'verify': path_to_pem}, kwargs)

    @patch('requests.request')
    def test_perform_request_returns_correctly_on_empty_response(
            self, mock_request):
        class Object:
            pass

        resp = Object()
        resp.status_code = 200
        resp.text = ''

        mock_request.return_value = resp

        response = self.client._perform_request(self.client.root_url)

        nt.assert_equal(response, (200, None))
Exemplo n.º 10
0
class TestCoreRundeckAPIClient:
    def setup(self):
        self.token = 'dummy token'
        self.client = RundeckApiClient(self.token, config.root_url)

        class Object(object):
            pass

        self.resp = Object()  # Dummy response object
        self.resp.status_code = 200
        self.resp.text = """<test_xml attribute="foo">
  <element other_attribute="lala">Text</element>
  <element>Other Text</element>
</test_xml>
"""

    def test_initialization_sets_up_default_client_correctly(self):
        nt.assert_equal(self.token, self.client.token)
        nt.assert_dict_contains_subset({'X-Rundeck-Auth-Token':
                                        self.token, 'User-Agent':
                                        'PyRundeck v ' + __version__},
                                       self.client.client_args['headers'])

        new_client = RundeckApiClient(self.token, config.root_url,
                                      client_args={'headers':
                                                   {'User-Agent':
                                                    'dummy agent string'}})
        nt.assert_equal(self.token, new_client.token)
        nt.assert_dict_contains_subset({
            'X-Rundeck-Auth-Token': self.token,
            'User-Agent': 'dummy agent string'
        }, new_client.client_args['headers'])

        newest_client = RundeckApiClient(self.token, config.root_url,
                                         client_args={
                                             'headers':
                                             {
                                                 'bogus_header': 'bogus_value'
                                             }
                                         })

        nt.assert_dict_contains_subset({'X-Rundeck-Auth-Token': self.token,
                                        'User-Agent':
                                        'PyRundeck v ' + __version__},
                                       newest_client.client_args['headers'])

        nt.assert_equal(self.token, newest_client.token)

    def test_initialization_strips_final_slash_from_url(self):
        url = 'http://rundeck.example.com/'
        client = RundeckApiClient(self.token, url)

        nt.assert_equal(client.root_url, url[:-1])

    @patch('pyrundeck.RundeckApiClient._perform_request')
    def test_get_method_correctly_calls_perform(self, mock_perform):
        url = 'https://rundeck.example.com/api/13/foo'
        params = {
            'a': 'b',
            'c': 'd'
        }
        self.client.get(url, params=params)
        mock_perform.assert_called_once_with(url, params=params, method='GET')

    @patch('pyrundeck.RundeckApiClient._perform_request')
    def test_post_method_correctly_calls_perform(self, mock_perform):
        url = 'https://rundeck.example.com/api/13/foo'
        params = {
            'a': 'b',
            'c': 'd'
        }
        self.client.post(url, params=params)
        mock_perform.assert_called_once_with(url, params=params, method='POST')

    @patch('pyrundeck.RundeckApiClient._perform_request')
    def test_delete_method_correctly_calls_perform(self, mock_perform):
        url = 'https://rundeck.example.com/api/13/foo'
        params = {
            'a': 'b',
            'c': 'd'
        }
        self.client.delete(url, params=params)
        mock_perform.assert_called_once_with(url, params=params,
                                             method='DELETE')

    @patch('pyrundeck.RundeckApiClient._perform_request')
    def test_all_methods_return_correctly_perform_request_result(self,
                                                                 mock_perform):
        ret = 'mock_perform_value'
        mock_perform.return_value = ret
        res1 = self.client.get('foo')
        nt.assert_equal(res1, ret)

        res2 = self.client.post('foo')
        nt.assert_equal(res2, ret)

        res3 = self.client.delete('foo')
        nt.assert_equal(res3, ret)

    @patch('requests.request')
    def test_perform_request_called_correctly_for_get_method(self,
                                                             mock_request):
        url = 'https://rundeck.example.com/api/13/test_endpoint'
        mock_request.return_value = self.resp

        self.client._perform_request(url)
        args = mock_request.call_args
        nt.assert_equal(2, len(args))
        nt.assert_equal(('GET', url,), args[0])
        nt.assert_in('headers', args[1])
        headers = args[1]['headers']
        nt.assert_dict_contains_subset({'X-Rundeck-Auth-Token': self.token,
                                        'User-Agent':
                                        'PyRundeck v ' + __version__},
                                       headers)

    @patch('requests.request')
    def test_perform_requests_called_correctly_for_post_method(self,
                                                               mock_request):
        url = 'https://rundeck.example.com/api/13/test_endpoint'
        mock_request.return_value = self.resp

        self.client._perform_request(url, method='POST',
                                     params={'xmlBatch': '123\n456'})

        args = mock_request.call_args
        nt.assert_equal(2, len(args))
        nt.assert_equal(('POST', url,), args[0])
        nt.assert_in('headers', args[1])
        nt.assert_in('data', args[1])
        headers = args[1]['headers']
        nt.assert_dict_contains_subset({'X-Rundeck-Auth-Token': self.token,
                                        'User-Agent':
                                        'PyRundeck v ' + __version__},
                                       headers)
        data = args[1]['data']
        nt.assert_dict_contains_subset({'xmlBatch': '123\n456'}, data)

    @patch('requests.request')
    def test_perform_request_returns_correctly_for_get_method(self, mock_get):
        mock_get.return_value = self.resp

        url = 'https://rundeck.example.com/api/13/test_endpoint'
        status, data = self.client._perform_request(url)
        nt.assert_equal(200, status)
        nt.assert_equal(self.resp.text,
                        etree.tostring(data,
                                       pretty_print=True).decode('utf-8'))

    @patch('requests.request')
    def test_perform_request_calls_request_correctly_with_https(self,
                                                                mock_request):
        mock_request.return_value = self.resp

        https_url = 'https://rundeck.example.com'

        client = RundeckApiClient(self.token, https_url)
        client._perform_request(https_url)

        args, kwargs = mock_request.call_args
        nt.assert_dict_contains_subset({'verify': True}, kwargs)

        path_to_pem = '/path/to/pem/file'
        other_client = RundeckApiClient(self.token, https_url,
                                        pem_file_path=path_to_pem)
        other_client._perform_request(https_url)
        args, kwargs = mock_request.call_args

        nt.assert_dict_contains_subset({'verify': path_to_pem}, kwargs)

    @patch('requests.request')
    def test_perform_request_returns_correctly_on_empty_response(self,
                                                                 mock_request):
        class Object:
            pass

        resp = Object()
        resp.status_code = 200
        resp.text = ''

        mock_request.return_value = resp

        response = self.client._perform_request(self.client.root_url)

        nt.assert_equal(response, (200, None))