def search_and_install_packs_and_their_dependencies_private(
        test_pack_path: str,
        pack_ids: list,
        client: demisto_client,
        prints_manager: ParallelPrintsManager,
        thread_index: int = 0):
    """ Searches for the packs from the specified list, searches their dependencies, and then installs them.
    Args:
        test_pack_path (str): Path of where the test packs are located.
        pack_ids (list): A list of the pack ids to search and install.
        client (demisto_client): The client to connect to.
        prints_manager (ParallelPrintsManager): A prints manager object.
        thread_index (int): the thread index.

    Returns (list, bool):
        A list of the installed packs' ids, or an empty list if is_nightly == True.
        A flag that indicates if the operation succeeded or not.
    """
    host = client.api_client.configuration.host

    msg = f'Starting to search and install packs in server: {host}'
    prints_manager.add_print_job(msg, print_color, thread_index,
                                 LOG_COLORS.GREEN)
    prints_manager.execute_thread_prints(thread_index)

    install_packs_private(client, host, prints_manager, thread_index, pack_ids,
                          test_pack_path)

    return SUCCESS_FLAG
def install_packs_from_artifacts(client: demisto_client, host: str,
                                 prints_manager: ParallelPrintsManager,
                                 thread_index: int, test_pack_path: str,
                                 pack_ids_to_install: List):
    """
    Installs all the packs located in the artifacts folder of the BitHub actions build. Please note:
    The server always returns a 200 status even if the pack was not installed.

    :param client: Demisto-py client to connect to the server.
    :param host: FQDN of the server.
    :param prints_manager: ParallelPrintsManager - Will be deprecated.
    :param thread_index: Integer indicating which thread the test is running on.
    :param test_pack_path: Path the the test pack directory.
    :param pack_ids_to_install: List of pack IDs to install.
    :return: None. Call to server waits until a successful response.
    """
    print(f"Test pack path is: {test_pack_path}")
    print(f"Pack IDs to install are: {pack_ids_to_install}")
    local_packs = glob.glob(f"{test_pack_path}/*.zip")
    for local_pack in local_packs:
        if any(pack_id in local_pack for pack_id in pack_ids_to_install):
            packs_install_msg = f'Installing the following pack: {local_pack}'
            prints_manager.add_print_job(packs_install_msg,
                                         print_color,
                                         thread_index,
                                         LOG_COLORS.GREEN,
                                         include_timestamp=True)
            upload_zipped_packs(client=client,
                                host=host,
                                prints_manager=prints_manager,
                                thread_index=thread_index,
                                pack_path=local_pack)
Beispiel #3
0
def install_packs_private(build: Build,
                          prints_manager: ParallelPrintsManager,
                          pack_ids: list = None) -> bool:
    """
    Wrapper for the search and install packs function.

    :param build: Build object containing the build settings.
    :param prints_manager: PrintsManager object used for reporting status. Will be deprecated.
    :param pack_ids: Optional, list of packs to install. List contains pack id and version requested.
    :return: Boolean indicating if the installation was successful.
    """
    pack_ids = pack_ids if pack_ids else build.pack_ids_to_install
    installed_content_packs_successfully = True
    for server in build.servers:
        try:
            flag = search_and_install_packs_and_their_dependencies_private(
                build.test_pack_path, pack_ids, server.client)
            if not flag:
                raise Exception('Failed to search and install packs.')
        except Exception as exc:
            prints_manager.add_print_job(str(exc), print_error, 0)
            prints_manager.execute_thread_prints(0)
            installed_content_packs_successfully = False

    return installed_content_packs_successfully
def update_round_set_and_sleep_if_round_completed(
        executed_in_current_round: set, prints_manager: ParallelPrintsManager,
        t: dict, thread_index: int) -> set:
    """
    Checks if the string representation of the current test configuration is already in
    the executed_in_current_round set.
    If it is- it means we have already executed this test and the we have reached a round and
    there are tests that
    were not able to be locked by this execution..
    In that case we want to start a new round monitoring by emptying the
    'executed_in_current_round' set and sleep
    in order to let the tests be unlocked
    Args:
        executed_in_current_round: A set containing the string representation of all tests
        configuration as they appear
        in conf.json file that were already executed in the current round
        prints_manager: ParallelPrintsManager object
        t: test configuration as it appears in conf.json file
        thread_index: Currently executing thread

    Returns:
        A new executed_in_current_round set which contains only the current tests configuration if a
        round was completed else it just adds the new test to the set.
    """
    if str(t) in executed_in_current_round:
        prints_manager.add_print_job(
            'all tests in the queue were executed, sleeping for 30 seconds to let locked tests get unlocked.',
            print, thread_index)
        executed_in_current_round = set()
        time.sleep(30)
    executed_in_current_round.add(str(t))
    return executed_in_current_round
Beispiel #5
0
def test_instances(secret_conf_path, server, username, password):
    integrations = get_integrations(secret_conf_path)

    instance_ids = []
    failed_integrations = []
    integrations_counter = 0

    prints_manager = ParallelPrintsManager(1)

    content_installation_client = demisto_client.configure(base_url=server,
                                                           username=username,
                                                           password=password,
                                                           verify_ssl=False)
    install_new_content(content_installation_client, server)
    for integration in integrations:
        c = demisto_client.configure(base_url=server,
                                     username=username,
                                     password=password,
                                     verify_ssl=False)
        integrations_counter += 1
        integration_name = integration.get('name')
        integration_instance_name = integration.get('instance_name', '')
        integration_params = integration.get('params')
        devops_comments = integration.get('devops_comments')
        product_description = integration.get('product_description', '')
        is_byoi = integration.get('byoi', True)
        has_integration = integration.get('has_integration', True)
        validate_test = integration.get('validate_test', True)

        if has_integration:
            instance_id, failure_message, _ = __create_integration_instance(
                c,
                integration_name,
                integration_instance_name,
                integration_params,
                is_byoi,
                prints_manager,
                validate_test=validate_test)
            if failure_message == 'No configuration':
                print_warning(
                    "Warning: skipping {} as it exists in content-test-conf conf.json but not "
                    "in content repo".format(integration_name))
                continue
            if not instance_id:
                print_error(
                    'Failed to create instance of {} with message: {}'.format(
                        integration_name, failure_message))
                failed_integrations.append(
                    "{} {} - devops comments: {}".format(
                        integration_name, product_description,
                        devops_comments))
            else:
                instance_ids.append(instance_id)
                print('Create integration %s succeed' % (integration_name, ))
                __delete_integrations_instances(c, instance_ids,
                                                prints_manager)

            prints_manager.execute_thread_prints(0)

    return failed_integrations, integrations_counter
def search_and_install_packs_and_their_dependencies_private(
        test_pack_path: str,
        pack_ids: list,
        client: demisto_client,
        prints_manager: ParallelPrintsManager,
        thread_index: int = 0):
    """ Searches for the packs from the specified list, searches their dependencies, and then installs them.
    Args:
        test_pack_path (str): Path of where the test packs are located.
        pack_ids (list): A list of the pack ids to search and install.
        client (demisto_client): The client to connect to.
        prints_manager (ParallelPrintsManager): A prints manager object.
        thread_index (int): the thread index.

    Returns (list, bool):
        A list of the installed packs' ids, or an empty list if is_nightly == True.
        A flag that indicates if the operation succeeded or not.
    """
    host = client.api_client.configuration.host

    msg = f'Starting to search and install packs in server: {host}'
    prints_manager.add_print_job(msg, print_color, thread_index,
                                 LOG_COLORS.GREEN)
    prints_manager.execute_thread_prints(thread_index)

    packs_to_install = [
    ]  # we save all the packs we want to install, to avoid duplications
    installation_request_body = [
    ]  # the packs to install, in the request format

    threads_list = []
    lock = Lock()

    for pack_id in pack_ids:
        thread = Thread(target=search_pack_and_its_dependencies,
                        kwargs={
                            'client': client,
                            'prints_manager': prints_manager,
                            'pack_id': pack_id,
                            'packs_to_install': packs_to_install,
                            'installation_request_body':
                            installation_request_body,
                            'thread_index': thread_index,
                            'lock': lock
                        })
        threads_list.append(thread)
    run_threads_list(threads_list)

    install_packs_private(client, host, prints_manager, thread_index, pack_ids,
                          test_pack_path)

    return packs_to_install, SUCCESS_FLAG
