From 8572ecd82246277bd5ca6895de3510c05dcb3b50 Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Thu, 27 Mar 2025 17:23:05 +0100 Subject: [PATCH 1/8] feat: new role sap_software_download --- .ansible-lint | 24 ++++ roles/sap_software_download/defaults/main.yml | 58 +++++++++ .../tasks/download_files.yml | 62 ++++++++++ .../tasks/download_plan.yml | 61 ++++++++++ roles/sap_software_download/tasks/main.yml | 42 +++++++ .../01_cleanup_python_environment.yml | 8 ++ .../tasks/pre_steps/01_include_variables.yml | 112 ++++++++++++++++++ .../02_prepare_python_environment.yml | 40 +++++++ .../tasks/pre_steps/03_get_plan_files.yml | 57 +++++++++ .../tasks/pre_steps/04_validate_relations.yml | 88 ++++++++++++++ .../tasks/pre_steps/05_validate_sap_hana.yml | 71 +++++++++++ roles/sap_software_download/vars/RedHat.yml | 13 ++ .../sap_software_download/vars/RedHat_10.yml | 12 ++ roles/sap_software_download/vars/Suse.yml | 25 ++++ roles/sap_software_download/vars/main.yml | 10 ++ 15 files changed, 683 insertions(+) create mode 100644 .ansible-lint create mode 100644 roles/sap_software_download/defaults/main.yml create mode 100644 roles/sap_software_download/tasks/download_files.yml create mode 100644 roles/sap_software_download/tasks/download_plan.yml create mode 100644 roles/sap_software_download/tasks/main.yml create mode 100644 roles/sap_software_download/tasks/post_steps/01_cleanup_python_environment.yml create mode 100644 roles/sap_software_download/tasks/pre_steps/01_include_variables.yml create mode 100644 roles/sap_software_download/tasks/pre_steps/02_prepare_python_environment.yml create mode 100644 roles/sap_software_download/tasks/pre_steps/03_get_plan_files.yml create mode 100644 roles/sap_software_download/tasks/pre_steps/04_validate_relations.yml create mode 100644 roles/sap_software_download/tasks/pre_steps/05_validate_sap_hana.yml create mode 100644 roles/sap_software_download/vars/RedHat.yml create mode 100644 roles/sap_software_download/vars/RedHat_10.yml create mode 100644 roles/sap_software_download/vars/Suse.yml create mode 100644 roles/sap_software_download/vars/main.yml diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 0000000..829e107 --- /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/roles/sap_software_download/defaults/main.yml b/roles/sap_software_download/defaults/main.yml new file mode 100644 index 0000000..efa3501 --- /dev/null +++ b/roles/sap_software_download/defaults/main.yml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# Set which Python version will be used on managed node. +# This is python executable name, which can differ from python package name. +# The default value is set in var file corresponding with OS version. +# Example: python3.11 (Suse), python3.9 (RedHat) +sap_software_download_python_interpreter: + "{{ __sap_software_download_python_interpreter }}" + +# Set which Python package will be installed on managed node. +# The default value is set in var file corresponding with OS version. +# Example: python311 (Suse), python3.9 (RedHat) +sap_software_download_python_package: + "{{ __sap_software_download_python_package }}" + +# Execute role in Python Virtual Environment (recommended). +# If set to `false`, the role will install Python pip modules directly without. +sap_software_download_use_venv: true + +# Set S-User ID with appropriate authorizations for SAP Software download. +sap_software_download_suser_id: '' + +# Set S-User password for user defined in `sap_software_download_suser_id`. +sap_software_download_suser_password: '' + +# Enter list of SAP Software files to download. +sap_software_download_files: [] + +# Enter Transaction Name or Transaction Display ID from SAP Maintenance planner. +sap_software_download_plan: '' + +# Set to `false` to disable searching for alternatives for unavailable files. +sap_software_download_find_alternatives: true + +# Enable handling of duplicate file results. +# Available values: first , last +# sap_software_download_deduplicate: first + +# Set directory where SAP Software will be downloaded. +sap_software_download_directory: '/software' + +# Set to `false` to disable check for known combinations of related files. +# This functionality is not used with `sap_software_download_plan` +# Example: Verify version of IMDB_LCAPPS against IMDB_SERVER if available. +sap_software_download_validate_relations: true + +# Set to `true` to ignore errors during validation of file relations. +# Applicable to `sap_software_download_validate_relations: true` +sap_software_download_ignore_relation_warning: false + +# Set to `true` to ignore role errors when file is not found. +# Download of files will proceed only for files that were found. +sap_software_download_ignore_file_not_found: false + +# Set to `true` to ignore role errors when Maintenance Plan is not found. +# Role will continue with rest of files if `sap_software_download_files` is defined. +sap_software_download_ignore_plan_not_found: false 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..7d6f936 --- /dev/null +++ b/roles/sap_software_download/tasks/download_files.yml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: Download - SAP Software Files - Get files 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: "{{ item }}" + download_path: "{{ sap_software_download_directory }}" + search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}" + loop: "{{ sap_software_download_files }}" + 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 default Python + 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: "{{ item }}" + download_path: "{{ sap_software_download_directory }}" + search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}" + loop: "{{ sap_software_download_files }}" + 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: Relation Validation - Show failed results in dry run + 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 + - __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..3752694 --- /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 + 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 }}" + download_link: "{{ item.DirectLink }}" + download_filename: "{{ item.Filename }}" + download_path: "{{ sap_software_download_directory }}" + loop: "{{ __sap_software_download_plan_results.download_basket }}" + 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 default Python + 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 }}" + download_link: "{{ item.DirectLink }}" + download_filename: "{{ item.Filename }}" + download_path: "{{ sap_software_download_directory }}" + loop: "{{ __sap_software_download_plan_results.download_basket }}" + 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') | 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 + - __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..586ffca --- /dev/null +++ b/roles/sap_software_download/tasks/main.yml @@ -0,0 +1,42 @@ +# 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 - Find files for Maintenance Plan + ansible.builtin.include_tasks: + file: pre_steps/03_get_plan_files.yml + when: + - sap_software_download_plan | 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/04_validate_relations.yml + when: + - sap_software_download_files | length > 0 + - sap_software_download_validate_relations + + +- name: SAP Software Download - Download - Maintenance Plan {{ sap_software_download_plan | d('') }} + ansible.builtin.include_tasks: + file: download_plan.yml + when: + - sap_software_download_plan | length > 0 + - __sap_software_download_plan_results.download_basket is defined + and __sap_software_download_plan_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..2be6a76 --- /dev/null +++ b/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml @@ -0,0 +1,112 @@ +# 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 | length > 0) + or (sap_software_download_plan is defined and sap_software_download_plan | length > 0) + fail_msg: | + Neither `sap_software_download_files` or `sap_software_download_plan` 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_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. + +- 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_use_venv" + ansible.builtin.assert: + that: + - sap_software_download_use_venv is defined + - sap_software_download_use_venv is boolean + fail_msg: | + Variable `sap_software_download_use_venv` is not boolean. + +- 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 defined + - sap_software_download_find_alternatives is boolean + fail_msg: | + Variable `sap_software_download_find_alternatives` is not boolean. + +- 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..bc06da5 --- /dev/null +++ b/roles/sap_software_download/tasks/pre_steps/02_prepare_python_environment.yml @@ -0,0 +1,40 @@ +# 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: + - name: Pre-Steps - Install Python modules in default Python + ansible.builtin.pip: + name: "{{ __sap_software_download_python_modules }}" diff --git a/roles/sap_software_download/tasks/pre_steps/03_get_plan_files.yml b/roles/sap_software_download/tasks/pre_steps/03_get_plan_files.yml new file mode 100644 index 0000000..46707f4 --- /dev/null +++ b/roles/sap_software_download/tasks/pre_steps/03_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_plan }}" + register: __sap_software_download_plan_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_plan }}" + register: __sap_software_download_plan_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_plan_results: "{{ __sap_software_download_plan_results_venv + if sap_software_download_use_venv | d(true) else __sap_software_download_plan_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_plan` + or ignore this error with `sap_software_download_ignore_plan_not_found` set to `true`. + when: + - not sap_software_download_ignore_plan_not_found + - __sap_software_download_plan_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 + - __sap_software_download_plan_results.failed diff --git a/roles/sap_software_download/tasks/pre_steps/04_validate_relations.yml b/roles/sap_software_download/tasks/pre_steps/04_validate_relations.yml new file mode 100644 index 0000000..75cc482 --- /dev/null +++ b/roles/sap_software_download/tasks/pre_steps/04_validate_relations.yml @@ -0,0 +1,88 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: Block - Relation Validation - Check availability of files (with alternatives) + when: sap_software_download_find_alternatives + block: + + - name: Relation Validation - Check availability of files 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: "{{ item }}" + dest: "{{ sap_software_download_directory }}" + search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}" + dry_run: true + loop: "{{ sap_software_download_files }}" + 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: Relation Validation - Check availability of files with default Python + 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: "{{ item }}" + dest: "{{ sap_software_download_directory }}" + search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}" + dry_run: true + loop: "{{ sap_software_download_files }}" + 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: Relation 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: Relation Validation - Show failed results + ansible.builtin.fail: + msg: | + Relation 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 + - __failed_items | length > 0 + + +- name: Relation 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: Relation 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 relation validation! + when: __sap_software_download_files | select('match', '^IMDB_SERVER.*') | list | length > 1 + + +- name: Relation Validation - Include tasks for SAP HANA relation validation + when: __sap_software_download_files | select('match', '^IMDB_SERVER.*') | list | length > 0 + ansible.builtin.include_tasks: + file: pre_steps/05_validate_sap_hana.yml + loop: "{{ __sap_software_download_files | select('match', '^IMDB_SERVER.*') | list }}" + loop_control: + loop_var: __sap_software_download_sap_hana diff --git a/roles/sap_software_download/tasks/pre_steps/05_validate_sap_hana.yml b/roles/sap_software_download/tasks/pre_steps/05_validate_sap_hana.yml new file mode 100644 index 0000000..689c6d2 --- /dev/null +++ b/roles/sap_software_download/tasks/pre_steps/05_validate_sap_hana.yml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: Apache-2.0 +--- +# Logic behind relation validation: +# - Known variations for files are validated in dedicated tasks +# - Each SAP HANA version have different handling due to different versioning +# - SAP HANA SPS is used to search for + +- name: Relation Validation - SAP HANA - Set HANA variables + ansible.builtin.set_fact: + # "{{ '1' if __sap_software_download_sap_hana | regex_search('^IMDB_SERVER1') else '2' }}" + __sap_software_download_sap_hana_1_sps: + "{{ __sap_software_download_sap_hana.split('_')[2] | regex_replace('[^0-9]', '') }}" # 122 for IMDB_SERVER100_122_35-10009569.SAR + __sap_software_download_sap_hana_1_sps_rev: + "{{ __sap_software_download_sap_hana.split('_')[3].split('-')[0] | regex_replace('[^0-9]', '') }}" # 35 for IMDB_SERVER100_122_35-10009569.SAR + + __sap_software_download_sap_hana_2_version: + "{{ __sap_software_download_sap_hana.split('_')[2] }}" # 084 for IMDB_SERVER20_084_0-80002031.SAR + + +# Warning is triggered only when following conditions are fulfilled +# - 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: Relation Check - SAP HANA 1.00 - IMDB_SERVER and IMDB_LCAPPS + ansible.builtin.fail: + msg: | + Warning: Incompatible SAP HANA 1.0 LCAPPS files were found. + Ensure that correct version is selected: SPS {{ __sap_software_download_sap_hana_1_sps + }} and Revision {{ __sap_software_download_sap_hana_1_sps_rev }} + + Expected file pattern: IMDB_LCAPPS_{{ __sap_software_download_sap_hana_1_sps }}*_{{ __sap_software_download_sap_hana_1_sps_rev }}* + Actual files detected: {{ __sap_software_download_sap_hana_1_lcapps_list | 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_sps ~ '.*_' ~ __sap_software_download_sap_hana_1_sps_rev) | list }}" + ignore_errors: "{{ sap_software_download_ignore_relation_warning | d(false) }}" + when: + - __sap_software_download_sap_hana | regex_search('^IMDB_SERVER1') + - __sap_software_download_sap_hana_1_lcapps_list | length > 0 + - __sap_software_download_sap_hana_1_lcapps_list_filtered | length == 0 + + +# Warning is triggered only when following conditions are fulfilled +# - At least one IMDB_LCAPPS_1 was found +# - No IMDB_LCAPPS__ 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: Relation Check - SAP HANA 2.00 - IMDB_SERVER and IMDB_LCAPPS + ansible.builtin.fail: + msg: | + Warning: Incompatible SAP HANA 2.0 LCAPPS files were found. + Ensure that correct version is selected: {{ __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 | 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_relation_warning | d(false) }}" + when: + - __sap_software_download_sap_hana | regex_search('^IMDB_SERVER2') + - __sap_software_download_sap_hana_2_lcapps_list | length > 0 + - __sap_software_download_sap_hana_2_lcapps_list_filtered | length == 0 diff --git a/roles/sap_software_download/vars/RedHat.yml b/roles/sap_software_download/vars/RedHat.yml new file mode 100644 index 0000000..610fea6 --- /dev/null +++ b/roles/sap_software_download/vars/RedHat.yml @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# Variables specific to following versions: +# - Red Hat Linux Enterprise Server 8 +# - 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' 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..122cc07 --- /dev/null +++ b/roles/sap_software_download/vars/RedHat_10.yml @@ -0,0 +1,12 @@ +# 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' diff --git a/roles/sap_software_download/vars/Suse.yml b/roles/sap_software_download/vars/Suse.yml new file mode 100644 index 0000000..2cd68f3 --- /dev/null +++ b/roles/sap_software_download/vars/Suse.yml @@ -0,0 +1,25 @@ +# 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 -%} diff --git a/roles/sap_software_download/vars/main.yml b/roles/sap_software_download/vars/main.yml new file mode 100644 index 0000000..2897c1d --- /dev/null +++ b/roles/sap_software_download/vars/main.yml @@ -0,0 +1,10 @@ +# 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 From fb109c59c484f2153fd99eb3221d8dc82dca7fb1 Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Fri, 28 Mar 2025 16:19:03 +0100 Subject: [PATCH 2/8] feat: hana validation readme, defaults update --- roles/sap_software_download/.yamllint.yml | 27 +++ roles/sap_software_download/README.md | 225 ++++++++++++++++++ roles/sap_software_download/defaults/main.yml | 73 +++--- .../meta/argument_spec.yml | 136 +++++++++++ .../tasks/download_files.yml | 10 +- .../tasks/download_plan.yml | 8 +- .../tasks/pre_steps/01_include_variables.yml | 19 +- .../tasks/pre_steps/04_validate_relations.yml | 14 +- .../tasks/pre_steps/05_validate_sap_hana.yml | 127 ++++++++-- 9 files changed, 572 insertions(+), 67 deletions(-) create mode 100644 roles/sap_software_download/.yamllint.yml create mode 100644 roles/sap_software_download/README.md create mode 100644 roles/sap_software_download/meta/argument_spec.yml 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..9b95326 --- /dev/null +++ b/roles/sap_software_download/README.md @@ -0,0 +1,225 @@ + +# sap_software_download Ansible Role + + +## Description + +The Ansible Role `sap_software_download` is used to download SAP Software Media from SAP. + + + + + + +## 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. **Maintenance Plan File List:** If the `sap_software_download_plan` variable is provided, the role retrieves the list of files associated with the specified Maintenance Plan transaction. +4. **File Relationship Validation:** If `sap_software_download_validate_relations` 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) +5. **Maintenance Plan File Download:** If `sap_software_download_plan` is provided, the role downloads the files associated with the Maintenance Plan. +6. **Direct File Download:** If `sap_software_download_files` is provided, the role downloads the specified files. +7. **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_plan: 'Transaction Name or Display ID from Maintenance Planner' +``` + + + + + + +## 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`, `Revision 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 prevented by setting `sap_software_download_ignore_relation_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 prevented by setting `sap_software_download_ignore_relation_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`
+ +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`
+ +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_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_plan +- _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_relations +- _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_relation_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_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 index efa3501..d844f9b 100644 --- a/roles/sap_software_download/defaults/main.yml +++ b/roles/sap_software_download/defaults/main.yml @@ -1,58 +1,71 @@ # SPDX-License-Identifier: Apache-2.0 --- -# Set which Python version will be used on managed node. -# This is python executable name, which can differ from python package name. -# The default value is set in var file corresponding with OS version. -# Example: python3.11 (Suse), python3.9 (RedHat) +# 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 }}" -# Set which Python package will be installed on managed node. -# The default value is set in var file corresponding with OS version. -# Example: python311 (Suse), python3.9 (RedHat) +# 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 }}" -# Execute role in Python Virtual Environment (recommended). -# If set to `false`, the role will install Python pip modules directly without. +# 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 -# Set S-User ID with appropriate authorizations for SAP Software download. +# The SAP S-User ID with download authorization for SAP software. sap_software_download_suser_id: '' -# Set S-User password for user defined in `sap_software_download_suser_id`. +# The password for the SAP S-User specified in `sap_software_download_suser_id`. sap_software_download_suser_password: '' -# Enter list of SAP Software files to download. +# A list of SAP software file names to download. sap_software_download_files: [] -# Enter Transaction Name or Transaction Display ID from SAP Maintenance planner. +# 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_plan: '' -# Set to `false` to disable searching for alternatives for unavailable files. +# 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 -# Enable handling of duplicate file results. -# Available values: first , last -# sap_software_download_deduplicate: first - -# Set directory where SAP Software will be downloaded. +# The directory where downloaded SAP software files will be stored. sap_software_download_directory: '/software' -# Set to `false` to disable check for known combinations of related files. -# This functionality is not used with `sap_software_download_plan` -# Example: Verify version of IMDB_LCAPPS against IMDB_SERVER if available. +# 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_relations: true -# Set to `true` to ignore errors during validation of file relations. -# Applicable to `sap_software_download_validate_relations: true` -sap_software_download_ignore_relation_warning: false - -# Set to `true` to ignore role errors when file is not found. -# Download of files will proceed only for files that were found. +# 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 -# Set to `true` to ignore role errors when Maintenance Plan is not found. -# Role will continue with rest of files if `sap_software_download_files` is defined. +# 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 + +# 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_relation_warning: 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..19016b9 --- /dev/null +++ b/roles/sap_software_download/meta/argument_spec.yml @@ -0,0 +1,136 @@ +# 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: true + 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_use_venv: + type: bool + required: true + 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_plan: + 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_relations: + type: bool + required: true + 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: true + 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: true + 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_relation_warning: + type: bool + required: true + 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_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/tasks/download_files.yml b/roles/sap_software_download/tasks/download_files.yml index 7d6f936..0e7ba73 100644 --- a/roles/sap_software_download/tasks/download_files.yml +++ b/roles/sap_software_download/tasks/download_files.yml @@ -2,14 +2,15 @@ --- - name: Download - SAP Software Files - Get files 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: "{{ item }}" download_path: "{{ sap_software_download_directory }}" search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}" - loop: "{{ sap_software_download_files }}" + 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 @@ -25,14 +26,15 @@ - name: Download - SAP Software Files - Get files with default Python - 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: "{{ item }}" download_path: "{{ sap_software_download_directory }}" search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}" - loop: "{{ sap_software_download_files }}" + 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 diff --git a/roles/sap_software_download/tasks/download_plan.yml b/roles/sap_software_download/tasks/download_plan.yml index 3752694..0a33c5b 100644 --- a/roles/sap_software_download/tasks/download_plan.yml +++ b/roles/sap_software_download/tasks/download_plan.yml @@ -2,14 +2,14 @@ --- - name: Download - Maintenance Plan - Get files 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 }}" download_link: "{{ item.DirectLink }}" download_filename: "{{ item.Filename }}" download_path: "{{ sap_software_download_directory }}" - loop: "{{ __sap_software_download_plan_results.download_basket }}" + # Loop condition acts as when conditional + loop: "{{ __sap_software_download_plan_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 @@ -25,14 +25,14 @@ - name: Download - Maintenance Plan - Get files with default Python - 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 }}" download_link: "{{ item.DirectLink }}" download_filename: "{{ item.Filename }}" download_path: "{{ sap_software_download_directory }}" - loop: "{{ __sap_software_download_plan_results.download_basket }}" + # Loop condition acts as when conditional + loop: "{{ __sap_software_download_plan_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 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 index 2be6a76..35c90a7 100644 --- a/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml +++ b/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml @@ -49,6 +49,14 @@ 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 defined + - sap_software_download_use_venv is boolean + fail_msg: | + Variable `sap_software_download_use_venv` is not boolean. + - name: "Pre-Steps - Verify variable: sap_software_download_python_interpreter" ansible.builtin.assert: that: @@ -56,7 +64,8 @@ - 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. + 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: @@ -67,14 +76,6 @@ 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_use_venv" - ansible.builtin.assert: - that: - - sap_software_download_use_venv is defined - - sap_software_download_use_venv is boolean - fail_msg: | - Variable `sap_software_download_use_venv` is not boolean. - - name: "Pre-Steps - Verify variable: sap_software_download_suser_id" ansible.builtin.assert: that: diff --git a/roles/sap_software_download/tasks/pre_steps/04_validate_relations.yml b/roles/sap_software_download/tasks/pre_steps/04_validate_relations.yml index 75cc482..f18d87d 100644 --- a/roles/sap_software_download/tasks/pre_steps/04_validate_relations.yml +++ b/roles/sap_software_download/tasks/pre_steps/04_validate_relations.yml @@ -6,15 +6,16 @@ block: - name: Relation Validation - Check availability of files 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: "{{ item }}" - dest: "{{ sap_software_download_directory }}" + download_path: "{{ sap_software_download_directory }}" search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}" + deduplicate: "{{ sap_software_download_deduplicate | d('') }}" dry_run: true - loop: "{{ sap_software_download_files }}" + # 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 @@ -30,15 +31,16 @@ - name: Relation Validation - Check availability of files with default Python - 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: "{{ item }}" - dest: "{{ sap_software_download_directory }}" + download_path: "{{ sap_software_download_directory }}" search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}" + deduplicate: "{{ sap_software_download_deduplicate | d('') }}" dry_run: true - loop: "{{ sap_software_download_files }}" + # 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 diff --git a/roles/sap_software_download/tasks/pre_steps/05_validate_sap_hana.yml b/roles/sap_software_download/tasks/pre_steps/05_validate_sap_hana.yml index 689c6d2..7500805 100644 --- a/roles/sap_software_download/tasks/pre_steps/05_validate_sap_hana.yml +++ b/roles/sap_software_download/tasks/pre_steps/05_validate_sap_hana.yml @@ -3,23 +3,22 @@ # Logic behind relation validation: # - Known variations for files are validated in dedicated tasks # - Each SAP HANA version have different handling due to different versioning -# - SAP HANA SPS is used to search for - name: Relation Validation - SAP HANA - Set HANA variables ansible.builtin.set_fact: # "{{ '1' if __sap_software_download_sap_hana | regex_search('^IMDB_SERVER1') else '2' }}" - __sap_software_download_sap_hana_1_sps: + __sap_software_download_sap_hana_1_version: "{{ __sap_software_download_sap_hana.split('_')[2] | regex_replace('[^0-9]', '') }}" # 122 for IMDB_SERVER100_122_35-10009569.SAR - __sap_software_download_sap_hana_1_sps_rev: + __sap_software_download_sap_hana_1_revision: "{{ __sap_software_download_sap_hana.split('_')[3].split('-')[0] | regex_replace('[^0-9]', '') }}" # 35 for IMDB_SERVER100_122_35-10009569.SAR __sap_software_download_sap_hana_2_version: "{{ __sap_software_download_sap_hana.split('_')[2] }}" # 084 for IMDB_SERVER20_084_0-80002031.SAR -# Warning is triggered only when following conditions are fulfilled +# Warning conditions: # - At least one IMDB_LCAPPS_1 was found -# - No IMDB_LCAPPS__ 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 @@ -27,17 +26,17 @@ ansible.builtin.fail: msg: | Warning: Incompatible SAP HANA 1.0 LCAPPS files were found. - Ensure that correct version is selected: SPS {{ __sap_software_download_sap_hana_1_sps - }} and Revision {{ __sap_software_download_sap_hana_1_sps_rev }} + Ensure that correct version is selected: {{ __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_sps }}*_{{ __sap_software_download_sap_hana_1_sps_rev }}* - Actual files detected: {{ __sap_software_download_sap_hana_1_lcapps_list | join(', ') }} + 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_sps ~ '.*_' ~ __sap_software_download_sap_hana_1_sps_rev) | list }}" + ~ __sap_software_download_sap_hana_1_version ~ '.*_' ~ __sap_software_download_sap_hana_1_revision) | list }}" ignore_errors: "{{ sap_software_download_ignore_relation_warning | d(false) }}" when: - __sap_software_download_sap_hana | regex_search('^IMDB_SERVER1') @@ -45,9 +44,9 @@ - __sap_software_download_sap_hana_1_lcapps_list_filtered | length == 0 -# Warning is triggered only when following conditions are fulfilled -# - At least one IMDB_LCAPPS_1 was found -# - No IMDB_LCAPPS__ was found +# 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 @@ -58,7 +57,7 @@ Ensure that correct version is selected: {{ __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 | join(', ') }} + 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 }}" @@ -69,3 +68,103 @@ - __sap_software_download_sap_hana | regex_search('^IMDB_SERVER2') - __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_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: Relation Check - SAP HANA 1.00 - IMDB_SERVER and IMDB_AFL + ansible.builtin.fail: + msg: | + Warning: Incompatible SAP HANA AFL 1.0 files were found. + Ensure that correct version is selected: {{ __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_relation_warning | d(false) }}" + when: + - __sap_software_download_sap_hana | regex_search('^IMDB_SERVER1') + - __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_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: Relation Check - SAP HANA 2.00 - IMDB_SERVER and IMDB_AFL + ansible.builtin.fail: + msg: | + Warning: Incompatible SAP HANA AFL 2.0 files were found. + Ensure that correct version is selected: {{ __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_relation_warning | d(false) }}" + when: + - __sap_software_download_sap_hana | regex_search('^IMDB_SERVER2') + - __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_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: Relation Check - SAP HANA 1.00 - IMDB_SERVER and IMDB_CLIENT + ansible.builtin.fail: + msg: | + Warning: SAP HANA CLIENT 1.00 was not found. + + 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_relation_warning | d(false) }}" + when: + - __sap_software_download_sap_hana | regex_search('^IMDB_SERVER1') + and __sap_software_download_sap_hana_client_list | length > 0 + and __sap_software_download_sap_hana_client_list | select('match', '^IMDB_CLIENT1.*') | 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: Relation Check - SAP HANA 2.00 - IMDB_SERVER and IMDB_CLIENT + ansible.builtin.fail: + msg: | + Warning: SAP HANA CLIENT 2.00 was not found. + + 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_relation_warning | d(false) }}" + when: + - __sap_software_download_sap_hana | regex_search('^IMDB_SERVER2') + and __sap_software_download_sap_hana_client_list | length > 0 + and __sap_software_download_sap_hana_client_list | select('match', '^IMDB_CLIENT2.*') | length == 0 From 62907170e3fb34a1419aa78f3219e0a4739ff3e4 Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Mon, 31 Mar 2025 12:45:20 +0200 Subject: [PATCH 3/8] feat: add dry run connection check, improve verbosity --- roles/sap_software_download/README.md | 27 ++- roles/sap_software_download/defaults/main.yml | 12 +- .../meta/argument_spec.yml | 26 ++- .../tasks/download_files.yml | 6 +- .../tasks/download_plan.yml | 10 +- roles/sap_software_download/tasks/main.yml | 21 ++- .../tasks/pre_steps/01_include_variables.yml | 12 +- .../pre_steps/03_validate_credentials.yml | 49 +++++ ...t_plan_files.yml => 04_get_plan_files.yml} | 22 +-- ...elations.yml => 05_validate_relations.yml} | 36 ++-- .../tasks/pre_steps/05_validate_sap_hana.yml | 170 ------------------ .../pre_steps/06_validate_sap_hana_1.yml | 87 +++++++++ .../pre_steps/07_validate_sap_hana_2.yml | 80 +++++++++ 13 files changed, 321 insertions(+), 237 deletions(-) create mode 100644 roles/sap_software_download/tasks/pre_steps/03_validate_credentials.yml rename roles/sap_software_download/tasks/pre_steps/{03_get_plan_files.yml => 04_get_plan_files.yml} (73%) rename roles/sap_software_download/tasks/pre_steps/{04_validate_relations.yml => 05_validate_relations.yml} (73%) delete mode 100644 roles/sap_software_download/tasks/pre_steps/05_validate_sap_hana.yml create mode 100644 roles/sap_software_download/tasks/pre_steps/06_validate_sap_hana_1.yml create mode 100644 roles/sap_software_download/tasks/pre_steps/07_validate_sap_hana_2.yml diff --git a/roles/sap_software_download/README.md b/roles/sap_software_download/README.md index 9b95326..a85a387 100644 --- a/roles/sap_software_download/README.md +++ b/roles/sap_software_download/README.md @@ -34,11 +34,11 @@ The target node must meet the following requirements: 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. **Maintenance Plan File List:** If the `sap_software_download_plan` variable is provided, the role retrieves the list of files associated with the specified Maintenance Plan transaction. -4. **File Relationship Validation:** If `sap_software_download_validate_relations` is `true`, the role performs validation checks on the relationships between the files to be downloaded. +3. **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. +4. **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) -5. **Maintenance Plan File Download:** If `sap_software_download_plan` is provided, the role downloads the files associated with the Maintenance Plan. +5. **Maintenance Plan File Download:** If `sap_software_download_mp_transaction` is provided, the role downloads the files associated with the Maintenance Plan. 6. **Direct File Download:** If `sap_software_download_files` is provided, the role downloads the specified files. 7. **Virtual Environment Cleanup:** If a temporary Python virtual environment was used, it is removed. @@ -79,7 +79,7 @@ Download of SAP Software files using Maintenance Plan 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_plan: 'Transaction Name or Display ID from Maintenance Planner' + sap_software_download_mp_transaction: 'Transaction Name or Display ID from Maintenance Planner' ``` @@ -100,13 +100,13 @@ Example for SAP HANA Database Server 2.0 with LCAPPS and AFL.
- 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 prevented by setting `sap_software_download_ignore_relation_warning` to `true`. + In this case, validation will fail. This can be prevented 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 prevented by setting `sap_software_download_ignore_relation_warning` to `true`. + In this case, validation will fail. This can be prevented 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. @@ -163,7 +163,7 @@ The password for the SAP S-User specified in `sap_software_download_suser_id`. -### sap_software_download_plan +### sap_software_download_mp_transaction - _Type:_ `string`
The name or display ID of a transaction from the SAP Maintenance Planner.
@@ -182,7 +182,7 @@ If set to `false`, the role will not search for alternatives.
The directory where downloaded SAP software files will be stored.
-### sap_software_download_validate_relations +### sap_software_download_validate_relationships - _Type:_ `bool`
- _Default:_ `true`
@@ -207,7 +207,7 @@ Determines whether to ignore errors when a specified Maintenance Plan transactio 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_relation_warning +### sap_software_download_ignore_relationship_warning - _Type:_ `bool`
- _Default:_ `false`
@@ -215,6 +215,15 @@ 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`
diff --git a/roles/sap_software_download/defaults/main.yml b/roles/sap_software_download/defaults/main.yml index d844f9b..13787f9 100644 --- a/roles/sap_software_download/defaults/main.yml +++ b/roles/sap_software_download/defaults/main.yml @@ -32,7 +32,7 @@ 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_plan: '' +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`. @@ -46,7 +46,7 @@ sap_software_download_directory: '/software' # 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_relations: true +sap_software_download_validate_relationships: true # 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. @@ -62,7 +62,13 @@ sap_software_download_ignore_plan_not_found: 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_relation_warning: false +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. diff --git a/roles/sap_software_download/meta/argument_spec.yml b/roles/sap_software_download/meta/argument_spec.yml index 19016b9..dec55ce 100644 --- a/roles/sap_software_download/meta/argument_spec.yml +++ b/roles/sap_software_download/meta/argument_spec.yml @@ -34,7 +34,7 @@ argument_specs: sap_software_download_use_venv: type: bool - required: true + required: false default: true description: - Determines whether to execute the role within a Python virtual environment. @@ -62,7 +62,7 @@ argument_specs: description: - A list of SAP software file names to download. - sap_software_download_plan: + sap_software_download_mp_transaction: type: str required: false default: "" @@ -86,9 +86,9 @@ argument_specs: description: - The directory where downloaded SAP software files will be stored. - sap_software_download_validate_relations: + sap_software_download_validate_relationships: type: bool - required: true + required: false default: true description: - Enables validation of relationships between SAP software files. @@ -98,7 +98,7 @@ argument_specs: sap_software_download_ignore_file_not_found: type: bool - required: true + required: false default: false description: - Determines whether to ignore errors when a requested file is not found. @@ -107,7 +107,7 @@ argument_specs: sap_software_download_ignore_plan_not_found: type: bool - required: true + required: false default: false description: - Determines whether to ignore errors when a specified Maintenance Plan transaction is not found. @@ -115,12 +115,22 @@ argument_specs: - 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_relation_warning: + sap_software_download_ignore_relationship_warning: type: bool - required: true + 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. diff --git a/roles/sap_software_download/tasks/download_files.yml b/roles/sap_software_download/tasks/download_files.yml index 0e7ba73..6afcc76 100644 --- a/roles/sap_software_download/tasks/download_files.yml +++ b/roles/sap_software_download/tasks/download_files.yml @@ -25,7 +25,7 @@ ignore_errors: true # Errors are ignored and validated afterwards -- name: Download - SAP Software Files - Get files with default Python +- 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 }}" @@ -50,7 +50,7 @@ __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: Relation Validation - Show failed results in dry run +- name: Download - SAP Software Files - Show failed results ansible.builtin.fail: msg: | Download failed for following files: {{ __failed_items | map(attribute='item') | list | join(', ') }} @@ -60,5 +60,5 @@ __failed_items: "{{ __sap_software_download_files_results.results | selectattr('failed', 'defined') | selectattr('failed', 'true') }}" when: - - not sap_software_download_ignore_file_not_found + - 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 index 0a33c5b..34b4d31 100644 --- a/roles/sap_software_download/tasks/download_plan.yml +++ b/roles/sap_software_download/tasks/download_plan.yml @@ -9,7 +9,7 @@ download_filename: "{{ item.Filename }}" download_path: "{{ sap_software_download_directory }}" # Loop condition acts as when conditional - loop: "{{ __sap_software_download_plan_results.download_basket if sap_software_download_use_venv | d(true) else [] }}" + 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 @@ -24,7 +24,7 @@ ignore_errors: true # Errors are ignored and validated afterwards -- name: Download - Maintenance Plan - Get files with default Python +- 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 }}" @@ -32,7 +32,7 @@ download_filename: "{{ item.Filename }}" download_path: "{{ sap_software_download_directory }}" # Loop condition acts as when conditional - loop: "{{ __sap_software_download_plan_results.download_basket if not sap_software_download_use_venv | d(true) else [] }}" + 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 @@ -51,11 +51,11 @@ - name: Download - Maintenance Plan - Show failed results ansible.builtin.fail: msg: | - Maintenance Plan file(s) not found: {{ __failed_items | map(attribute='item') | list | join(', ') }} + Maintenance Plan file(s) not found: {{ __failed_items | map(attribute='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 + - 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 index 586ffca..299dcf5 100644 --- a/roles/sap_software_download/tasks/main.yml +++ b/roles/sap_software_download/tasks/main.yml @@ -9,28 +9,33 @@ 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/03_get_plan_files.yml + file: pre_steps/04_get_plan_files.yml when: - - sap_software_download_plan | length > 0 + - 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/04_validate_relations.yml + file: pre_steps/05_validate_relations.yml when: - sap_software_download_files | length > 0 - - sap_software_download_validate_relations + - sap_software_download_validate_relationships -- name: SAP Software Download - Download - Maintenance Plan {{ sap_software_download_plan | d('') }} +- 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_plan | length > 0 - - __sap_software_download_plan_results.download_basket is defined - and __sap_software_download_plan_results.download_basket | length > 0 + - 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: 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 index 35c90a7..f8611db 100644 --- a/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml +++ b/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml @@ -35,9 +35,9 @@ ansible.builtin.assert: that: - (sap_software_download_files is defined and sap_software_download_files | length > 0) - or (sap_software_download_plan is defined and sap_software_download_plan | 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_plan` are valid. + 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" @@ -52,10 +52,10 @@ - name: "Pre-Steps - Verify variable: sap_software_download_use_venv" ansible.builtin.assert: that: - - sap_software_download_use_venv is defined - sap_software_download_use_venv is boolean fail_msg: | - Variable `sap_software_download_use_venv` is not boolean. + 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: @@ -98,10 +98,10 @@ - name: "Pre-Steps - Verify variable: sap_software_download_find_alternatives" ansible.builtin.assert: that: - - sap_software_download_find_alternatives is defined - sap_software_download_find_alternatives is boolean fail_msg: | - Variable `sap_software_download_find_alternatives` is not boolean. + 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: 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..ef63819 --- /dev/null +++ b/roles/sap_software_download/tasks/pre_steps/03_validate_credentials.yml @@ -0,0 +1,49 @@ +# 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 to download test file 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" + download_path: "{{ sap_software_download_directory }}" + search_alternatives: true + deduplicate: "last" + dry_run: true + register: __sap_software_download_validate_credentials_venv + 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 to download test file 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" + download_path: "{{ sap_software_download_directory }}" + search_alternatives: true + deduplicate: "last" + dry_run: true + register: __sap_software_download_validate_credentials_default + 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/03_get_plan_files.yml b/roles/sap_software_download/tasks/pre_steps/04_get_plan_files.yml similarity index 73% rename from roles/sap_software_download/tasks/pre_steps/03_get_plan_files.yml rename to roles/sap_software_download/tasks/pre_steps/04_get_plan_files.yml index 46707f4..11e8c4c 100644 --- a/roles/sap_software_download/tasks/pre_steps/03_get_plan_files.yml +++ b/roles/sap_software_download/tasks/pre_steps/04_get_plan_files.yml @@ -6,8 +6,8 @@ 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_plan }}" - register: __sap_software_download_plan_results_venv + 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 }}" @@ -23,8 +23,8 @@ 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_plan }}" - register: __sap_software_download_plan_results_default + 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 }}" @@ -33,19 +33,19 @@ - name: Maintenance Plan - Set fact with maintenance_planner_files output ansible.builtin.set_fact: - __sap_software_download_plan_results: "{{ __sap_software_download_plan_results_venv - if sap_software_download_use_venv | d(true) else __sap_software_download_plan_results_default }}" + __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_plan` + 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 - - __sap_software_download_plan_results.failed + - 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: @@ -53,5 +53,5 @@ 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 - - __sap_software_download_plan_results.failed + - 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/04_validate_relations.yml b/roles/sap_software_download/tasks/pre_steps/05_validate_relations.yml similarity index 73% rename from roles/sap_software_download/tasks/pre_steps/04_validate_relations.yml rename to roles/sap_software_download/tasks/pre_steps/05_validate_relations.yml index f18d87d..b0b0915 100644 --- a/roles/sap_software_download/tasks/pre_steps/04_validate_relations.yml +++ b/roles/sap_software_download/tasks/pre_steps/05_validate_relations.yml @@ -1,11 +1,11 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: Block - Relation Validation - Check availability of files (with alternatives) +- name: Block - Relationship Validation - Check availability of files (with alternatives) when: sap_software_download_find_alternatives block: - - name: Relation Validation - Check availability of files with Python venv + - 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 }}" @@ -30,7 +30,7 @@ ignore_errors: true # Errors are ignored and validated afterwards - - name: Relation Validation - Check availability of files with default Python + - 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 }}" @@ -51,40 +51,48 @@ ignore_errors: true # Errors are ignored and validated afterwards - - name: Relation Validation - Set fact with software_center_download output + - 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: Relation Validation - Show failed results + - name: Relationship Validation - Show failed results ansible.builtin.fail: msg: | - Relation validation failed because following files were not found: {{ __failed_items | map(attribute='item') | list | join(', ') }} + 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 + - not sap_software_download_ignore_file_not_found | d(false) - __failed_items | length > 0 -- name: Relation Validation - Define list of files +- 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: Relation Validation - SAP HANA - Multiple IMDB_SERVER files found +- 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 relation validation! + 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: Relation Validation - Include tasks for SAP HANA relation validation - when: __sap_software_download_files | select('match', '^IMDB_SERVER.*') | list | length > 0 +- 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/05_validate_sap_hana.yml - loop: "{{ __sap_software_download_files | select('match', '^IMDB_SERVER.*') | list }}" + 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/05_validate_sap_hana.yml b/roles/sap_software_download/tasks/pre_steps/05_validate_sap_hana.yml deleted file mode 100644 index 7500805..0000000 --- a/roles/sap_software_download/tasks/pre_steps/05_validate_sap_hana.yml +++ /dev/null @@ -1,170 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 ---- -# Logic behind relation validation: -# - Known variations for files are validated in dedicated tasks -# - Each SAP HANA version have different handling due to different versioning - -- name: Relation Validation - SAP HANA - Set HANA variables - ansible.builtin.set_fact: - # "{{ '1' if __sap_software_download_sap_hana | regex_search('^IMDB_SERVER1') else '2' }}" - __sap_software_download_sap_hana_1_version: - "{{ __sap_software_download_sap_hana.split('_')[2] | regex_replace('[^0-9]', '') }}" # 122 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]', '') }}" # 35 for IMDB_SERVER100_122_35-10009569.SAR - - __sap_software_download_sap_hana_2_version: - "{{ __sap_software_download_sap_hana.split('_')[2] }}" # 084 for IMDB_SERVER20_084_0-80002031.SAR - - -# 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: Relation Check - SAP HANA 1.00 - IMDB_SERVER and IMDB_LCAPPS - ansible.builtin.fail: - msg: | - Warning: Incompatible SAP HANA 1.0 LCAPPS files were found. - Ensure that correct version is selected: {{ __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_relation_warning | d(false) }}" - when: - - __sap_software_download_sap_hana | regex_search('^IMDB_SERVER1') - - __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_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: Relation Check - SAP HANA 2.00 - IMDB_SERVER and IMDB_LCAPPS - ansible.builtin.fail: - msg: | - Warning: Incompatible SAP HANA 2.0 LCAPPS files were found. - Ensure that correct version is selected: {{ __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_relation_warning | d(false) }}" - when: - - __sap_software_download_sap_hana | regex_search('^IMDB_SERVER2') - - __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_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: Relation Check - SAP HANA 1.00 - IMDB_SERVER and IMDB_AFL - ansible.builtin.fail: - msg: | - Warning: Incompatible SAP HANA AFL 1.0 files were found. - Ensure that correct version is selected: {{ __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_relation_warning | d(false) }}" - when: - - __sap_software_download_sap_hana | regex_search('^IMDB_SERVER1') - - __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_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: Relation Check - SAP HANA 2.00 - IMDB_SERVER and IMDB_AFL - ansible.builtin.fail: - msg: | - Warning: Incompatible SAP HANA AFL 2.0 files were found. - Ensure that correct version is selected: {{ __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_relation_warning | d(false) }}" - when: - - __sap_software_download_sap_hana | regex_search('^IMDB_SERVER2') - - __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_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: Relation Check - SAP HANA 1.00 - IMDB_SERVER and IMDB_CLIENT - ansible.builtin.fail: - msg: | - Warning: SAP HANA CLIENT 1.00 was not found. - - 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_relation_warning | d(false) }}" - when: - - __sap_software_download_sap_hana | regex_search('^IMDB_SERVER1') - and __sap_software_download_sap_hana_client_list | length > 0 - and __sap_software_download_sap_hana_client_list | select('match', '^IMDB_CLIENT1.*') | 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: Relation Check - SAP HANA 2.00 - IMDB_SERVER and IMDB_CLIENT - ansible.builtin.fail: - msg: | - Warning: SAP HANA CLIENT 2.00 was not found. - - 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_relation_warning | d(false) }}" - when: - - __sap_software_download_sap_hana | regex_search('^IMDB_SERVER2') - and __sap_software_download_sap_hana_client_list | length > 0 - and __sap_software_download_sap_hana_client_list | select('match', '^IMDB_CLIENT2.*') | length == 0 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..dbe9e82 --- /dev/null +++ b/roles/sap_software_download/tasks/pre_steps/06_validate_sap_hana_1.yml @@ -0,0 +1,87 @@ +# 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 {{ + __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 {{ + __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..3bbb21b --- /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 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 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 From 024f0836f8d3c8e0fce8c5396240bf8c342638bc Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Tue, 1 Apr 2025 13:56:39 +0200 Subject: [PATCH 4/8] feat: response error handling, SPS version, verbosity, plan debug --- plugins/module_utils/sap_api_common.py | 20 ++++++++++++++++--- roles/sap_software_download/meta/main.yml | 20 +++++++++++++++++++ .../tasks/download_plan.yml | 2 +- .../pre_steps/03_validate_credentials.yml | 8 ++++++-- .../pre_steps/06_validate_sap_hana_1.yml | 12 ++++++----- .../pre_steps/07_validate_sap_hana_2.yml | 8 ++++---- 6 files changed, 55 insertions(+), 15 deletions(-) create mode 100644 roles/sap_software_download/meta/main.yml 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/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_plan.yml b/roles/sap_software_download/tasks/download_plan.yml index 34b4d31..ecd8565 100644 --- a/roles/sap_software_download/tasks/download_plan.yml +++ b/roles/sap_software_download/tasks/download_plan.yml @@ -51,7 +51,7 @@ - name: Download - Maintenance Plan - Show failed results ansible.builtin.fail: msg: | - Maintenance Plan file(s) not found: {{ __failed_items | map(attribute='Filename') | list | join(', ') }} + 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 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 index ef63819..51a9801 100644 --- a/roles/sap_software_download/tasks/pre_steps/03_validate_credentials.yml +++ b/roles/sap_software_download/tasks/pre_steps/03_validate_credentials.yml @@ -2,7 +2,7 @@ --- # This task attempts dry run to check SAPCAR file in order to validate provided credentials. -- name: Validate Credentials - Dry run to download test file with Python venv +- 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 }}" @@ -13,6 +13,8 @@ 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" @@ -21,7 +23,7 @@ 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 to download test file with Python system default +- 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 }}" @@ -32,6 +34,8 @@ 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 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 index dbe9e82..9a72e54 100644 --- 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 @@ -6,7 +6,7 @@ # 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]', '') }}" @@ -21,8 +21,9 @@ - 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 {{ - __sap_software_download_sap_hana_1_version }}.{{ __sap_software_download_sap_hana_1_revision }}. + 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 }}* @@ -48,8 +49,9 @@ - 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 {{ - __sap_software_download_sap_hana_1_version }}.{{ __sap_software_download_sap_hana_1_revision }}. + 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(', ') }} 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 index 3bbb21b..094fca7 100644 --- 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 @@ -17,8 +17,8 @@ - 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 Revision {{ - __sap_software_download_sap_hana_2_version }}. + 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(', ') }} @@ -42,8 +42,8 @@ - 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 Revision {{ - __sap_software_download_sap_hana_2_version }}. + 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(', ') }} From 2631c71794f01d9322cacf883baa60343f3d7332 Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Tue, 1 Apr 2025 15:59:58 +0200 Subject: [PATCH 5/8] feat: python default module packages --- roles/sap_software_download/README.md | 103 ++++++++++++++++-- roles/sap_software_download/defaults/main.yml | 9 ++ .../meta/argument_spec.yml | 14 ++- .../tasks/pre_steps/01_include_variables.yml | 12 +- .../02_prepare_python_environment.yml | 9 +- roles/sap_software_download/vars/RedHat.yml | 9 ++ .../sap_software_download/vars/RedHat_10.yml | 9 ++ roles/sap_software_download/vars/Suse.yml | 21 ++++ roles/sap_software_download/vars/main.yml | 10 ++ 9 files changed, 183 insertions(+), 13 deletions(-) diff --git a/roles/sap_software_download/README.md b/roles/sap_software_download/README.md index a85a387..93fdd7b 100644 --- a/roles/sap_software_download/README.md +++ b/roles/sap_software_download/README.md @@ -8,6 +8,22 @@ The Ansible Role `sap_software_download` is used to download SAP Software Media +## 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`. @@ -34,13 +50,14 @@ The target node must meet the following requirements: 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. **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. -4. **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. +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) -5. **Maintenance Plan File Download:** If `sap_software_download_mp_transaction` is provided, the role downloads the files associated with the Maintenance Plan. -6. **Direct File Download:** If `sap_software_download_files` is provided, the role downloads the specified files. -7. **Virtual Environment Cleanup:** If a temporary Python virtual environment was used, it is removed. +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. @@ -81,6 +98,62 @@ Download of SAP Software files using Maintenance Plan 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' +``` @@ -93,20 +166,20 @@ Validation is executed for known combinations of files, where we can validate th 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`, `Revision 084`. +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 prevented by setting `sap_software_download_ignore_relationship_warning` to `true`. + 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 prevented by setting `sap_software_download_ignore_relationship_warning` to `true`. + 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. @@ -125,6 +198,7 @@ Apache 2.0 ### 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`.
@@ -134,12 +208,25 @@ 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`
diff --git a/roles/sap_software_download/defaults/main.yml b/roles/sap_software_download/defaults/main.yml index 13787f9..cc2fcab 100644 --- a/roles/sap_software_download/defaults/main.yml +++ b/roles/sap_software_download/defaults/main.yml @@ -16,6 +16,15 @@ sap_software_download_python_interpreter: 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. diff --git a/roles/sap_software_download/meta/argument_spec.yml b/roles/sap_software_download/meta/argument_spec.yml index dec55ce..adfb6c9 100644 --- a/roles/sap_software_download/meta/argument_spec.yml +++ b/roles/sap_software_download/meta/argument_spec.yml @@ -25,13 +25,25 @@ argument_specs: sap_software_download_python_package: type: str - required: true + 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 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 index f8611db..2eeac53 100644 --- a/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml +++ b/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml @@ -34,7 +34,7 @@ - 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 | length > 0) + - (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. @@ -76,6 +76,16 @@ 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: 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 index bc06da5..2be5480 100644 --- 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 @@ -35,6 +35,9 @@ - name: Pre-Steps - Block for default Python preparation when: not sap_software_download_use_venv | d(true) block: - - name: Pre-Steps - Install Python modules in default Python - ansible.builtin.pip: - name: "{{ __sap_software_download_python_modules }}" + # 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/vars/RedHat.yml b/roles/sap_software_download/vars/RedHat.yml index 610fea6..6f8dc21 100644 --- a/roles/sap_software_download/vars/RedHat.yml +++ b/roles/sap_software_download/vars/RedHat.yml @@ -11,3 +11,12 @@ __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/RedHat_10.yml b/roles/sap_software_download/vars/RedHat_10.yml index 122cc07..13cb27b 100644 --- a/roles/sap_software_download/vars/RedHat_10.yml +++ b/roles/sap_software_download/vars/RedHat_10.yml @@ -10,3 +10,12 @@ __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/Suse.yml b/roles/sap_software_download/vars/Suse.yml index 2cd68f3..f540820 100644 --- a/roles/sap_software_download/vars/Suse.yml +++ b/roles/sap_software_download/vars/Suse.yml @@ -23,3 +23,24 @@ __sap_software_download_python_package: >- {%- 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 index 2897c1d..e40f28e 100644 --- a/roles/sap_software_download/vars/main.yml +++ b/roles/sap_software_download/vars/main.yml @@ -8,3 +8,13 @@ __sap_software_download_python_modules: - 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 From a9868329d09868066e0df1ba5353b0349a142c0a Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Wed, 2 Apr 2025 15:44:37 +0200 Subject: [PATCH 6/8] fix: ansible-lint corrections --- .ansible-lint | 2 +- .gitignore | 1 + roles/sap_software_download/defaults/main.yml | 16 ++++++++-------- .../sap_software_download/meta/argument_spec.yml | 4 ++-- .../tasks/download_files.yml | 6 +++--- .../tasks/download_plan.yml | 6 +++--- .../tasks/pre_steps/01_include_variables.yml | 6 +++--- .../tasks/pre_steps/03_validate_credentials.yml | 6 +++--- .../tasks/pre_steps/04_get_plan_files.yml | 6 +++--- .../tasks/pre_steps/05_validate_relations.yml | 6 +++--- .../tasks/pre_steps/06_validate_sap_hana_1.yml | 2 +- 11 files changed, 31 insertions(+), 30 deletions(-) diff --git a/.ansible-lint b/.ansible-lint index 829e107..ff93a8f 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -5,7 +5,7 @@ exclude_paths: - .ansible/ - .cache/ - .github/ - #- docs/ + # - docs/ - changelogs/ - playbooks/ - tests/ 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/roles/sap_software_download/defaults/main.yml b/roles/sap_software_download/defaults/main.yml index cc2fcab..50ac01f 100644 --- a/roles/sap_software_download/defaults/main.yml +++ b/roles/sap_software_download/defaults/main.yml @@ -33,7 +33,7 @@ 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`. +# 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. @@ -44,19 +44,13 @@ sap_software_download_files: [] 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`. +# 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' -# 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 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. @@ -68,6 +62,12 @@ sap_software_download_ignore_file_not_found: false # 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. diff --git a/roles/sap_software_download/meta/argument_spec.yml b/roles/sap_software_download/meta/argument_spec.yml index adfb6c9..6a64e3e 100644 --- a/roles/sap_software_download/meta/argument_spec.yml +++ b/roles/sap_software_download/meta/argument_spec.yml @@ -64,7 +64,7 @@ argument_specs: required: true no_log: true description: - - The password for the SAP S-User specified in `sap_software_download_suser_id`. + - The password for the SAP S-User specified in `sap_software_download_suser_id`. sap_software_download_files: type: list @@ -88,7 +88,7 @@ argument_specs: 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`. + - 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: diff --git a/roles/sap_software_download/tasks/download_files.yml b/roles/sap_software_download/tasks/download_files.yml index 6afcc76..f209caf 100644 --- a/roles/sap_software_download/tasks/download_files.yml +++ b/roles/sap_software_download/tasks/download_files.yml @@ -17,9 +17,9 @@ 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 }}" + 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 diff --git a/roles/sap_software_download/tasks/download_plan.yml b/roles/sap_software_download/tasks/download_plan.yml index ecd8565..a301294 100644 --- a/roles/sap_software_download/tasks/download_plan.yml +++ b/roles/sap_software_download/tasks/download_plan.yml @@ -16,9 +16,9 @@ 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 }}" + 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 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 index 2eeac53..edfec13 100644 --- a/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml +++ b/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml @@ -74,7 +74,7 @@ - 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. + 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: @@ -84,7 +84,7 @@ - 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. + 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: @@ -93,7 +93,7 @@ - sap_software_download_suser_id | length > 0 fail_msg: | Empty variable `sap_software_download_suser_id`. - Enter valid S-User ID with download authorizations. + Enter valid S-User ID with download authorizations. - name: "Pre-Steps - Verify variable: sap_software_download_suser_password" ansible.builtin.assert: 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 index 51a9801..0769386 100644 --- a/roles/sap_software_download/tasks/pre_steps/03_validate_credentials.yml +++ b/roles/sap_software_download/tasks/pre_steps/03_validate_credentials.yml @@ -16,9 +16,9 @@ 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 }}" + 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 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 index 11e8c4c..a4baef1 100644 --- 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 @@ -10,9 +10,9 @@ 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 }}" + 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 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 index b0b0915..5dc195e 100644 --- a/roles/sap_software_download/tasks/pre_steps/05_validate_relations.yml +++ b/roles/sap_software_download/tasks/pre_steps/05_validate_relations.yml @@ -22,9 +22,9 @@ 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 }}" + 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 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 index 9a72e54..93ac892 100644 --- 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 @@ -24,7 +24,7 @@ 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(', ') }} From 45adb7621cb2bc6b7fed70587f907e9c83b75e8a Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Thu, 3 Apr 2025 11:49:03 +0200 Subject: [PATCH 7/8] revert download_path to dest --- .../maintenance_planner_stack_xml_download.py | 10 +++--- plugins/modules/software_center_download.py | 32 +++++++++---------- roles/.gitkeep | 0 .../tasks/download_files.yml | 4 +-- .../tasks/download_plan.yml | 4 +-- .../pre_steps/03_validate_credentials.yml | 4 +-- .../tasks/pre_steps/05_validate_relations.yml | 4 +-- 7 files changed, 29 insertions(+), 29 deletions(-) delete mode 100644 roles/.gitkeep 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/tasks/download_files.yml b/roles/sap_software_download/tasks/download_files.yml index f209caf..177e76f 100644 --- a/roles/sap_software_download/tasks/download_files.yml +++ b/roles/sap_software_download/tasks/download_files.yml @@ -6,7 +6,7 @@ suser_id: "{{ sap_software_download_suser_id }}" suser_password: "{{ sap_software_download_suser_password }}" search_query: "{{ item }}" - download_path: "{{ sap_software_download_directory }}" + 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 @@ -30,7 +30,7 @@ suser_id: "{{ sap_software_download_suser_id }}" suser_password: "{{ sap_software_download_suser_password }}" search_query: "{{ item }}" - download_path: "{{ sap_software_download_directory }}" + 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 diff --git a/roles/sap_software_download/tasks/download_plan.yml b/roles/sap_software_download/tasks/download_plan.yml index a301294..b89af1f 100644 --- a/roles/sap_software_download/tasks/download_plan.yml +++ b/roles/sap_software_download/tasks/download_plan.yml @@ -7,7 +7,7 @@ suser_password: "{{ sap_software_download_suser_password }}" download_link: "{{ item.DirectLink }}" download_filename: "{{ item.Filename }}" - download_path: "{{ sap_software_download_directory }}" + 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: @@ -30,7 +30,7 @@ suser_password: "{{ sap_software_download_suser_password }}" download_link: "{{ item.DirectLink }}" download_filename: "{{ item.Filename }}" - download_path: "{{ sap_software_download_directory }}" + 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: 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 index 0769386..8154b72 100644 --- a/roles/sap_software_download/tasks/pre_steps/03_validate_credentials.yml +++ b/roles/sap_software_download/tasks/pre_steps/03_validate_credentials.yml @@ -8,7 +8,7 @@ suser_id: "{{ sap_software_download_suser_id }}" suser_password: "{{ sap_software_download_suser_password }}" search_query: "SAPCAR" - download_path: "{{ sap_software_download_directory }}" + dest: "{{ sap_software_download_directory }}" search_alternatives: true deduplicate: "last" dry_run: true @@ -29,7 +29,7 @@ suser_id: "{{ sap_software_download_suser_id }}" suser_password: "{{ sap_software_download_suser_password }}" search_query: "SAPCAR" - download_path: "{{ sap_software_download_directory }}" + dest: "{{ sap_software_download_directory }}" search_alternatives: true deduplicate: "last" dry_run: true 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 index 5dc195e..39c9687 100644 --- a/roles/sap_software_download/tasks/pre_steps/05_validate_relations.yml +++ b/roles/sap_software_download/tasks/pre_steps/05_validate_relations.yml @@ -10,7 +10,7 @@ suser_id: "{{ sap_software_download_suser_id }}" suser_password: "{{ sap_software_download_suser_password }}" search_query: "{{ item }}" - download_path: "{{ sap_software_download_directory }}" + dest: "{{ sap_software_download_directory }}" search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}" deduplicate: "{{ sap_software_download_deduplicate | d('') }}" dry_run: true @@ -35,7 +35,7 @@ suser_id: "{{ sap_software_download_suser_id }}" suser_password: "{{ sap_software_download_suser_password }}" search_query: "{{ item }}" - download_path: "{{ sap_software_download_directory }}" + dest: "{{ sap_software_download_directory }}" search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}" deduplicate: "{{ sap_software_download_deduplicate | d('') }}" dry_run: true From 56f42ba5b15c9ae0da4e4fb221d03a9bbfae4be1 Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Thu, 3 Apr 2025 15:01:30 +0200 Subject: [PATCH 8/8] update redhat variable files --- roles/sap_software_download/vars/RedHat_8.yml | 21 +++++++++++++++++++ .../vars/{RedHat.yml => RedHat_9.yml} | 1 - 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 roles/sap_software_download/vars/RedHat_8.yml rename roles/sap_software_download/vars/{RedHat.yml => RedHat_9.yml} (95%) 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.yml b/roles/sap_software_download/vars/RedHat_9.yml similarity index 95% rename from roles/sap_software_download/vars/RedHat.yml rename to roles/sap_software_download/vars/RedHat_9.yml index 6f8dc21..f472adf 100644 --- a/roles/sap_software_download/vars/RedHat.yml +++ b/roles/sap_software_download/vars/RedHat_9.yml @@ -2,7 +2,6 @@ --- # Variables specific to following versions: -# - Red Hat Linux Enterprise Server 8 # - Red Hat Linux Enterprise Server 9 # Set which Python version will be used on destination node.