def generate_example_dict(examples_file: Optional[str], insecure=False): """ Generate the example dict via an XSOAR server and return dict results. Args: examples_file: yaml as python dict. insecure: wether to run the examples without checking ssl. """ command_examples = get_command_examples(examples_file, None) example_dict, build_errors = build_example_dict(command_examples, insecure) if build_errors: raise Exception(f'Command examples had errors: {build_errors}') return example_dict
def generate_integration_doc(input, output, examples, id_set, verbose=False): try: yml_data = get_yaml(input) errors = [] example_dict = {} if examples and os.path.isfile(examples): command_examples = get_command_examples(examples) example_dict, build_errors = build_example_dict(command_examples) errors.extend(build_errors) else: errors.append(f'Command examples was not found {examples}.') docs = [] # type: list docs.extend(add_lines(yml_data.get('description'))) docs.append( 'This integration was integrated and tested with version xx of {}'. format(yml_data['name'])) # Setup integration to work with Demisto docs.extend( generate_section( 'Configure {} on Demisto'.format(yml_data['name']), '')) # Setup integration on Demisto docs.extend(generate_setup_section(yml_data)) # Commands command_section, command_errors = generate_commands_section( yml_data, example_dict) docs.extend(command_section) errors.extend(command_errors) # Additional info docs.extend(generate_section('Additional Information', '')) # Known limitations docs.extend(generate_section('Known Limitations', '')) doc_text = '\n'.join(docs) save_output(output, 'README.md', doc_text) if errors: print_warning('Possible Errors:') for error in errors: print_warning(error) except Exception as ex: if verbose: raise else: print_error(f'Error: {str(ex)}') return
def generate_script_doc(input_path, examples, output: str = None, permissions: str = None, limitations: str = None, insecure: bool = False, verbose: bool = False): try: doc: list = [] errors: list = [] example_section: list = [] if not output: # default output dir will be the dir of the input file output = os.path.dirname(os.path.realpath(input_path)) if examples: if os.path.isfile(examples): with open(examples, 'r') as examples_file: examples = examples_file.read().splitlines() else: examples = examples.split(',') for i, example in enumerate(examples): if not example.startswith('!'): examples[i] = f'!{examples}' example_dict, build_errors = build_example_dict(examples, insecure) script_name = list( example_dict.keys())[0] if example_dict else None example_section, example_errors = generate_script_example( script_name, example_dict) errors.extend(build_errors) errors.extend(example_errors) else: errors.append( 'Note: Script example was not provided. For a more complete documentation,run with the -e ' 'option with an example command. For example: -e "!ConvertFile entry_id=<entry_id>".' ) script = get_yaml(input_path) # get script data script_info = get_script_info(input_path) script_id = script.get('commonfields')['id'] # get script dependencies dependencies, _ = get_depends_on(script) # get the script usages by the id set if not os.path.isfile(DEFAULT_ID_SET_PATH): id_set_creator = IDSetCreator(output='', print_logs=False) id_set, _, _ = id_set_creator.create_id_set() else: id_set = open_id_set_file(DEFAULT_ID_SET_PATH) used_in = get_used_in(id_set, script_id) description = script.get('comment', '') # get inputs/outputs inputs, inputs_errors = get_inputs(script) outputs, outputs_errors = get_outputs(script) errors.extend(inputs_errors) errors.extend(outputs_errors) if not description: errors.append( 'Error! You are missing a description for the Script') doc.append(description + '\n') doc.extend(generate_table_section(script_info, 'Script Data')) if dependencies: doc.extend( generate_list_section( 'Dependencies', dependencies, True, text='This script uses the following commands and scripts.' )) # Script global permissions if permissions == 'general': doc.extend(generate_section('Permissions', '')) if used_in: if len(used_in) <= 10: doc.extend( generate_list_section( 'Used In', used_in, True, text= 'This script is used in the following playbooks and scripts.' )) else: # if we have more than 10 use a sample print_warning( f'"Used In" section found too many scripts/playbooks ({len(used_in)}). Will use a sample of 10.' ' Full list is available as a comment in the README file.') sample_used_in = random.sample(used_in, 10) doc.extend( generate_list_section( 'Used In', sorted(sample_used_in), True, text= 'Sample usage of this script can be found in the following playbooks and scripts.' )) used_in_str = '\n'.join(used_in) doc.append( f"<!--\nUsed In: list was truncated. Full list commented out for reference:\n\n{used_in_str}\n -->\n" ) doc.extend( generate_table_section(inputs, 'Inputs', 'There are no inputs for this script.')) doc.extend( generate_table_section(outputs, 'Outputs', 'There are no outputs for this script.')) if example_section: doc.extend(example_section) # Known limitations if limitations: doc.extend( generate_numbered_section('Known Limitations', limitations)) doc_text = '\n'.join(doc) save_output(output, 'README.md', doc_text) if errors: print_warning('Possible Errors:') for error in errors: print_warning(error) except Exception as ex: if verbose: raise else: print_error(f'Error: {str(ex)}') return
def generate_integration_doc(input_path: str, examples: Optional[str] = None, output: Optional[str] = None, use_cases: Optional[str] = None, permissions: Optional[str] = None, command_permissions: Optional[str] = None, limitations: Optional[str] = None, insecure: bool = False, verbose: bool = False, command: Optional[str] = None): """ Generate integration documentation. Args: input_path: path to the yaml integration examples: path to the command examples output: path to the output documentation use_cases: use cases string permissions: global permissions for the docs command_permissions: permissions per command limitations: limitations description insecure: should use insecure verbose: verbose (debug mode) command: specific command to generate docs for """ try: yml_data = get_yaml(input_path) if not output: # default output dir will be the dir of the input file output = os.path.dirname(os.path.realpath(input_path)) errors: list = [] example_dict = {} if examples and os.path.isfile(examples): command_examples = get_command_examples(examples) example_dict, build_errors = build_example_dict( command_examples, insecure) errors.extend(build_errors) else: errors.append(f'Command examples was not found {examples}.') if permissions == 'per-command': command_permissions_dict: Any = {} if command_permissions and os.path.isfile(command_permissions): permission_list = get_command_permissions(command_permissions) for command_permission in permission_list: # get all the permissions after the command name key, value = command_permission.split(" ", 1) command_permissions_dict.update({key: value}) else: errors.append( f'Command permissions was not found {command_permissions}.' ) else: # permissions in ['none', 'general'] command_permissions_dict = None if command: specific_commands = command.split(',') readme_path = os.path.join(output, 'README.md') with open(readme_path) as f: doc_text = f.read() for specific_command in specific_commands: print(f'Generating docs for command `{command}`') command_section, command_errors = generate_commands_section( yml_data, example_dict, command_permissions_dict, command=specific_command) command_section_str = '\n'.join(command_section) doc_text, err = append_or_replace_command_in_docs( doc_text, command_section_str, specific_command) errors.extend(err) else: docs = [] # type: list docs.extend(add_lines(yml_data.get('description'))) docs.extend([ 'This integration was integrated and tested with version xx of {}' .format(yml_data['name']) ]) # Integration use cases if use_cases: docs.extend(generate_numbered_section('Use Cases', use_cases)) # Integration general permissions if permissions == 'general': docs.extend(generate_section('Permissions', '')) # Setup integration to work with Demisto docs.extend( generate_section( 'Configure {} on Cortex XSOAR'.format(yml_data['name']), '')) # Setup integration on Demisto docs.extend(generate_setup_section(yml_data)) # Commands command_section, command_errors = generate_commands_section( yml_data, example_dict, command_permissions_dict, command=command) docs.extend(command_section) errors.extend(command_errors) # Known limitations if limitations: docs.extend( generate_numbered_section('Known Limitations', limitations)) doc_text = '\n'.join(docs) save_output(output, 'README.md', doc_text) if errors: print_warning('Possible Errors:') for error in errors: print_warning(error) except Exception as ex: if verbose: raise else: print_error(f'Error: {str(ex)}') return
def generate_script_doc(input, output, examples, id_set='', verbose=False): try: doc = [] errors = [] used_in = [] example_section = [] if examples: if not examples.startswith('!'): examples = f'!{examples}' example_dict, build_errors = build_example_dict([examples]) script_name = examples.split(' ')[0][1:] example_section, example_errors = generate_script_example( script_name, example_dict) errors.extend(build_errors) errors.extend(example_errors) else: errors.append( f'Note: Script example was not provided. For a more complete documentation,run with the -e ' f'option with an example command. For example: -e "!ConvertFile entry_id=<entry_id>".' ) script = get_yaml(input) # get script data secript_info = get_script_info(input) script_id = script.get('commonfields')['id'] # get script dependencies dependencies, _ = get_depends_on(script) if not id_set: errors.append(f'id_set.json file is missing') elif not os.path.isfile(id_set): errors.append(f'id_set.json file {id_set} was not found') else: used_in = get_used_in(id_set, script_id) description = script.get('comment', '') deprecated = script.get('deprecated', False) # get inputs/outputs inputs, inputs_errors = get_inputs(script) outputs, outputs_errors = get_outputs(script) errors.extend(inputs_errors) errors.extend(outputs_errors) if not description: errors.append( 'Error! You are missing description for the playbook') if deprecated: doc.append('`Deprecated`') doc.append(description) doc.extend(generate_table_section(secript_info, 'Script Data')) if dependencies: doc.extend( generate_list_section( 'Dependencies', dependencies, True, text='This script uses the following commands and scripts.' )) if used_in: doc.extend( generate_list_section( 'Used In', used_in, True, text= 'This script is used in the following playbooks and scripts.' )) doc.extend( generate_table_section(inputs, 'Inputs', 'There are no inputs for this script.')) doc.extend( generate_table_section(outputs, 'Outputs', 'There are no outputs for this script.')) if example_section: doc.extend(example_section) doc_text = '\n'.join(doc) save_output(output, 'README.md', doc_text) if errors: print_warning('Possible Errors:') for error in errors: print_warning(error) except Exception as ex: if verbose: raise else: print_error(f'Error: {str(ex)}') return
def generate_integration_doc(input, examples, output: str = None, use_cases: str = None, permissions: str = None, command_permissions: str = None, limitations: str = None, insecure: bool = False, verbose: bool = False): try: yml_data = get_yaml(input) if not output: # default output dir will be the dir of the input file output = os.path.dirname(os.path.realpath(input)) errors = [] example_dict = {} if examples and os.path.isfile(examples): command_examples = get_command_examples(examples) example_dict, build_errors = build_example_dict(command_examples, insecure) errors.extend(build_errors) else: errors.append(f'Command examples was not found {examples}.') if permissions == 'per-command': command_permissions_dict = {} if command_permissions and os.path.isfile(command_permissions): command_permissions = get_command_permissions(command_permissions) for command_permission in command_permissions: # get all the permissions after the command name key, value = command_permission.split(" ", 1) command_permissions_dict.update({key: value}) else: errors.append(f'Command permissions was not found {command_permissions}.') else: # permissions in ['none', 'general'] command_permissions_dict = None docs = [] # type: list docs.extend(add_lines(yml_data.get('description'))) docs.extend(['This integration was integrated and tested with version xx of {}'.format(yml_data['name'])]) # Integration use cases if use_cases: docs.extend(generate_numbered_section('Use Cases', use_cases)) # Integration general permissions if permissions == 'general': docs.extend(generate_section('Permissions', '')) # Setup integration to work with Demisto docs.extend(generate_section('Configure {} on Demisto'.format(yml_data['name']), '')) # Setup integration on Demisto docs.extend(generate_setup_section(yml_data)) # Commands command_section, command_errors = generate_commands_section(yml_data, example_dict, command_permissions_dict) docs.extend(command_section) errors.extend(command_errors) # Known limitations if limitations: docs.extend(generate_numbered_section('Known Limitations', limitations)) doc_text = '\n'.join(docs) save_output(output, 'README.md', doc_text) if errors: print_warning('Possible Errors:') for error in errors: print_warning(error) except Exception as ex: if verbose: raise else: print_error(f'Error: {str(ex)}') return
def generate_script_doc(input, examples, output: str = None, permissions: str = None, limitations: str = None, insecure: bool = False, verbose: bool = False): try: doc = [] errors = [] used_in = [] example_section = [] if not output: # default output dir will be the dir of the input file output = os.path.dirname(os.path.realpath(input)) if examples: if not examples.startswith('!'): examples = f'!{examples}' example_dict, build_errors = build_example_dict([examples], insecure) script_name = examples.split(' ')[0][1:] example_section, example_errors = generate_script_example( script_name, example_dict) errors.extend(build_errors) errors.extend(example_errors) else: errors.append( f'Note: Script example was not provided. For a more complete documentation,run with the -e ' f'option with an example command. For example: -e "!ConvertFile entry_id=<entry_id>".' ) script = get_yaml(input) # get script data secript_info = get_script_info(input) script_id = script.get('commonfields')['id'] # get script dependencies dependencies, _ = get_depends_on(script) # get the script usages by the id set id_set_creator = IDSetCreator() id_set = id_set_creator.create_id_set() used_in = get_used_in(id_set, script_id) description = script.get('comment', '') deprecated = script.get('deprecated', False) # get inputs/outputs inputs, inputs_errors = get_inputs(script) outputs, outputs_errors = get_outputs(script) errors.extend(inputs_errors) errors.extend(outputs_errors) if not description: errors.append( 'Error! You are missing description for the playbook') if deprecated: doc.append('`Deprecated`') doc.append(description) doc.extend(generate_table_section(secript_info, 'Script Data')) if dependencies: doc.extend( generate_list_section( 'Dependencies', dependencies, True, text='This script uses the following commands and scripts.' )) # Script global permissions if permissions == 'general': doc.extend(generate_section('Permissions', '')) if used_in: doc.extend( generate_list_section( 'Used In', used_in, True, text= 'This script is used in the following playbooks and scripts.' )) doc.extend( generate_table_section(inputs, 'Inputs', 'There are no inputs for this script.')) doc.extend( generate_table_section(outputs, 'Outputs', 'There are no outputs for this script.')) if example_section: doc.extend(example_section) # Known limitations if limitations: doc.extend( generate_numbered_section('Known Limitations', limitations)) doc_text = '\n'.join(doc) save_output(output, 'README.md', doc_text) if errors: print_warning('Possible Errors:') for error in errors: print_warning(error) except Exception as ex: if verbose: raise else: print_error(f'Error: {str(ex)}') return
def generate_integration_doc(input_path: str, examples: Optional[str] = None, output: Optional[str] = None, use_cases: Optional[str] = None, permissions: Optional[str] = None, command_permissions: Optional[str] = None, limitations: Optional[str] = None, insecure: bool = False, verbose: bool = False, command: Optional[str] = None, old_version: str = '', skip_breaking_changes: bool = False, is_contribution: bool = False): """ Generate integration documentation. Args: input_path: path to the yaml integration examples: path to the command examples output: path to the output documentation use_cases: use cases string permissions: global permissions for the docs command_permissions: permissions per command limitations: limitations description insecure: should use insecure verbose: verbose (debug mode) command: specific command to generate docs for is_contribution: Check if the content item is a new integration contribution or not. """ try: yml_data = get_yaml(input_path) if not output: # default output dir will be the dir of the input file output = os.path.dirname(os.path.realpath(input_path)) errors: list = [] example_dict: dict = {} if examples: specific_commands = command.split(',') if command else None command_examples = get_command_examples(examples, specific_commands) example_dict, build_errors = build_example_dict( command_examples, insecure) errors.extend(build_errors) else: errors.append(f'Command examples was not found: {examples}.') if permissions == 'per-command': command_permissions_dict: Any = {} if command_permissions and os.path.isfile(command_permissions): permission_list = get_command_permissions(command_permissions) for command_permission in permission_list: # get all the permissions after the command name key, value = command_permission.split(" ", 1) command_permissions_dict.update({key: value}) else: errors.append( f'Command permissions was not found {command_permissions}.' ) else: # permissions in ['none', 'general'] command_permissions_dict = None if command: specific_commands = command.split(',') readme_path = os.path.join(output, 'README.md') with open(readme_path) as f: doc_text = f.read() for specific_command in specific_commands: print(f'Generating docs for command `{specific_command}`') command_section, command_errors = generate_commands_section( yml_data, example_dict, command_permissions_dict, command=specific_command) command_section_str = '\n'.join(command_section) doc_text, err = append_or_replace_command_in_docs( doc_text, command_section_str, specific_command) errors.extend(err) else: docs = [] # type: list docs.extend(add_lines(yml_data.get('description'))) if not is_contribution: docs.extend([ 'This integration was integrated and tested with version xx of {}' .format(yml_data['name']), '' ]) # Checks if the integration is a new version integration_version = re.findall("[vV][2-9]$", yml_data.get("display", "")) if integration_version and not skip_breaking_changes: docs.extend([ 'Some changes have been made that might affect your existing content. ' '\nIf you are upgrading from a previous of this integration, see [Breaking Changes]' '(#breaking-changes-from-the-previous-version-of-this-integration-' f'{yml_data.get("display", "").replace(" ", "-").lower()}).', '' ]) # Integration use cases if use_cases: docs.extend(generate_numbered_section('Use Cases', use_cases)) # Integration general permissions if permissions == 'general': docs.extend(generate_section('Permissions', '')) # Setup integration to work with Demisto docs.extend( generate_section( 'Configure {} on Cortex XSOAR'.format(yml_data['display']), '')) # Setup integration on Demisto docs.extend(generate_setup_section(yml_data)) # Commands command_section, command_errors = generate_commands_section( yml_data, example_dict, command_permissions_dict, command=command) docs.extend(command_section) # breaking changes if integration_version and not skip_breaking_changes: docs.extend( generate_versions_differences_section( input_path, old_version, yml_data.get("display", ""))) errors.extend(command_errors) # Known limitations if limitations: docs.extend( generate_numbered_section('Known Limitations', limitations)) doc_text = '\n'.join(docs) save_output(output, 'README.md', doc_text) if errors: print_warning('Possible Errors:') for error in errors: print_warning(error) except Exception as ex: if verbose: raise else: print_error(f'Error: {str(ex)}') return