def manage_tests(tests_settings: SettingsTester):
    """
    This function manages the execution of Demisto's tests.

    Args:
        tests_settings (SettingsTester): An object containing all the relevant data regarding how the
                                        tests should be ran.

    """
    tests_settings.serverNumericVersion = get_server_numeric_version(tests_settings.serverVersion,
                                                                     tests_settings.is_local_run)
    instances_ips = get_instances_ips_and_names(tests_settings)
    number_of_instances = len(instances_ips)
    prints_manager = ParallelPrintsManager(number_of_instances)
    tests_data_keeper = DataKeeperTester()

    for ami_instance_name, ami_instance_ip in instances_ips:
        if ami_instance_name == tests_settings.serverVersion:
            print_color("Starting private testing for {}".format(ami_instance_name), LOG_COLORS.GREEN)
            print("Starts tests with server url - https://{}".format(ami_instance_ip))
            all_tests = get_all_tests(tests_settings)
            execute_testing(tests_settings, ami_instance_ip, all_tests, tests_data_keeper,
                            prints_manager, thread_index=0)
            sleep(8)

    print_test_summary(tests_data_keeper, tests_settings.isAMI)
    create_result_files(tests_data_keeper)

    if tests_data_keeper.failed_playbooks:
        tests_failed_msg = "Some tests have failed. Not destroying instances."
        print(tests_failed_msg)
        sys.exit(1)
def test_install_packs_private(mocker):
    """
    Scenario: Given a pack ID to install, the test will simulate opening the content_packs_to_install
              file and will first install the Demisto test license, then install the pack from the
              artifacts directory. Important to note here, that the server does not return any status
              code to indicate that the upload was successful. As long as the request returns a 200,
              we assume the installation was successful. This should be changed at some point however.
    Given: The test pack ID "TEST"
    When: Installing the pack from the artifacts directory
    Then: Collect the pack ID from the packs to install file, update the license, and upload the pack.
    """

    prints_manager = ParallelPrintsManager(len(BuildMock().servers))
    mocker.patch('Tests.Marketplace.search_and_install_packs.open', return_value=StringIO('HelloWorld\nTEST'))
    mocker.patch('Tests.Marketplace.search_and_install_packs.search_pack_and_its_dependencies')

    def mocked_generic_request_func(self, path: str, method, body=None, accept=None,
                                    _request_timeout=None):
        if path == '/contentpacks/marketplace/install':
            return 'MOCK_PACKS_INSTALLATION_RESULT', 200, None
        return None, None, None

    mocker.patch.object(demisto_client, 'generic_request_func',
                        side_effect=mocked_generic_request_func)
    mocker.patch.object(glob, 'glob', return_value=['content/artifacts/packs/TEST.zip'])
    mock_build = BuildMock()
    mock_build.test_pack_path = 'content/artifacts/packs'
    mock_build.pack_ids_to_install = ['TestPack']
    test_results = install_packs_private(build=mock_build, prints_manager=prints_manager,
                                         pack_ids=['TEST'])
    assert test_results is True
def test_search_and_install_packs_and_their_dependencies(mocker):
    """
    Given
    - Valid and invalid integrations paths.
    When
    - Running integrations configuration tests.
    Then
    - Ensure packs & their dependencies' search requests are valid.
    - Ensure packs & their dependencies' installation requests are valid.
    """
    good_pack_ids = ['HelloWorld', 'AzureSentinel']

    bad_pack_ids = ['malformed_pack_id']

    client = MockClient()

    mocker.patch.object(demisto_client,
                        'generic_request_func',
                        side_effect=mocked_generic_request_func)
    mocker.patch.object(script,
                        'get_pack_display_name',
                        side_effect=mocked_get_pack_display_name)
    prints_manager = ParallelPrintsManager(1)

    installed_packs, success = script.search_and_install_packs_and_their_dependencies(
        good_pack_ids, client, prints_manager, is_private=False)
    assert 'HelloWorld' in installed_packs
    assert 'AzureSentinel' in installed_packs
    assert 'TestPack' in installed_packs
    assert success is True

    installed_packs, _ = script.search_and_install_packs_and_their_dependencies(
        bad_pack_ids, client, prints_manager, is_private=False)
    assert bad_pack_ids[0] not in installed_packs
Beispiel #10
0
def main():
    install_logging('Configure and Install Packs.log')
    options = options_handler()

    # Get the host by the ami env
    hosts, _ = Build.get_servers(ami_env=options.ami_env)

    logging.info('Retrieving the credentials for Cortex XSOAR server')
    secret_conf_file = get_json_file(path=options.secret)
    username: str = secret_conf_file.get('username')
    password: str = secret_conf_file.get('userPassword')

    # Configure the Servers
    for host in hosts:
        server = Server(host=host, user_name=username, password=password)
        logging.info(f'Adding Marketplace configuration to {host}')
        error_msg: str = 'Failed to set marketplace configuration.'
        server.add_server_configuration(config_dict=MARKET_PLACE_CONFIGURATION,
                                        error_msg=error_msg)
        set_marketplace_url(servers=[server],
                            branch_name=options.branch,
                            ci_build_number=options.build_number)

        # Acquire the server's host and install all content packs (one threaded execution)
        logging.info(f'Starting to install all content packs in {host}')
        server_host: str = server.client.api_client.configuration.host
        install_all_content_packs(client=server.client,
                                  host=server_host,
                                  prints_manager=ParallelPrintsManager(1))
        logging.success(f'Finished installing all content packs in {host}')
def test_search_and_install_packs_and_their_dependencies_with_error(mocker):
    """
    Given
    - Error when searching for a pack
    When
    - Running integrations configuration tests.
    Then
    - Ensure a flag is raised
    """
    good_pack_ids = ['HelloWorld']

    client = MockClient()

    mocker.patch.object(script, 'install_packs')
    mocker.patch.object(demisto_client,
                        'generic_request_func',
                        return_value=('', 500, None))
    mocker.patch.object(script,
                        'get_pack_display_name',
                        side_effect=mocked_get_pack_display_name)
    prints_manager = ParallelPrintsManager(1)

    installed_packs, success = script.search_and_install_packs_and_their_dependencies(
        good_pack_ids, client, prints_manager, is_private=False)
    assert success is False
def test_search_and_install_packs_and_their_dependencies(mocker):
    """
    Given
    - Valid and invalid integrations paths.
    When
    - Running integrations configuration tests.
    Then
    - Ensure packs & their depenencies' search requests are valid.
    - Ensure packs & their depenencies' installation requests are valid.
    """
    good_integrations_files = [
        'Packs/HelloWorld/Integrations/HelloWorld/HelloWorld.yml',
        'Packs/AzureSentinel/Integrations/AzureSentinel/AzureSentinel.yml'
    ]

    bad_integrations_files = ['malformed_integration_file']

    client = MockClient()

    mocker.patch.object(demisto_client,
                        'generic_request_func',
                        side_effect=mocked_generic_request_func)
    prints_manager = ParallelPrintsManager(1)

    installed_packs = search_and_install_packs_and_their_dependencies(
        good_integrations_files, client, prints_manager)
    assert 'HelloWorld' in installed_packs
    assert 'AzureSentinel' in installed_packs
    assert 'TestPack' in installed_packs
    assert 'Base' in installed_packs
    assert len(installed_packs) == 4

    installed_packs = search_and_install_packs_and_their_dependencies(
        bad_integrations_files, client, prints_manager)
    assert len(installed_packs) == 0
def test_search_pack_with_failure(mocker):
    """
   Given
   - Error when searching for pack
   - Response with missing data
   When
   - Searching the pack in the Demsito instance for installation.
   Then
   - Ensure error is raised.
   """
    client = MockClient()
    prints_manager = ParallelPrintsManager(1)
    lock = MockLock()

    # Error when searching for pack
    mocker.patch.object(demisto_client,
                        'generic_request_func',
                        return_value=('', 500, None))
    script.search_pack(client, prints_manager, "New Hello World", 'HelloWorld',
                       0, lock)
    assert not script.SUCCESS_FLAG

    # Response with missing data
    mocker.patch.object(demisto_client,
                        'generic_request_func',
                        return_value=('{"id": "HelloWorld"}', 200, None))
    script.search_pack(client, prints_manager, "New Hello World", 'HelloWorld',
                       0, lock)
    assert not script.SUCCESS_FLAG
