diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 0000000..ff93a8f --- /dev/null +++ b/.ansible-lint @@ -0,0 +1,24 @@ +--- +# Collection wide lint-file +# DO NOT CHANGE +exclude_paths: + - .ansible/ + - .cache/ + - .github/ + # - docs/ + - changelogs/ + - playbooks/ + - tests/ +enable_list: + - yaml +skip_list: + # We don't want to enforce new Ansible versions for Galaxy: + - meta-runtime[unsupported-version] + # We do not want to use checks which are marked as experimental: + - experimental + # We use ignore_errors for all the assert tasks, which should be acceptable: + - ignore-errors + # We want to allow single digit version numbers in a role's meta/main.yml file: + - schema + # Allow templating inside name because it creates more detailed output: + - name[template] diff --git a/.gitignore b/.gitignore index 4938417..9ff6291 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,4 @@ __pycache__/ # VSCode .vscode +.ansible diff --git a/plugins/module_utils/sap_api_common.py b/plugins/module_utils/sap_api_common.py index 204b492..164b173 100644 --- a/plugins/module_utils/sap_api_common.py +++ b/plugins/module_utils/sap_api_common.py @@ -37,9 +37,23 @@ def _request(url, **kwargs): method = 'POST' if kwargs.get('data') or kwargs.get('json') else 'GET' res = https_session.request(method, url, **kwargs) - if (res.status_code == 403 - and res.json()['errorMessage'].startswith('Account Temporarily Locked Out')): - raise Exception('SAP ID Service has reported `Account Temporarily Locked Out`. Please reset password to regain access and try again.') + # Validating against `res.text` can cause long execution time, because fuzzy search result can contain large `res.text`. + # This can be prevented by validating `res.status_code` check before `res.text`. + # Example: 'Two-Factor Authentication' is only in `res.text`, which can lead to long execution. + + if res.status_code == 403: + if 'You are not authorized to download this file' in res.text: + raise Exception(f'You are not authorized to download this file.') + elif 'Account Temporarily Locked Out' in res.text: + raise Exception(f'Account Temporarily Locked Out. Please reset password to regain access and try again.') + else: + res.raise_for_status() + + if res.status_code == 404: + if 'The file you have requested cannot be found' in res.text: + raise Exception(f'The file you have requested cannot be found.') + else: + res.raise_for_status() res.raise_for_status() diff --git a/plugins/modules/maintenance_planner_stack_xml_download.py b/plugins/modules/maintenance_planner_stack_xml_download.py index 3f444db..6e958eb 100644 --- a/plugins/modules/maintenance_planner_stack_xml_download.py +++ b/plugins/modules/maintenance_planner_stack_xml_download.py @@ -30,7 +30,7 @@ - Transaction Name or Transaction Display ID from Maintenance Planner. required: true type: str - download_path: + dest: description: - Destination folder path. required: true @@ -46,7 +46,7 @@ suser_id: 'SXXXXXXXX' suser_password: 'password' transaction_name: 'MP_NEW_INST_20211015_044854' - download_path: "/tmp/" + dest: "/tmp/" register: sap_mp_register - name: Display the list of download links and filenames debug: @@ -79,7 +79,7 @@ def run_module(): suser_id=dict(type='str', required=True), suser_password=dict(type='str', required=True, no_log=True), transaction_name=dict(type='str', required=True), - download_path=dict(type='str', required=True) + dest=dict(type='str', required=True) ) # Define result dictionary objects to be passed back to Ansible @@ -102,7 +102,7 @@ def run_module(): username = module.params.get('suser_id') password = module.params.get('suser_password') transaction_name = module.params.get('transaction_name') - download_path = module.params.get('download_path') + dest = module.params.get('dest') # Main run @@ -118,7 +118,7 @@ def run_module(): transaction_id = get_transaction_id(transaction_name) # EXEC: Download the MP Stack XML file - get_transaction_stack_xml(transaction_id, download_path) + get_transaction_stack_xml(transaction_id, dest) # Process return dictionary for Ansible result['changed'] = True diff --git a/plugins/modules/software_center_download.py b/plugins/modules/software_center_download.py index 4e1fc79..5b909e8 100644 --- a/plugins/modules/software_center_download.py +++ b/plugins/modules/software_center_download.py @@ -48,7 +48,7 @@ - Download filename of the SAP software. required: false type: str - download_path: + dest: description: - Destination folder path. required: true @@ -80,14 +80,14 @@ suser_password: 'password' search_query: - 'SAPCAR_1324-80000936.EXE' - download_path: "/tmp/" + dest: "/tmp/" - name: Download using direct link and filename community.sap_launchpad.software_center_download: suser_id: 'SXXXXXXXX' suser_password: 'password' download_link: 'https://softwaredownloads.sap.com/file/0010000000048502015' download_filename: 'IW_FNDGC100.SAR' - download_path: "/tmp/" + dest: "/tmp/" ''' RETURN = r''' @@ -116,21 +116,21 @@ from ..module_utils.sap_launchpad_software_center_download_runner import * from ..module_utils.sap_id_sso import sap_sso_login -def _check_similar_files(download_path, filename): +def _check_similar_files(dest, filename): """ Checks for similar files in the download path based on the given filename. Args: - download_path (str): The path where files are downloaded. + dest (str): The path where files are downloaded. filename (str): The filename to check for similar files. Returns: bool: True if similar files exist, False otherwise. filename_similar_names: A list of similar filenames if they exist, empty list otherwise. """ - # pattern = download_path + '/**/' + os.path.splitext(filename)[0] + # pattern = dest + '/**/' + os.path.splitext(filename)[0] filename_base = os.path.splitext(filename)[0] - filename_pattern = os.path.join(download_path, "**", filename_base) + filename_pattern = os.path.join(dest, "**", filename_base) filename_similar = glob.glob(filename_pattern, recursive=True) if filename_similar: @@ -150,7 +150,7 @@ def run_module(): search_query=dict(type='str', required=False, default=''), download_link=dict(type='str', required=False, default=''), download_filename=dict(type='str', required=False, default=''), - download_path=dict(type='str', required=True), + dest=dict(type='str', required=True), dry_run=dict(type='bool', required=False, default=False), deduplicate=dict(type='str', required=False, default=''), search_alternatives=dict(type='bool', required=False, default=False) @@ -174,7 +174,7 @@ def run_module(): else: query = None - download_path = module.params['download_path'] + dest = module.params['dest'] download_link= module.params.get('download_link') download_filename= module.params.get('download_filename') dry_run = module.params.get('dry_run') @@ -207,7 +207,7 @@ def run_module(): # Search for existing files using exact filename filename = query if query else download_filename - filename_exact = os.path.join(download_path, filename) + filename_exact = os.path.join(dest, filename) result['filename'] = filename if os.path.exists(filename_exact): @@ -216,7 +216,7 @@ def run_module(): module.exit_json(**result) else: # Exact file not found, search for similar files with pattern - filename_similar_exists, filename_similar_names = _check_similar_files(download_path, filename) + filename_similar_exists, filename_similar_names = _check_similar_files(dest, filename) if filename_similar_exists and not (query and search_alternatives): result['skipped'] = True result['msg'] = f"Similar file(s) already exist: {', '.join(filename_similar_names)}" @@ -235,14 +235,14 @@ def run_module(): result['filename'] = download_filename result['alternative'] = True - filename_alternative_exact = os.path.join(download_path, download_filename) + filename_alternative_exact = os.path.join(dest, download_filename) if os.path.exists(filename_alternative_exact): result['skipped'] = True result['msg'] = f"Alternative file already exists: {download_filename} - original file {query} is not available to download" module.exit_json(**result) else: # Exact file not found, search for similar files with pattern - filename_similar_exists, filename_similar_names = _check_similar_files(download_path, download_filename) + filename_similar_exists, filename_similar_names = _check_similar_files(dest, download_filename) if filename_similar_exists: result['skipped'] = True result['msg'] = f"Similar alternative file(s) already exist: {', '.join(filename_similar_names)}" @@ -252,13 +252,13 @@ def run_module(): elif filename != download_filename and not alternative_found: result['filename'] = download_filename - if os.path.exists(os.path.join(download_path, download_filename)): + if os.path.exists(os.path.join(dest, download_filename)): result['skipped'] = True result['msg'] = f"File already exists with correct name: {download_filename}" module.exit_json(**result) else: # Exact file not found, search for similar files with pattern - filename_similar_exists, filename_similar_names = _check_similar_files(download_path, download_filename) + filename_similar_exists, filename_similar_names = _check_similar_files(dest, download_filename) if filename_similar_exists: result['skipped'] = True result['msg'] = f"Similar file(s) already exist for correct name {download_filename}: {', '.join(filename_similar_names)}" @@ -281,7 +281,7 @@ def run_module(): else: module.fail_json(msg="Download link {} is not available".format(download_link)) - download_software(download_link, download_filename, download_path) + download_software(download_link, download_filename, dest) # Update final results json result['changed'] = True diff --git a/roles/.gitkeep b/roles/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/roles/sap_software_download/.yamllint.yml b/roles/sap_software_download/.yamllint.yml new file mode 100644 index 0000000..ee4457c --- /dev/null +++ b/roles/sap_software_download/.yamllint.yml @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: Apache-2.0 +--- +# Based on ansible-lint config +extends: default + +rules: + braces: {max-spaces-inside: 1, level: error} + brackets: {max-spaces-inside: 1, level: error} +# colons: {max-spaces-after: -1, level: error} +# commas: {max-spaces-after: -1, level: error} + comments: + require-starting-space: false + min-spaces-from-content: 1 + comments-indentation: disable +# document-start: disable +# empty-lines: {max: 3, level: error} +# hyphens: {level: error} +# indentation: disable +# key-duplicates: enable + line-length: disable +# new-line-at-end-of-file: disable +# new-lines: {type: unix} +# trailing-spaces: disable + truthy: disable + octal-values: + forbid-implicit-octal: true + forbid-explicit-octal: true diff --git a/roles/sap_software_download/README.md b/roles/sap_software_download/README.md new file mode 100644 index 0000000..93fdd7b --- /dev/null +++ b/roles/sap_software_download/README.md @@ -0,0 +1,321 @@ + +# sap_software_download Ansible Role + + +## Description + +The Ansible Role `sap_software_download` is used to download SAP Software Media from SAP. + + + +## Dependencies +This role requires the following Python modules to be installed on the target node (the machine where SAP software will be downloaded): + +- wheel +- urllib3 +- requests +- beautifulsoup4 +- lxml + +The role installs these modules if they are not already present. Installation can be done in one of the following ways: + +- **Virtual Environment (Default):** + - When `sap_software_download_use_venv` is `true` (default), a temporary virtual environment is created, and modules are installed via `pip`. + - The Python version is determined by `sap_software_download_python_interpreter`. +- **System Environment:** + - When `sap_software_download_use_venv` is `false`, modules are installed directly into the system's Python environment using OS packages specified by `sap_software_download_python_module_packages`. + + + +## Prerequisites +The target node must meet the following requirements: + +* **OS Package Repositories:** The operating system must be registered and have access to repositories to install the required Python packages. + * The actual package name is determined by the `sap_software_download_python_package` variable. + * For example, on some systems, these packages might be named `python3` and `python3-pip`. + + + + +## Execution + + + + + + +### Execution Flow + +1. **Input Validation:** The role first checks if all required input variables have been provided. +2. **Python Environment Preparation:** The role prepares the Python environment: + * **Virtual Environment (Default):** A temporary Python virtual environment is created, and all necessary dependencies are installed within it. + * **System Environment:** Alternatively, if `sap_software_download_use_venv` is set to `false`, dependencies are installed directly into the system's default Python environment. +3. **Validate provided S-User credentials** The role will search for `SAPCAR` file to validate credentials and download authorization. +4. **Maintenance Plan File List:** If the `sap_software_download_mp_transaction` variable is provided, the role retrieves the list of files associated with the specified Maintenance Plan transaction. +5. **File Relationship Validation:** If `sap_software_download_validate_relationships` is `true`, the role performs validation checks on the relationships between the files to be downloaded. + * **Alternative File Search:** If `sap_software_download_find_alternatives` is `true`, the role will search for alternative files if the requested files are not found. + * More information about validation logic is available at [Explanation of relationship validation logic](#explanation-of-relationship-validation-logic) +6. **Maintenance Plan File Download:** If `sap_software_download_mp_transaction` is provided, the role downloads the files associated with the Maintenance Plan. +7. **Direct File Download:** If `sap_software_download_files` is provided, the role downloads the specified files. +8. **Virtual Environment Cleanup:** If a temporary Python virtual environment was used, it is removed. + + + +### Example + +Download of SAP Software files using input list +```yaml +--- +- name: Ansible Play for downloading SAP Software + hosts: localhost + become: true + tasks: + - name: Include role sap_software_download + ansible.builtin.include_role: + name: community.sap_launchpad.sap_software_download + vars: + sap_software_download_suser_id: "Enter SAP S-User ID" + sap_software_download_suser_password: "Enter SAP S-User Password" + sap_software_download_directory: "/software" + sap_software_download_files: + - 'SAPCAR_1115-70006178.EXE' + - 'SAPEXE_100-80005509.SAR' +``` + +Download of SAP Software files using Maintenance Plan +```yaml +--- +- name: Ansible Play for downloading SAP Software + hosts: localhost + become: true + tasks: + - name: Include role sap_software_download + ansible.builtin.include_role: + name: community.sap_launchpad.sap_software_download + vars: + sap_software_download_suser_id: "Enter SAP S-User ID" + sap_software_download_suser_password: "Enter SAP S-User Password" + sap_software_download_directory: "/software" + sap_software_download_mp_transaction: 'Transaction Name or Display ID from Maintenance Planner' +``` + +Combined download of SAP Software files and Maintenance Plan transaction together with settings: +- Use default Python instead of Python virtual environment +- No validation of S-User credentials +- No validation of relationships +- No warnings for unavailable files +- No warnings for unavailable Maintenance Plan transaction +```yaml +- name: Ansible Play for downloading SAP Software + hosts: localhost + become: true + tasks: + - name: Include role sap_software_download + ansible.builtin.include_role: + name: community.sap_launchpad.sap_software_download + vars: + sap_software_download_suser_id: "Enter SAP S-User ID" + sap_software_download_suser_password: "Enter SAP S-User Password" + sap_software_download_directory: "/software" + sap_software_download_use_venv: false + sap_software_download_ignore_validate_credentials: true + sap_software_download_ignore_file_not_found: true + sap_software_download_ignore_plan_not_found: true + sap_software_download_validate_relationships: false + sap_software_download_deduplicate: first + sap_software_download_files: + - 'SAPCAR_1115-70006178.EXE' + - 'SAPEXE_100-80005509.SAR' + sap_software_download_mp_transaction: 'Transaction Name or Display ID from Maintenance Planner' +``` +Download of SAP Software files using Python version `3.13`. +```yaml +--- +- name: Ansible Play for downloading SAP Software + hosts: localhost + become: true + tasks: + - name: Include role sap_software_download + ansible.builtin.include_role: + name: community.sap_launchpad.sap_software_download + vars: + sap_software_download_python_interpreter: python3.13 + sap_software_download_python_package: python313 + sap_software_download_python_module_packages: + - python313-wheel + - python313-urllib3 + - python313-requests + - python313-beautifulsoup4 + - python313-lxml + sap_software_download_suser_id: "Enter SAP S-User ID" + sap_software_download_suser_password: "Enter SAP S-User Password" + sap_software_download_directory: "/software" + sap_software_download_files: + - 'SAPCAR_1115-70006178.EXE' + - 'SAPEXE_100-80005509.SAR' +``` + + + + + + +## Further Information +### Explanation of relationship validation logic +Validation is executed for known combinations of files, where we can validate their name and version.
+Example for SAP HANA Database Server 2.0 with LCAPPS and AFL.
+ +1. All files are examined, and a file starting with `IMDB_SERVER2` is found: `IMDB_SERVER20_084_0-80002031.SAR (Revision 2.00.084.0 (SPS08))`. This indicates a SAP HANA 2.0 database server file. +2. The HANA version and revision are extracted from the file name: `HANA 2.0`, `Version 084`. +3. Validation for HANA 1.0 is skipped because it expects files starting with `IMDB_SERVER1`. The following steps are only for `IMDB_SERVER2` (HANA 2.0). +4. All files are examined for files starting with `IMDB_LCAPPS_2` (indicating LCAPPS for HANA 2.0). Then the list is filtered to only include files starting with `IMDB_LCAPPS_2084` (indicating LCAPPS for HANA 2.0 revision 084). +5. Validation will have two outcomes: + - A file like `IMDB_LCAPPS_2084_0-20010426.SAR` is present. In this case, validation will pass because the LCAPPS version is compatible with the HANA revision. + - No file starting with `IMDB_LCAPPS_2084` is present, but there are files starting with `IMDB_LCAPPS_2`.
+ This indicates a mismatch because the LCAPPS version is not compatible with the specific HANA revision (084) found in step 2.
+ In this case, validation will fail. This can be ignored by setting `sap_software_download_ignore_relationship_warning` to `true`. +6. All files are examined for files starting with `IMDB_AFL20` (indicating AFL for HANA 2.0). Then the list is filtered to only include files starting with `IMDB_AFL20_084` (indicating AFL for HANA 2.0 revision 084). +7. Validation will have two outcomes: + - A file like `IMDB_AFL20_084_1-80001894.SAR` is present. In this case, validation will pass because the AFL version is compatible with the HANA revision. + - No file starting with `IMDB_AFL20_084` is present, but there are files starting with `IMDB_AFL20`.
+ This indicates a mismatch because the AFL version is not compatible with the specific HANA revision (084) found in step 2.
+ In this case, validation will fail. This can be ignored by setting `sap_software_download_ignore_relationship_warning` to `true`. + +This validation example checks major and minor release (SPS and Revision), but it does not validate patch version. + + +## License + +Apache 2.0 + + +## Maintainers + +- [Marcel Mamula](https://github.com/marcelmamula) + + +## Role Variables + +### sap_software_download_python_interpreter +- _Type:_ `string`
+- _Default:_ **Determined by the operating system.**
+ +The Python interpreter executable to use when creating a Python virtual environment.
+**Mandatory** when `sap_software_download_use_venv` is `true`.
+This is the name of the Python executable (e.g., `python3.11`, `python3.9`), which may differ from the Python package name.
+The default value is determined by the operating system and is set in the corresponding OS-specific variables file.
+Examples: `python3.11` (SUSE), `python3.9` (Red Hat)
+ +### sap_software_download_python_package +- _Type:_ `string`
+- _Default:_ **Determined by the operating system.**
+ +The name of the OS package that provides the desired Python version.
+The Python version provided by this package must match the version specified by `sap_software_download_python_interpreter`.
+The default value is determined by the operating system and is set in the corresponding OS-specific variables file.
+Examples: `python311` (SUSE), `python3.9` (Red Hat)
+ +### sap_software_download_python_module_packages +- _Type:_ `list` with elements of type `string`
+- _Default:_ **Determined by the operating system.**
+ +The list of the OS packages that provide modules for the desired Python version.
+Required modules are wheel, urllib3, requests, beautifulsoup4, lxml
+The listed package versions must match the Python version specified by `sap_software_download_python_interpreter`.
+The default value is determined by the operating system and is set in the corresponding OS-specific variables file.
+Examples:
+- `['python311-wheel', 'python311-urllib3', 'python311-requests', 'python311-beautifulsoup4', 'python311-lxml']` (SUSE)
+- `['python3.9-wheel', 'python3.9-urllib3', 'python3.9-requests', 'python3.9-beautifulsoup4', 'python3.9-lxml']` (Red Hat)
+ +### sap_software_download_use_venv +- _Type:_ `boolean`
+- _Default:_ `true`
+ +Determines whether to execute the role within a Python virtual environment.
+Using a virtual environment is strongly recommended to isolate dependencies.
+If set to `false`, the role will install Python dependencies directly into the system's Python environment.
+ +### sap_software_download_suser_id +- _Type:_ `string`
+ +The SAP S-User ID with download authorization for SAP software.
+ +### sap_software_download_suser_password +- _Type:_ `string`
+ +The password for the SAP S-User specified in `sap_software_download_suser_id`.
+ +### sap_software_download_files +- _Type:_ `list` with elements of type `string`
+ +A list of SAP software file names to download.
+ +### sap_software_download_mp_transaction +- _Type:_ `string`
+ +The name or display ID of a transaction from the SAP Maintenance Planner.
+If provided, the role will download all files associated with this Maintenance Plan transaction.
+ +### sap_software_download_find_alternatives +- _Type:_ `boolean`
+- _Default:_ `true`
+ +Enables searching for alternative files if the requested file is not found.
+Only applies to files specified in `sap_software_download_files`.
+If set to `false`, the role will not search for alternatives.
+ +### sap_software_download_directory +- _Type:_ `string`
+ +The directory where downloaded SAP software files will be stored.
+ +### sap_software_download_validate_relationships +- _Type:_ `bool`
+- _Default:_ `true`
+ +Enables validation of relationships between SAP software files.
+Only applies to files specified in `sap_software_download_files`.
+If set to `false`, no relationship validation will be performed.
+Example: Verify version of IMDB_LCAPPS against IMDB_SERVER if IMDB_SERVER was found.
+ +### sap_software_download_ignore_file_not_found +- _Type:_ `bool`
+- _Default:_ `false`
+ +Determines whether to ignore errors when a requested file is not found.
+If set to `true`, the role will continue execution and download other files, even if some files are not found.
+If set to `false`, the role will fail if any requested file is not found.
+ +### sap_software_download_ignore_plan_not_found +- _Type:_ `bool`
+- _Default:_ `false`
+ +Determines whether to ignore errors when a specified Maintenance Plan transaction is not found.
+If set to `true` and a Maintenance Plan is not found, the role will continue execution, downloading any files specified in `sap_software_download_files`.
+If set to `false`, the role will fail if the specified Maintenance Plan is not found.
+ +### sap_software_download_ignore_relationship_warning +- _Type:_ `bool`
+- _Default:_ `false`
+ +Determines whether to ignore warnings during file relationship validation.
+If set to `true`, the role will continue execution even if there are warnings during the validation of file relationships.
+If set to `false`, the role will fail if any warnings are encountered during file relationship validation.
+ +### sap_software_download_ignore_validate_credentials +- _Type:_ `bool`
+- _Default:_ `false`
+ +Determines whether to ignore validate credentials task.
+Disabling this check can lead to locked account, if password is incorrect.
+If set to `true`, the role will continue execution without validating S-User credentials.
+If set to `false`, the role will execute dry run to validate S-User credentials.
+ +### sap_software_download_deduplicate +- _Type:_ `string`
+ +Specifies how to handle duplicate file results when using `sap_software_download_files`.
+If multiple files with the same name are found, this setting determines which one to download.
+- `first`: Download the first file found
+- `last`: Download the last file found.
+ diff --git a/roles/sap_software_download/defaults/main.yml b/roles/sap_software_download/defaults/main.yml new file mode 100644 index 0000000..50ac01f --- /dev/null +++ b/roles/sap_software_download/defaults/main.yml @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# The Python interpreter executable to use when creating a Python virtual environment. +# Mandatory when `sap_software_download_use_venv` is `true`. +# This is the name of the Python executable (e.g., `python3.11`, `python3.9`), which may differ from the Python package name. +# The default value is determined by the operating system and is set in the corresponding OS-specific variables file. +# Examples: `python3.11` (SUSE), `python3.9` (Red Hat) +sap_software_download_python_interpreter: + "{{ __sap_software_download_python_interpreter }}" + +# The name of the OS package that provides the desired Python version. +# The Python version provided by this package must match the version specified by `sap_software_download_python_interpreter`. +# The default value is determined by the operating system and is set in the corresponding OS-specific variables file. +# Examples: `python311` (SUSE), `python3.9` (Red Hat) +sap_software_download_python_package: + "{{ __sap_software_download_python_package }}" + +# The list of the OS packages that provide modules for the desired Python version. +# Required modules: wheel, urllib3, requests, beautifulsoup4, lxml +# The listed package versions must match the Python version specified by `sap_software_download_python_interpreter`. +# The default value is determined by the operating system and is set in the corresponding OS-specific variables file. Examples: +# python311-wheel, python311-urllib3, python311-requests, python311-beautifulsoup4, python311-lxml (SUSE) +# python3.9-wheel, python3.9-urllib3, python3.9-requests, python3.9-beautifulsoup4, python3.9-lxml (Red Hat) +sap_software_download_python_module_packages: + "{{ __sap_software_download_python_module_packages }}" + +# Determines whether to execute the role within a Python virtual environment. +# Using a virtual environment is strongly recommended to isolate dependencies. +# If set to `false`, the role will install Python dependencies directly into the system's Python environment. +sap_software_download_use_venv: true + +# The SAP S-User ID with download authorization for SAP software. +sap_software_download_suser_id: '' + +# The password for the SAP S-User specified in `sap_software_download_suser_id`. +sap_software_download_suser_password: '' + +# A list of SAP software file names to download. +sap_software_download_files: [] + +# The name or display ID of a transaction from the SAP Maintenance Planner. +# If provided, the role will download all files associated with this Maintenance Plan transaction. +sap_software_download_mp_transaction: '' + +# Enables searching for alternative files if the requested file is not found. +# Only applies to files specified in `sap_software_download_files`. +# If set to `false`, the role will not search for alternatives. +sap_software_download_find_alternatives: true + +# The directory where downloaded SAP software files will be stored. +sap_software_download_directory: '/software' + +# Determines whether to ignore errors when a requested file is not found. +# If set to `true`, the role will continue execution and download other files, even if some files are not found. +# If set to `false`, the role will fail if any requested file is not found. +sap_software_download_ignore_file_not_found: false + +# Determines whether to ignore errors when a specified Maintenance Plan transaction is not found. +# If set to `true` and a Maintenance Plan is not found, the role will continue execution, +# downloading any files specified in `sap_software_download_files`. +# If set to `false`, the role will fail if the specified Maintenance Plan is not found. +sap_software_download_ignore_plan_not_found: false + +# Enables validation of relationships between SAP software files. +# Only applies to files specified in `sap_software_download_files`. +# If set to `false`, no relationship validation will be performed. +# Example: Verify version of IMDB_LCAPPS against IMDB_SERVER if IMDB_SERVER was found. +sap_software_download_validate_relationships: true + +# Determines whether to ignore warnings during file relationship validation. +# If set to `true`, the role will continue execution even if there are warnings during the validation of file relationships. +# If set to `false`, the role will fail if any warnings are encountered during file relationship validation. +sap_software_download_ignore_relationship_warning: false + +# Determines whether to ignore validate credentials task. +# Disabling this check can lead to locked account, if password is incorrect. +# If set to `true`, the role will continue execution without validating S-User credentials. +# If set to `false`, the role will execute dry run to validate S-User credentials. +sap_software_download_ignore_validate_credentials: false + +# Specifies how to handle duplicate file results when using `sap_software_download_files`. +# If multiple files with the same name are found, this setting determines which one to download. +# `first`: Download the first file found. +# `last`: Download the last file found. +# sap_software_download_deduplicate: first diff --git a/roles/sap_software_download/meta/argument_spec.yml b/roles/sap_software_download/meta/argument_spec.yml new file mode 100644 index 0000000..6a64e3e --- /dev/null +++ b/roles/sap_software_download/meta/argument_spec.yml @@ -0,0 +1,158 @@ +# SPDX-License-Identifier: Apache-2.0 +--- +# Requires: ansible 2.16 +# Argument specifications in this separate file maintain backwards compatibility. +argument_specs: + + main: + short_description: Downloads SAP Software Media from SAP using an S-User ID and password. + description: + - This role downloads SAP Software Media from SAP using an S-User ID and password. + - It supports both direct file downloads and Maintenance Plan transactions. + options: + + sap_software_download_python_interpreter: + description: + - If set to `false`, the role will only execute or verify the installation or configuration steps of SAP notes. + - Default is to perform installation and configuration steps. + required: false + type: str + - The Python interpreter executable to use when creating a Python virtual environment. + - Mandatory when `sap_software_download_use_venv` is `true`. + - This is the name of the Python executable (e.g., `python3.11`, `python3.9`), which may differ from the Python package name. + - The default value is determined by the operating system and is set in the corresponding OS-specific variables file. + - Examples are `python3.11` (SUSE), `python3.9` (Red Hat) + + sap_software_download_python_package: + type: str + required: false + description: + - The name of the OS package that provides the desired Python version. + - The Python version provided by this package must match the version specified by `sap_software_download_python_interpreter`. + - The default value is determined by the operating system and is set in the corresponding OS-specific variables file. + - Examples are `python311` (SUSE), `python3.9` (Red Hat) + + sap_software_download_python_module_packages: + type: list + elements: str + required: false + description: + - The list of the OS packages that provide modules for the desired Python version. + - Required modules are wheel, urllib3, requests, beautifulsoup4, lxml + - The listed package versions must match the Python version specified by `sap_software_download_python_interpreter`. + - The default value is determined by the operating system and is set in the corresponding OS-specific variables file. Examples are + - python311-wheel, python311-urllib3, python311-requests, python311-beautifulsoup4, python311-lxml (SUSE) + - python3.9-wheel, python3.9-urllib3, python3.9-requests, python3.9-beautifulsoup4, python3.9-lxml (Red Hat) + + sap_software_download_use_venv: + type: bool + required: false + default: true + description: + - Determines whether to execute the role within a Python virtual environment. + - Using a virtual environment is strongly recommended to isolate dependencies. + - If set to `false`, the role will install Python dependencies directly into the system's Python environment. + + sap_software_download_suser_id: + type: str + required: true + description: + - The SAP S-User ID with download authorization for SAP software. + + sap_software_download_suser_password: + type: str + required: true + no_log: true + description: + - The password for the SAP S-User specified in `sap_software_download_suser_id`. + + sap_software_download_files: + type: list + elements: str + required: false + default: [] + description: + - A list of SAP software file names to download. + + sap_software_download_mp_transaction: + type: str + required: false + default: "" + description: + - The name or display ID of a transaction from the SAP Maintenance Planner. + - If provided, the role will download all files associated with this Maintenance Plan transaction. + + sap_software_download_find_alternatives: + type: bool + required: true + default: true + description: + - Enables searching for alternative files if the requested file is not found. + - Only applies to files specified in `sap_software_download_files`. + - If set to `false`, the role will not search for alternatives. + + sap_software_download_directory: + type: str + required: true + default: "/software" + description: + - The directory where downloaded SAP software files will be stored. + + sap_software_download_validate_relationships: + type: bool + required: false + default: true + description: + - Enables validation of relationships between SAP software files. + - Only applies to files specified in `sap_software_download_files`. + - If set to `false`, no relationship validation will be performed. + - Example Verify version of IMDB_LCAPPS against IMDB_SERVER if IMDB_SERVER was found. + + sap_software_download_ignore_file_not_found: + type: bool + required: false + default: false + description: + - Determines whether to ignore errors when a requested file is not found. + - If set to `true`, the role will continue execution and download other files, even if some files are not found. + - If set to `false`, the role will fail if any requested file is not found. + + sap_software_download_ignore_plan_not_found: + type: bool + required: false + default: false + description: + - Determines whether to ignore errors when a specified Maintenance Plan transaction is not found. + - If set to `true` and a Maintenance Plan is not found, the role will continue execution, + - downloading any files specified in `sap_software_download_files`. + - If set to `false`, the role will fail if the specified Maintenance Plan is not found. + + sap_software_download_ignore_relationship_warning: + type: bool + required: false + default: false + description: + - Determines whether to ignore warnings during file relationship validation. + - If set to `true`, the role will continue execution even if there are warnings during the validation of file relationships. + - If set to `false`, the role will fail if any warnings are encountered during file relationship validation. + + sap_software_download_ignore_validate_credentials: + type: bool + required: false + default: false + description: + - Determines whether to ignore warnings during file relationship validation. + - Disabling this check can lead to locked account, if password is incorrect. + - If set to `true`, the role will continue execution even if there are warnings during the validation of file relationships. + - If set to `false`, the role will fail if any warnings are encountered during file relationship validation. + + sap_software_download_deduplicate: + type: str + required: false + default: "first" + choices: ["first", "last"] + description: + - Specifies how to handle duplicate file results when using `sap_software_download_files`. + - If multiple files with the same name are found, this setting determines which one to download. + - Value `first` - Download the first file found. + - Value `last` - Download the last file found. diff --git a/roles/sap_software_download/meta/main.yml b/roles/sap_software_download/meta/main.yml new file mode 100644 index 0000000..cdd1066 --- /dev/null +++ b/roles/sap_software_download/meta/main.yml @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: Apache-2.0 +--- +galaxy_info: + namespace: community + author: SUSE, Marcel Mamula + description: Downloads SAP Software Media from SAP using an S-User ID and password, supporting both direct file downloads and Maintenance Plan transactions. + company: SUSE + license: Apache-2.0 + min_ansible_version: 2.16 + platforms: + - name: EL + versions: ["7", "8", "9"] + - name: SLES + versions: ["15", "16"] + galaxy_tags: + - sap + - download + - suse + - redhat +dependencies: [] diff --git a/roles/sap_software_download/tasks/download_files.yml b/roles/sap_software_download/tasks/download_files.yml new file mode 100644 index 0000000..177e76f --- /dev/null +++ b/roles/sap_software_download/tasks/download_files.yml @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: Download - SAP Software Files - Get files with Python venv + community.sap_launchpad.software_center_download: + suser_id: "{{ sap_software_download_suser_id }}" + suser_password: "{{ sap_software_download_suser_password }}" + search_query: "{{ item }}" + dest: "{{ sap_software_download_directory }}" + search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}" + deduplicate: "{{ sap_software_download_deduplicate | d('') }}" + # Loop condition acts as when conditional + loop: "{{ sap_software_download_files if sap_software_download_use_venv | d(true) else [] }}" + loop_control: + label: "{{ item }} : {{ __sap_software_download_files_results_venv.msg | d('') }}" + register: __sap_software_download_files_results_venv + retries: 1 + until: __sap_software_download_files_results_venv is not failed + environment: + PATH: "{{ __sap_software_download_venv.path }}/bin:{{ ansible_env.PATH }}" + PYTHONPATH: "{{ __sap_software_download_venv.path }}/lib/{{ sap_software_download_python_interpreter }}/site-packages" + VIRTUAL_ENV: "{{ __sap_software_download_venv.path }}" + vars: + ansible_python_interpreter: "{{ __sap_software_download_venv.path ~ '/bin/' ~ sap_software_download_python_interpreter }}" + ignore_errors: true # Errors are ignored and validated afterwards + + +- name: Download - SAP Software Files - Get files with Python system default + community.sap_launchpad.software_center_download: + suser_id: "{{ sap_software_download_suser_id }}" + suser_password: "{{ sap_software_download_suser_password }}" + search_query: "{{ item }}" + dest: "{{ sap_software_download_directory }}" + search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}" + deduplicate: "{{ sap_software_download_deduplicate | d('') }}" + # Loop condition acts as when conditional + loop: "{{ sap_software_download_files if not sap_software_download_use_venv | d(true) else [] }}" + loop_control: + label: "{{ item }} : {{ __sap_software_download_files_results_default.msg | d('') }}" + register: __sap_software_download_files_results_default + retries: 1 + until: __sap_software_download_files_results_default is not failed + vars: + ansible_python_interpreter: "{{ '/usr/bin/' ~ sap_software_download_python_interpreter }}" + ignore_errors: true # Errors are ignored and validated afterwards + + +- name: Download - SAP Software Files - Set fact with software_center_download output + ansible.builtin.set_fact: + __sap_software_download_files_results: "{{ __sap_software_download_files_results_venv + if sap_software_download_use_venv | d(true) else __sap_software_download_files_results_default }}" + +- name: Download - SAP Software Files - Show failed results + ansible.builtin.fail: + msg: | + Download failed for following files: {{ __failed_items | map(attribute='item') | list | join(', ') }} + Either set `sap_software_download_find_alternatives` to `true` to search for alternative files + or ignore this error with `sap_software_download_ignore_file_not_found` set to `true`. + vars: + __failed_items: "{{ __sap_software_download_files_results.results + | selectattr('failed', 'defined') | selectattr('failed', 'true') }}" + when: + - not sap_software_download_ignore_file_not_found | d(false) + - __failed_items | length > 0 diff --git a/roles/sap_software_download/tasks/download_plan.yml b/roles/sap_software_download/tasks/download_plan.yml new file mode 100644 index 0000000..b89af1f --- /dev/null +++ b/roles/sap_software_download/tasks/download_plan.yml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: Download - Maintenance Plan - Get files with Python venv + community.sap_launchpad.software_center_download: + suser_id: "{{ sap_software_download_suser_id }}" + suser_password: "{{ sap_software_download_suser_password }}" + download_link: "{{ item.DirectLink }}" + download_filename: "{{ item.Filename }}" + dest: "{{ sap_software_download_directory }}" + # Loop condition acts as when conditional + loop: "{{ __sap_software_download_mp_transaction_results.download_basket if sap_software_download_use_venv | d(true) else [] }}" + loop_control: + label: "{{ item.Filename }} : {{ __sap_software_download_files_plan_results_venv.msg | d('') }}" + register: __sap_software_download_files_plan_results_venv + retries: 1 + until: __sap_software_download_files_plan_results_venv is not failed + environment: + PATH: "{{ __sap_software_download_venv.path }}/bin:{{ ansible_env.PATH }}" + PYTHONPATH: "{{ __sap_software_download_venv.path }}/lib/{{ sap_software_download_python_interpreter }}/site-packages" + VIRTUAL_ENV: "{{ __sap_software_download_venv.path }}" + vars: + ansible_python_interpreter: "{{ __sap_software_download_venv.path ~ '/bin/' ~ sap_software_download_python_interpreter }}" + ignore_errors: true # Errors are ignored and validated afterwards + + +- name: Download - Maintenance Plan - Get files with Python system default + community.sap_launchpad.software_center_download: + suser_id: "{{ sap_software_download_suser_id }}" + suser_password: "{{ sap_software_download_suser_password }}" + download_link: "{{ item.DirectLink }}" + download_filename: "{{ item.Filename }}" + dest: "{{ sap_software_download_directory }}" + # Loop condition acts as when conditional + loop: "{{ __sap_software_download_mp_transaction_results.download_basket if not sap_software_download_use_venv | d(true) else [] }}" + loop_control: + label: "{{ item.Filename }} : {{ __sap_software_download_files_plan_results_default.msg | d('') }}" + register: __sap_software_download_files_plan_results_default + retries: 1 + until: __sap_software_download_files_plan_results_default is not failed + vars: + ansible_python_interpreter: "{{ '/usr/bin/' ~ sap_software_download_python_interpreter }}" + ignore_errors: true # Errors are ignored and validated afterwards + + +- name: Download - Maintenance Plan - Set fact with software_center_download output + ansible.builtin.set_fact: + __sap_software_download_files_plan_results: "{{ __sap_software_download_files_plan_results_venv + if sap_software_download_use_venv | d(true) else __sap_software_download_files_plan_results_default }}" + +- name: Download - Maintenance Plan - Show failed results + ansible.builtin.fail: + msg: | + Maintenance Plan file(s) not found: {{ __failed_items | map(attribute='item.Filename') | list | join(', ') }} + Verify your Maintenance Plan on SAP Launchpad before retrying. + vars: + __failed_items: "{{ __sap_software_download_files_plan_results.results + | selectattr('failed', 'defined') | selectattr('failed', 'true') }}" + when: + - not sap_software_download_ignore_file_not_found | d(false) + - __failed_items | length > 0 diff --git a/roles/sap_software_download/tasks/main.yml b/roles/sap_software_download/tasks/main.yml new file mode 100644 index 0000000..299dcf5 --- /dev/null +++ b/roles/sap_software_download/tasks/main.yml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: SAP Software Download - Pre-Steps - Include role variables + ansible.builtin.include_tasks: + file: pre_steps/01_include_variables.yml + +- name: SAP Software Download - Pre-Steps - Prepare Python environment + ansible.builtin.include_tasks: + file: pre_steps/02_prepare_python_environment.yml + +- name: SAP Software Download - Pre-Steps - Validate user credentials + ansible.builtin.include_tasks: + file: pre_steps/03_validate_credentials.yml + when: not sap_software_download_ignore_validate_credentials | d(false) + +- name: SAP Software Download - Pre-Steps - Find files for Maintenance Plan + ansible.builtin.include_tasks: + file: pre_steps/04_get_plan_files.yml + when: + - sap_software_download_mp_transaction | length > 0 + +# NOTE: We do not validate files generated by Maintenance Plan. +- name: SAP Software Download - Pre-Steps - Check related SAP Software combinations + ansible.builtin.include_tasks: + file: pre_steps/05_validate_relations.yml + when: + - sap_software_download_files | length > 0 + - sap_software_download_validate_relationships + + +- name: SAP Software Download - Download - Maintenance Plan {{ sap_software_download_mp_transaction | d('') }} + ansible.builtin.include_tasks: + file: download_plan.yml + when: + - sap_software_download_mp_transaction | length > 0 + - __sap_software_download_mp_transaction_results.download_basket is defined + and __sap_software_download_mp_transaction_results.download_basket | length > 0 + +- name: SAP Software Download - Download - Files in sap_software_download_files + ansible.builtin.include_tasks: + file: download_files.yml + + +- name: SAP Software Download - Post-Steps - Cleanup Python environment + ansible.builtin.include_tasks: + file: post_steps/01_cleanup_python_environment.yml diff --git a/roles/sap_software_download/tasks/post_steps/01_cleanup_python_environment.yml b/roles/sap_software_download/tasks/post_steps/01_cleanup_python_environment.yml new file mode 100644 index 0000000..e3d303b --- /dev/null +++ b/roles/sap_software_download/tasks/post_steps/01_cleanup_python_environment.yml @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: Post-Steps - Remove temporary Python Virtual Environment + ansible.builtin.file: + path: "{{ __sap_software_download_venv.path }}" + state: absent + when: sap_software_download_use_venv | d(true) diff --git a/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml b/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml new file mode 100644 index 0000000..edfec13 --- /dev/null +++ b/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml @@ -0,0 +1,123 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# Example of files loading order: +# 1. Suse.yml / RedHat.yml - Specific to OS family. +# 2. SLES_15.yml / RedHat_9.yml - Specific to distribution (SLES, SLES_SAP or RedHat) and major release. +# 3. SLES_15.6.yml / RedHat_9.2 - Specific to distribution (SLES, SLES_SAP or RedHat) and minor release. +# 4. SLES_SAP_15.yml - Specific to distribution SLES_SAP and major release. +# 5. SLES_SAP_15.6.yml - Specific to distribution SLES_SAP and minor release. +- name: Pre-Steps - Include OS specific variables + ansible.builtin.include_vars: "{{ __vars_file }}" + loop: "{{ __var_files }}" + vars: + __vars_file: "{{ role_path }}/vars/{{ item }}" + __distribution_major: "{{ ansible_distribution ~ '_' ~ ansible_distribution_major_version }}" + __distribution_minor: "{{ ansible_distribution ~ '_' ~ ansible_distribution_version }}" + # Enables loading of shared vars between SLES and SLES_SAP + __distribution_major_split: "{{ ansible_distribution.split('_')[0] ~ '_' ~ ansible_distribution_major_version }}" + __distribution_minor_split: "{{ ansible_distribution.split('_')[0] ~ '_' ~ ansible_distribution_version }}" + __var_files: >- + {{ + [ + ansible_os_family ~ '.yml', + (ansible_distribution ~ '.yml') if ansible_distribution != ansible_os_family else None, + (__distribution_major_split ~ '.yml') if __distribution_major_split != __distribution_major else None, + (__distribution_minor_split ~ '.yml') if __distribution_minor_split != __distribution_minor else None, + __distribution_major ~ '.yml', + __distribution_minor ~ '.yml' + ] | select('defined') | select('string') | list + }} + when: __vars_file is file + + +- name: Pre-Steps - Assert that SAP Software files were specified + ansible.builtin.assert: + that: + - (sap_software_download_files is defined and sap_software_download_files | type_debug == 'list' and sap_software_download_files | length > 0) + or (sap_software_download_mp_transaction is defined and sap_software_download_mp_transaction | length > 0) + fail_msg: | + Neither `sap_software_download_files` or `sap_software_download_mp_transaction` are valid. + Ensure that it at least one of them is valid. + +- name: "Pre-Steps - Assert that download directory was provided" + ansible.builtin.assert: + that: + - sap_software_download_directory is defined + - sap_software_download_directory | length > 0 + fail_msg: | + Empty variable `sap_software_download_directory`. + + +- name: "Pre-Steps - Verify variable: sap_software_download_use_venv" + ansible.builtin.assert: + that: + - sap_software_download_use_venv is boolean + fail_msg: | + Variable `sap_software_download_use_venv` is not boolean. + when: sap_software_download_use_venv is defined + +- name: "Pre-Steps - Verify variable: sap_software_download_python_interpreter" + ansible.builtin.assert: + that: + - sap_software_download_python_interpreter is defined + - sap_software_download_python_interpreter | length > 0 + fail_msg: | + Empty variable `sap_software_download_python_interpreter`. + Ensure that it contains correct Python interpreter or revert back to defaults. + when: sap_software_download_use_venv + +- name: "Pre-Steps - Verify variable: sap_software_download_python_package" + ansible.builtin.assert: + that: + - sap_software_download_python_package is defined + - sap_software_download_python_package | length > 0 + fail_msg: | + Empty variable `sap_software_download_python_package`. + Ensure that it contains correct Python package name or revert back to defaults. + +- name: "Pre-Steps - Verify variable: sap_software_download_python_module_packages" + ansible.builtin.assert: + that: + - sap_software_download_python_module_packages is defined + - sap_software_download_python_module_packages | type_debug == 'list' + - sap_software_download_python_module_packages | length > 0 + fail_msg: | + Empty variable `sap_software_download_python_module_packages`. + Ensure that it contains correct list of Python module package names or revert back to defaults. + +- name: "Pre-Steps - Verify variable: sap_software_download_suser_id" + ansible.builtin.assert: + that: + - sap_software_download_suser_id is defined + - sap_software_download_suser_id | length > 0 + fail_msg: | + Empty variable `sap_software_download_suser_id`. + Enter valid S-User ID with download authorizations. + +- name: "Pre-Steps - Verify variable: sap_software_download_suser_password" + ansible.builtin.assert: + that: + - sap_software_download_suser_password is defined + - sap_software_download_suser_password | length > 0 + fail_msg: | + Empty variable `sap_software_download_suser_password`. + Enter valid S-User password. + no_log: true + +- name: "Pre-Steps - Verify variable: sap_software_download_find_alternatives" + ansible.builtin.assert: + that: + - sap_software_download_find_alternatives is boolean + fail_msg: | + Variable `sap_software_download_find_alternatives` is not boolean. + when: sap_software_download_find_alternatives is defined + +- name: "Pre-Steps - Verify variable: sap_software_download_deduplicate" + ansible.builtin.assert: + that: + - sap_software_download_deduplicate in ['first', 'last'] + fail_msg: | + Enter valid option for `sap_software_download_deduplicate` variable. + Options: first, last + when: sap_software_download_deduplicate is defined diff --git a/roles/sap_software_download/tasks/pre_steps/02_prepare_python_environment.yml b/roles/sap_software_download/tasks/pre_steps/02_prepare_python_environment.yml new file mode 100644 index 0000000..2be5480 --- /dev/null +++ b/roles/sap_software_download/tasks/pre_steps/02_prepare_python_environment.yml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: Pre-Steps - Install Python and Python package manager pip + ansible.builtin.package: + name: + - "{{ sap_software_download_python_package }}" + - "{{ sap_software_download_python_package }}-pip" + state: present + + +- name: Pre-Steps - Create download directory {{ sap_software_download_directory }} + ansible.builtin.file: + path: "{{ sap_software_download_directory }}" + state: directory + mode: '0755' + + +- name: Pre-Steps - Block for Python venv preparation + when: sap_software_download_use_venv | d(true) + block: + - name: Pre-Steps - Create temporary directory for venv + ansible.builtin.tempfile: + state: directory + suffix: __sap_software_download_venv + register: __sap_software_download_venv + + - name: Pre-Steps - Install Python modules to Python venv + ansible.builtin.pip: + name: "{{ __sap_software_download_python_modules }}" + virtualenv: "{{ __sap_software_download_venv.path }}" + virtualenv_command: "{{ sap_software_download_python_interpreter }} -m venv" + + +- name: Pre-Steps - Block for default Python preparation + when: not sap_software_download_use_venv | d(true) + block: + # Packages with python modules are installed instead of modules to avoid error: + # `externally-managed-environment` which requires `--break-system-packages` + - name: Pre-Steps - Install Python module packages + ansible.builtin.package: + name: "{{ __sap_software_download_python_module_packages }}" + state: present diff --git a/roles/sap_software_download/tasks/pre_steps/03_validate_credentials.yml b/roles/sap_software_download/tasks/pre_steps/03_validate_credentials.yml new file mode 100644 index 0000000..8154b72 --- /dev/null +++ b/roles/sap_software_download/tasks/pre_steps/03_validate_credentials.yml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: Apache-2.0 +--- +# This task attempts dry run to check SAPCAR file in order to validate provided credentials. + +- name: Validate Credentials - Dry run check user credentials and download privilege with Python venv + when: sap_software_download_use_venv | d(true) + community.sap_launchpad.software_center_download: + suser_id: "{{ sap_software_download_suser_id }}" + suser_password: "{{ sap_software_download_suser_password }}" + search_query: "SAPCAR" + dest: "{{ sap_software_download_directory }}" + search_alternatives: true + deduplicate: "last" + dry_run: true + register: __sap_software_download_validate_credentials_venv + retries: 1 + delay: 5 + environment: + PATH: "{{ __sap_software_download_venv.path }}/bin:{{ ansible_env.PATH }}" + PYTHONPATH: "{{ __sap_software_download_venv.path }}/lib/{{ sap_software_download_python_interpreter }}/site-packages" + VIRTUAL_ENV: "{{ __sap_software_download_venv.path }}" + vars: + ansible_python_interpreter: "{{ __sap_software_download_venv.path ~ '/bin/' ~ sap_software_download_python_interpreter }}" + ignore_errors: true # Errors are ignored and validated afterwards + +- name: Validate Credentials - Dry run check user credentials and download privilege with Python system default + when: not sap_software_download_use_venv | d(true) + community.sap_launchpad.software_center_download: + suser_id: "{{ sap_software_download_suser_id }}" + suser_password: "{{ sap_software_download_suser_password }}" + search_query: "SAPCAR" + dest: "{{ sap_software_download_directory }}" + search_alternatives: true + deduplicate: "last" + dry_run: true + register: __sap_software_download_validate_credentials_default + retries: 1 + delay: 5 + vars: + ansible_python_interpreter: "{{ '/usr/bin/' ~ sap_software_download_python_interpreter }}" + ignore_errors: true # Errors are ignored and validated afterwards + +- name: Validate Credentials - Show failed results + ansible.builtin.fail: + msg: | + Validation of provided S-User credentials failed. + Ensure correct S-User credentials are provided in: + `sap_software_download_suser_id` and `sap_software_download_suser_password` + when: + - (sap_software_download_use_venv | d(true) + and __sap_software_download_validate_credentials_venv.failed is defined and __sap_software_download_validate_credentials_venv.failed) + or (not sap_software_download_use_venv | d(true) + and __sap_software_download_validate_credentials_default is defined and __sap_software_download_validate_credentials_default.failed) diff --git a/roles/sap_software_download/tasks/pre_steps/04_get_plan_files.yml b/roles/sap_software_download/tasks/pre_steps/04_get_plan_files.yml new file mode 100644 index 0000000..a4baef1 --- /dev/null +++ b/roles/sap_software_download/tasks/pre_steps/04_get_plan_files.yml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: Maintenance Plan - Get list of files with Python venv + when: sap_software_download_use_venv | d(true) + community.sap_launchpad.maintenance_planner_files: + suser_id: "{{ sap_software_download_suser_id }}" + suser_password: "{{ sap_software_download_suser_password }}" + transaction_name: "{{ sap_software_download_mp_transaction }}" + register: __sap_software_download_mp_transaction_results_venv + retries: 1 + environment: + PATH: "{{ __sap_software_download_venv.path }}/bin:{{ ansible_env.PATH }}" + PYTHONPATH: "{{ __sap_software_download_venv.path }}/lib/{{ sap_software_download_python_interpreter }}/site-packages" + VIRTUAL_ENV: "{{ __sap_software_download_venv.path }}" + vars: + ansible_python_interpreter: "{{ __sap_software_download_venv.path ~ '/bin/' ~ sap_software_download_python_interpreter }}" + changed_when: false # Getting list of files does not change anything + ignore_errors: true # Errors are ignored and validated afterwards + +- name: Maintenance Plan - Get list of files with default Python + when: not sap_software_download_use_venv | d(true) + community.sap_launchpad.maintenance_planner_files: + suser_id: "{{ sap_software_download_suser_id }}" + suser_password: "{{ sap_software_download_suser_password }}" + transaction_name: "{{ sap_software_download_mp_transaction }}" + register: __sap_software_download_mp_transaction_results_default + retries: 1 + vars: + ansible_python_interpreter: "{{ '/usr/bin/' ~ sap_software_download_python_interpreter }}" + changed_when: false # Getting list of files does not change anything + ignore_errors: true # Errors are ignored and validated afterwards + +- name: Maintenance Plan - Set fact with maintenance_planner_files output + ansible.builtin.set_fact: + __sap_software_download_mp_transaction_results: "{{ __sap_software_download_mp_transaction_results_venv + if sap_software_download_use_venv | d(true) else __sap_software_download_mp_transaction_results_default }}" + + +- name: Maintenance Plan - Show failed results + ansible.builtin.fail: + msg: | + Maintenance Plan was not found. + Either ensure correct value in `sap_software_download_mp_transaction` + or ignore this error with `sap_software_download_ignore_plan_not_found` set to `true`. + when: + - not sap_software_download_ignore_plan_not_found | d(false) + - __sap_software_download_mp_transaction_results.failed + +- name: Maintenance Plan - Show ignored failed results + ansible.builtin.debug: + msg: | + Maintenance Plan was not found. + Error was ignored with `sap_software_download_ignore_plan_not_found` set to `true`. + when: + - sap_software_download_ignore_plan_not_found | d(false) + - __sap_software_download_mp_transaction_results.failed diff --git a/roles/sap_software_download/tasks/pre_steps/05_validate_relations.yml b/roles/sap_software_download/tasks/pre_steps/05_validate_relations.yml new file mode 100644 index 0000000..39c9687 --- /dev/null +++ b/roles/sap_software_download/tasks/pre_steps/05_validate_relations.yml @@ -0,0 +1,98 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: Block - Relationship Validation - Check availability of files (with alternatives) + when: sap_software_download_find_alternatives + block: + + - name: Relationship Validation - Dry run to check availability of files with Python venv + community.sap_launchpad.software_center_download: + suser_id: "{{ sap_software_download_suser_id }}" + suser_password: "{{ sap_software_download_suser_password }}" + search_query: "{{ item }}" + dest: "{{ sap_software_download_directory }}" + search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}" + deduplicate: "{{ sap_software_download_deduplicate | d('') }}" + dry_run: true + # Loop condition acts as when conditional + loop: "{{ sap_software_download_files if sap_software_download_use_venv | d(true) else [] }}" + loop_control: + label: "{{ item }} : {{ __sap_software_download_files_results_dryrun_venv.msg | d('') }}" + register: __sap_software_download_files_results_dryrun_venv + retries: 1 + until: __sap_software_download_files_results_dryrun_venv is not failed + environment: + PATH: "{{ __sap_software_download_venv.path }}/bin:{{ ansible_env.PATH }}" + PYTHONPATH: "{{ __sap_software_download_venv.path }}/lib/{{ sap_software_download_python_interpreter }}/site-packages" + VIRTUAL_ENV: "{{ __sap_software_download_venv.path }}" + vars: + ansible_python_interpreter: "{{ __sap_software_download_venv.path ~ '/bin/' ~ sap_software_download_python_interpreter }}" + ignore_errors: true # Errors are ignored and validated afterwards + + + - name: Relationship Validation - Dry run to check availability of files with Python system default + community.sap_launchpad.software_center_download: + suser_id: "{{ sap_software_download_suser_id }}" + suser_password: "{{ sap_software_download_suser_password }}" + search_query: "{{ item }}" + dest: "{{ sap_software_download_directory }}" + search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}" + deduplicate: "{{ sap_software_download_deduplicate | d('') }}" + dry_run: true + # Loop condition acts as when conditional + loop: "{{ sap_software_download_files if not sap_software_download_use_venv | d(true) else [] }}" + loop_control: + label: "{{ item }} : {{ __sap_software_download_files_results_dryrun_default.msg | d('') }}" + register: __sap_software_download_files_results_dryrun_default + retries: 1 + until: __sap_software_download_files_results_dryrun_default is not failed + vars: + ansible_python_interpreter: "{{ '/usr/bin/' ~ sap_software_download_python_interpreter }}" + ignore_errors: true # Errors are ignored and validated afterwards + + + - name: Relationship Validation - Set fact with software_center_download output + ansible.builtin.set_fact: + __sap_software_download_files_results_dryrun: "{{ __sap_software_download_files_results_dryrun_venv + if sap_software_download_use_venv | d(true) else __sap_software_download_files_results_dryrun_default }}" + + - name: Relationship Validation - Show failed results + ansible.builtin.fail: + msg: | + Relationship validation failed because following files were not found: {{ __failed_items | map(attribute='item') | list | join(', ') }} + Either ensure correct list of files in `sap_software_download_files` + or ignore this error with `sap_software_download_ignore_file_not_found` set to `true`. + vars: + __failed_items: "{{ __sap_software_download_files_results_dryrun.results | selectattr('failed', 'defined') | selectattr('failed', 'true') }}" + when: + - not sap_software_download_ignore_file_not_found | d(false) + - __failed_items | length > 0 + + +- name: Relationship Validation - Define list of files + ansible.builtin.set_fact: + __sap_software_download_files: "{{ sap_software_download_files if not sap_software_download_find_alternatives + else __sap_software_download_files_results_dryrun.results | selectattr('failed', 'false')| map(attribute='filename') | list | unique | d([])}}" + + +- name: Relationship Validation - SAP HANA - Multiple IMDB_SERVER files found + ansible.builtin.debug: + msg: Warning - Multiple SAP HANA Database (IMDB_SERVER) found, which can result in inaccurate relationship validation! + when: __sap_software_download_files | select('match', '^IMDB_SERVER.*') | list | length > 1 + + +- name: Relationship Validation - Include tasks for SAP HANA 1.0 relationship validation + when: __sap_software_download_files | select('match', '^IMDB_SERVER1.*') | list | length > 0 + ansible.builtin.include_tasks: + file: pre_steps/06_validate_sap_hana_1.yml + loop: "{{ __sap_software_download_files | select('match', '^IMDB_SERVER1.*') | list }}" + loop_control: + loop_var: __sap_software_download_sap_hana + +- name: Relationship Validation - Include tasks for SAP HANA 2.0 relationship validation + when: __sap_software_download_files | select('match', '^IMDB_SERVER2.*') | list | length > 0 + ansible.builtin.include_tasks: + file: pre_steps/07_validate_sap_hana_2.yml + loop: "{{ __sap_software_download_files | select('match', '^IMDB_SERVER2.*') | list }}" + loop_control: + loop_var: __sap_software_download_sap_hana diff --git a/roles/sap_software_download/tasks/pre_steps/06_validate_sap_hana_1.yml b/roles/sap_software_download/tasks/pre_steps/06_validate_sap_hana_1.yml new file mode 100644 index 0000000..93ac892 --- /dev/null +++ b/roles/sap_software_download/tasks/pre_steps/06_validate_sap_hana_1.yml @@ -0,0 +1,89 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: Relationship Validation - SAP HANA 1.00 - Set HANA variables + ansible.builtin.set_fact: + # 122 for IMDB_SERVER100_122_35-10009569.SAR + __sap_software_download_sap_hana_1_version: + "{{ __sap_software_download_sap_hana.split('_')[2] | regex_replace('[^0-9]', '') }}" + + # 35 for IMDB_SERVER100_122_35-10009569.SAR + __sap_software_download_sap_hana_1_revision: + "{{ __sap_software_download_sap_hana.split('_')[3].split('-')[0] | regex_replace('[^0-9]', '') }}" + + +# Warning conditions: +# - At least one IMDB_LCAPPS_1 was found +# - No IMDB_LCAPPS__ was found +# Examples: +# - IMDB_SERVER100_122_35-10009569.SAR - Maintenance Revision 122.35 (SPS12) for HANA DB 1.00 +# - IMDB_LCAPPS_122P_3500-20010426.SAR - LCAPPS for HANA 1.00.122.35 Build 100.47 PL 017 +- name: Relationship Validation - SAP HANA 1.00 - IMDB_SERVER and IMDB_LCAPPS + ansible.builtin.fail: + msg: | + Warning: Incompatible SAP HANA component LCAPPS files were found for detected SAP HANA DATABASE 1.0 SPS {{ + __sap_software_download_sap_hana_1_version[:2] }} Revision {{ __sap_software_download_sap_hana_1_version + }}.{{ __sap_software_download_sap_hana_1_revision }}. + + Expected file pattern: IMDB_LCAPPS_{{ + __sap_software_download_sap_hana_1_version }}*_{{__sap_software_download_sap_hana_1_revision }}* + Actual files detected: {{ __sap_software_download_sap_hana_1_lcapps_list | unique | join(', ') }} + vars: + __sap_software_download_sap_hana_1_lcapps_list: + "{{ __sap_software_download_files | select('match', '^IMDB_LCAPPS_1.*') | list }}" + __sap_software_download_sap_hana_1_lcapps_list_filtered: + "{{ sap_software_download_files | select('match', '^IMDB_LCAPPS_.*' + ~ __sap_software_download_sap_hana_1_version ~ '.*_' ~ __sap_software_download_sap_hana_1_revision) | list }}" + ignore_errors: "{{ sap_software_download_ignore_relationship_warning | d(false) }}" + when: + - __sap_software_download_sap_hana_1_lcapps_list | length > 0 + - __sap_software_download_sap_hana_1_lcapps_list_filtered | length == 0 + + +# Warning conditions: +# - At least one IMDB_AFL100 was found +# - No IMDB_AFL100__ was found +# Examples: +# - IMDB_SERVER100_122_35-10009569.SAR - Maintenance Revision 122.35 (SPS12) for HANA DB 1.00 +# - IMDB_AFL100_122P_3500-10012328.SAR - SAP HANA AFL 1.0 Revision 122.3500 only for HANA DB 122.35 +- name: Relationship Validation - SAP HANA 1.00 - IMDB_SERVER and IMDB_AFL + ansible.builtin.fail: + msg: | + Warning: Incompatible SAP HANA component AFL files were found for detected SAP HANA DATABASE 1.0 SPS {{ + __sap_software_download_sap_hana_1_version[:2] }} Revision {{ __sap_software_download_sap_hana_1_version + }}.{{ __sap_software_download_sap_hana_1_revision }}. + + Expected file pattern: IMDB_AFL100_{{ __sap_software_download_sap_hana_1_version }}*_{{ __sap_software_download_sap_hana_1_revision }}* + Actual files detected: {{ __sap_software_download_sap_hana_1_afl_list | unique | join(', ') }} + vars: + __sap_software_download_sap_hana_1_afl_list: + "{{ __sap_software_download_files | select('match', '^IMDB_AFL100.*') | list }}" + __sap_software_download_sap_hana_1_afl_list_filtered: + "{{ sap_software_download_files | select('match', '^IMDB_AFL100_.*' + ~ __sap_software_download_sap_hana_1_version ~ '.*_' ~ __sap_software_download_sap_hana_1_revision) | list }}" + ignore_errors: "{{ sap_software_download_ignore_relationship_warning | d(false) }}" + when: + - __sap_software_download_sap_hana_1_afl_list | length > 0 + - __sap_software_download_sap_hana_1_afl_list_filtered | length == 0 + + +# Warning conditions: +# - At least one IMDB_CLIENT was found +# - No IMDB_CLIENT1* was found +# Examples: + # - IMDB_SERVER100_122_35-10009569.SAR - Maintenance Revision 122.35 (SPS12) for HANA DB 1.00 + # - IMDB_CLIENT100_120_140-10009663.SAR - Revision 120 for SAP HANA CLIENT 1.00 +- name: Relationship Validation - SAP HANA 1.00 - IMDB_SERVER and IMDB_CLIENT + ansible.builtin.fail: + msg: | + Warning: Incompatible SAP HANA client files were found for detected SAP HANA DATABASE 1.0. + + Expected file pattern: IMDB_CLIENT100_* + Actual files detected: {{ __sap_software_download_sap_hana_client_list | unique | join(', ') }} + vars: + __sap_software_download_sap_hana_client_list: + "{{ __sap_software_download_files | select('match', '^IMDB_CLIENT.*') | list }}" + ignore_errors: "{{ sap_software_download_ignore_relationship_warning | d(false) }}" + when: + - __sap_software_download_sap_hana_client_list | length > 0 + - __sap_software_download_sap_hana_client_list | select('match', '^IMDB_CLIENT1.*') | length == 0 diff --git a/roles/sap_software_download/tasks/pre_steps/07_validate_sap_hana_2.yml b/roles/sap_software_download/tasks/pre_steps/07_validate_sap_hana_2.yml new file mode 100644 index 0000000..094fca7 --- /dev/null +++ b/roles/sap_software_download/tasks/pre_steps/07_validate_sap_hana_2.yml @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: Relationship Validation - SAP HANA 2.00 - Set HANA variables + ansible.builtin.set_fact: + # 084 for IMDB_SERVER20_084_0-80002031.SAR + __sap_software_download_sap_hana_2_version: + "{{ __sap_software_download_sap_hana.split('_')[2] }}" + + +# Warning conditions: +# - At least one IMDB_LCAPPS_2 was found +# - No IMDB_LCAPPS_2 was found +# Examples: + # - IMDB_SERVER20_084_0-80002031.SAR - Revision 2.00.084.0 (SPS08) for HANA DB 2.0 + # - IMDB_LCAPPS_2084_0-20010426.SAR - LCAPPS for HANA 2.0 Rev 84 Build 101.19 PL 007 +- name: Relationship Validation - SAP HANA 2.00 - IMDB_SERVER and IMDB_LCAPPS + ansible.builtin.fail: + msg: | + Warning: Incompatible SAP HANA component LCAPPS files were found for detected SAP HANA DATABASE 2.0 SPS {{ + __sap_software_download_sap_hana_2_version[:2] }} Revision {{ __sap_software_download_sap_hana_2_version }}. + + Expected file pattern: IMDB_LCAPPS_2{{ __sap_software_download_sap_hana_2_version }}* + Actual files detected: {{ __sap_software_download_sap_hana_2_lcapps_list | unique | join(', ') }} + vars: + __sap_software_download_sap_hana_2_lcapps_list: + "{{ __sap_software_download_files | select('match', '^IMDB_LCAPPS_2.*') | list }}" + __sap_software_download_sap_hana_2_lcapps_list_filtered: + "{{ sap_software_download_files | select('match', '^IMDB_LCAPPS_2' ~ __sap_software_download_sap_hana_2_version) | list }}" + ignore_errors: "{{ sap_software_download_ignore_relationship_warning | d(false) }}" + when: + - __sap_software_download_sap_hana_2_lcapps_list | length > 0 + - __sap_software_download_sap_hana_2_lcapps_list_filtered | length == 0 + + +# Warning conditions: +# - At least one IMDB_AFL20 was found +# - No IMDB_AFL20_ was found +# Examples: + # - IMDB_SERVER20_084_0-80002031.SAR - Revision 2.00.084.0 (SPS08) for HANA DB 2.0 + # - IMDB_AFL20_084_1-80001894.SAR - SAP HANA AFL Rev 84.1 only for HANA 2.0 Rev 84 +- name: Relationship Validation - SAP HANA 2.00 - IMDB_SERVER and IMDB_AFL + ansible.builtin.fail: + msg: | + Warning: Incompatible SAP HANA component AFL files were found for detected SAP HANA DATABASE 2.0 SPS {{ + __sap_software_download_sap_hana_2_version[:2] }} Revision {{ __sap_software_download_sap_hana_2_version }}. + + Expected file pattern: IMDB_AFL20_{{ __sap_software_download_sap_hana_2_version }}* + Actual files detected: {{ __sap_software_download_sap_hana_2_afl_list | unique | join(', ') }} + vars: + __sap_software_download_sap_hana_2_afl_list: + "{{ __sap_software_download_files | select('match', '^IMDB_AFL20.*') | list }}" + __sap_software_download_sap_hana_2_afl_list_filtered: + "{{ sap_software_download_files | select('match', '^IMDB_AFL20_.*' ~ __sap_software_download_sap_hana_2_version) | list }}" + ignore_errors: "{{ sap_software_download_ignore_relationship_warning | d(false) }}" + when: + - __sap_software_download_sap_hana_2_afl_list | length > 0 + - __sap_software_download_sap_hana_2_afl_list_filtered | length == 0 + + +# Warning conditions: +# - At least one IMDB_CLIENT was found +# - No IMDB_CLIENT2* was found +# Examples: + # - IMDB_SERVER20_084_0-80002031.SAR - Revision 2.00.084.0 (SPS08) for HANA DB 2.0 + # - IMDB_CLIENT20_024_21-80002082.SAR - SAP HANA CLIENT Version 2.24 +- name: Relationship Validation - SAP HANA 2.00 - IMDB_SERVER and IMDB_CLIENT + ansible.builtin.fail: + msg: | + Warning: Incompatible SAP HANA client files were found for detected SAP HANA DATABASE 2.0. + + Expected file pattern: IMDB_CLIENT20_* + Actual files detected: {{ __sap_software_download_sap_hana_client_list | unique | join(', ') }} + vars: + __sap_software_download_sap_hana_client_list: + "{{ __sap_software_download_files | select('match', '^IMDB_CLIENT.*') | list }}" + ignore_errors: "{{ sap_software_download_ignore_relationship_warning | d(false) }}" + when: + - __sap_software_download_sap_hana_client_list | length > 0 + - __sap_software_download_sap_hana_client_list | select('match', '^IMDB_CLIENT2.*') | length == 0 diff --git a/roles/sap_software_download/vars/RedHat_10.yml b/roles/sap_software_download/vars/RedHat_10.yml new file mode 100644 index 0000000..13cb27b --- /dev/null +++ b/roles/sap_software_download/vars/RedHat_10.yml @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# Variables specific to following versions: +# - Red Hat Linux Enterprise Server 10 + +# Set which Python version will be used on destination node. +# This is python executable name, which can differ from python package name. +__sap_software_download_python_interpreter: 'python3.12' + +# Set which Python package will be installed on destination node. +__sap_software_download_python_package: 'python3.12' + +# The list of required Python Modules in packages +# This is required in order to avoid externally-managed-environment error. +__sap_software_download_python_module_packages: + - python3.12-wheel + - python3.12-urllib3 + - python3.12-requests + - python3.12-beautifulsoup4 + - python3.12-lxml diff --git a/roles/sap_software_download/vars/RedHat_8.yml b/roles/sap_software_download/vars/RedHat_8.yml new file mode 100644 index 0000000..453b5ce --- /dev/null +++ b/roles/sap_software_download/vars/RedHat_8.yml @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# Variables specific to following versions: +# - Red Hat Linux Enterprise Server 8 + +# Set which Python version will be used on destination node. +# This is python executable name, which can differ from python package name. +__sap_software_download_python_interpreter: 'python3.9' + +# Set which Python package will be installed on destination node. +__sap_software_download_python_package: 'python39' + +# The list of required Python Modules in packages +# This is required in order to avoid externally-managed-environment error. +__sap_software_download_python_module_packages: + - python39-wheel + - python39-urllib3 + - python39-requests + - python39-beautifulsoup4 + - python39-lxml diff --git a/roles/sap_software_download/vars/RedHat_9.yml b/roles/sap_software_download/vars/RedHat_9.yml new file mode 100644 index 0000000..f472adf --- /dev/null +++ b/roles/sap_software_download/vars/RedHat_9.yml @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# Variables specific to following versions: +# - Red Hat Linux Enterprise Server 9 + +# Set which Python version will be used on destination node. +# This is python executable name, which can differ from python package name. +__sap_software_download_python_interpreter: 'python3.9' + +# Set which Python package will be installed on destination node. +__sap_software_download_python_package: 'python3.9' + +# The list of required Python Modules in packages +# This is required in order to avoid externally-managed-environment error. +__sap_software_download_python_module_packages: + - python3.9-wheel + - python3.9-urllib3 + - python3.9-requests + - python3.9-beautifulsoup4 + - python3.9-lxml diff --git a/roles/sap_software_download/vars/Suse.yml b/roles/sap_software_download/vars/Suse.yml new file mode 100644 index 0000000..f540820 --- /dev/null +++ b/roles/sap_software_download/vars/Suse.yml @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# Variables specific to following versions: +# - SUSE Linux Enterprise Server 15 +# - SUSE Linux Enterprise Server 16 + +# NOTE: SLES 15 SP5 introduced Python 3.11. + +# Set which Python version will be used on destination node. +# This is python executable name, which can differ from python package name. +__sap_software_download_python_interpreter: >- + {%- if ansible_distribution_major_version == '15' and ansible_distribution_version.split('.')[1] | int < 5 -%} + python3 + {%- else -%} + python3.11 + {%- endif -%} + +# Set which Python package will be installed on destination node. +__sap_software_download_python_package: >- + {%- if ansible_distribution_major_version == '15' and ansible_distribution_version.split('.')[1] | int < 5 -%} + python3 + {%- else -%} + python311 + {%- endif -%} + +# The list of required Python Modules in packages +# This is required in order to avoid externally-managed-environment error. +__sap_software_download_python_module_packages: >- + {%- if ansible_distribution_major_version == '15' and ansible_distribution_version.split('.')[1] | int < 5 -%} + [ + "python3-wheel", + "python3-urllib3", + "python3-requests", + "python3-beautifulsoup4", + "python3-lxml" + ] + {%- else -%} + [ + "python311-wheel", + "python311-urllib3", + "python311-requests", + "python311-beautifulsoup4", + "python311-lxml" + ] + {%- endif -%} diff --git a/roles/sap_software_download/vars/main.yml b/roles/sap_software_download/vars/main.yml new file mode 100644 index 0000000..e40f28e --- /dev/null +++ b/roles/sap_software_download/vars/main.yml @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# The list of required Python Modules for download module +__sap_software_download_python_modules: + - wheel + - urllib3 + - requests + - beautifulsoup4 + - lxml + +# The list of required Python Modules in packages +# This is required in order to avoid externally-managed-environment error. +# Specific packages are available in OS specific var files +__sap_software_download_python_module_packages: + - python3-wheel + - python3-urllib3 + - python3-requests + - python3-beautifulsoup4 + - python3-lxml