def test_incomplete_and_failing_produce_warnings(self):
        """
        When both saved search fails with Check Exception, the code should continue and send topology.
        """
        instance = {
            'url': 'http://localhost:8089',
            'authentication': {
                'basic_auth': {
                    'username': "******",
                    'password': "******"
                }
            },
            'ignore_saved_search_errors': True,
        }

        instance = SplunkInstanceConfig(instance, {}, mock_defaults)
        searches = SavedSearches(instance, self.mock_splunk_client, [SplunkSavedSearch(instance, {'name': 'search1'}),
                                                                     SplunkSavedSearch(instance,
                                                                                       {'name': 'search_broken'})])
        self.mock_splunk_client.dispatch_results['search1'] = 'sid1'
        self.mock_splunk_client.dispatch_results['search_broken'] = 'broken_sid'

        data1 = {'messages': [], 'results': [{'data': 'result1'}]}
        self.mock_splunk_client.saved_search_results_results['sid1'] = [data1]
        self.mock_process_data.ret_val = 1

        searches.run_saved_searches(self.mock_process_data.function, self.mock_service_check.function, self.log,
                                    self.committable_state)

        assert self.mock_service_check.results == [
                                                   [AgentCheck.WARNING, [], None,
                                                    "All result of saved search 'search1' contained incomplete data"],
                                                   [AgentCheck.WARNING, [], None, "'broken_sid'"]]
    def test_wildcard_topology(self):
        instance = SplunkInstanceConfig(base_instance, {}, mock_defaults)
        searches = SavedSearches(instance, self.mock_splunk_client, [SplunkSavedSearch(instance, {'match': 'comp.*'}),
                                                                     SplunkSavedSearch(instance, {'match': 'rel.*'})])
        self.mock_splunk_client.saved_searches_result = ["components", "relations"]
        self.mock_splunk_client.dispatch_results['components'] = 'sid1'
        self.mock_splunk_client.dispatch_results['relations'] = 'sid2'

        data1 = {'messages': [], 'results': [{'data': 'result1'}]}
        data2 = {'messages': [], 'results': [{'data': 'result2'}]}
        self.mock_splunk_client.saved_search_results_results['sid1'] = [data1]
        self.mock_splunk_client.saved_search_results_results['sid2'] = [data2]

        searches.run_saved_searches(self.mock_process_data.function, self.mock_service_check.function, self.log,
                                    self.committable_state)
        assert len(self.mock_process_data.results) == 2
        assert self.mock_service_check.results == [[AgentCheck.OK, None, None, None]]

        # Now drop all saved searches and see them disappear
        self.mock_splunk_client.saved_searches_result = []
        self.mock_process_data = MockProcessData()
        self.mock_service_check = MockServiceCheck()
        searches.run_saved_searches(self.mock_process_data.function, self.mock_service_check.function, self.log,
                                    self.committable_state)
        assert self.mock_process_data.results == []
        assert self.mock_service_check.results == [[AgentCheck.OK, None, None, None]]
    def test_ignore_saved_search_errors_continue(self):
        """
        When 1 saved search fails with Check Exception, the code should continue and send
        topology if issues are ignored.
        """
        instance = {
            'url': 'http://localhost:8089',
            'ignore_saved_search_errors': True,
            'authentication': {
                'basic_auth': {
                    'username': "******",
                    'password': "******"
                }
            },
            'tags': ['mytag', 'mytag2']
        }

        instance = SplunkInstanceConfig(instance, {}, mock_defaults)
        searches = SavedSearches(instance, self.mock_splunk_client,
                                 [SplunkSavedSearch(instance, {'name': 'search_broken'}),
                                  SplunkSavedSearch(instance, {'name': 'search1'})])
        self.mock_splunk_client.dispatch_results['search_broken'] = 'sid_broken'
        self.mock_splunk_client.dispatch_results['search1'] = 'sid1'

        data1 = {'messages': [], 'results': [{'data': 'result1'}]}
        self.mock_splunk_client.saved_search_results_results['sid1'] = [data1]

        searches.run_saved_searches(self.mock_process_data.function, self.mock_service_check.function, self.log,
                                    self.committable_state)
        assert self.mock_process_data.results == [data1]
        assert self.mock_service_check.results == [[AgentCheck.WARNING, ['mytag', 'mytag2'], None, "'sid_broken'"]]
    def test_partially_incomplete_and_incomplete(self):
        instance = SplunkInstanceConfig(base_instance, {}, mock_defaults)
        searches = SavedSearches(instance, self.mock_splunk_client, [SplunkSavedSearch(instance, {'name': 'search1'}),
                                                                     SplunkSavedSearch(instance, {'name': 'search2'})])
        self.mock_splunk_client.dispatch_results['search1'] = 'sid1'
        self.mock_splunk_client.dispatch_results['search2'] = 'sid2'

        data1 = {'messages': [], 'results': [{'data': 'result1'}, {'data': 'result1_2'}]}
        data2 = {'messages': [], 'results': [{'data': 'result2'}]}
        self.mock_splunk_client.saved_search_results_results['sid1'] = [data1]
        self.mock_splunk_client.saved_search_results_results['sid2'] = [data2]
        self.mock_process_data.ret_val = 1

        issue = None
        try:
            searches.run_saved_searches(self.mock_process_data.function, self.mock_service_check.function, self.log,
                                        self.committable_state)
            issue = False
        except CheckException:
            issue = True
        assert issue

        assert self.mock_process_data.results == [data1, data2]
        assert self.mock_service_check.results == [[AgentCheck.WARNING, ['mytag', 'mytag2'], None,
                                                    "The saved search 'search1' contained 1 incomplete records"]]
    def test_process_data(self):
        instance = SplunkInstanceConfig(base_instance, {}, mock_defaults)
        searches = SavedSearches(instance, self.mock_splunk_client, [SplunkSavedSearch(instance, {'name': 'search1'}),
                                                                     SplunkSavedSearch(instance, {'name': 'search2'})])
        self.mock_splunk_client.dispatch_results['search1'] = 'sid1'
        self.mock_splunk_client.dispatch_results['search2'] = 'sid2'

        data1 = {'messages': [], 'results': [{'data': 'result1'}]}
        data2 = {'messages': [], 'results': [{'data': 'result2'}]}
        self.mock_splunk_client.saved_search_results_results['sid1'] = [data1]
        self.mock_splunk_client.saved_search_results_results['sid2'] = [data2]

        searches.run_saved_searches(self.mock_process_data.function, self.mock_service_check.function, self.log,
                                    self.committable_state)
        assert self.mock_process_data.results == [data1, data2]
        assert self.mock_service_check.results == [[AgentCheck.OK, None, None, None]]
    def test_keep_sid_when_finalize_fails(self):
        instance = SplunkInstanceConfig(base_instance, {}, mock_defaults)
        mock_splunk_client = MockSplunkClientFailFinalize()
        searches = SavedSearches(instance, mock_splunk_client, [SplunkSavedSearch(instance, {'name': 'breaking'})])

        # Dispatch should succeed, but not the result retrieval
        mock_splunk_client.dispatch_results['breaking'] = 'sid1'

        issue = None
        try:
            searches.run_saved_searches(self.mock_process_data.function, self.mock_service_check.function, self.log,
                                        self.committable_state)
            issue = False
        except Exception:
            issue = True
        assert issue
        assert self.mock_service_check.results == []
        assert self.committable_state.state == {'sid_breaking': 'sid1'}

        # Run again, this will trigger an issue during finalize
        issue2 = None
        try:
            searches.run_saved_searches(self.mock_process_data.function, self.mock_service_check.function, self.log,
                                        self.committable_state)
            issue2 = False
        except FinalizeException:
            issue2 = True
        assert issue2

        assert mock_splunk_client.finalized == ['sid1']
        assert self.mock_service_check.results == []
        assert self.committable_state.state == {'sid_breaking': 'sid1'}
    def test_store_and_finalize_sids(self):
        instance = SplunkInstanceConfig(base_instance, {}, mock_defaults)
        searches = SavedSearches(instance, self.mock_splunk_client, [SplunkSavedSearch(instance, {'name': 'breaking'})])

        # Dispatch should succeed, but not the result retrieval
        self.mock_splunk_client.dispatch_results['breaking'] = 'sid1'

        issue = True
        try:
            searches.run_saved_searches(self.mock_process_data.function, self.mock_service_check.function, self.log,
                                        self.committable_state)
            issue = False
        except Exception:
            issue = True
        assert issue
        assert self.mock_service_check.results == []
        assert self.committable_state.state == {'sid_breaking': 'sid1'}

        # Make sure it now runs correctly
        data1 = {'messages': [], 'results': [{'data': 'result1'}]}
        self.mock_splunk_client.saved_search_results_results['sid1'] = [data1]

        # Run again, this finalizes and reruns the search
        searches.run_saved_searches(self.mock_process_data.function, self.mock_service_check.function, self.log,
                                    self.committable_state)
        assert self.mock_splunk_client.finalized == ['sid1']
        assert self.mock_service_check.results == [[AgentCheck.OK, None, None, None]]
        assert self.committable_state.state == {'sid_breaking': 'sid1'}
    def test_does_not_exceed_parallel_dispatches(self):
        saved_searches_parallel = 2

        instance = {
            'url': 'http://localhost:8089',
            'saved_searches_parallel': saved_searches_parallel,
            'authentication': {
                'basic_auth': {
                    'username': "******",
                    'password': "******"
                }
            },
            'tags': ['mytag', 'mytag2']
        }

        instance = SplunkInstanceConfig(instance, {}, mock_defaults)
        searches = SavedSearches(instance, self.mock_splunk_client, [SplunkSavedSearch(instance, {'name': 'search1'}),
                                                                     SplunkSavedSearch(instance, {'name': 'search2'}),
                                                                     SplunkSavedSearch(instance, {'name': 'search3'}),
                                                                     SplunkSavedSearch(instance, {'name': 'search4'})
                                                                     ])
        self.mock_splunk_client.max_parallel_searches = saved_searches_parallel

        self.mock_splunk_client.dispatch_results['search1'] = 'sid1'
        self.mock_splunk_client.dispatch_results['search2'] = 'sid2'
        self.mock_splunk_client.dispatch_results['search3'] = 'sid3'
        self.mock_splunk_client.dispatch_results['search4'] = 'sid4'

        self.mock_splunk_client.saved_search_results_results['sid1'] = []
        self.mock_splunk_client.saved_search_results_results['sid2'] = []
        self.mock_splunk_client.saved_search_results_results['sid3'] = []
        self.mock_splunk_client.saved_search_results_results['sid4'] = []

        searches.run_saved_searches(self.mock_process_data.function, self.mock_service_check.function, self.log,
                                    self.committable_state)
        assert self.mock_process_data.results == []
        assert self.mock_service_check.results == [[AgentCheck.OK, None, None, None]]
    def test_incomplete_data(self):
        instance = SplunkInstanceConfig(base_instance, {}, mock_defaults)
        searches = SavedSearches(instance, self.mock_splunk_client, [SplunkSavedSearch(instance, {'name': 'search1'}),
                                                                     SplunkSavedSearch(instance, {'name': 'search2'})])
        self.mock_splunk_client.dispatch_results['search1'] = 'sid1'
        self.mock_splunk_client.dispatch_results['search2'] = 'sid2'

        data1 = {'messages': [], 'results': [{'data': 'result1'}]}
        data2 = {'messages': [], 'results': [{'data': 'result2'}]}
        self.mock_splunk_client.saved_search_results_results['sid1'] = [data1]
        self.mock_splunk_client.saved_search_results_results['sid2'] = [data2]
        self.mock_process_data.ret_val = 1

        issue = None
        try:
            searches.run_saved_searches(self.mock_process_data.function, self.mock_service_check.function, self.log,
                                        self.committable_state)
            issue = False
        except CheckException:
            issue = True
        assert issue

        assert self.mock_process_data.results == [data1]
        assert self.mock_service_check.results == []