Beispiel #14
0
def test_print_investigation_error(command, output, mocker):
    """
    Given
    -  A failed playbook task command line.
    When
    - Extracting the task error reason from the server
    Then
    - Ensure message sent to print manager contains `password=******` instead of `password="******"`
    - Ensure message sent to print manager contains `password=******` instead of `Password="******"`
    - Ensure message sent to print manager contains "pass word="123123!""

    """
    prints_manager = ParallelPrintsManager(1)
    body = {
        'entries': [{
            'type': 4,
            'parentContent': command,
            'taskId': '12',
            'contents': '2'
        }]
    }
    mocker.patch.object(demisto_client,
                        "generic_request_func",
                        return_value=[str(body), '200'])

    client = demisto_client
    __print_investigation_error(client, '', '', prints_manager)
    prints_to_execute = prints_manager.threads_print_jobs[0]
    assert prints_to_execute[2].message_to_print == output
def run_test(tests_settings: SettingsTester, demisto_user: str, demisto_pass: str,
             failed_playbooks: list, integrations: list, playbook_id: str, succeed_playbooks: list,
             test_message: str, test_options: dict, slack: str, circle_ci: str, build_number: str,
             server_url: str, build_name: str, prints_manager: ParallelPrintsManager,
             thread_index: int = 0) -> None:
    """
    Wrapper for the run_test_logic function. Helps by indicating when the test is starting and ending.

    :param tests_settings: SettingsTester object which contains the test variables
    :param demisto_user: Username of the demisto user running the tests.
    :param demisto_pass: Password of the demisto user running the tests.
    :param failed_playbooks: List of failed playbooks, additional failed playbooks will be added if
                             they failed.
    :param integrations: List of integrations being tested.
    :param playbook_id: ID of the test playbook being tested.
    :param succeed_playbooks: List of playbooks which have passed tests.
    :param test_message: Name of the playbook/integration being tested. This is reported back in the
                         build and used to print in the console the test being ran.
    :param test_options: Options being passed to the test. PID, Docker Threshold, Timeout, etc.
    :param slack: Slack client used for notifications.
    :param circle_ci: CircleCI token. Used to get name of dev who triggered the build.
    :param build_number: The build number of the CI run. Used in slack message.
    :param server_url: The FQDN of the server tests are being ran on.
    :param build_name: Name of the build. (Nightly, etc.)
    :param prints_manager: PrintsManager object used in reporting. Will be deprecated.
    :param thread_index: Integer indicating what thread the test is running on.
    :return: No object is returned.
    """
    start_message = f'------ Test {test_message} start ------'
    client = demisto_client.configure(base_url=server_url, username=demisto_user, password=demisto_pass, verify_ssl=False)
    prints_manager.add_print_job(start_message + ' (Private Build Test)', print, thread_index,
                                 include_timestamp=True)
    run_test_logic(tests_settings, client, failed_playbooks, integrations, playbook_id,
                   succeed_playbooks, test_message, test_options, slack, circle_ci, build_number,
                   server_url, demisto_user, demisto_pass, build_name, prints_manager,
                   thread_index=thread_index)
    prints_manager.add_print_job('------ Test %s end ------\n' % (test_message,), print,
                                 thread_index,
                                 include_timestamp=True)

    return
def install_private_testing_pack(build: Build,
                                 prints_manager: ParallelPrintsManager,
                                 test_pack_zip_path: str):
    """
    Creates and installs the test pack used in the private build. This pack contains the test
    playbooks and test scripts that will be used for the tests.

    :param build: Build object containing the build settings.
    :param prints_manager: PrintsManager object used for reporting status. Will be deprecated.
    :param test_pack_zip_path: Path to test_pack zip.
    :return: No object is returned. nightly_install_packs will wait for the process to finish.
    """
    threads_print_manager = ParallelPrintsManager(len(build.servers))
    nightly_install_packs(build,
                          threads_print_manager,
                          install_method=upload_zipped_packs,
                          pack_path=test_pack_zip_path)

    prints_manager.add_print_job('Sleeping for 45 seconds...',
                                 print_warning,
                                 0,
                                 include_timestamp=True)
    prints_manager.execute_thread_prints(0)
def main():
    build = Build(options_handler())
    prints_manager = ParallelPrintsManager(1)

    configure_servers_and_restart(build, prints_manager)
    #  Get a list of the test we need to run.
    tests_for_iteration = get_tests(build.server_numeric_version,
                                    prints_manager, build.tests)
    #  Installing the packs.
    installed_content_packs_successfully = install_packs_private(
        build, prints_manager)
    #  Get a list of the integrations that have changed.
    new_integrations, modified_integrations = get_changed_integrations(
        build, prints_manager)
    #  Configuring the instances which are used in testing.
    all_module_instances, brand_new_integrations = \
        configure_server_instances(build, tests_for_iteration, new_integrations,
                                   modified_integrations, prints_manager)

    #  Running the instance tests (pushing the test button)
    successful_tests_pre, failed_tests_pre = instance_testing(
        build, all_module_instances, prints_manager, pre_update=True)
    #  Adding the new integrations to the instance test list and testing them.
    all_module_instances.extend(brand_new_integrations)
    successful_tests_post, failed_tests_post = instance_testing(
        build, all_module_instances, prints_manager, pre_update=False)
    #  Done running tests so we are disabling the instances.
    disable_instances(build, all_module_instances, prints_manager)
    #  Gather tests to add to test pack
    test_playbooks_from_id_set = build.id_set.get('TestPlaybooks', [])
    tests_to_add_to_test_pack = find_needed_test_playbook_paths(
        test_playbooks=test_playbooks_from_id_set,
        tests_to_run=build.tests_to_run,
        path_to_content=build.content_root)
    #  Write the test pack
    private_content_test_zip = write_test_pack_zip(
        zip_destination_dir=build.test_pack_path,
        tests_file_paths=tests_to_add_to_test_pack,
        path_to_content=build.content_root)
    # Create and install private test pack
    install_private_testing_pack(build, prints_manager,
                                 private_content_test_zip)

    success = report_tests_status(failed_tests_pre, failed_tests_post,
                                  successful_tests_pre, successful_tests_post,
                                  new_integrations, prints_manager)
    sleep(30)
    if not success or not installed_content_packs_successfully:
        sys.exit(2)
def test_search_pack_with_id(mocker):
    """
   Given
   - Pack with a new name (different from its ID)
   When
   - Searching the pack in the Demsito instance.
   Then
   - Ensure the pack is found using its ID
   """
    client = MockClient()
    prints_manager = ParallelPrintsManager(1)
    mocker.patch.object(demisto_client, 'generic_request_func', side_effect=mocked_generic_request_func)
    expected_response = {
        'id': 'HelloWorld',
        'version': '1.1.10'
    }
    assert expected_response == script.search_pack(client, prints_manager, "New Hello World", 'HelloWorld', 0, None)
def test_create_install_private_testing_pack(mocker):
    """
    Scenario: Creating and installing a pack for testing. Pack will contain no items as it is mocked
              in this test. Empty pack will be created and uploaded to mock server. Server returns a
              200 status code.
    Given: A mocked test pack
    When: Installing a pack to the server
    Then: Return the success flag set to true indicating the request to install the pack was successful

    """

    prints_manager = ParallelPrintsManager(len(BuildMock().servers))

    def mocked_generic_request_func(self, path: str, method, body=None, accept=None,
                                    _request_timeout=None):
        if path == '/contentpacks/marketplace/install':
            return 'MOCK_PACKS_INSTALLATION_RESULT', 200, None
        return None, None, None

    mocker.patch.object(demisto_client, 'generic_request_func',
                        side_effect=mocked_generic_request_func)
    mock_build = BuildMock()
    install_private_testing_pack(mock_build, prints_manager, 'testing/path/to/test_pack.zip')
    assert script.SUCCESS_FLAG
def get_pack_dependencies(client: demisto_client,
                          prints_manager: ParallelPrintsManager,
                          pack_data: dict, thread_index: int, lock: Lock):
    """ Get the pack's required dependencies.

    Args:
        client (demisto_client): The configured client to use.
        prints_manager (ParallelPrintsManager): A prints manager object.
        pack_data (dict): Contains the pack ID and version.
        thread_index (int): the thread index.
        lock (Lock): A lock object.
    Returns:
        (list) The pack's dependencies.
    """
    pack_id = pack_data['id']

    try:
        response_data, status_code, _ = demisto_client.generic_request_func(
            client,
            path='/contentpacks/marketplace/search/dependencies',
            method='POST',
            body=[pack_data],
            accept='application/json',
            _request_timeout=None)

        if 200 <= status_code < 300:
            dependencies_data = []
            dependants_ids = [pack_id]
            reseponse_data = ast.literal_eval(response_data).get(
                'dependencies', [])
            create_dependencies_data_structure(reseponse_data, dependants_ids,
                                               dependencies_data,
                                               dependants_ids)
            dependencies_str = ', '.join(
                [dep['id'] for dep in dependencies_data])
            if dependencies_data:
                message = 'Found the following dependencies for pack {}:\n{}\n'.format(
                    pack_id, dependencies_str)
                prints_manager.add_print_job(message, print_color,
                                             thread_index, LOG_COLORS.GREEN)
                prints_manager.execute_thread_prints(thread_index)
            return dependencies_data
        if status_code == 400:
            err_msg = f"Unable to find dependencies for {pack_id}."
            prints_manager.add_print_job(err_msg, print_color, thread_index,
                                         LOG_COLORS.RED)
            prints_manager.execute_thread_prints(thread_index)
            return []
        else:
            result_object = ast.literal_eval(response_data)
            msg = result_object.get('message', '')
            err_msg = 'Failed to get pack {} dependencies - with status code {}\n{}\n'.format(
                pack_id, status_code, msg)
            raise Exception(err_msg)
    except Exception as e:
        err_msg = 'The request to get pack {} dependencies has failed. Reason:\n{}\n'.format(
            pack_id, str(e))
        prints_manager.add_print_job(err_msg, print_color, thread_index,
                                     LOG_COLORS.RED)
        prints_manager.execute_thread_prints(thread_index)

        lock.acquire()
        global SUCCESS_FLAG
        SUCCESS_FLAG = False
        lock.release()
def upload_zipped_packs(client: demisto_client, host: str,
                        prints_manager: ParallelPrintsManager,
                        thread_index: int, pack_path: str):
    """ Install packs from zip file.

        Args:
            client (demisto_client): The configured client to use.
            host (str): The server URL.
            prints_manager (ParallelPrintsManager): Print manager object.
            thread_index (int): the index (for prints_manager).
            pack_path (str): path to pack zip.
        """
    header_params = {'Content-Type': 'multipart/form-data'}
    file_path = os.path.abspath(pack_path)
    files = {'file': file_path}

    message = 'Making "POST" request to server {} - to install all packs from file {}'.format(
        host, pack_path)
    prints_manager.add_print_job(message, print_color, thread_index,
                                 LOG_COLORS.GREEN)
    prints_manager.execute_thread_prints(thread_index)

    # make the pack installation request
    try:
        response_data, status_code, _ = client.api_client.call_api(
            resource_path='/contentpacks/installed/upload',
            method='POST',
            header_params=header_params,
            files=files)

        if 200 <= status_code < 300:
            message = 'All packs from {} were successfully installed!\n'.format(
                pack_path)
            prints_manager.add_print_job(message, print_color, thread_index,
                                         LOG_COLORS.GREEN)
            prints_manager.execute_thread_prints(thread_index)
        else:
            result_object = ast.literal_eval(response_data)
            message = result_object.get('message', '')
            err_msg = 'Failed to install packs - with status code {}\n{}\n'.format(
                status_code, message)
            raise Exception(err_msg)
    except Exception as e:
        if e.__class__ == ApiException:
            err_msg = 'The request to install packs has failed. Reason:\n{}\n'.format(
                str(e.body))
        else:
            err_msg = 'The request to install packs has failed. Reason:\n{}\n'.format(
                str(e))
        prints_manager.add_print_job(err_msg, print_color, thread_index,
                                     LOG_COLORS.GREEN)
        prints_manager.execute_thread_prints(thread_index)
        sys.exit(1)
def install_new_content(client, server):
    prints_manager = ParallelPrintsManager(1)
    update_content_on_demisto_instance(client, server, prints_manager, 0)
    prints_manager.execute_thread_prints(0)
def execute_testing(tests_settings: SettingsTester,
                    server_ip: str,
                    all_tests: set,
                    tests_data_keeper: DataKeeperTester,
                    prints_manager: ParallelPrintsManager,
                    thread_index: int = 0):
    """
    Main function used to handle the testing process. Starts by turning off telemetry and disabling
    any left over tests. Afterwards it will create a test queue object which then is used to run the
    specific test scenario.

    :param tests_settings: SettingsTester object which contains the test variables
    :param server_ip: IP address of the server. Will be formatted before use.
    :param all_tests: All tests currently in the test conf.
    :param tests_data_keeper: Object containing all the test results. Used by report tests function.
    :param prints_manager: PrintsManager object used in reporting. Will be deprecated.
    :param thread_index: Integer indicating what thread the test is running on.
    :return: No object is returned, just updates the tests_data_keep object.
    """
    server = SERVER_URL.format(server_ip)
    server_numeric_version = tests_settings.serverNumericVersion
    start_message = "Executing tests with the server {} - and the server ip {}".format(
        server, server_ip)
    prints_manager.add_print_job(start_message, print, thread_index)
    slack = tests_settings.slack
    circle_ci = tests_settings.circleci
    build_number = tests_settings.buildNumber
    build_name = tests_settings.buildName
    conf, secret_conf = load_conf_files(tests_settings.conf_path,
                                        tests_settings.secret_conf_path)
    demisto_api_key = tests_settings.api_key
    demisto_user = secret_conf['username']
    demisto_pass = secret_conf['userPassword']

    default_test_timeout = conf.get('testTimeout', 30)

    tests = conf['tests']
    skipped_tests_conf = conf['skipped_tests']
    nightly_integrations = conf['nightly_integrations']
    skipped_integrations_conf = conf['skipped_integrations']
    unmockable_integrations = conf['unmockable_integrations']

    secret_params = secret_conf['integrations'] if secret_conf else []

    filtered_tests = extract_filtered_tests()

    if not tests or len(tests) == 0:
        prints_manager.add_print_job('no integrations are configured for test',
                                     print, thread_index)
        prints_manager.execute_thread_prints(thread_index)
        return
    xsoar_client = demisto_client.configure(base_url=server,
                                            username=demisto_user,
                                            password=demisto_pass,
                                            verify_ssl=False)

    # turn off telemetry
    turn_off_telemetry(xsoar_client)

    failed_playbooks = []
    succeed_playbooks = []
    skipped_tests = set([])
    skipped_integration = set([])
    playbook_skipped_integration = set([])

    disable_all_integrations(xsoar_client,
                             prints_manager,
                             thread_index=thread_index)
    prints_manager.execute_thread_prints(thread_index)
    #  Private builds do not use mocking. Here we copy the mocked test list to the unmockable list.
    private_tests = get_test_records_of_given_test_names(
        tests_settings, all_tests)
    try:
        # first run the mock tests to avoid mockless side effects in container
        prints_manager.add_print_job("\nRunning private tests", print,
                                     thread_index)
        executed_in_current_round, private_tests_queue = initialize_queue_and_executed_tests_set(
            private_tests)
        while not private_tests_queue.empty():
            t = private_tests_queue.get()
            executed_in_current_round = update_round_set_and_sleep_if_round_completed(
                executed_in_current_round, prints_manager, t, thread_index)
            run_private_test_scenario(tests_settings,
                                      t,
                                      default_test_timeout,
                                      skipped_tests_conf,
                                      nightly_integrations,
                                      skipped_integrations_conf,
                                      skipped_integration,
                                      filtered_tests,
                                      skipped_tests,
                                      secret_params,
                                      failed_playbooks,
                                      playbook_skipped_integration,
                                      succeed_playbooks,
                                      slack,
                                      circle_ci,
                                      build_number,
                                      server,
                                      build_name,
                                      server_numeric_version,
                                      demisto_user,
                                      demisto_pass,
                                      demisto_api_key,
                                      prints_manager,
                                      thread_index=thread_index)
            prints_manager.execute_thread_prints(thread_index)

    except Exception as exc:
        if exc.__class__ == ApiException:
            error_message = exc.body
        else:
            error_message = f'~~ Thread {thread_index + 1} failed ~~\n{str(exc)}\n{traceback.format_exc()}'
        prints_manager.add_print_job(error_message, print_error, thread_index)
        prints_manager.execute_thread_prints(thread_index)
        failed_playbooks.append(f'~~ Thread {thread_index + 1} failed ~~')
        raise

    finally:
        tests_data_keeper.add_tests_data(succeed_playbooks, failed_playbooks,
                                         skipped_tests, skipped_integration,
                                         unmockable_integrations)
def main():
    options = options_handler()
    username = options.user
    password = options.password
    ami_env = options.ami_env
    git_sha1 = options.git_sha1
    conf_path = options.conf
    secret_conf_path = options.secret
    branch_name = options.branch
    ci_build_number = options.build_number

    servers = determine_servers_urls(ami_env)
    server_numeric_version = get_server_numeric_version(ami_env)

    prints_manager = ParallelPrintsManager(1)

    conf, secret_conf = load_conf_files(conf_path, secret_conf_path)
    secret_params = secret_conf.get('integrations', []) if secret_conf else []

    username = secret_conf.get('username') if not username else username
    password = secret_conf.get('userPassword') if not password else password

    if LooseVersion(server_numeric_version) >= LooseVersion('6.0.0'):
        for server in servers:
            client = demisto_client.configure(base_url=server, username=username, password=password,
                                              verify_ssl=False)
            set_marketplace_gcp_bucket_for_build(client, prints_manager, branch_name, ci_build_number)
            print('Restarting servers to apply GCS server config ...')
            ssh_string = 'ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null {}@{} ' \
                         '"sudo systemctl restart demisto"'
            try:
                subprocess.check_output(
                    ssh_string.format('ec2-user', server.replace('https://', '')), shell=True)
            except subprocess.CalledProcessError as exc:
                print(exc.output)
        print('Done restarting servers.')

    tests = conf['tests']
    skipped_integrations_conf = conf['skipped_integrations']
    all_module_instances = []

    filtered_tests, filter_configured, run_all_tests = extract_filtered_tests(is_nightly=options.is_nightly)
    tests_for_iteration = tests
    if run_all_tests:
        # skip test button testing
        skipped_instance_test_message = 'Not running instance tests when {} is turned on'.format(RUN_ALL_TESTS_FORMAT)
        prints_manager.add_print_job(skipped_instance_test_message, print_warning, 0)
        tests_for_iteration = []
    elif filter_configured and filtered_tests:
        tests_for_iteration = [test for test in tests if test.get('playbookID', '') in filtered_tests]

    tests_for_iteration = filter_tests_with_incompatible_version(tests_for_iteration, server_numeric_version,
                                                                 prints_manager)
    prints_manager.execute_thread_prints(0)

    # get a list of brand new integrations that way we filter them out to only configure instances
    # after updating content
    new_integrations_files, modified_integrations_files = get_new_and_modified_integration_files(git_sha1)
    new_integrations_names, modified_integrations_names = [], []

    installed_content_packs_successfully = True

    if LooseVersion(server_numeric_version) >= LooseVersion('6.0.0'):
        # sleep for one minute before starting to search and install packs to ensure bucket is ready
        prints_manager.add_print_job('Sleeping for 1 minute...', print_warning, 0)
        prints_manager.execute_thread_prints(0)
        sleep(60)

        pack_ids = get_pack_ids_to_install()
        # install content packs in every server
        for server_url in servers:
            try:
                client = demisto_client.configure(base_url=server_url, username=username, password=password,
                                                  verify_ssl=False)
                search_and_install_packs_and_their_dependencies(pack_ids, client, prints_manager, options.is_nightly)
            except Exception as exc:
                prints_manager.add_print_job(str(exc), print_error, 0)
                prints_manager.execute_thread_prints(0)
                installed_content_packs_successfully = False

    if new_integrations_files:
        new_integrations_names = get_integration_names_from_files(new_integrations_files)
        new_integrations_names_message = \
            'New Integrations Since Last Release:\n{}\n'.format('\n'.join(new_integrations_names))
        prints_manager.add_print_job(new_integrations_names_message, print_warning, 0)

    if modified_integrations_files:
        modified_integrations_names = get_integration_names_from_files(modified_integrations_files)
        modified_integrations_names_message = \
            'Updated Integrations Since Last Release:\n{}\n'.format('\n'.join(modified_integrations_names))
        prints_manager.add_print_job(modified_integrations_names_message, print_warning, 0)
    prints_manager.execute_thread_prints(0)
    # Each test is a dictionary from Tests/conf.json which may contain the following fields
    # "playbookID", "integrations", "instance_names", "timeout", "nightly", "fromversion", "toversion"
    # Note that only the "playbookID" field is required with all of the others being optional.
    # Most tests have an "integrations" field listing the integration used for that playbook
    # and sometimes an "instance_names" field which is used when there are multiple instances
    # of an integration that we want to configure with different configuration values. Look at
    # [conf.json](../conf.json) for examples
    brand_new_integrations = []

    for test in tests_for_iteration:
        testing_client = demisto_client.configure(base_url=servers[0], username=username, password=password,
                                                  verify_ssl=False)
        integrations = get_integrations_for_test(test, skipped_integrations_conf)
        instance_names_conf = test.get('instance_names', [])
        if not isinstance(instance_names_conf, list):
            instance_names_conf = [instance_names_conf]

        integrations_names = [i.get('name') for i in integrations]
        prints_manager.add_print_job('All Integrations for test "{}":'.format(test.get('playbookID')), print_warning, 0)
        prints_manager.add_print_job(integrations_names, print_warning, 0)

        new_integrations, modified_integrations, unchanged_integrations, integration_to_status = group_integrations(
            integrations, skipped_integrations_conf, new_integrations_names, modified_integrations_names
        )

        integrations_msg = '\n'.join(['"{}" - {}'.format(key, val) for key, val in integration_to_status.items()])
        prints_manager.add_print_job('{}\n'.format(integrations_msg), print_warning, 0)

        integrations_to_configure = modified_integrations[:]
        integrations_to_configure.extend(unchanged_integrations)

        # set params for new integrations and [modified + unchanged] integrations, then add the new ones
        # to brand_new_integrations list for later use
        placeholders_map = {'%%SERVER_HOST%%': servers[0]}
        new_ints_params_set = set_integration_params(new_integrations, secret_params, instance_names_conf,
                                                     placeholders_map)
        ints_to_configure_params_set = set_integration_params(integrations_to_configure, secret_params,
                                                              instance_names_conf, placeholders_map)
        if not new_ints_params_set:
            prints_manager.add_print_job(
                'failed setting parameters for integrations "{}"'.format('\n'.join(new_integrations)), print_error, 0)
        if not ints_to_configure_params_set:
            prints_manager.add_print_job(
                'failed setting parameters for integrations "{}"'.format('\n'.join(integrations_to_configure)),
                print_error, 0)
        if not (new_ints_params_set and ints_to_configure_params_set):
            continue
        prints_manager.execute_thread_prints(0)

        brand_new_integrations.extend(new_integrations)

        module_instances = []
        for integration in integrations_to_configure:
            placeholders_map = {'%%SERVER_HOST%%': servers[0]}
            module_instance = configure_integration_instance(integration, testing_client, prints_manager,
                                                             placeholders_map)
            if module_instance:
                module_instances.append(module_instance)

        all_module_instances.extend(module_instances)

    preupdate_fails = set()
    postupdate_fails = set()
    preupdate_success = set()
    postupdate_success = set()

    # Test all module instances (of modified + unchanged integrations) pre-updating content
    if all_module_instances:
        # only print start message if there are instances to configure
        prints_manager.add_print_job('Start of Instance Testing ("Test" button) prior to Content Update:',
                                     print_warning, 0)
    else:
        prints_manager.add_print_job('No integrations to configure for the chosen tests. (Pre-update)',
                                     print_warning, 0)
    prints_manager.execute_thread_prints(0)

    for instance in all_module_instances:
        testing_client = demisto_client.configure(base_url=servers[0], username=username, password=password,
                                                  verify_ssl=False)
        integration_of_instance = instance.get('brand', '')
        instance_name = instance.get('name', '')
        msg = 'Testing ("Test" button) for instance "{}" of integration "{}".'.format(instance_name,
                                                                                      integration_of_instance)
        prints_manager.add_print_job(msg, print_color, 0, LOG_COLORS.GREEN)
        prints_manager.execute_thread_prints(0)
        # If there is a failure, __test_integration_instance will print it
        success, _ = __test_integration_instance(testing_client, instance, prints_manager)
        prints_manager.execute_thread_prints(0)
        if not success:
            preupdate_fails.add((instance_name, integration_of_instance))
        else:
            preupdate_success.add((instance_name, integration_of_instance))

    if LooseVersion(server_numeric_version) < LooseVersion('6.0.0'):
        threads_list = []
        threads_prints_manager = ParallelPrintsManager(len(servers))
        # For each server url we install content
        for thread_index, server_url in enumerate(servers):
            client = demisto_client.configure(base_url=server_url, username=username,
                                              password=password, verify_ssl=False)
            t = Thread(target=update_content_on_demisto_instance,
                       kwargs={'client': client, 'server': server_url, 'ami_name': ami_env,
                               'prints_manager': threads_prints_manager,
                               'thread_index': thread_index})
            threads_list.append(t)

        run_threads_list(threads_list)

    # configure instances for new integrations
    new_integration_module_instances = []
    for integration in brand_new_integrations:
        placeholders_map = {'%%SERVER_HOST%%': servers[0]}
        new_integration_module_instance = configure_integration_instance(integration, testing_client, prints_manager,
                                                                         placeholders_map)
        if new_integration_module_instance:
            new_integration_module_instances.append(new_integration_module_instance)

    all_module_instances.extend(new_integration_module_instances)

    # After content upload has completed - test ("Test" button) integration instances
    # Test all module instances (of pre-existing AND new integrations) post-updating content
    if all_module_instances:
        # only print start message if there are instances to configure
        prints_manager.add_print_job('Start of Instance Testing ("Test" button) after the Content Update:',
                                     print_warning, 0)
    else:
        prints_manager.add_print_job('No integrations to configure for the chosen tests. (Post-update)',
                                     print_warning, 0)
    prints_manager.execute_thread_prints(0)

    for instance in all_module_instances:
        integration_of_instance = instance.get('brand', '')
        instance_name = instance.get('name', '')
        msg = 'Testing ("Test" button) for instance "{}" of integration "{}" .'.format(instance_name,
                                                                                       integration_of_instance)
        prints_manager.add_print_job(msg, print_color, 0, LOG_COLORS.GREEN)
        prints_manager.execute_thread_prints(0)
        # If there is a failure, __test_integration_instance will print it
        success, _ = __test_integration_instance(testing_client, instance, prints_manager)
        prints_manager.execute_thread_prints(0)
        if not success:
            postupdate_fails.add((instance_name, integration_of_instance))
        else:
            postupdate_success.add((instance_name, integration_of_instance))
    # reinitialize all clients since their authorization has probably expired by now
    for server_url in servers:
        client = demisto_client.configure(base_url=server_url, username=username, password=password, verify_ssl=False)
        __disable_integrations_instances(client, all_module_instances, prints_manager)
    prints_manager.execute_thread_prints(0)

    success = report_tests_status(preupdate_fails, postupdate_fails, preupdate_success, postupdate_success,
                                  new_integrations_names, prints_manager)
    prints_manager.execute_thread_prints(0)
    if not success or not installed_content_packs_successfully:
        sys.exit(2)
def run_private_test_scenario(tests_settings: SettingsTester,
                              t: dict,
                              default_test_timeout: int,
                              skipped_tests_conf: set,
                              nightly_integrations: list,
                              skipped_integrations_conf: set,
                              skipped_integration: set,
                              filtered_tests: list,
                              skipped_tests: set,
                              secret_params: dict,
                              failed_playbooks: list,
                              playbook_skipped_integration: set,
                              succeed_playbooks: list,
                              slack: str,
                              circle_ci: str,
                              build_number: str,
                              server: str,
                              build_name: str,
                              server_numeric_version: str,
                              demisto_user: str,
                              demisto_pass: str,
                              demisto_api_key: str,
                              prints_manager: ParallelPrintsManager,
                              thread_index: int = 0):
    """
    Checks to see if test should run given the scenario. If the test should run, it will collect the
    integrations which are required to run the test.

    :param tests_settings: SettingsTester object which contains the test variables
    :param t: Options being passed to the test. PID, Docker Threshold, Timeout, etc.
    :param default_test_timeout: Time in seconds indicating when the test should timeout if no
                                 status is reported.
    :param skipped_tests_conf: Collection of the tests which are skipped.
    :param nightly_integrations: List of integrations which should only be tested on a nightly build.
    :param skipped_integrations_conf: Collection of integrations which are skiped.
    :param skipped_integration: Set of skipped integrations. Currently not used in private.
    :param filtered_tests: List of tests excluded from testing.
    :param skipped_tests: List of skipped tests.
    :param secret_params: Parameters found in the content-test-conf. Used to configure the instance.
    :param failed_playbooks: List of failed playbooks, additional failed playbooks will be added if
                             they failed.
    :param playbook_skipped_integration: Not used.
    :param succeed_playbooks: List of playbooks which have passed tests.
    :param slack: Slack client used for notifications.
    :param circle_ci: CircleCI token. Used to get name of dev who triggered the build.
    :param build_number: The build number of the CI run. Used in slack message.
    :param server: The FQDN of the server tests are being ran on.
    :param build_name: Name of the build. (Nightly, etc.)
    :param server_numeric_version: Version of XSOAR currently installed on the server.
    :param demisto_user: Username of the demisto user running the tests.
    :param demisto_pass: Password of the demisto user running the tests.
    :param demisto_api_key: API key for the demisto instance.
    :param prints_manager: PrintsManager object used in reporting. Will be deprecated.
    :param thread_index: Integer indicating what thread the test is running on.
    :return:
    """
    playbook_id = t['playbookID']
    integrations_conf = t.get('integrations', [])
    instance_names_conf = t.get('instance_names', [])

    test_message = 'playbook: ' + playbook_id

    test_options = {
        'timeout':
        t.get('timeout', default_test_timeout),
        'memory_threshold':
        t.get('memory_threshold', Docker.DEFAULT_CONTAINER_MEMORY_USAGE),
        'pid_threshold':
        t.get('pid_threshold', Docker.DEFAULT_CONTAINER_PIDS_USAGE)
    }

    if not isinstance(integrations_conf, list):
        integrations_conf = [
            integrations_conf,
        ]

    if not isinstance(instance_names_conf, list):
        instance_names_conf = [
            instance_names_conf,
        ]

    test_skipped_integration, integrations, is_nightly_integration = collect_integrations(
        integrations_conf, skipped_integration, skipped_integrations_conf,
        nightly_integrations)

    if playbook_id in filtered_tests:
        playbook_skipped_integration.update(test_skipped_integration)

    # Skip tests that are missing from filtered list
    if filtered_tests and playbook_id not in filtered_tests:
        return

    # Skip bad test
    if playbook_id in skipped_tests_conf:
        skipped_tests.add(
            f'{playbook_id} - reason: {skipped_tests_conf[playbook_id]}')
        return

    # Skip integration
    if test_skipped_integration:
        return

    # Skip version mismatch test
    test_from_version = t.get('fromversion', '0.0.0')
    test_to_version = t.get('toversion', '99.99.99')

    if not (LooseVersion(test_from_version) <=
            LooseVersion(server_numeric_version) <=
            LooseVersion(test_to_version)):
        prints_manager.add_print_job(
            f'\n------ Test {test_message} start ------',
            print,
            thread_index,
            include_timestamp=True)
        warning_message = 'Test {} ignored due to version mismatch (test versions: {}-{})'.format(
            test_message, test_from_version, test_to_version)
        prints_manager.add_print_job(warning_message, print_warning,
                                     thread_index)
        prints_manager.add_print_job(
            f'------ Test {test_message} end ------\n',
            print,
            thread_index,
            include_timestamp=True)
        return

    placeholders_map = {'%%SERVER_HOST%%': server}
    are_params_set = set_integration_params(demisto_api_key,
                                            integrations,
                                            secret_params,
                                            instance_names_conf,
                                            playbook_id,
                                            prints_manager,
                                            placeholders_map,
                                            thread_index=thread_index)
    if not are_params_set:
        failed_playbooks.append(playbook_id)
        return

    test_message = update_test_msg(integrations, test_message)
    run_test(tests_settings,
             demisto_user,
             demisto_pass,
             failed_playbooks,
             integrations,
             playbook_id,
             succeed_playbooks,
             test_message,
             test_options,
             slack,
             circle_ci,
             build_number,
             server,
             build_name,
             prints_manager,
             thread_index=thread_index)
Beispiel #26
0
def main():
    options = options_handler()
    username = options.user
    password = options.password
    ami_env = options.ami_env
    git_sha1 = options.git_sha1
    servers = determine_servers_urls(ami_env)
    conf_path = options.conf
    secret_conf_path = options.secret

    prints_manager = ParallelPrintsManager(1)
    server_numeric_version = get_server_numeric_version(ami_env)

    conf, secret_conf = load_conf_files(conf_path, secret_conf_path)
    secret_params = secret_conf.get('integrations', []) if secret_conf else []

    username = secret_conf.get('username') if not username else username
    password = secret_conf.get('userPassword') if not password else password

    clients = []
    for server_url in servers:
        client = demisto_client.configure(base_url=server_url,
                                          username=username,
                                          password=password,
                                          verify_ssl=False)
        clients.append(client)

    testing_client = clients[0]

    tests = conf['tests']
    skipped_integrations_conf = conf['skipped_integrations']
    all_module_instances = []

    filtered_tests, filter_configured, run_all_tests = extract_filtered_tests(
        is_nightly=False)
    tests_for_iteration = tests
    if run_all_tests:
        # Use all tests for testing, leave 'tests_for_iteration' as is
        pass
    elif filter_configured and filtered_tests:
        tests_for_iteration = [
            test for test in tests
            if test.get('playbookID', '') in filtered_tests
        ]
    tests_for_iteration = filter_tests_with_incompatible_version(
        tests_for_iteration, server_numeric_version, prints_manager)

    # get a list of brand new integrations that way we filter them out to only configure instances
    # after updating content
    new_integrations_names, modified_integrations_names = get_new_and_modified_integrations(
        git_sha1)
    if new_integrations_names:
        print_warning('New Integrations Since Last Release:\n{}\n'.format(
            '\n'.join(new_integrations_names)))
    if modified_integrations_names:
        print_warning('Updated Integrations Since Last Release:\n{}\n'.format(
            '\n'.join(modified_integrations_names)))

    # Each test is a dictionary from Tests/conf.json which may contain the following fields
    # "playbookID", "integrations", "instance_names", "timeout", "nightly", "fromversion", "toversion"
    # Note that only the "playbookID" field is required with all of the others being optional.
    # Most tests have an "integrations" field listing the integration used for that playbook
    # and sometimes an "instance_names" field which is used when there are multiple instances
    # of an integration that we want to configure with different configuration values. Look at
    # [conf.json](../conf.json) for examples
    brand_new_integrations = []
    for test in tests_for_iteration:
        integrations = get_integrations_for_test(test,
                                                 skipped_integrations_conf)
        instance_names_conf = test.get('instance_names', [])
        if not isinstance(instance_names_conf, list):
            instance_names_conf = [instance_names_conf]

        integrations_names = [i.get('name') for i in integrations]
        print_warning('All Integrations for test "{}":'.format(
            test.get('playbookID')))
        print_warning(integrations_names)

        new_integrations, modified_integrations, unchanged_integrations, integration_to_status = group_integrations(
            integrations, skipped_integrations_conf, new_integrations_names,
            modified_integrations_names)

        integrations_msg = '\n'.join([
            '"{}" - {}'.format(key, val)
            for key, val in integration_to_status.items()
        ])
        print_warning('{}\n'.format(integrations_msg))

        integrations_to_configure = modified_integrations[:]
        integrations_to_configure.extend(unchanged_integrations)

        # set params for new integrations and [modified + unchanged] integrations, then add the new ones
        # to brand_new_integrations list for later use
        new_ints_params_set = set_integration_params(new_integrations,
                                                     secret_params,
                                                     instance_names_conf)
        ints_to_configure_params_set = set_integration_params(
            integrations_to_configure, secret_params, instance_names_conf)
        if not new_ints_params_set:
            print_error(
                'failed setting parameters for integrations "{}"'.format(
                    '\n'.join(new_integrations)))
        if not ints_to_configure_params_set:
            print_error(
                'failed setting parameters for integrations "{}"'.format(
                    '\n'.join(integrations_to_configure)))
        if not (new_ints_params_set and ints_to_configure_params_set):
            continue

        brand_new_integrations.extend(new_integrations)

        module_instances = []
        for integration in integrations_to_configure:
            module_instances.append(
                configure_integration_instance(integration, testing_client,
                                               prints_manager))
        all_module_instances.extend(module_instances)

    preupdate_fails = set()
    postupdate_fails = set()

    # Test all module instances (of modified + unchanged integrations) pre-updating content
    if all_module_instances:
        # only print start message if there are instances to configure
        print_warning(
            'Start of Instance Testing ("Test" button) prior to Content Update:'
        )
    else:
        print_warning(
            'No integrations to configure for the chosen tests. (Pre-update)')
    for instance in all_module_instances:
        integration_of_instance = instance.get('brand', '')
        instance_name = instance.get('name', '')
        msg = 'Testing ("Test" button) for instance "{}" of integration "{}".'.format(
            instance_name, integration_of_instance)
        print(msg)
        # If there is a failure, __test_integration_instance will print it
        success = __test_integration_instance(testing_client, instance,
                                              prints_manager)
        prints_manager.execute_thread_prints(0)
        if not success:
            preupdate_fails.add((instance_name, integration_of_instance))
    threads_list = []
    threads_prints_manager = ParallelPrintsManager(len(clients))
    # For each server url we install content
    for thread_index, (client, server_url) in enumerate(zip(clients, servers)):
        t = Thread(target=update_content_on_demisto_instance,
                   kwargs={
                       'client': client,
                       'server': server_url,
                       'prints_manager': threads_prints_manager,
                       'thread_index': thread_index
                   })
        threads_list.append(t)

    run_threads_list(threads_list)

    # configure instances for new integrations
    new_integration_module_instances = []
    for integration in brand_new_integrations:
        new_integration_module_instances.append(
            configure_integration_instance(integration, testing_client,
                                           prints_manager))
    all_module_instances.extend(new_integration_module_instances)

    # After content upload has completed - test ("Test" button) integration instances
    # Test all module instances (of pre-existing AND new integrations) post-updating content
    if all_module_instances:
        print_warning(
            'Start of Instance Testing ("Test" button) after the Content Update:'
        )
    else:
        print_warning(
            'No integrations to configure for the chosen tests. (Post-update)')
    for instance in all_module_instances:
        integration_of_instance = instance.get('brand', '')
        instance_name = instance.get('name', '')
        msg = 'Testing ("Test" button) for instance "{}" of integration "{}" .'.format(
            instance_name, integration_of_instance)
        print(msg)
        # If there is a failure, __test_integration_instance will print it
        success = __test_integration_instance(testing_client, instance,
                                              prints_manager)
        prints_manager.execute_thread_prints(0)
        if not success:
            postupdate_fails.add((instance_name, integration_of_instance))

    # reinitialize all clients since their authorization has probably expired by now
    for server_url in servers:
        client = demisto_client.configure(base_url=server_url,
                                          username=username,
                                          password=password,
                                          verify_ssl=False)
        __disable_integrations_instances(client, all_module_instances,
                                         prints_manager)
    prints_manager.execute_thread_prints(0)

    success = report_tests_status(preupdate_fails, postupdate_fails,
                                  new_integrations_names)
    if not success:
        sys.exit(1)
Beispiel #27
0
def search_pack(client: demisto_client, prints_manager: ParallelPrintsManager,
                pack_display_name: str, pack_id: str, thread_index: int,
                lock: Lock) -> dict:
    """ Make a pack search request.

    Args:
        client (demisto_client): The configured client to use.
        prints_manager (ParallelPrintsManager): Print manager object.
        pack_display_name (string): The pack display name.
        pack_id (string): The pack ID.
        thread_index (int): the thread index.
        lock (Lock): A lock object.
    Returns:
        (dict): Returns the pack data if found, or empty dict otherwise.
    """

    try:
        # make the search request
        response_data, status_code, _ = demisto_client.generic_request_func(
            client,
            path=f'/contentpacks/marketplace/{pack_id}',
            method='GET',
            accept='application/json',
            _request_timeout=None)

        if 200 <= status_code < 300:
            result_object = ast.literal_eval(response_data)

            if result_object and result_object.get('currentVersion'):
                print_msg = f'Found pack "{pack_display_name}" by its ID "{pack_id}" in bucket!\n'
                prints_manager.add_print_job(print_msg, print_color,
                                             thread_index, LOG_COLORS.GREEN)
                prints_manager.execute_thread_prints(thread_index)

                pack_data = {
                    'id': result_object.get('id'),
                    'version': result_object.get('currentVersion')
                }
                return pack_data

            else:
                print_msg = f'Did not find pack "{pack_display_name}" by its ID "{pack_id}" in bucket.\n'
                prints_manager.add_print_job(print_msg, print_color,
                                             thread_index, LOG_COLORS.RED)
                prints_manager.execute_thread_prints(thread_index)
                raise Exception(print_msg)
        else:
            result_object = ast.literal_eval(response_data)
            msg = result_object.get('message', '')
            err_msg = f'Search request for pack "{pack_display_name}" with ID "{pack_id}", failed with status code ' \
                      f'{status_code}\n{msg}'
            raise Exception(err_msg)
    except Exception as e:
        err_msg = f'Search request for pack "{pack_display_name}" with ID "{pack_id}", failed. Reason:\n{str(e)}'
        prints_manager.add_print_job(err_msg, print_color, thread_index,
                                     LOG_COLORS.RED)

        lock.acquire()
        global SUCCESS_FLAG
        SUCCESS_FLAG = False
        lock.release()
Beispiel #28
0
def install_nightly_packs(client: demisto_client,
                          host: str,
                          prints_manager: ParallelPrintsManager,
                          thread_index: int,
                          packs_to_install: List,
                          request_timeout: int = 999999):
    """
    Install content packs on nightly build.
    We will catch the exception if pack fails to install and send the request to install packs again without the
    corrupted pack.
    Args:
        client(demisto_client): The configured client to use.
        host (str): The server URL.
        prints_manager (ParallelPrintsManager): Print manager object.
        thread_index (int): the thread index.
        packs_to_install (list): A list of the packs to install.
        request_timeout (int): Timeout settings for the installation request.

    Returns:
        None: No data returned.
    """
    packs_to_install_str = ', '.join([pack['id'] for pack in packs_to_install])
    message = 'Installing the following packs in server {}:\n{}'.format(
        host, packs_to_install_str)
    prints_manager.add_print_job(message,
                                 print_color,
                                 thread_index,
                                 LOG_COLORS.GREEN,
                                 include_timestamp=True)
    prints_manager.execute_thread_prints(thread_index)
    # make the pack installation request
    all_packs_install_successfully = False
    request_data = {'packs': packs_to_install, 'ignoreWarnings': True}
    while not all_packs_install_successfully:
        try:
            response_data, status_code, _ = demisto_client.generic_request_func(
                client,
                path='/contentpacks/marketplace/install',
                method='POST',
                body=request_data,
                accept='application/json',
                _request_timeout=request_timeout)

            if 200 <= status_code < 300:
                packs_data = [{
                    'ID': pack.get('id'),
                    'CurrentVersion': pack.get('currentVersion')
                } for pack in ast.literal_eval(response_data)]
                packs_message = f'The following packs were successfully installed:\n{packs_data}'
                prints_manager.add_print_job(packs_message,
                                             print_color,
                                             thread_index,
                                             LOG_COLORS.GREEN,
                                             include_timestamp=True)
            else:
                result_object = ast.literal_eval(response_data)
                message = result_object.get('message', '')
                err_msg = f'Failed to install packs - with status code {status_code}\n{message}\n'
                prints_manager.add_print_job(err_msg,
                                             print_error,
                                             thread_index,
                                             include_timestamp=True)
                raise Exception(err_msg)
            break

        except Exception as e:
            err_msg = f'The request to install packs has failed. Reason:\n{str(e)}\n'
            prints_manager.add_print_job(err_msg,
                                         print_error,
                                         thread_index,
                                         include_timestamp=True)
            all_packs_install_successfully = False
            malformed_pack_id = find_malformed_pack_id(str(e))
            if not malformed_pack_id:
                break
            # Remove the malformed pack from the pack to install list.
            packs = [
                pack for pack in packs_to_install
                if pack['id'] not in malformed_pack_id
            ]
            request_data = {'packs': packs, 'ignoreWarnings': True}

        finally:
            prints_manager.execute_thread_prints(thread_index)
def install_packs(client: demisto_client,
                  host: str,
                  prints_manager: ParallelPrintsManager,
                  thread_index: int,
                  packs_to_install: list,
                  request_timeout: int = 999999,
                  is_nightly: bool = False):
    """ Make a packs installation request.

    Args:
        client (demisto_client): The configured client to use.
        host (str): The server URL.
        prints_manager (ParallelPrintsManager): Print manager object.
        thread_index (int): the thread index.
        packs_to_install (list): A list of the packs to install.
        request_timeout (int): Timeout settings for the installation request.
        is_nightly (bool): Is the build nightly or not.
    """
    if is_nightly:
        install_nightly_packs(client, host, prints_manager, thread_index,
                              packs_to_install)
    request_data = {'packs': packs_to_install, 'ignoreWarnings': True}

    packs_to_install_str = ', '.join([pack['id'] for pack in packs_to_install])
    message = 'Installing the following packs in server {}:\n{}'.format(
        host, packs_to_install_str)
    prints_manager.add_print_job(message,
                                 print_color,
                                 thread_index,
                                 LOG_COLORS.GREEN,
                                 include_timestamp=True)
    prints_manager.execute_thread_prints(thread_index)

    # make the pack installation request
    try:
        response_data, status_code, _ = demisto_client.generic_request_func(
            client,
            path='/contentpacks/marketplace/install',
            method='POST',
            body=request_data,
            accept='application/json',
            _request_timeout=request_timeout)

        if 200 <= status_code < 300:
            packs_data = [{
                'ID': pack.get('id'),
                'CurrentVersion': pack.get('currentVersion')
            } for pack in ast.literal_eval(response_data)]
            packs_message = f'The following packs were successfully installed:\n{packs_data}'
            prints_manager.add_print_job(packs_message,
                                         print_color,
                                         thread_index,
                                         LOG_COLORS.GREEN,
                                         include_timestamp=True)
        else:
            result_object = ast.literal_eval(response_data)
            message = result_object.get('message', '')
            err_msg = f'Failed to install packs - with status code {status_code}\n{message}\n'
            prints_manager.add_print_job(err_msg,
                                         print_error,
                                         thread_index,
                                         include_timestamp=True)
            raise Exception(err_msg)
    except Exception as e:
        err_msg = f'The request to install packs has failed. Reason:\n{str(e)}\n'
        prints_manager.add_print_job(err_msg,
                                     print_error,
                                     thread_index,
                                     include_timestamp=True)

        global SUCCESS_FLAG
        SUCCESS_FLAG = False
    finally:
        prints_manager.execute_thread_prints(thread_index)