From ad00eee0ddd6001c6e1316892968a794c0b0beae Mon Sep 17 00:00:00 2001 From: Vinny Valdez Date: Fri, 23 Oct 2026 10:35:21 -0500 Subject: [PATCH 1/8] refactor: rename preflight role to validate_environment Pair symmetry with validate_migration (companion PR #108, post-only). Clean break: v2 is unreleased and nothing in-repo consumed the old names. Role dirs, playbooks (vmf_validate_environment.yml), variable prefixes, test targets, docs, and the changelog fragment all use the new name. Assisted-by: opencode:enmaas/rits/zai-org/glm-5-3 --- GLOSSARY.md | 27 +++ README.md | 2 +- changelogs/fragments/107-preflight-role.yml | 7 - .../110-validate-environment-role.yml | 6 + docs/architecture-v2.md | 6 +- ...light.yml => vmf_validate_environment.yml} | 4 +- roles/preflight/tasks/validate_aap.yml | 44 ----- roles/preflight/tasks/validate_cnv.yml | 53 ------ roles/preflight/tasks/validate_mtv.yml | 53 ------ roles/preflight/tasks/validate_openshift.yml | 38 ---- roles/preflight/tasks/validate_vcenter.yml | 97 ---------- .../README.md | 178 +++++++++--------- .../defaults/main.yml | 96 +++++----- .../meta/argument_specs.yml | 54 +++--- .../meta/main.yml | 2 +- .../tasks/main.yml | 6 +- .../tasks/pre_validate.yml | 14 +- .../tasks/report.yml | 52 ++--- .../tasks/validate_aap.yml | 45 +++++ .../tasks/validate_cnv.yml | 53 ++++++ .../tasks/validate_mtv.yml | 53 ++++++ .../tasks/validate_openshift.yml | 38 ++++ .../tasks/validate_vcenter.yml | 99 ++++++++++ .../tasks/validate_vddk.yml | 20 +- .../vars/main.yml | 4 +- .../targets/preflight_report/tasks/main.yml | 103 ---------- .../tasks/main.yml | 103 ++++++++++ 27 files changed, 646 insertions(+), 611 deletions(-) create mode 100644 GLOSSARY.md delete mode 100644 changelogs/fragments/107-preflight-role.yml create mode 100644 changelogs/fragments/110-validate-environment-role.yml rename playbooks/{vmf_preflight.yml => vmf_validate_environment.yml} (59%) delete mode 100644 roles/preflight/tasks/validate_aap.yml delete mode 100644 roles/preflight/tasks/validate_cnv.yml delete mode 100644 roles/preflight/tasks/validate_mtv.yml delete mode 100644 roles/preflight/tasks/validate_openshift.yml delete mode 100644 roles/preflight/tasks/validate_vcenter.yml rename roles/{preflight => validate_environment}/README.md (67%) rename roles/{preflight => validate_environment}/defaults/main.yml (61%) rename roles/{preflight => validate_environment}/meta/argument_specs.yml (79%) rename roles/{preflight => validate_environment}/meta/main.yml (92%) rename roles/{preflight => validate_environment}/tasks/main.yml (93%) rename roles/{preflight => validate_environment}/tasks/pre_validate.yml (66%) rename roles/{preflight => validate_environment}/tasks/report.yml (53%) create mode 100644 roles/validate_environment/tasks/validate_aap.yml create mode 100644 roles/validate_environment/tasks/validate_cnv.yml create mode 100644 roles/validate_environment/tasks/validate_mtv.yml create mode 100644 roles/validate_environment/tasks/validate_openshift.yml create mode 100644 roles/validate_environment/tasks/validate_vcenter.yml rename roles/{preflight => validate_environment}/tasks/validate_vddk.yml (51%) rename roles/{preflight => validate_environment}/vars/main.yml (52%) delete mode 100644 tests/integration/targets/preflight_report/tasks/main.yml create mode 100644 tests/integration/targets/validate_environment_report/tasks/main.yml diff --git a/GLOSSARY.md b/GLOSSARY.md new file mode 100644 index 0000000..9ff0007 --- /dev/null +++ b/GLOSSARY.md @@ -0,0 +1,27 @@ +# Glossary + +Domain vocabulary for the openshift-virtualization-migration collection. + +## Environment validation + +The pre-migration validation pass (role `validate_environment`, playbook `vmf_validate_environment.yml`). Validates the migration environment before seeding AAP and running a migration: OpenShift API authentication, OpenShift Virtualization and MTV operator health, AAP access, vCenter connectivity, and VDDK init image configuration. Read-only probes; fails the play with an actionable message per failed check. + +## Migration validation + +The post-migration validation pass (role `validate_migration`, playbook `vmf_validate_migration.yml`). Runs as a standalone playbook after `vmf_migrate` completes — the operator or an AAP job template invokes it; it is not wired into the MTV pipeline (the in-pipeline hook path is `mtv_hook_invoke_aap`). Validates migration outcomes and performs the source power-off. + +## Source VM + +The original VMware virtual machine being migrated to OpenShift Virtualization. Queried read-only via the vCenter API. + +## Migrated VM + +The OpenShift Virtualization virtual machine produced by a migration; the counterpart of one source VM. Verified via the Kubernetes API (VirtualMachine / VirtualMachineInstance status). + +## Migration plan + +The MTV (Forklift) Plan custom resource that groups source VMs with network and storage maps and drives the migration. Referenced by name and namespace (`mtv_migrate_plan_name`, `mtv_migrate_plan_namespace`). + +## Source power-off + +The post-migration cutover step of powering off source VMs whose migrated counterparts passed validation — a hard stop via the vCenter API. Performed by validate_migration, controlled by a toggle (default: on), gated per-VM and fail-closed — see docs/adr/0001-validate-migration-fail-closed-power-off.md. diff --git a/README.md b/README.md index 0af0c62..c5601f8 100644 --- a/README.md +++ b/README.md @@ -51,10 +51,10 @@ This collection includes the following roles for managing OpenShift Virtualizati * [mtv_provider](roles/mtv_provider/README.md) - Ensure host OpenShift provider and source provider CRs exist on target clusters. Designed to run from AAP with credential injection. * [mtv_query_inventory](roles/mtv_query_inventory/README.md) - Queries MTV inventory. * [pre_migration_vm](roles/pre_migration_vm/README.md) - Perform VM related activities prior to a migration -* [preflight](roles/preflight/README.md) - Validate the migration environment before seeding AAP — OpenShift API authentication, OpenShift Virtualization and MTV operator health, AAP access, vCenter connectivity, and VDDK init image configuration. * [utility_aap_deploy](roles/utility_aap_deploy/README.md) - Deploys an instance of Ansible Automation Platform. * [utility_openshift_target_credential](roles/utility_openshift_target_credential/README.md) - A utility role to manage OpenShift target cluster credentials for migration * [utility_registry_credentials](roles/utility_registry_credentials/README.md) - Manages registry credentials in an OpenShift namespace. +* [validate_environment](roles/validate_environment/README.md) - Validate the migration environment before seeding AAP — OpenShift API authentication, OpenShift Virtualization and MTV operator health, AAP access, vCenter connectivity, and VDDK init image configuration. ## Requirements diff --git a/changelogs/fragments/107-preflight-role.yml b/changelogs/fragments/107-preflight-role.yml deleted file mode 100644 index 49130db..0000000 --- a/changelogs/fragments/107-preflight-role.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -minor_changes: - - Add preflight role to validate the migration environment before seeding AAP — OpenShift API authentication, OpenShift Virtualization and MTV operator health, AAP access, vCenter connectivity, and VDDK init image configuration. - - Add vmf_preflight.yml playbook to run the preflight role from a controller or an AAP job template. -bugfixes: - - Preserve an explicit false for validate_certs in the preflight role's vCenter and AAP TLS-verification cascade — the previous fallback converted it to true. -... diff --git a/changelogs/fragments/110-validate-environment-role.yml b/changelogs/fragments/110-validate-environment-role.yml new file mode 100644 index 0000000..7bb93bb --- /dev/null +++ b/changelogs/fragments/110-validate-environment-role.yml @@ -0,0 +1,6 @@ +--- +minor_changes: + - Add validate_environment role to validate the migration environment before seeding AAP and running a migration — OpenShift API auth, OpenShift Virtualization and MTV operator health, AAP access, vCenter connectivity, and VDDK init image configuration (playbook vmf_validate_environment.yml). +bugfixes: + - Preserve an explicit false for validate_certs in the validate_environment role's vCenter and AAP TLS-verification cascade — the previous fallback converted it to true. +... diff --git a/docs/architecture-v2.md b/docs/architecture-v2.md index bd2e1af..13eee2f 100644 --- a/docs/architecture-v2.md +++ b/docs/architecture-v2.md @@ -61,7 +61,7 @@ flowchart TD end subgraph Migration["Phase C: Migration Execution"] - PreFlight["Pre-flight validation\nstorage, network, provider checks"] + EnvValidation["Environment validation\nstorage, network, provider checks"] Migrate["mtv_migrate role\nPlan creation + execution"] Monitor["Migration monitoring\nfailure_strategy handling"] PostVal["Post-migration validation"] @@ -77,8 +77,8 @@ flowchart TD EnvMgr --> Ops Ops --> Net Net --> MTV - MigReq --> PreFlight - PreFlight --> Migrate + MigReq --> EnvValidation + EnvValidation --> Migrate Migrate --> Monitor Monitor --> PostVal Seed -.-> EnvConfig diff --git a/playbooks/vmf_preflight.yml b/playbooks/vmf_validate_environment.yml similarity index 59% rename from playbooks/vmf_preflight.yml rename to playbooks/vmf_validate_environment.yml index 631baa8..2417b68 100644 --- a/playbooks/vmf_preflight.yml +++ b/playbooks/vmf_validate_environment.yml @@ -5,7 +5,7 @@ gather_facts: false tasks: - - name: Run preflight validation checks + - name: Run environment validation checks ansible.builtin.import_role: - name: infra.openshift_virtualization_migration.preflight + name: infra.openshift_virtualization_migration.validate_environment ... diff --git a/roles/preflight/tasks/validate_aap.yml b/roles/preflight/tasks/validate_aap.yml deleted file mode 100644 index 042fb5c..0000000 --- a/roles/preflight/tasks/validate_aap.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -# Probe the AAP API with the configured account. -# ansible.builtin.uri is used instead of ansible.controller modules because -# the preflight runs before seeding and needs only a lightweight auth probe -# (the me/ endpoint returns the authenticated account); controller modules -# pull in full controller configuration context that does not exist yet. - -- name: validate_aap | Probe AAP API with the configured account - when: preflight_aap_hostname | length > 0 - ansible.builtin.uri: - url: "{{ preflight_aap_hostname }}{{ preflight_aap_api_path }}me/" - method: GET - validate_certs: "{{ preflight_aap_validate_certs }}" - headers: - Authorization: >- - {{ - ('Bearer ' ~ (preflight_aap_token | trim)) - if preflight_aap_token | length > 0 - else ('Basic ' ~ ((preflight_aap_username ~ ':' ~ preflight_aap_password) | b64encode)) - }} - status_code: [200, 401, 403] - register: __preflight_aap - failed_when: false - no_log: "{{ preflight_secure_logging }}" - -- name: validate_aap | Record the AAP access check result - ansible.builtin.set_fact: - __preflight_result_aap: - ran: true - passed: "{{ (preflight_aap_hostname | length > 0) and ((__preflight_aap.status | default(0)) == 200) }}" - detail: >- - {% if preflight_aap_hostname | length == 0 %} - Not configured — set aap_hostname in the inventory (or AAP_HOSTNAME) - to enable the AAP access check - {% elif (__preflight_aap.status | default(0)) == 200 %} - HTTP 200 at {{ preflight_aap_hostname }} (authenticated as - {{ __preflight_aap.json.results[0].username | default('unknown', true) }}) - {% else %} - HTTP {{ __preflight_aap.status | default('connection error') }} at - {{ preflight_aap_hostname }} — 401/403 means the account or token is - wrong or expired; 404 means the API path is wrong — AAP 2.4 - and earlier deployments need preflight_aap_api_path=/api/v2/ - {% endif %} -... diff --git a/roles/preflight/tasks/validate_cnv.yml b/roles/preflight/tasks/validate_cnv.yml deleted file mode 100644 index 75b9fab..0000000 --- a/roles/preflight/tasks/validate_cnv.yml +++ /dev/null @@ -1,53 +0,0 @@ ---- -# Query the ClusterServiceVersion list in the CNV namespace. -# kubernetes.core.k8s_info is certified content and the collection's -# established pattern for cluster queries. - -- name: validate_cnv | List ClusterServiceVersions in the CNV namespace - kubernetes.core.k8s_info: - host: "{{ preflight_openshift_host }}" - api_key: "{{ preflight_openshift_api_key }}" - validate_certs: "{{ preflight_openshift_verify_ssl }}" - api_version: operators.coreos.com/v1alpha1 - kind: ClusterServiceVersion - namespace: "{{ preflight_cnv_namespace }}" - register: __preflight_cnv_csvs - failed_when: false - no_log: "{{ preflight_secure_logging }}" - -- name: validate_cnv | Find the OpenShift Virtualization CSV - ansible.builtin.set_fact: - __preflight_cnv_found: >- - {{ __preflight_cnv_csvs.resources | default([]) - | selectattr('metadata.name', 'search', 'kubevirt-hyperconverged') - | list | length > 0 }} - __preflight_cnv_csv: >- - {{ __preflight_cnv_csvs.resources | default([]) - | selectattr('metadata.name', 'search', 'kubevirt-hyperconverged') - | list | first | default({}) }} - -- name: validate_cnv | Record the OpenShift Virtualization operator check result - ansible.builtin.set_fact: - __preflight_result_cnv: - ran: true - passed: "{{ __preflight_cnv_found - and (__preflight_cnv_csv.status.phase | default('')) == 'Succeeded' }}" - detail: >- - {% if __preflight_cnv_csvs.resources is not defined %} - Cluster API query failed in {{ preflight_cnv_namespace }} — - check the OpenShift connection and credentials first; the - operator check is inconclusive when the API is unreachable - {% elif not __preflight_cnv_found %} - No kubevirt-hyperconverged CSV found in - {{ preflight_cnv_namespace }} — install the OpenShift - Virtualization operator before seeding - {% elif (__preflight_cnv_csv.status.phase | default('')) != 'Succeeded' %} - CSV {{ __preflight_cnv_csv.metadata.name }} in - {{ preflight_cnv_namespace }} is - {{ __preflight_cnv_csv.status.phase | default('unknown') }} — - expected Succeeded - {% else %} - CSV {{ __preflight_cnv_csv.metadata.name }} Succeeded in - {{ preflight_cnv_namespace }} - {% endif %} -... diff --git a/roles/preflight/tasks/validate_mtv.yml b/roles/preflight/tasks/validate_mtv.yml deleted file mode 100644 index b1e1cbd..0000000 --- a/roles/preflight/tasks/validate_mtv.yml +++ /dev/null @@ -1,53 +0,0 @@ ---- -# Query the ClusterServiceVersion list in the MTV namespace. -# kubernetes.core.k8s_info is certified content and the collection's -# established pattern for cluster queries. - -- name: validate_mtv | List ClusterServiceVersions in the MTV namespace - kubernetes.core.k8s_info: - host: "{{ preflight_openshift_host }}" - api_key: "{{ preflight_openshift_api_key }}" - validate_certs: "{{ preflight_openshift_verify_ssl }}" - api_version: operators.coreos.com/v1alpha1 - kind: ClusterServiceVersion - namespace: "{{ preflight_mtv_namespace }}" - register: __preflight_mtv_csvs - failed_when: false - no_log: "{{ preflight_secure_logging }}" - -- name: validate_mtv | Find the MTV CSV - ansible.builtin.set_fact: - __preflight_mtv_found: >- - {{ __preflight_mtv_csvs.resources | default([]) - | selectattr('metadata.name', 'search', 'mtv-operator') - | list | length > 0 }} - __preflight_mtv_csv: >- - {{ __preflight_mtv_csvs.resources | default([]) - | selectattr('metadata.name', 'search', 'mtv-operator') - | list | first | default({}) }} - -- name: validate_mtv | Record the MTV operator check result - ansible.builtin.set_fact: - __preflight_result_mtv: - ran: true - passed: "{{ __preflight_mtv_found - and (__preflight_mtv_csv.status.phase | default('')) == 'Succeeded' }}" - detail: >- - {% if __preflight_mtv_csvs.resources is not defined %} - Cluster API query failed in {{ preflight_mtv_namespace }} — - check the OpenShift connection and credentials first; the - operator check is inconclusive when the API is unreachable - {% elif not __preflight_mtv_found %} - No mtv-operator CSV found in {{ preflight_mtv_namespace }} — - install the Migration Toolkit for Virtualization operator before - seeding - {% elif (__preflight_mtv_csv.status.phase | default('')) != 'Succeeded' %} - CSV {{ __preflight_mtv_csv.metadata.name }} in - {{ preflight_mtv_namespace }} is - {{ __preflight_mtv_csv.status.phase | default('unknown') }} — - expected Succeeded - {% else %} - CSV {{ __preflight_mtv_csv.metadata.name }} Succeeded in - {{ preflight_mtv_namespace }} - {% endif %} -... diff --git a/roles/preflight/tasks/validate_openshift.yml b/roles/preflight/tasks/validate_openshift.yml deleted file mode 100644 index 8e8b803..0000000 --- a/roles/preflight/tasks/validate_openshift.yml +++ /dev/null @@ -1,38 +0,0 @@ ---- -# Probe the OpenShift API with the configured credential. -# ansible.builtin.uri is used instead of the k8s modules because the HTTP -# status code cleanly distinguishes 401/403 (credential rejected) from -# 200/201 (authenticated). - -- name: validate_openshift | Probe OpenShift API SelfSubjectReview with the configured credential - ansible.builtin.uri: - url: "{{ preflight_openshift_host }}/apis/authentication.k8s.io/v1/selfsubjectreviews" - method: POST - body: '{"apiVersion":"authentication.k8s.io/v1","kind":"SelfSubjectReview"}' - body_format: json - validate_certs: "{{ preflight_openshift_verify_ssl }}" - headers: - Authorization: "{{ 'Bearer ' ~ (preflight_openshift_api_key | trim) }}" - status_code: [200, 201, 401, 403] - register: __preflight_ocp - # No module state is created — the review object is informational only, - # so this probe must never report changed. - changed_when: false - failed_when: false - no_log: "{{ preflight_secure_logging }}" - -- name: validate_openshift | Record the OpenShift authentication check result - ansible.builtin.set_fact: - __preflight_result_openshift: - ran: true - passed: "{{ (__preflight_ocp.status | default(0)) in [200, 201] }}" - detail: >- - {% if (__preflight_ocp.status | default(0)) in [200, 201] %} - HTTP {{ __preflight_ocp.status }} at {{ preflight_openshift_host }} - (identity: {{ __preflight_ocp.json.status.userInfo.username | default('unknown', true) }}) - {% else %} - HTTP {{ __preflight_ocp.status | default('connection error') }} at - {{ preflight_openshift_host }} — 401/403 means the token or - credential is missing, expired, or rejected - {% endif %} -... diff --git a/roles/preflight/tasks/validate_vcenter.yml b/roles/preflight/tasks/validate_vcenter.yml deleted file mode 100644 index 927e71c..0000000 --- a/roles/preflight/tasks/validate_vcenter.yml +++ /dev/null @@ -1,97 +0,0 @@ ---- -# Probe vCenter connectivity and authentication. -# Two paths: the certified vmware.vmware_rest REST collection (vCenter 7.0+) -# first, then a community.vmware SOAP (pyVmomi) fallback that also covers 6.x -# — older vCenters do not serve the /api/ REST tree at all, and proxies in -# front of them commonly map only /sdk and /rest. Listing datacenters is the -# lightest operation that proves both connectivity and authentication against -# the configured source. The check only applies to vmware sources — other -# source types (ovirt) skip it. -# -# Module tier justification (community content): the certified -# vmware.vmware_rest collection requires vCenter 7.0+ and cannot reach 6.x at -# all (no /api/ tree), and the certified successor vmware.vmware collection -# does not yet ship a datacenter_info module. community.vmware -# .vmware_datacenter_info (pyVmomi, vCenter 6.5+) is the only content that -# covers the 6.x path, so the SOAP fallback runs only when the REST probe -# cannot return data. - -- name: validate_vcenter | List vCenter datacenters via the REST API (vCenter 7.0+) - when: - - preflight_vcenter_hostname | length > 0 - - __preflight_source_type | length == 0 or __preflight_source_type == 'vmware' - vmware.vmware_rest.vcenter_datacenter_info: - vcenter_hostname: "{{ preflight_vcenter_hostname }}" - vcenter_username: "{{ preflight_vcenter_username }}" - vcenter_password: "{{ preflight_vcenter_password }}" - vcenter_validate_certs: "{{ preflight_vcenter_validate_certs }}" - register: __preflight_vcenter_rest - failed_when: false - # A module crash (e.g. aiohttp ContentTypeError when the endpoint answers - # with a non-JSON body) bypasses failed_when and would abort the run; the - # fallback and record tasks below turn the fault into a graceful check - # result. - ignore_errors: true - no_log: "{{ preflight_secure_logging }}" - -- name: validate_vcenter | Fall back to the SOAP SDK for vCenter 6.x (no REST API) - when: - - preflight_vcenter_hostname | length > 0 - - __preflight_source_type | length == 0 or __preflight_source_type == 'vmware' - - __preflight_vcenter_rest.value is not defined or __preflight_vcenter_rest.value | length == 0 - community.vmware.vmware_datacenter_info: - hostname: "{{ preflight_vcenter_hostname }}" - username: "{{ preflight_vcenter_username }}" - password: "{{ preflight_vcenter_password }}" - validate_certs: "{{ preflight_vcenter_validate_certs }}" - register: __preflight_vcenter_soap - failed_when: false - ignore_errors: true - no_log: "{{ preflight_secure_logging }}" - -- name: validate_vcenter | Merge the REST and SOAP results into one datacenter list - # Prefers a result with datacenters (the SOAP fallback can find data the - # proxied REST path misses); falls back to an empty result from either - # path (connected but none visible), then the empty-string sentinel when - # neither path returned data — the record task distinguishes a real list - # from '' by type. - ansible.builtin.set_fact: - __preflight_vcenter_dcs: "{{ ([(__preflight_vcenter_rest.value | default(none)), - (__preflight_vcenter_soap.datacenter_info | default(none))] - | reject('none') | select('truthy') | first) - | default([(__preflight_vcenter_rest.value | default(none)), - (__preflight_vcenter_soap.datacenter_info | default(none))] - | reject('none') | first | default(none), true) }}" - -- name: validate_vcenter | Record the vCenter connectivity check result - ansible.builtin.set_fact: - __preflight_result_vcenter: - ran: true - passed: "{{ (__preflight_source_type | length > 0 and __preflight_source_type != 'vmware') - or ((preflight_vcenter_hostname | length > 0) - and (__preflight_vcenter_dcs is not string) - and (__preflight_vcenter_dcs | length) > 0) }}" - detail: >- - {% if __preflight_source_type | length > 0 and __preflight_source_type != 'vmware' %} - Skipped — source type is {{ __preflight_source_type }}, not vmware; - the vCenter check does not apply - {% elif preflight_vcenter_hostname | length == 0 %} - Not configured — set host/username/password on the source host - (or run from AAP where the source credential injects VMWARE_*) to - enable the vCenter check - {% elif __preflight_vcenter_dcs is not string and __preflight_vcenter_dcs | length > 0 %} - HTTP session established at {{ preflight_vcenter_hostname }} - ({{ __preflight_vcenter_dcs | length }} datacenters visible via - {{ 'REST' if __preflight_vcenter_rest.value is defined and __preflight_vcenter_rest.value | length > 0 - else 'the SOAP SDK' }}) - {% elif __preflight_vcenter_dcs is not string %} - Connected to {{ preflight_vcenter_hostname }} but no datacenters - are visible — a migration source needs at least one - {% else %} - vCenter authentication or connectivity failed at - {{ preflight_vcenter_hostname }} — re-run the vCenter check alone - (--tags vcenter) as a one-off CLI run with - preflight_secure_logging=false to see the fault, then rotate the - exposed credential - {% endif %} -... diff --git a/roles/preflight/README.md b/roles/validate_environment/README.md similarity index 67% rename from roles/preflight/README.md rename to roles/validate_environment/README.md index d7edc70..53ae8da 100644 --- a/roles/preflight/README.md +++ b/roles/validate_environment/README.md @@ -1,5 +1,5 @@ -# preflight +# validate_environment Validate the migration environment before seeding AAP. Runs every check and reports a summary, then fails the play if any check failed — one run reports everything that needs attention. @@ -19,25 +19,25 @@ If any check fails, fix it before you seed. Do not seed to paper over a missing ## Example ```bash -ansible-playbook playbooks/vmf_preflight.yml \ +ansible-playbook playbooks/vmf_validate_environment.yml \ --inventory inventory-sample.yml ``` From an AAP job template the target credential injects `K8S_AUTH_*`, the source credential injects `VMWARE_*`, and the controller injects `CONTROLLER_HOST`/`CONTROLLER_API_TOKEN` — the same role runs unchanged. -The AAP access check defaults to the AAP 2.5 platform controller API path (`/api/controller/v2/`). AAP 2.4 and earlier serve the API at `/api/v2/` — set `preflight_aap_api_path: /api/v2/` for those environments (a 404 from the AAP check means the path is wrong). +The AAP access check defaults to the AAP 2.5 platform controller API path (`/api/controller/v2/`). AAP 2.4 and earlier serve the API at `/api/v2/` — set `validate_environment_aap_api_path: /api/v2/` for those environments (a 404 from the AAP check means the path is wrong). -With the sample inventory the connection variables resolve from the target cluster host (`openshift_host`, `openshift_api_key`), the source host (`host`, `username`, `password`, `vddk.image`), and the AAP host (`aap_hostname`, `aap_token`) — selected by `preflight_target_name`, `preflight_source_name`, and `preflight_aap_name`, which default to the `target_name`/`source_name` extra vars (injected by the seeded credentials) or the first host of each group. +With the sample inventory the connection variables resolve from the target cluster host (`openshift_host`, `openshift_api_key`), the source host (`host`, `username`, `password`, `vddk.image`), and the AAP host (`aap_hostname`, `aap_token`) — selected by `validate_environment_target_name`, `validate_environment_source_name`, and `validate_environment_aap_name`, which default to the `target_name`/`source_name` extra vars (injected by the seeded credentials) or the first host of each group. All checks run on every invocation, and the summary assert requires every check green — the per-check tags (`openshift`, `cnv`, `mtv`, `aap`, `vcenter`, `vddk`) exist for isolated debugging; the summary asserts only over the checks that ran, so a tagged debug run ends green when the targeted check passed. A source whose `type` is not `vmware` (for example `ovirt`) skips the vCenter and VDDK checks. ## Check Mode -Not supported. The connection probes use the `uri` module, which is skipped under `--check`, so a check-mode run reports false authentication failures for the OpenShift and AAP checks. Run the preflight without `--check` — every probe is read-only (SelfSubjectReview creates no state, `/api/v2/me/` is a GET, operator queries are list calls). +Not supported. The connection probes use the `uri` module, which is skipped under `--check`, so a check-mode run reports false authentication failures for the OpenShift and AAP checks. Run the validate_environment without `--check` — every probe is read-only (SelfSubjectReview creates no state, `/api/v2/me/` is a GET, operator queries are list calls). -## preflight +## validate_environment ``` Role belongs to infra/openshift_virtualization_migration @@ -56,104 +56,104 @@ Description: Validate the migration environment before seeding AAP — OpenShift #### Key: main -* **Description**: ['Runs every preflight check and reports a summary, then fails the play if any check failed. Checks: OpenShift API auth, CNV and MTV operator health, AAP access, vCenter connectivity, and VDDK init image configuration.', 'Designed to run from an AAP job template (credentials inject K8S_AUTH_*, VMWARE_*, CONTROLLER_HOST, CONTROLLER_API_TOKEN) or a controller with the sample inventory. Connection variables cascade from environment variables to inventory host variables.', 'All checks run on every invocation. An unconfigured target fails that check with guidance rather than crashing the play, so one run reports everything that needs attention.'] +* **Description**: ['Runs every validate_environment check and reports a summary, then fails the play if any check failed. Checks: OpenShift API auth, CNV and MTV operator health, AAP access, vCenter connectivity, and VDDK init image configuration.', 'Designed to run from an AAP job template (credentials inject K8S_AUTH_*, VMWARE_*, CONTROLLER_HOST, CONTROLLER_API_TOKEN) or a controller with the sample inventory. Connection variables cascade from environment variables to inventory host variables.', 'All checks run on every invocation. An unconfigured target fails that check with guidance rather than crashing the play, so one run reports everything that needs attention.'] * **Options**: - * **preflight_aap_api_path**: + * **validate_environment_aap_api_path**: * **Required**: False * **Type**: str * **Default**: /api/v2/ * **Description**: API base path for the access check. Defaults to /api/v2/ (AWX and AAP 2.4 and earlier); AAP 2.5 platform deployments serve the controller API at /api/controller/v2/. - * **preflight_aap_hostname**: + * **validate_environment_aap_hostname**: * **Required**: False * **Type**: str * **Default**: - * **Description**: AAP controller URL for the access check. Resolves from AAP_HOSTNAME env var, the CONTROLLER_HOST env var injected by the controller for its own jobs, or the aap_hostname variable on the AAP host (preflight_aap_name). When unset, the AAP check fails with instructions. - * **preflight_aap_name**: + * **Description**: AAP controller URL for the access check. Resolves from AAP_HOSTNAME env var, the CONTROLLER_HOST env var injected by the controller for its own jobs, or the aap_hostname variable on the AAP host (validate_environment_aap_name). When unset, the AAP check fails with instructions. + * **validate_environment_aap_name**: * **Required**: False * **Type**: str * **Default**: none * **Description**: Inventory host whose aap_* variables feed the AAP check. Defaults to the first migration_aap host. - * **preflight_aap_password**: + * **validate_environment_aap_password**: * **Required**: False * **Type**: str * **Default**: * **Description**: AAP password for the access check when no token is set. - * **preflight_aap_token**: + * **validate_environment_aap_token**: * **Required**: False * **Type**: str * **Default**: * **Description**: AAP OAuth2 token. Resolves from AAP_TOKEN env var, the CONTROLLER_API_TOKEN env var injected by the controller for its own jobs, or the aap_token variable on the AAP host. Takes precedence over username/password. - * **preflight_aap_username**: + * **validate_environment_aap_username**: * **Required**: False * **Type**: str * **Default**: * **Description**: AAP username for the access check. - * **preflight_aap_validate_certs**: + * **validate_environment_aap_validate_certs**: * **Required**: False * **Type**: bool * **Default**: True * **Description**: Validate the AAP TLS certificate. - * **preflight_cnv_namespace**: + * **validate_environment_cnv_namespace**: * **Required**: False * **Type**: str * **Default**: openshift-cnv * **Description**: Namespace holding the OpenShift Virtualization operator CSV. - * **preflight_mtv_namespace**: + * **validate_environment_mtv_namespace**: * **Required**: False * **Type**: str * **Default**: openshift-mtv * **Description**: Namespace holding the MTV operator CSV. Resolves from the mtv_namespace inventory variable by default. - * **preflight_openshift_api_key**: + * **validate_environment_openshift_api_key**: * **Required**: False * **Type**: str * **Default**: - * **Description**: OpenShift API token. Resolves from K8S_AUTH_API_KEY env var or the openshift_api_key variable on the target cluster host (preflight_target_name). Required — the preflight aborts without it. - * **preflight_openshift_host**: + * **Description**: OpenShift API token. Resolves from K8S_AUTH_API_KEY env var or the openshift_api_key variable on the target cluster host (validate_environment_target_name). Required — the validate_environment aborts without it. + * **validate_environment_openshift_host**: * **Required**: False * **Type**: str * **Default**: - * **Description**: OpenShift API endpoint. Resolves from K8S_AUTH_HOST env var or the openshift_host variable on the target cluster host (preflight_target_name). Required — the preflight aborts without it. - * **preflight_openshift_verify_ssl**: + * **Description**: OpenShift API endpoint. Resolves from K8S_AUTH_HOST env var or the openshift_host variable on the target cluster host (validate_environment_target_name). Required — the validate_environment aborts without it. + * **validate_environment_openshift_verify_ssl**: * **Required**: False * **Type**: bool * **Default**: True * **Description**: Validate the OpenShift API TLS certificate. - * **preflight_secure_logging**: + * **validate_environment_secure_logging**: * **Required**: False * **Type**: bool * **Default**: True * **Description**: Whether to enable secure logging for tasks that handle credentials. Set to false to debug failed probes. Prefer a one-off CLI run (--tags ) over flipping the toggle on a job template; if you must, rotate the exposed credential (token or password) afterwards. - * **preflight_source_name**: + * **validate_environment_source_name**: * **Required**: False * **Type**: str * **Default**: none * **Description**: Inventory host whose variables feed the vCenter and VDDK checks. Defaults to the source_name extra var (injected by the seeded credentials) or the first vm_sources host. - * **preflight_target_name**: + * **validate_environment_target_name**: * **Required**: False * **Type**: str * **Default**: none * **Description**: Inventory host whose variables feed the OpenShift checks. Defaults to the target_name extra var (injected by the seeded credentials) or the first migration_clusters host. - * **preflight_vcenter_hostname**: + * **validate_environment_vcenter_hostname**: * **Required**: False * **Type**: str * **Default**: - * **Description**: vCenter endpoint for the connectivity check. Resolves from VMWARE_HOST env var or the host variable on the source host (preflight_source_name). The check applies to vmware sources; other source types skip it. When unset, the vCenter check fails with instructions. - * **preflight_vcenter_password**: + * **Description**: vCenter endpoint for the connectivity check. Resolves from VMWARE_HOST env var or the host variable on the source host (validate_environment_source_name). The check applies to vmware sources; other source types skip it. When unset, the vCenter check fails with instructions. + * **validate_environment_vcenter_password**: * **Required**: False * **Type**: str * **Default**: - * **Description**: vCenter password. Resolves from VMWARE_PASSWORD env var or the password variable on the source host (preflight_source_name). - * **preflight_vcenter_username**: + * **Description**: vCenter password. Resolves from VMWARE_PASSWORD env var or the password variable on the source host (validate_environment_source_name). + * **validate_environment_vcenter_username**: * **Required**: False * **Type**: str * **Default**: - * **Description**: vCenter username. Resolves from VMWARE_USER env var or the username variable on the source host (preflight_source_name). - * **preflight_vcenter_validate_certs**: + * **Description**: vCenter username. Resolves from VMWARE_USER env var or the username variable on the source host (validate_environment_source_name). + * **validate_environment_vcenter_validate_certs**: * **Required**: False * **Type**: bool * **Default**: True * **Description**: Validate the vCenter TLS certificate. - * **preflight_vddk_image**: + * **validate_environment_vddk_image**: * **Required**: False * **Type**: str * **Default**: @@ -169,68 +169,68 @@ Description: Validate the migration environment before seeding AAP — OpenShift | Var | Type | Value |Choices |Required | Title | |--------------|--------------|-------------|-------------|-------------|-------------| -| [`preflight_aap_api_path`](defaults/main.yml#L130) | str | `/api/controller/v2/` | None | False | AAP API Path | -| [`preflight_aap_hostname`](defaults/main.yml#L116) | str | `` | None | False | AAP Hostname | -| [`preflight_aap_name`](defaults/main.yml#L20) | str | `{{ groups['migration_aap'] ¦ default([], true) ¦ first ¦ default('', true) }}` | None | None | None | -| [`preflight_aap_password`](defaults/main.yml#L148) | str | `` | None | False | AAP Password | -| [`preflight_aap_token`](defaults/main.yml#L161) | str | `` | None | False | AAP Token | -| [`preflight_aap_username`](defaults/main.yml#L137) | str | `` | None | False | AAP Username | -| [`preflight_aap_validate_certs`](defaults/main.yml#L174) | str | `{{ (lookup('env', 'AAP_VALIDATE_CERTS') ¦ default(hostvars[preflight_aap_name]['aap_validate_certs'] ¦ default(true), true)) ¦ bool }}` | None | False | AAP Verify SSL | -| [`preflight_cnv_namespace`](defaults/main.yml#L183) | str | `` | None | False | CNV Namespace | -| [`preflight_mtv_namespace`](defaults/main.yml#L200) | str | `` | None | False | MTV Namespace | -| [`preflight_openshift_api_key`](defaults/main.yml#L46) | str | `` | None | True | OpenShift API Key | -| [`preflight_openshift_host`](defaults/main.yml#L33) | str | `` | None | True | OpenShift Host | -| [`preflight_openshift_verify_ssl`](defaults/main.yml#L63) | str | `{{ (lookup('env', 'K8S_AUTH_VERIFY_SSL') ¦ default(hostvars[preflight_target_name]['openshift_verify_ssl'] ¦ default(true), true)) ¦ bool }}` | None | False | OpenShift Verify SSL | -| [`preflight_secure_logging`](defaults/main.yml#L25) | str | `{{ secure_logging ¦ default(true) }}` | None | None | None | -| [`preflight_source_name`](defaults/main.yml#L17) | str | `{{ source_name ¦ default(groups['vm_sources'] ¦ default([], true) ¦ first ¦ default('', true), true) }}` | None | None | None | -| [`preflight_target_name`](defaults/main.yml#L14) | str | `{{ target_name ¦ default(groups['migration_clusters'] ¦ default([], true) ¦ first ¦ default('', true), true) }}` | None | None | None | -| [`preflight_vcenter_hostname`](defaults/main.yml#L72) | str | `` | None | False | vCenter Hostname | -| [`preflight_vcenter_password`](defaults/main.yml#L94) | str | `` | None | False | vCenter Password | -| [`preflight_vcenter_username`](defaults/main.yml#L83) | str | `` | None | False | vCenter Username | -| [`preflight_vcenter_validate_certs`](defaults/main.yml#L106) | str | `{{ (lookup('env', 'VMWARE_VALIDATE_CERTS') ¦ default(hostvars[preflight_source_name]['validate_certs'] ¦ default(true), true)) ¦ bool }}` | None | False | vCenter Verify SSL | -| [`preflight_vddk_image`](defaults/main.yml#L217) | str | `` | None | False | VDDK Init Image | +| [`validate_environment_aap_api_path`](defaults/main.yml#L130) | str | `/api/controller/v2/` | None | False | AAP API Path | +| [`validate_environment_aap_hostname`](defaults/main.yml#L116) | str | `` | None | False | AAP Hostname | +| [`validate_environment_aap_name`](defaults/main.yml#L20) | str | `{{ groups['migration_aap'] ¦ default([], true) ¦ first ¦ default('', true) }}` | None | None | None | +| [`validate_environment_aap_password`](defaults/main.yml#L148) | str | `` | None | False | AAP Password | +| [`validate_environment_aap_token`](defaults/main.yml#L161) | str | `` | None | False | AAP Token | +| [`validate_environment_aap_username`](defaults/main.yml#L137) | str | `` | None | False | AAP Username | +| [`validate_environment_aap_validate_certs`](defaults/main.yml#L174) | str | `{{ (lookup('env', 'AAP_VALIDATE_CERTS') ¦ default(hostvars[validate_environment_aap_name]['aap_validate_certs'] ¦ default(true), true)) ¦ bool }}` | None | False | AAP Verify SSL | +| [`validate_environment_cnv_namespace`](defaults/main.yml#L183) | str | `` | None | False | CNV Namespace | +| [`validate_environment_mtv_namespace`](defaults/main.yml#L200) | str | `` | None | False | MTV Namespace | +| [`validate_environment_openshift_api_key`](defaults/main.yml#L46) | str | `` | None | True | OpenShift API Key | +| [`validate_environment_openshift_host`](defaults/main.yml#L33) | str | `` | None | True | OpenShift Host | +| [`validate_environment_openshift_verify_ssl`](defaults/main.yml#L63) | str | `{{ (lookup('env', 'K8S_AUTH_VERIFY_SSL') ¦ default(hostvars[validate_environment_target_name]['openshift_verify_ssl'] ¦ default(true), true)) ¦ bool }}` | None | False | OpenShift Verify SSL | +| [`validate_environment_secure_logging`](defaults/main.yml#L25) | str | `{{ secure_logging ¦ default(true) }}` | None | None | None | +| [`validate_environment_source_name`](defaults/main.yml#L17) | str | `{{ source_name ¦ default(groups['vm_sources'] ¦ default([], true) ¦ first ¦ default('', true), true) }}` | None | None | None | +| [`validate_environment_target_name`](defaults/main.yml#L14) | str | `{{ target_name ¦ default(groups['migration_clusters'] ¦ default([], true) ¦ first ¦ default('', true), true) }}` | None | None | None | +| [`validate_environment_vcenter_hostname`](defaults/main.yml#L72) | str | `` | None | False | vCenter Hostname | +| [`validate_environment_vcenter_password`](defaults/main.yml#L94) | str | `` | None | False | vCenter Password | +| [`validate_environment_vcenter_username`](defaults/main.yml#L83) | str | `` | None | False | vCenter Username | +| [`validate_environment_vcenter_validate_certs`](defaults/main.yml#L106) | str | `{{ (lookup('env', 'VMWARE_VALIDATE_CERTS') ¦ default(hostvars[validate_environment_source_name]['validate_certs'] ¦ default(true), true)) ¦ bool }}` | None | False | vCenter Verify SSL | +| [`validate_environment_vddk_image`](defaults/main.yml#L217) | str | `` | None | False | VDDK Init Image | 🖇️ Full descriptions for vars in defaults/main.yml
-`preflight_aap_api_path`: >- +`validate_environment_aap_api_path`: >-
-`preflight_aap_hostname`: >- +`validate_environment_aap_hostname`: >-
-`preflight_aap_name`: None +`validate_environment_aap_name`: None
-`preflight_aap_password`: >- +`validate_environment_aap_password`: >-
-`preflight_aap_token`: >- +`validate_environment_aap_token`: >-
-`preflight_aap_username`: >- +`validate_environment_aap_username`: >-
-`preflight_aap_validate_certs`: >- +`validate_environment_aap_validate_certs`: >-
-`preflight_cnv_namespace`: >- +`validate_environment_cnv_namespace`: >-
-`preflight_mtv_namespace`: >- +`validate_environment_mtv_namespace`: >-
-`preflight_openshift_api_key`: >- +`validate_environment_openshift_api_key`: >-
-`preflight_openshift_host`: >- +`validate_environment_openshift_host`: >-
-`preflight_openshift_verify_ssl`: >- +`validate_environment_openshift_verify_ssl`: >-
-`preflight_secure_logging`: None +`validate_environment_secure_logging`: None
-`preflight_source_name`: None +`validate_environment_source_name`: None
-`preflight_target_name`: None +`validate_environment_target_name`: None
-`preflight_vcenter_hostname`: >- +`validate_environment_vcenter_hostname`: >-
-`preflight_vcenter_password`: >- +`validate_environment_vcenter_password`: >-
-`preflight_vcenter_username`: >- +`validate_environment_vcenter_username`: >-
-`preflight_vcenter_validate_certs`: >- +`validate_environment_vcenter_validate_certs`: >-
-`preflight_vddk_image`: >- +`validate_environment_vddk_image`: >-

@@ -242,8 +242,8 @@ Description: Validate the migration environment before seeding AAP — OpenShift | Var | Type | Value | |--------------|--------------|-------------| -| [__preflight_source_type](vars/main.yml#L4) | str | `{{ hostvars[preflight_source_name]['type'] ¦ default('', true) }}` | -| [__preflight_source_vddk](vars/main.yml#L8) | str | `{{ hostvars[preflight_source_name]['vddk'] ¦ default({}, true) }}` | +| [__validate_environment_source_type](vars/main.yml#L4) | str | `{{ hostvars[validate_environment_source_name]['type'] ¦ default('', true) }}` | +| [__validate_environment_source_vddk](vars/main.yml#L8) | str | `{{ hostvars[validate_environment_source_name]['vddk'] ¦ default({}, true) }}` | ### Tasks @@ -252,7 +252,7 @@ Description: Validate the migration environment before seeding AAP — OpenShift | Name | Module | Has Conditions | | ---- | ------ | --------- | | Include pre-validation of required connection variables | `ansible.builtin.include_tasks` | False | -| Run preflight checks | `block` | False | +| Run environment validation checks | `block` | False | | Include OpenShift API authentication check | `ansible.builtin.include_tasks` | False | | Include OpenShift Virtualization operator check | `ansible.builtin.include_tasks` | False | | Include MTV operator check | `ansible.builtin.include_tasks` | False | @@ -271,9 +271,9 @@ Description: Validate the migration environment before seeding AAP — OpenShift | Name | Module | Has Conditions | | ---- | ------ | --------- | -| report ¦ Build the preflight summary | `ansible.builtin.set_fact` | False | -| report ¦ Display the preflight summary | `ansible.builtin.debug` | False | -| report ¦ Assert every ran preflight check passed | `ansible.builtin.assert` | False | +| report ¦ Build the validate_environment summary | `ansible.builtin.set_fact` | False | +| report ¦ Display the validate_environment summary | `ansible.builtin.debug` | False | +| report ¦ Assert every ran validate_environment check passed | `ansible.builtin.assert` | False | | report ¦ Remind the operator to rotate credentials exposed in debug output | `ansible.builtin.debug` | True | #### File: tasks/validate_aap.yml @@ -338,14 +338,14 @@ classDef includeVars stroke:#8e44ad,stroke-width:2px; classDef rescue stroke:#665352,stroke-width:2px; Start-->|Include task| Include_pre_validation_of_required_connection_variables_pre_validate_yml_0[include pre validation of required connection
variables
include_task: pre validate yml]:::includeTasks - Include_pre_validation_of_required_connection_variables_pre_validate_yml_0-->|Block Start| Run_preflight_checks1_block_start_0[[run preflight checks]]:::block - Run_preflight_checks1_block_start_0-->|Include task| Include_OpenShift_API_authentication_check_validate_openshift_yml_0[include openshift api authentication check
include_task: validate openshift yml]:::includeTasks + Include_pre_validation_of_required_connection_variables_pre_validate_yml_0-->|Block Start| Run_environment_validation_checks1_block_start_0[[run environment validation checks]]:::block + Run_environment_validation_checks1_block_start_0-->|Include task| Include_OpenShift_API_authentication_check_validate_openshift_yml_0[include openshift api authentication check
include_task: validate openshift yml]:::includeTasks Include_OpenShift_API_authentication_check_validate_openshift_yml_0-->|Include task| Include_OpenShift_Virtualization_operator_check_validate_cnv_yml_1[include openshift virtualization operator check
include_task: validate cnv yml]:::includeTasks Include_OpenShift_Virtualization_operator_check_validate_cnv_yml_1-->|Include task| Include_MTV_operator_check_validate_mtv_yml_2[include mtv operator check
include_task: validate mtv yml]:::includeTasks Include_MTV_operator_check_validate_mtv_yml_2-->|Include task| Include_AAP_access_check_validate_aap_yml_3[include aap access check
include_task: validate aap yml]:::includeTasks Include_AAP_access_check_validate_aap_yml_3-->|Include task| Include_vCenter_connectivity_check_validate_vcenter_yml_4[include vcenter connectivity check
include_task: validate vcenter yml]:::includeTasks Include_vCenter_connectivity_check_validate_vcenter_yml_4-->|Include task| Include_VDDK_init_image_check_validate_vddk_yml_5[include vddk init image check
include_task: validate vddk yml]:::includeTasks - Include_VDDK_init_image_check_validate_vddk_yml_5-.->|End of Block| Run_preflight_checks1_block_start_0 + Include_VDDK_init_image_check_validate_vddk_yml_5-.->|End of Block| Run_environment_validation_checks1_block_start_0 Include_VDDK_init_image_check_validate_vddk_yml_5-->End ``` @@ -382,10 +382,10 @@ classDef importRole stroke:#699ba7,stroke-width:2px; classDef includeVars stroke:#8e44ad,stroke-width:2px; classDef rescue stroke:#665352,stroke-width:2px; - Start-->|Task| report___Build_the_preflight_summary0[report build the preflight summary]:::task - report___Build_the_preflight_summary0-->|Task| report___Display_the_preflight_summary1[report display the preflight summary]:::task - report___Display_the_preflight_summary1-->|Task| report___Assert_every_ran_preflight_check_passed2[report assert every ran preflight check passed]:::task - report___Assert_every_ran_preflight_check_passed2-->|Task| report___Remind_the_operator_to_rotate_credentials_exposed_in_debug_output3[report remind the operator to rotate credentials
exposed in debug output
When: **not preflight secure logging default true
bool**]:::task + Start-->|Task| report___Build_the_validate_environment_summary0[report build the validate environment summary]:::task + report___Build_the_validate_environment_summary0-->|Task| report___Display_the_validate_environment_summary1[report display the validate environment summary]:::task + report___Display_the_validate_environment_summary1-->|Task| report___Assert_every_ran_validate_environment_check_passed2[report assert every ran validate environment
check passed]:::task + report___Assert_every_ran_validate_environment_check_passed2-->|Task| report___Remind_the_operator_to_rotate_credentials_exposed_in_debug_output3[report remind the operator to rotate credentials
exposed in debug output
When: **not validate environment secure logging default
true bool**]:::task report___Remind_the_operator_to_rotate_credentials_exposed_in_debug_output3-->End ``` @@ -403,7 +403,7 @@ classDef importRole stroke:#699ba7,stroke-width:2px; classDef includeVars stroke:#8e44ad,stroke-width:2px; classDef rescue stroke:#665352,stroke-width:2px; - Start-->|Task| validate_aap___Probe_AAP_API_with_the_configured_account0[validate aap probe aap api with the configured
account
When: **preflight aap hostname length 0**]:::task + Start-->|Task| validate_aap___Probe_AAP_API_with_the_configured_account0[validate aap probe aap api with the configured
account
When: **validate environment aap hostname length 0**]:::task validate_aap___Probe_AAP_API_with_the_configured_account0-->|Task| validate_aap___Record_the_AAP_access_check_result1[validate aap record the aap access check result]:::task validate_aap___Record_the_AAP_access_check_result1-->End ``` @@ -481,8 +481,8 @@ classDef importRole stroke:#699ba7,stroke-width:2px; classDef includeVars stroke:#8e44ad,stroke-width:2px; classDef rescue stroke:#665352,stroke-width:2px; - Start-->|Task| validate_vcenter___List_vCenter_datacenters_via_the_REST_API__vCenter_7_0__0[validate vcenter list vcenter datacenters via
the rest api vcenter 7 0
When: **preflight vcenter hostname length 0 and
preflight source type length 0 or preflight
source type vmware**]:::task - validate_vcenter___List_vCenter_datacenters_via_the_REST_API__vCenter_7_0__0-->|Task| validate_vcenter___Fall_back_to_the_SOAP_SDK_for_vCenter_6_x__no_REST_API_1[validate vcenter fall back to the soap sdk for
vcenter 6 x no rest api
When: **preflight vcenter hostname length 0 and
preflight source type length 0 or preflight
source type vmware and preflight vcenter
rest value is not defined or preflight vcenter
rest value length 0**]:::task + Start-->|Task| validate_vcenter___List_vCenter_datacenters_via_the_REST_API__vCenter_7_0__0[validate vcenter list vcenter datacenters via
the rest api vcenter 7 0
When: **validate environment vcenter hostname length 0
and validate environment source type length
0 or validate environment source type vmware
**]:::task + validate_vcenter___List_vCenter_datacenters_via_the_REST_API__vCenter_7_0__0-->|Task| validate_vcenter___Fall_back_to_the_SOAP_SDK_for_vCenter_6_x__no_REST_API_1[validate vcenter fall back to the soap sdk for
vcenter 6 x no rest api
When: **validate environment vcenter hostname length 0
and validate environment source type length
0 or validate environment source type vmware
and validate environment vcenter rest value is
not defined or validate environment vcenter rest
value length 0**]:::task validate_vcenter___Fall_back_to_the_SOAP_SDK_for_vCenter_6_x__no_REST_API_1-->|Task| validate_vcenter___Merge_the_REST_and_SOAP_results_into_one_datacenter_list2[validate vcenter merge the rest and soap results
into one datacenter list]:::task validate_vcenter___Merge_the_REST_and_SOAP_results_into_one_datacenter_list2-->|Task| validate_vcenter___Record_the_vCenter_connectivity_check_result3[validate vcenter record the vcenter connectivity
check result]:::task validate_vcenter___Record_the_vCenter_connectivity_check_result3-->End diff --git a/roles/preflight/defaults/main.yml b/roles/validate_environment/defaults/main.yml similarity index 61% rename from roles/preflight/defaults/main.yml rename to roles/validate_environment/defaults/main.yml index 90ea9b3..7afc67f 100644 --- a/roles/preflight/defaults/main.yml +++ b/roles/validate_environment/defaults/main.yml @@ -1,5 +1,5 @@ --- -# Preflight role defaults. +# Environment validation role defaults. # # Connection variables cascade from AAP-injected environment variables to # inventory host variables resolved through the target, source, and AAP @@ -11,29 +11,29 @@ # Resolver options — the inventory hosts whose variables feed the checks. # target_name and source_name match the names the seeded credentials # inject as extra vars; each falls back to the first host of its group. -preflight_target_name: "{{ target_name +validate_environment_target_name: "{{ target_name | default(groups['migration_clusters'] | default([], true) | first | default('', true), true) }}" -preflight_source_name: "{{ source_name +validate_environment_source_name: "{{ source_name | default(groups['vm_sources'] | default([], true) | first | default('', true), true) }}" -preflight_aap_name: "{{ groups['migration_aap'] | default([], true) | first | default('', true) }}" +validate_environment_aap_name: "{{ groups['migration_aap'] | default([], true) | first | default('', true) }}" # Secure logging toggle for tasks that handle credentials. # NEVER hardcode no_log: true — always reference this variable so failures -# can be debugged with preflight_secure_logging=false. -preflight_secure_logging: "{{ secure_logging | default(true) }}" +# can be debugged with validate_environment_secure_logging=false. +validate_environment_secure_logging: "{{ secure_logging | default(true) }}" # title: OpenShift Host # required: True # description: >- # OpenShift API endpoint. Cascades from K8S_AUTH_HOST env var (injected # by the AAP target credential) or the openshift_host variable on the -# target cluster host (preflight_target_name). -preflight_openshift_host: >- +# target cluster host (validate_environment_target_name). +validate_environment_openshift_host: >- {{ lookup('env', 'K8S_AUTH_HOST') - | default(hostvars[preflight_target_name]['openshift_host'] | default('', true), true) + | default(hostvars[validate_environment_target_name]['openshift_host'] | default('', true), true) }} # title: OpenShift API Key @@ -41,14 +41,14 @@ preflight_openshift_host: >- # description: >- # OpenShift API token. Cascades from K8S_AUTH_API_KEY env var (injected # by the AAP target credential) or the openshift_api_key variable on the -# target cluster host (preflight_target_name), falling back to +# target cluster host (validate_environment_target_name), falling back to # openshift_temporary_api_key. -preflight_openshift_api_key: >- +validate_environment_openshift_api_key: >- {{ lookup('env', 'K8S_AUTH_API_KEY') | default( - hostvars[preflight_target_name]['openshift_api_key'] - | default(hostvars[preflight_target_name]['openshift_temporary_api_key'] | default('', true), true), + hostvars[validate_environment_target_name]['openshift_api_key'] + | default(hostvars[validate_environment_target_name]['openshift_temporary_api_key'] | default('', true), true), true ) }} @@ -60,41 +60,41 @@ preflight_openshift_api_key: >- # K8S_AUTH_VERIFY_SSL env var or the openshift_verify_ssl variable on # the target cluster host. Defaults to true; the bool cast keeps the # argument-spec type honest when a raw env string feeds the value. -preflight_openshift_verify_ssl: "{{ (lookup('env', 'K8S_AUTH_VERIFY_SSL') - | default(hostvars[preflight_target_name]['openshift_verify_ssl'] | default(true), true)) | bool }}" +validate_environment_openshift_verify_ssl: "{{ (lookup('env', 'K8S_AUTH_VERIFY_SSL') + | default(hostvars[validate_environment_target_name]['openshift_verify_ssl'] | default(true), true)) | bool }}" # title: vCenter Hostname # required: False # description: >- # vCenter endpoint for the connectivity check. Cascades from # VMWARE_HOST env var (injected by the AAP source credential) or the -# host variable on the source host (preflight_source_name). -preflight_vcenter_hostname: >- +# host variable on the source host (validate_environment_source_name). +validate_environment_vcenter_hostname: >- {{ lookup('env', 'VMWARE_HOST') - | default(hostvars[preflight_source_name]['host'] | default('', true), true) + | default(hostvars[validate_environment_source_name]['host'] | default('', true), true) }} # title: vCenter Username # required: False # description: >- # vCenter username. Cascades from VMWARE_USER env var or the username -# variable on the source host (preflight_source_name). -preflight_vcenter_username: >- +# variable on the source host (validate_environment_source_name). +validate_environment_vcenter_username: >- {{ lookup('env', 'VMWARE_USER') - | default(hostvars[preflight_source_name]['username'] | default('', true), true) + | default(hostvars[validate_environment_source_name]['username'] | default('', true), true) }} # title: vCenter Password # required: False # description: >- # vCenter password. Cascades from VMWARE_PASSWORD env var or the -# password variable on the source host (preflight_source_name). -preflight_vcenter_password: >- +# password variable on the source host (validate_environment_source_name). +validate_environment_vcenter_password: >- {{ lookup('env', 'VMWARE_PASSWORD') - | default(hostvars[preflight_source_name]['password'] | default('', true), true) + | default(hostvars[validate_environment_source_name]['password'] | default('', true), true) }} # title: vCenter Verify SSL @@ -103,8 +103,8 @@ preflight_vcenter_password: >- # Validate the vCenter TLS certificate. Cascades from # VMWARE_VALIDATE_CERTS env var or the validate_certs variable on the # source host. Defaults to true. -preflight_vcenter_validate_certs: "{{ (lookup('env', 'VMWARE_VALIDATE_CERTS') - | default(hostvars[preflight_source_name]['validate_certs'] | default(true), true)) | bool }}" +validate_environment_vcenter_validate_certs: "{{ (lookup('env', 'VMWARE_VALIDATE_CERTS') + | default(hostvars[validate_environment_source_name]['validate_certs'] | default(true), true)) | bool }}" # title: AAP Hostname # required: False @@ -112,12 +112,12 @@ preflight_vcenter_validate_certs: "{{ (lookup('env', 'VMWARE_VALIDATE_CERTS') # Ansible Automation Platform controller URL for the access check. # Cascades from AAP_HOSTNAME env var, the CONTROLLER_HOST env var # injected by the controller for its own jobs, or the aap_hostname -# variable on the AAP host (preflight_aap_name). -preflight_aap_hostname: >- +# variable on the AAP host (validate_environment_aap_name). +validate_environment_aap_hostname: >- {{ lookup('env', 'AAP_HOSTNAME') | default(lookup('env', 'CONTROLLER_HOST') - | default(hostvars[preflight_aap_name]['aap_hostname'] | default('', true), true), true) + | default(hostvars[validate_environment_aap_name]['aap_hostname'] | default('', true), true), true) }} # title: AAP API Path @@ -127,28 +127,28 @@ preflight_aap_hostname: >- # Defaults to /api/controller/v2/ (AAP 2.5 platform and AWX). AAP 2.4 # and earlier serve the API at /api/v2/ — set that value for those # environments. -preflight_aap_api_path: /api/controller/v2/ +validate_environment_aap_api_path: /api/controller/v2/ # title: AAP Username # required: False # description: >- # AAP username. Cascades from AAP_USERNAME env var or the aap_username -# variable on the AAP host (preflight_aap_name). -preflight_aap_username: >- +# variable on the AAP host (validate_environment_aap_name). +validate_environment_aap_username: >- {{ lookup('env', 'AAP_USERNAME') - | default(hostvars[preflight_aap_name]['aap_username'] | default('', true), true) + | default(hostvars[validate_environment_aap_name]['aap_username'] | default('', true), true) }} # title: AAP Password # required: False # description: >- # AAP password. Cascades from AAP_PASSWORD env var or the aap_password -# variable on the AAP host (preflight_aap_name). -preflight_aap_password: >- +# variable on the AAP host (validate_environment_aap_name). +validate_environment_aap_password: >- {{ lookup('env', 'AAP_PASSWORD') - | default(hostvars[preflight_aap_name]['aap_password'] | default('', true), true) + | default(hostvars[validate_environment_aap_name]['aap_password'] | default('', true), true) }} # title: AAP Token @@ -158,11 +158,11 @@ preflight_aap_password: >- # CONTROLLER_API_TOKEN env var injected by the controller for its own # jobs, or the aap_token variable on the AAP host. Takes precedence # over username/password. -preflight_aap_token: >- +validate_environment_aap_token: >- {{ lookup('env', 'AAP_TOKEN') | default(lookup('env', 'CONTROLLER_API_TOKEN') - | default(hostvars[preflight_aap_name]['aap_token'] | default('', true), true), true) + | default(hostvars[validate_environment_aap_name]['aap_token'] | default('', true), true), true) }} # title: AAP Verify SSL @@ -171,8 +171,8 @@ preflight_aap_token: >- # Validate the AAP TLS certificate. Cascades from AAP_VALIDATE_CERTS env # var or the aap_validate_certs variable on the AAP host. Defaults to # true. -preflight_aap_validate_certs: "{{ (lookup('env', 'AAP_VALIDATE_CERTS') - | default(hostvars[preflight_aap_name]['aap_validate_certs'] | default(true), true)) | bool }}" +validate_environment_aap_validate_certs: "{{ (lookup('env', 'AAP_VALIDATE_CERTS') + | default(hostvars[validate_environment_aap_name]['aap_validate_certs'] | default(true), true)) | bool }}" # title: CNV Namespace # required: False @@ -180,11 +180,11 @@ preflight_aap_validate_certs: "{{ (lookup('env', 'AAP_VALIDATE_CERTS') # Namespace holding the OpenShift Virtualization (CNV) operator CSV. # Resolves from the cnv_namespace variable or the target cluster # host's cnv_namespace, defaulting to openshift-cnv. -preflight_cnv_namespace: >- +validate_environment_cnv_namespace: >- {{ cnv_namespace | default( - hostvars[preflight_target_name]['cnv_namespace'] + hostvars[validate_environment_target_name]['cnv_namespace'] | default('openshift-cnv', true), true ) @@ -197,11 +197,11 @@ preflight_cnv_namespace: >- # CSV. Resolves from the mtv_namespace variable or the target cluster # host's mtv_namespace (inventory-sample sets it on the cluster host), # defaulting to openshift-mtv. -preflight_mtv_namespace: >- +validate_environment_mtv_namespace: >- {{ mtv_namespace | default( - hostvars[preflight_target_name]['mtv_namespace'] + hostvars[validate_environment_target_name]['mtv_namespace'] | default('openshift-mtv', true), true ) @@ -211,13 +211,13 @@ preflight_mtv_namespace: >- # required: False # description: >- # VDDK init image for direct-source migrations. Resolves from the -# source host's vddk.image dictionary entry (preflight_source_name) or +# source host's vddk.image dictionary entry (validate_environment_source_name) or # the vddk_image variable. The check enforces a scheme-less reference — # Forklift rejects scheme'd images with VDDKInitImageUnavailable. -preflight_vddk_image: >- +validate_environment_vddk_image: >- {{ - __preflight_source_vddk.get('image', vddk_image | default('', true)) - if __preflight_source_vddk is mapping + __validate_environment_source_vddk.get('image', vddk_image | default('', true)) + if __validate_environment_source_vddk is mapping else vddk_image | default('', true) }} ... diff --git a/roles/preflight/meta/argument_specs.yml b/roles/validate_environment/meta/argument_specs.yml similarity index 79% rename from roles/preflight/meta/argument_specs.yml rename to roles/validate_environment/meta/argument_specs.yml index f519815..6453ee8 100644 --- a/roles/preflight/meta/argument_specs.yml +++ b/roles/validate_environment/meta/argument_specs.yml @@ -5,7 +5,7 @@ argument_specs: Validate the migration environment before seeding AAP description: - >- - Runs every preflight check and reports a summary, then fails the + Runs every validate_environment check and reports a summary, then fails the play if any check failed. Checks: OpenShift API auth, CNV and MTV operator health, AAP access, vCenter connectivity, and VDDK init image configuration. @@ -19,7 +19,7 @@ argument_specs: that check with guidance rather than crashing the play, so one run reports everything that needs attention. options: - preflight_secure_logging: + validate_environment_secure_logging: type: bool required: false default: true @@ -30,7 +30,7 @@ argument_specs: job template; if you must, rotate the exposed credential (token or password) afterwards. - preflight_target_name: + validate_environment_target_name: type: str required: false description: >- @@ -38,7 +38,7 @@ argument_specs: Defaults to the target_name extra var (injected by the seeded credentials) or the first migration_clusters host. - preflight_source_name: + validate_environment_source_name: type: str required: false description: >- @@ -46,24 +46,24 @@ argument_specs: checks. Defaults to the source_name extra var (injected by the seeded credentials) or the first vm_sources host. - preflight_aap_name: + validate_environment_aap_name: type: str required: false description: >- Inventory host whose aap_* variables feed the AAP check. Defaults to the first migration_aap host. - preflight_openshift_host: + validate_environment_openshift_host: type: str required: false default: "" description: >- OpenShift API endpoint. Resolves from K8S_AUTH_HOST env var or the openshift_host variable on the target cluster host - (preflight_target_name). Required — the preflight aborts + (validate_environment_target_name). Required — the validate_environment aborts without it. - preflight_openshift_api_key: + validate_environment_openshift_api_key: type: str required: false default: "" @@ -71,52 +71,52 @@ argument_specs: description: >- OpenShift API token. Resolves from K8S_AUTH_API_KEY env var or the openshift_api_key variable on the target cluster host - (preflight_target_name). Required — the preflight aborts + (validate_environment_target_name). Required — the validate_environment aborts without it. - preflight_openshift_verify_ssl: + validate_environment_openshift_verify_ssl: type: bool required: false default: true description: >- Validate the OpenShift API TLS certificate. - preflight_vcenter_hostname: + validate_environment_vcenter_hostname: type: str required: false default: "" description: >- vCenter endpoint for the connectivity check. Resolves from VMWARE_HOST env var or the host variable on the source host - (preflight_source_name). The check applies to vmware sources; + (validate_environment_source_name). The check applies to vmware sources; other source types skip it. When unset, the vCenter check fails with instructions. - preflight_vcenter_username: + validate_environment_vcenter_username: type: str required: false default: "" description: >- vCenter username. Resolves from VMWARE_USER env var or the - username variable on the source host (preflight_source_name). + username variable on the source host (validate_environment_source_name). - preflight_vcenter_password: + validate_environment_vcenter_password: type: str required: false default: "" no_log: true description: >- vCenter password. Resolves from VMWARE_PASSWORD env var or the - password variable on the source host (preflight_source_name). + password variable on the source host (validate_environment_source_name). - preflight_vcenter_validate_certs: + validate_environment_vcenter_validate_certs: type: bool required: false default: true description: >- Validate the vCenter TLS certificate. - preflight_aap_hostname: + validate_environment_aap_hostname: type: str required: false default: "" @@ -124,10 +124,10 @@ argument_specs: AAP controller URL for the access check. Resolves from AAP_HOSTNAME env var, the CONTROLLER_HOST env var injected by the controller for its own jobs, or the aap_hostname variable - on the AAP host (preflight_aap_name). When unset, the AAP check + on the AAP host (validate_environment_aap_name). When unset, the AAP check fails with instructions. - preflight_aap_api_path: + validate_environment_aap_api_path: type: str required: false default: /api/v2/ @@ -136,14 +136,14 @@ argument_specs: and AAP 2.4 and earlier); AAP 2.5 platform deployments serve the controller API at /api/controller/v2/. - preflight_aap_username: + validate_environment_aap_username: type: str required: false default: "" description: >- AAP username for the access check. - preflight_aap_password: + validate_environment_aap_password: type: str required: false default: "" @@ -151,7 +151,7 @@ argument_specs: description: >- AAP password for the access check when no token is set. - preflight_aap_token: + validate_environment_aap_token: type: str required: false default: "" @@ -162,21 +162,21 @@ argument_specs: own jobs, or the aap_token variable on the AAP host. Takes precedence over username/password. - preflight_aap_validate_certs: + validate_environment_aap_validate_certs: type: bool required: false default: true description: >- Validate the AAP TLS certificate. - preflight_cnv_namespace: + validate_environment_cnv_namespace: type: str required: false default: openshift-cnv description: >- Namespace holding the OpenShift Virtualization operator CSV. - preflight_mtv_namespace: + validate_environment_mtv_namespace: type: str required: false default: openshift-mtv @@ -184,7 +184,7 @@ argument_specs: Namespace holding the MTV operator CSV. Resolves from the mtv_namespace inventory variable by default. - preflight_vddk_image: + validate_environment_vddk_image: type: str required: false default: "" diff --git a/roles/preflight/meta/main.yml b/roles/validate_environment/meta/main.yml similarity index 92% rename from roles/preflight/meta/main.yml rename to roles/validate_environment/meta/main.yml index 9b4cac3..292482d 100644 --- a/roles/preflight/meta/main.yml +++ b/roles/validate_environment/meta/main.yml @@ -1,6 +1,6 @@ --- galaxy_info: - role_name: preflight + role_name: validate_environment author: Red Hat description: >- Validate the migration environment before seeding AAP — OpenShift API diff --git a/roles/preflight/tasks/main.yml b/roles/validate_environment/tasks/main.yml similarity index 93% rename from roles/preflight/tasks/main.yml rename to roles/validate_environment/tasks/main.yml index 9454cf3..be1841b 100644 --- a/roles/preflight/tasks/main.yml +++ b/roles/validate_environment/tasks/main.yml @@ -1,5 +1,5 @@ --- -# Preflight validates the migration environment before seeding AAP. +# The environment validation pass runs before seeding AAP. # # All checks run on every invocation; the summary report (always-tagged) # fails the play if any ran check failed, so one run reports everything @@ -17,7 +17,7 @@ tags: - always -- name: Run preflight checks +- name: Run environment validation checks block: - name: Include OpenShift API authentication check ansible.builtin.include_tasks: @@ -86,7 +86,7 @@ - validate always: - - name: Include the preflight summary report + - name: Include the validate_environment summary report ansible.builtin.include_tasks: file: report.yml apply: diff --git a/roles/preflight/tasks/pre_validate.yml b/roles/validate_environment/tasks/pre_validate.yml similarity index 66% rename from roles/preflight/tasks/pre_validate.yml rename to roles/validate_environment/tasks/pre_validate.yml index 07be1be..36cd585 100644 --- a/roles/preflight/tasks/pre_validate.yml +++ b/roles/validate_environment/tasks/pre_validate.yml @@ -7,24 +7,24 @@ - name: pre_validate | Validate required OpenShift connection variables ansible.builtin.assert: that: - - preflight_openshift_host | length > 0 - - preflight_openshift_api_key | length > 0 + - validate_environment_openshift_host | length > 0 + - validate_environment_openshift_api_key | length > 0 fail_msg: >- OpenShift connection is required. Set openshift_host and openshift_api_key on the target cluster host in the inventory (or run from AAP where the target credential injects K8S_AUTH_HOST and K8S_AUTH_API_KEY). success_msg: >- - OpenShift connection configured: {{ preflight_openshift_host }} + OpenShift connection configured: {{ validate_environment_openshift_host }} quiet: true - name: pre_validate | Reject plaintext credential-bearing endpoints ansible.builtin.assert: that: - - (preflight_aap_hostname | trim | lower) is not match('^http://') - - (preflight_openshift_host | trim | lower) is not match('^http://') - - preflight_aap_hostname is not search('://[^/@]+:[^/@]+@') - - preflight_openshift_host is not search('://[^/@]+:[^/@]+@') + - (validate_environment_aap_hostname | trim | lower) is not match('^http://') + - (validate_environment_openshift_host | trim | lower) is not match('^http://') + - validate_environment_aap_hostname is not search('://[^/@]+:[^/@]+@') + - validate_environment_openshift_host is not search('://[^/@]+:[^/@]+@') fail_msg: >- Credential-bearing endpoints must use https and must not embed user:pass@ in the URL — bearer tokens sent to a plaintext endpoint diff --git a/roles/preflight/tasks/report.yml b/roles/validate_environment/tasks/report.yml similarity index 53% rename from roles/preflight/tasks/report.yml rename to roles/validate_environment/tasks/report.yml index f23388b..6b12f39 100644 --- a/roles/preflight/tasks/report.yml +++ b/roles/validate_environment/tasks/report.yml @@ -1,6 +1,6 @@ --- # Collect every check result and fail the play if any ran check failed. -# Check files register __preflight_result_* facts with ran: true; the +# Check files register __validate_environment_result_* facts with ran: true; the # summary assert only covers checks that ran, so an isolated --tags debug # run ends green when the targeted check passed. A check that never ran # (unexpected failure in a full run) still shows FAIL with "check did @@ -15,53 +15,59 @@ # (selectattr(..., 'falsy', true)) when filtering summary values by # key, as the fail_msg does. -- name: report | Build the preflight summary +- name: report | Build the validate_environment summary ansible.builtin.set_fact: - __preflight_summary: + __validate_environment_summary: OpenShift API auth: >- - {{ __preflight_result_openshift | default({'ran': false, 'passed': false, 'detail': 'check did not run'}) }} + {{ __validate_environment_result_openshift + | default({'ran': false, 'passed': false, 'detail': 'check did not run'}) }} OpenShift Virtualization operator: >- - {{ __preflight_result_cnv | default({'ran': false, 'passed': false, 'detail': 'check did not run'}) }} + {{ __validate_environment_result_cnv + | default({'ran': false, 'passed': false, 'detail': 'check did not run'}) }} MTV operator: >- - {{ __preflight_result_mtv | default({'ran': false, 'passed': false, 'detail': 'check did not run'}) }} + {{ __validate_environment_result_mtv + | default({'ran': false, 'passed': false, 'detail': 'check did not run'}) }} AAP access: >- - {{ __preflight_result_aap | default({'ran': false, 'passed': false, 'detail': 'check did not run'}) }} + {{ __validate_environment_result_aap + | default({'ran': false, 'passed': false, 'detail': 'check did not run'}) }} vCenter connectivity: >- - {{ __preflight_result_vcenter | default({'ran': false, 'passed': false, 'detail': 'check did not run'}) }} + {{ __validate_environment_result_vcenter + | default({'ran': false, 'passed': false, 'detail': 'check did not run'}) }} VDDK init image: >- - {{ __preflight_result_vddk | default({'ran': false, 'passed': false, 'detail': 'check did not run'}) }} + {{ __validate_environment_result_vddk + | default({'ran': false, 'passed': false, 'detail': 'check did not run'}) }} -- name: report | Display the preflight summary +- name: report | Display the validate_environment summary ansible.builtin.debug: msg: >- - {{ __preflight_check.value.passed | bool | ternary('PASS', 'FAIL') }} | - {{ __preflight_check.key }}: {{ __preflight_check.value.detail }} - loop: "{{ __preflight_summary | dict2items }}" + {{ __validate_environment_check.value.passed | bool | ternary('PASS', 'FAIL') }} | + {{ __validate_environment_check.key }}: {{ __validate_environment_check.value.detail }} + loop: "{{ __validate_environment_summary | dict2items }}" loop_control: - loop_var: __preflight_check - label: "{{ __preflight_check.key }}" + loop_var: __validate_environment_check + label: "{{ __validate_environment_check.key }}" -- name: report | Assert every ran preflight check passed +- name: report | Assert every ran validate_environment check passed ansible.builtin.assert: that: - >- - __preflight_summary | dict2items + __validate_environment_summary | dict2items | selectattr('value.ran', 'equalto', true) | map(attribute='value.passed') | map('bool') | select('equalto', false) | list | length == 0 fail_msg: >- - Preflight validation FAILED: - {{ __preflight_summary | dict2items + Environment validation FAILED: + {{ __validate_environment_summary | dict2items | selectattr('value.ran', 'equalto', true) | selectattr('value.passed', 'falsy', true) | map(attribute='key') | join(', ') }}. Fix each failed check before seeding — do not seed to paper over a missing operator. success_msg: >- - Preflight validation passed: all - {{ __preflight_summary | dict2items + Environment validation passed: all + {{ __validate_environment_summary | dict2items | selectattr('value.ran', 'equalto', true) | list | length }} checks green. The environment is ready to seed. quiet: true @@ -69,10 +75,10 @@ - name: report | Remind the operator to rotate credentials exposed in debug output ansible.builtin.debug: msg: >- - preflight_secure_logging is false — task parameters and API responses + validate_environment_secure_logging is false — task parameters and API responses were printed to job output. If this ran on a persistent AAP job template, rotate the exposed credentials now: the OpenShift API key (K8S_AUTH_API_KEY), the AAP token (AAP_TOKEN or CONTROLLER_API_TOKEN), and the vCenter password (VMWARE_PASSWORD). - when: not (preflight_secure_logging | default(true) | bool) + when: not (validate_environment_secure_logging | default(true) | bool) ... diff --git a/roles/validate_environment/tasks/validate_aap.yml b/roles/validate_environment/tasks/validate_aap.yml new file mode 100644 index 0000000..9dd9f9e --- /dev/null +++ b/roles/validate_environment/tasks/validate_aap.yml @@ -0,0 +1,45 @@ +--- +# Probe the AAP API with the configured account. +# ansible.builtin.uri is used instead of ansible.controller modules because +# the validate_environment runs before seeding and needs only a lightweight auth probe +# (the me/ endpoint returns the authenticated account); controller modules +# pull in full controller configuration context that does not exist yet. + +- name: validate_aap | Probe AAP API with the configured account + when: validate_environment_aap_hostname | length > 0 + ansible.builtin.uri: + url: "{{ validate_environment_aap_hostname }}{{ validate_environment_aap_api_path }}me/" + method: GET + validate_certs: "{{ validate_environment_aap_validate_certs }}" + headers: + Authorization: >- + {{ + ('Bearer ' ~ (validate_environment_aap_token | trim)) + if validate_environment_aap_token | length > 0 + else ('Basic ' ~ ((validate_environment_aap_username ~ ':' ~ validate_environment_aap_password) | b64encode)) + }} + status_code: [200, 401, 403] + register: __validate_environment_aap + failed_when: false + no_log: "{{ validate_environment_secure_logging }}" + +- name: validate_aap | Record the AAP access check result + ansible.builtin.set_fact: + __validate_environment_result_aap: + ran: true + passed: "{{ (validate_environment_aap_hostname | length > 0) + and ((__validate_environment_aap.status | default(0)) == 200) }}" + detail: >- + {% if validate_environment_aap_hostname | length == 0 %} + Not configured — set aap_hostname in the inventory (or AAP_HOSTNAME) + to enable the AAP access check + {% elif (__validate_environment_aap.status | default(0)) == 200 %} + HTTP 200 at {{ validate_environment_aap_hostname }} (authenticated as + {{ __validate_environment_aap.json.results[0].username | default('unknown', true) }}) + {% else %} + HTTP {{ __validate_environment_aap.status | default('connection error') }} at + {{ validate_environment_aap_hostname }} — 401/403 means the account or token is + wrong or expired; 404 means the API path is wrong — AAP 2.4 + and earlier deployments need validate_environment_aap_api_path=/api/v2/ + {% endif %} +... diff --git a/roles/validate_environment/tasks/validate_cnv.yml b/roles/validate_environment/tasks/validate_cnv.yml new file mode 100644 index 0000000..03580e7 --- /dev/null +++ b/roles/validate_environment/tasks/validate_cnv.yml @@ -0,0 +1,53 @@ +--- +# Query the ClusterServiceVersion list in the CNV namespace. +# kubernetes.core.k8s_info is certified content and the collection's +# established pattern for cluster queries. + +- name: validate_cnv | List ClusterServiceVersions in the CNV namespace + kubernetes.core.k8s_info: + host: "{{ validate_environment_openshift_host }}" + api_key: "{{ validate_environment_openshift_api_key }}" + validate_certs: "{{ validate_environment_openshift_verify_ssl }}" + api_version: operators.coreos.com/v1alpha1 + kind: ClusterServiceVersion + namespace: "{{ validate_environment_cnv_namespace }}" + register: __validate_environment_cnv_csvs + failed_when: false + no_log: "{{ validate_environment_secure_logging }}" + +- name: validate_cnv | Find the OpenShift Virtualization CSV + ansible.builtin.set_fact: + __validate_environment_cnv_found: >- + {{ __validate_environment_cnv_csvs.resources | default([]) + | selectattr('metadata.name', 'search', 'kubevirt-hyperconverged') + | list | length > 0 }} + __validate_environment_cnv_csv: >- + {{ __validate_environment_cnv_csvs.resources | default([]) + | selectattr('metadata.name', 'search', 'kubevirt-hyperconverged') + | list | first | default({}) }} + +- name: validate_cnv | Record the OpenShift Virtualization operator check result + ansible.builtin.set_fact: + __validate_environment_result_cnv: + ran: true + passed: "{{ __validate_environment_cnv_found + and (__validate_environment_cnv_csv.status.phase | default('')) == 'Succeeded' }}" + detail: >- + {% if __validate_environment_cnv_csvs.resources is not defined %} + Cluster API query failed in {{ validate_environment_cnv_namespace }} — + check the OpenShift connection and credentials first; the + operator check is inconclusive when the API is unreachable + {% elif not __validate_environment_cnv_found %} + No kubevirt-hyperconverged CSV found in + {{ validate_environment_cnv_namespace }} — install the OpenShift + Virtualization operator before seeding + {% elif (__validate_environment_cnv_csv.status.phase | default('')) != 'Succeeded' %} + CSV {{ __validate_environment_cnv_csv.metadata.name }} in + {{ validate_environment_cnv_namespace }} is + {{ __validate_environment_cnv_csv.status.phase | default('unknown') }} — + expected Succeeded + {% else %} + CSV {{ __validate_environment_cnv_csv.metadata.name }} Succeeded in + {{ validate_environment_cnv_namespace }} + {% endif %} +... diff --git a/roles/validate_environment/tasks/validate_mtv.yml b/roles/validate_environment/tasks/validate_mtv.yml new file mode 100644 index 0000000..9b7700d --- /dev/null +++ b/roles/validate_environment/tasks/validate_mtv.yml @@ -0,0 +1,53 @@ +--- +# Query the ClusterServiceVersion list in the MTV namespace. +# kubernetes.core.k8s_info is certified content and the collection's +# established pattern for cluster queries. + +- name: validate_mtv | List ClusterServiceVersions in the MTV namespace + kubernetes.core.k8s_info: + host: "{{ validate_environment_openshift_host }}" + api_key: "{{ validate_environment_openshift_api_key }}" + validate_certs: "{{ validate_environment_openshift_verify_ssl }}" + api_version: operators.coreos.com/v1alpha1 + kind: ClusterServiceVersion + namespace: "{{ validate_environment_mtv_namespace }}" + register: __validate_environment_mtv_csvs + failed_when: false + no_log: "{{ validate_environment_secure_logging }}" + +- name: validate_mtv | Find the MTV CSV + ansible.builtin.set_fact: + __validate_environment_mtv_found: >- + {{ __validate_environment_mtv_csvs.resources | default([]) + | selectattr('metadata.name', 'search', 'mtv-operator') + | list | length > 0 }} + __validate_environment_mtv_csv: >- + {{ __validate_environment_mtv_csvs.resources | default([]) + | selectattr('metadata.name', 'search', 'mtv-operator') + | list | first | default({}) }} + +- name: validate_mtv | Record the MTV operator check result + ansible.builtin.set_fact: + __validate_environment_result_mtv: + ran: true + passed: "{{ __validate_environment_mtv_found + and (__validate_environment_mtv_csv.status.phase | default('')) == 'Succeeded' }}" + detail: >- + {% if __validate_environment_mtv_csvs.resources is not defined %} + Cluster API query failed in {{ validate_environment_mtv_namespace }} — + check the OpenShift connection and credentials first; the + operator check is inconclusive when the API is unreachable + {% elif not __validate_environment_mtv_found %} + No mtv-operator CSV found in {{ validate_environment_mtv_namespace }} — + install the Migration Toolkit for Virtualization operator before + seeding + {% elif (__validate_environment_mtv_csv.status.phase | default('')) != 'Succeeded' %} + CSV {{ __validate_environment_mtv_csv.metadata.name }} in + {{ validate_environment_mtv_namespace }} is + {{ __validate_environment_mtv_csv.status.phase | default('unknown') }} — + expected Succeeded + {% else %} + CSV {{ __validate_environment_mtv_csv.metadata.name }} Succeeded in + {{ validate_environment_mtv_namespace }} + {% endif %} +... diff --git a/roles/validate_environment/tasks/validate_openshift.yml b/roles/validate_environment/tasks/validate_openshift.yml new file mode 100644 index 0000000..d61501c --- /dev/null +++ b/roles/validate_environment/tasks/validate_openshift.yml @@ -0,0 +1,38 @@ +--- +# Probe the OpenShift API with the configured credential. +# ansible.builtin.uri is used instead of the k8s modules because the HTTP +# status code cleanly distinguishes 401/403 (credential rejected) from +# 200/201 (authenticated). + +- name: validate_openshift | Probe OpenShift API SelfSubjectReview with the configured credential + ansible.builtin.uri: + url: "{{ validate_environment_openshift_host }}/apis/authentication.k8s.io/v1/selfsubjectreviews" + method: POST + body: '{"apiVersion":"authentication.k8s.io/v1","kind":"SelfSubjectReview"}' + body_format: json + validate_certs: "{{ validate_environment_openshift_verify_ssl }}" + headers: + Authorization: "{{ 'Bearer ' ~ (validate_environment_openshift_api_key | trim) }}" + status_code: [200, 201, 401, 403] + register: __validate_environment_ocp + # No module state is created — the review object is informational only, + # so this probe must never report changed. + changed_when: false + failed_when: false + no_log: "{{ validate_environment_secure_logging }}" + +- name: validate_openshift | Record the OpenShift authentication check result + ansible.builtin.set_fact: + __validate_environment_result_openshift: + ran: true + passed: "{{ (__validate_environment_ocp.status | default(0)) in [200, 201] }}" + detail: >- + {% if (__validate_environment_ocp.status | default(0)) in [200, 201] %} + HTTP {{ __validate_environment_ocp.status }} at {{ validate_environment_openshift_host }} + (identity: {{ __validate_environment_ocp.json.status.userInfo.username | default('unknown', true) }}) + {% else %} + HTTP {{ __validate_environment_ocp.status | default('connection error') }} at + {{ validate_environment_openshift_host }} — 401/403 means the token or + credential is missing, expired, or rejected + {% endif %} +... diff --git a/roles/validate_environment/tasks/validate_vcenter.yml b/roles/validate_environment/tasks/validate_vcenter.yml new file mode 100644 index 0000000..b8dff8f --- /dev/null +++ b/roles/validate_environment/tasks/validate_vcenter.yml @@ -0,0 +1,99 @@ +--- +# Probe vCenter connectivity and authentication. +# Two paths: the certified vmware.vmware_rest REST collection (vCenter 7.0+) +# first, then a community.vmware SOAP (pyVmomi) fallback that also covers 6.x +# — older vCenters do not serve the /api/ REST tree at all, and proxies in +# front of them commonly map only /sdk and /rest. Listing datacenters is the +# lightest operation that proves both connectivity and authentication against +# the configured source. The check only applies to vmware sources — other +# source types (ovirt) skip it. +# +# Module tier justification (community content): the certified +# vmware.vmware_rest collection requires vCenter 7.0+ and cannot reach 6.x at +# all (no /api/ tree), and the certified successor vmware.vmware collection +# does not yet ship a datacenter_info module. community.vmware +# .vmware_datacenter_info (pyVmomi, vCenter 6.5+) is the only content that +# covers the 6.x path, so the SOAP fallback runs only when the REST probe +# cannot return data. + +- name: validate_vcenter | List vCenter datacenters via the REST API (vCenter 7.0+) + when: + - validate_environment_vcenter_hostname | length > 0 + - __validate_environment_source_type | length == 0 or __validate_environment_source_type == 'vmware' + vmware.vmware_rest.vcenter_datacenter_info: + vcenter_hostname: "{{ validate_environment_vcenter_hostname }}" + vcenter_username: "{{ validate_environment_vcenter_username }}" + vcenter_password: "{{ validate_environment_vcenter_password }}" + vcenter_validate_certs: "{{ validate_environment_vcenter_validate_certs }}" + register: __validate_environment_vcenter_rest + failed_when: false + # A module crash (e.g. aiohttp ContentTypeError when the endpoint answers + # with a non-JSON body) bypasses failed_when and would abort the run; the + # fallback and record tasks below turn the fault into a graceful check + # result. + ignore_errors: true + no_log: "{{ validate_environment_secure_logging }}" + +- name: validate_vcenter | Fall back to the SOAP SDK for vCenter 6.x (no REST API) + when: + - validate_environment_vcenter_hostname | length > 0 + - __validate_environment_source_type | length == 0 or __validate_environment_source_type == 'vmware' + - __validate_environment_vcenter_rest.value is not defined + or __validate_environment_vcenter_rest.value | length == 0 + community.vmware.vmware_datacenter_info: + hostname: "{{ validate_environment_vcenter_hostname }}" + username: "{{ validate_environment_vcenter_username }}" + password: "{{ validate_environment_vcenter_password }}" + validate_certs: "{{ validate_environment_vcenter_validate_certs }}" + register: __validate_environment_vcenter_soap + failed_when: false + ignore_errors: true + no_log: "{{ validate_environment_secure_logging }}" + +- name: validate_vcenter | Merge the REST and SOAP results into one datacenter list + # Prefers a result with datacenters (the SOAP fallback can find data the + # proxied REST path misses); falls back to an empty result from either + # path (connected but none visible), then the empty-string sentinel when + # neither path returned data — the record task distinguishes a real list + # from '' by type. + ansible.builtin.set_fact: + __validate_environment_vcenter_dcs: "{{ ([(__validate_environment_vcenter_rest.value | default(none)), + (__validate_environment_vcenter_soap.datacenter_info | default(none))] + | reject('none') | select('truthy') | first) + | default([(__validate_environment_vcenter_rest.value | default(none)), + (__validate_environment_vcenter_soap.datacenter_info | default(none))] + | reject('none') | first | default(none), true) }}" + +- name: validate_vcenter | Record the vCenter connectivity check result + ansible.builtin.set_fact: + __validate_environment_result_vcenter: + ran: true + passed: "{{ (__validate_environment_source_type | length > 0 and __validate_environment_source_type != 'vmware') + or ((validate_environment_vcenter_hostname | length > 0) + and (__validate_environment_vcenter_dcs is not string) + and (__validate_environment_vcenter_dcs | length) > 0) }}" + detail: >- + {% if __validate_environment_source_type | length > 0 and __validate_environment_source_type != 'vmware' %} + Skipped — source type is {{ __validate_environment_source_type }}, not vmware; + the vCenter check does not apply + {% elif validate_environment_vcenter_hostname | length == 0 %} + Not configured — set host/username/password on the source host + (or run from AAP where the source credential injects VMWARE_*) to + enable the vCenter check + {% elif __validate_environment_vcenter_dcs is not string and __validate_environment_vcenter_dcs | length > 0 %} + HTTP session established at {{ validate_environment_vcenter_hostname }} + ({{ __validate_environment_vcenter_dcs | length }} datacenters visible via + {{ 'REST' if __validate_environment_vcenter_rest.value is defined + and __validate_environment_vcenter_rest.value | length > 0 + else 'the SOAP SDK' }}) + {% elif __validate_environment_vcenter_dcs is not string %} + Connected to {{ validate_environment_vcenter_hostname }} but no datacenters + are visible — a migration source needs at least one + {% else %} + vCenter authentication or connectivity failed at + {{ validate_environment_vcenter_hostname }} — re-run the vCenter check alone + (--tags vcenter) as a one-off CLI run with + validate_environment_secure_logging=false to see the fault, then rotate the + exposed credential + {% endif %} +... diff --git a/roles/preflight/tasks/validate_vddk.yml b/roles/validate_environment/tasks/validate_vddk.yml similarity index 51% rename from roles/preflight/tasks/validate_vddk.yml rename to roles/validate_environment/tasks/validate_vddk.yml index b02cadf..a9ca352 100644 --- a/roles/preflight/tasks/validate_vddk.yml +++ b/roles/validate_environment/tasks/validate_vddk.yml @@ -9,23 +9,23 @@ - name: validate_vddk | Record the VDDK init image check result ansible.builtin.set_fact: - __preflight_result_vddk: + __validate_environment_result_vddk: ran: true - passed: "{{ (__preflight_source_type | length > 0 and __preflight_source_type != 'vmware') - or (preflight_vddk_image | length > 0 - and not (preflight_vddk_image is match('^[A-Za-z][A-Za-z0-9+.-]*://'))) }}" + passed: "{{ (__validate_environment_source_type | length > 0 and __validate_environment_source_type != 'vmware') + or (validate_environment_vddk_image | length > 0 + and not (validate_environment_vddk_image is match('^[A-Za-z][A-Za-z0-9+.-]*://'))) }}" detail: >- - {% if __preflight_source_type | length > 0 and __preflight_source_type != 'vmware' %} - Skipped — source type is {{ __preflight_source_type }}, not vmware; + {% if __validate_environment_source_type | length > 0 and __validate_environment_source_type != 'vmware' %} + Skipped — source type is {{ __validate_environment_source_type }}, not vmware; the VDDK check does not apply - {% elif preflight_vddk_image | length == 0 %} + {% elif validate_environment_vddk_image | length == 0 %} No VDDK init image configured — set vddk.image on the source host (required for direct-source migrations with VDDK) - {% elif preflight_vddk_image is match('^[A-Za-z][A-Za-z0-9+.-]*://') %} - VDDK init image {{ preflight_vddk_image }} includes a scheme — + {% elif validate_environment_vddk_image is match('^[A-Za-z][A-Za-z0-9+.-]*://') %} + VDDK init image {{ validate_environment_vddk_image }} includes a scheme — Forklift rejects scheme'd references (VDDKInitImageUnavailable); remove the scheme prefix {% else %} - VDDK init image configured: {{ preflight_vddk_image }} + VDDK init image configured: {{ validate_environment_vddk_image }} {% endif %} ... diff --git a/roles/preflight/vars/main.yml b/roles/validate_environment/vars/main.yml similarity index 52% rename from roles/preflight/vars/main.yml rename to roles/validate_environment/vars/main.yml index e8a58ff..8d50508 100644 --- a/roles/preflight/vars/main.yml +++ b/roles/validate_environment/vars/main.yml @@ -1,9 +1,9 @@ --- # Internal derived values — not user-facing. Users set the source host's # type in the inventory; this resolves it for the vCenter and VDDK gates. -__preflight_source_type: "{{ hostvars[preflight_source_name]['type'] | default('', true) }}" +__validate_environment_source_type: "{{ hostvars[validate_environment_source_name]['type'] | default('', true) }}" # Internal: the source host's vddk dictionary (empty when the host or the # vddk entry is absent). -__preflight_source_vddk: "{{ hostvars[preflight_source_name]['vddk'] | default({}, true) }}" +__validate_environment_source_vddk: "{{ hostvars[validate_environment_source_name]['vddk'] | default({}, true) }}" ... diff --git a/tests/integration/targets/preflight_report/tasks/main.yml b/tests/integration/targets/preflight_report/tasks/main.yml deleted file mode 100644 index 9d5275d..0000000 --- a/tests/integration/targets/preflight_report/tasks/main.yml +++ /dev/null @@ -1,103 +0,0 @@ ---- -# Regression test for the preflight report aggregation. -# Runs the report tasks against pre-populated check facts — no real -# endpoints — covering the three summary paths: an isolated tagged run, -# an all-passed full run with mixed boolean forms, and a failed full run -# whose assert names the failed checks. - -- name: Main | Isolated run — two checks ran, the assert covers those only - vars: - __preflight_result_openshift: {ran: true, passed: true, detail: 'isolated pass'} - __preflight_result_aap: {ran: true, passed: 'True', detail: 'isolated pass (string form)'} - ansible.builtin.include_role: - name: infra.openshift_virtualization_migration.preflight - tasks_from: report.yml - -- name: Main | Full run — all checks ran and passed in mixed boolean forms - vars: - __preflight_result_openshift: {ran: true, passed: true, detail: 'bool true'} - __preflight_result_cnv: {ran: true, passed: 'True', detail: 'string true'} - __preflight_result_mtv: {ran: true, passed: true, detail: 'bool true'} - __preflight_result_aap: {ran: true, passed: 'True', detail: 'string true'} - __preflight_result_vcenter: {ran: true, passed: true, detail: 'bool true'} - __preflight_result_vddk: {ran: true, passed: 'True', detail: 'string true'} - ansible.builtin.include_role: - name: infra.openshift_virtualization_migration.preflight - tasks_from: report.yml - -- name: Main | Full run — ran checks failed, the assert names them - block: - - name: Main | Run the report with a failed check - vars: - __preflight_result_openshift: {ran: true, passed: true, detail: 'pass'} - __preflight_result_cnv: {ran: true, passed: false, detail: 'failed'} - __preflight_result_mtv: {ran: true, passed: 'False', detail: 'string false form'} - __preflight_result_aap: {ran: true, passed: 'True', detail: 'pass'} - __preflight_result_vcenter: {ran: true, passed: true, detail: 'pass'} - __preflight_result_vddk: {ran: true, passed: 'True', detail: 'pass'} - ansible.builtin.include_role: - name: infra.openshift_virtualization_migration.preflight - tasks_from: report.yml - rescue: - - name: Main | Mark the expected failure observed - ansible.builtin.set_fact: - __preflight_report_failure_observed: true - - - name: Main | Assert the summary marks both failed checks - ansible.builtin.assert: - that: - - not (__preflight_summary['OpenShift Virtualization operator'].passed | bool) - - not (__preflight_summary['MTV operator'].passed | bool) - quiet: true - -- name: Main | Assert the expected failure was observed - ansible.builtin.assert: - that: __preflight_report_failure_observed | default(false) | bool - quiet: true - -- name: Main | pre_validate accepts a clean https endpoint - vars: - preflight_openshift_host: https://api.cluster.example.com - preflight_openshift_api_key: test-token - preflight_aap_hostname: https://aap.example.com - ansible.builtin.include_role: - name: infra.openshift_virtualization_migration.preflight - tasks_from: pre_validate.yml - -- name: Main | pre_validate rejects a user:pass@ endpoint - block: - - name: Main | Run pre_validate with embedded credentials - vars: - preflight_openshift_host: https://svc-user:svc-pass@cluster.example.com - preflight_openshift_api_key: test-token - preflight_aap_hostname: https://aap.example.com - ansible.builtin.include_role: - name: infra.openshift_virtualization_migration.preflight - tasks_from: pre_validate.yml - rescue: - - name: Main | Mark the expected userinfo rejection observed - ansible.builtin.set_fact: - __preflight_userinfo_rejection_observed: true - -- name: Main | pre_validate rejects a case-variant plaintext endpoint - block: - - name: Main | Run pre_validate with an uppercase scheme - vars: - preflight_openshift_host: HTTP://api.cluster.example.com - preflight_openshift_api_key: test-token - preflight_aap_hostname: https://aap.example.com - ansible.builtin.include_role: - name: infra.openshift_virtualization_migration.preflight - tasks_from: pre_validate.yml - rescue: - - name: Main | Mark the expected plaintext rejection observed - ansible.builtin.set_fact: - __preflight_plaintext_rejection_observed: true - -- name: Main | Assert both endpoint rejections fired - ansible.builtin.assert: - that: - - __preflight_userinfo_rejection_observed | default(false) | bool - - __preflight_plaintext_rejection_observed | default(false) | bool - quiet: true -... diff --git a/tests/integration/targets/validate_environment_report/tasks/main.yml b/tests/integration/targets/validate_environment_report/tasks/main.yml new file mode 100644 index 0000000..b178206 --- /dev/null +++ b/tests/integration/targets/validate_environment_report/tasks/main.yml @@ -0,0 +1,103 @@ +--- +# Regression test for the validate_environment report aggregation. +# Runs the report tasks against pre-populated check facts — no real +# endpoints — covering the three summary paths: an isolated tagged run, +# an all-passed full run with mixed boolean forms, and a failed full run +# whose assert names the failed checks. + +- name: Main | Isolated run — two checks ran, the assert covers those only + vars: + __validate_environment_result_openshift: {ran: true, passed: true, detail: 'isolated pass'} + __validate_environment_result_aap: {ran: true, passed: 'True', detail: 'isolated pass (string form)'} + ansible.builtin.include_role: + name: infra.openshift_virtualization_migration.validate_environment + tasks_from: report.yml + +- name: Main | Full run — all checks ran and passed in mixed boolean forms + vars: + __validate_environment_result_openshift: {ran: true, passed: true, detail: 'bool true'} + __validate_environment_result_cnv: {ran: true, passed: 'True', detail: 'string true'} + __validate_environment_result_mtv: {ran: true, passed: true, detail: 'bool true'} + __validate_environment_result_aap: {ran: true, passed: 'True', detail: 'string true'} + __validate_environment_result_vcenter: {ran: true, passed: true, detail: 'bool true'} + __validate_environment_result_vddk: {ran: true, passed: 'True', detail: 'string true'} + ansible.builtin.include_role: + name: infra.openshift_virtualization_migration.validate_environment + tasks_from: report.yml + +- name: Main | Full run — ran checks failed, the assert names them + block: + - name: Main | Run the report with a failed check + vars: + __validate_environment_result_openshift: {ran: true, passed: true, detail: 'pass'} + __validate_environment_result_cnv: {ran: true, passed: false, detail: 'failed'} + __validate_environment_result_mtv: {ran: true, passed: 'False', detail: 'string false form'} + __validate_environment_result_aap: {ran: true, passed: 'True', detail: 'pass'} + __validate_environment_result_vcenter: {ran: true, passed: true, detail: 'pass'} + __validate_environment_result_vddk: {ran: true, passed: 'True', detail: 'pass'} + ansible.builtin.include_role: + name: infra.openshift_virtualization_migration.validate_environment + tasks_from: report.yml + rescue: + - name: Main | Mark the expected failure observed + ansible.builtin.set_fact: + __validate_environment_report_failure_observed: true + + - name: Main | Assert the summary marks both failed checks + ansible.builtin.assert: + that: + - not (__validate_environment_summary['OpenShift Virtualization operator'].passed | bool) + - not (__validate_environment_summary['MTV operator'].passed | bool) + quiet: true + +- name: Main | Assert the expected failure was observed + ansible.builtin.assert: + that: __validate_environment_report_failure_observed | default(false) | bool + quiet: true + +- name: Main | pre_validate accepts a clean https endpoint + vars: + validate_environment_openshift_host: https://api.cluster.example.com + validate_environment_openshift_api_key: test-token + validate_environment_aap_hostname: https://aap.example.com + ansible.builtin.include_role: + name: infra.openshift_virtualization_migration.validate_environment + tasks_from: pre_validate.yml + +- name: Main | pre_validate rejects a user:pass@ endpoint + block: + - name: Main | Run pre_validate with embedded credentials + vars: + validate_environment_openshift_host: https://svc-user:svc-pass@cluster.example.com + validate_environment_openshift_api_key: test-token + validate_environment_aap_hostname: https://aap.example.com + ansible.builtin.include_role: + name: infra.openshift_virtualization_migration.validate_environment + tasks_from: pre_validate.yml + rescue: + - name: Main | Mark the expected userinfo rejection observed + ansible.builtin.set_fact: + __validate_environment_userinfo_rejection_observed: true + +- name: Main | pre_validate rejects a case-variant plaintext endpoint + block: + - name: Main | Run pre_validate with an uppercase scheme + vars: + validate_environment_openshift_host: HTTP://api.cluster.example.com + validate_environment_openshift_api_key: test-token + validate_environment_aap_hostname: https://aap.example.com + ansible.builtin.include_role: + name: infra.openshift_virtualization_migration.validate_environment + tasks_from: pre_validate.yml + rescue: + - name: Main | Mark the expected plaintext rejection observed + ansible.builtin.set_fact: + __validate_environment_plaintext_rejection_observed: true + +- name: Main | Assert both endpoint rejections fired + ansible.builtin.assert: + that: + - __validate_environment_userinfo_rejection_observed | default(false) | bool + - __validate_environment_plaintext_rejection_observed | default(false) | bool + quiet: true +... From 9f7d6685927165c3f93d0622d0edbcc93a331b96 Mon Sep 17 00:00:00 2001 From: Vinny Valdez Date: Fri, 23 Oct 2026 19:35:08 -0500 Subject: [PATCH 2/8] fix(validate): match the codebase's tag conventions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the task-level tags (always/openshift/validate/cnv/mtv/aap/ vcenter/vddk) from validate_environment — no other role in the collection uses task tags, and all checks already run on every invocation regardless. Add the empty galaxy_tags key to meta/main.yml to match the existing roles' metadata shape. Assisted-by: opencode:enmaas/rits/zai-org/glm-5-3 --- roles/validate_environment/meta/main.yml | 1 + roles/validate_environment/tasks/main.yml | 62 ++--------------------- 2 files changed, 5 insertions(+), 58 deletions(-) diff --git a/roles/validate_environment/meta/main.yml b/roles/validate_environment/meta/main.yml index 292482d..735ec21 100644 --- a/roles/validate_environment/meta/main.yml +++ b/roles/validate_environment/meta/main.yml @@ -13,6 +13,7 @@ galaxy_info: - name: EL versions: - all + galaxy_tags: [] dependencies: [] ... diff --git a/roles/validate_environment/tasks/main.yml b/roles/validate_environment/tasks/main.yml index be1841b..60d4e62 100644 --- a/roles/validate_environment/tasks/main.yml +++ b/roles/validate_environment/tasks/main.yml @@ -1,97 +1,43 @@ --- # The environment validation pass runs before seeding AAP. # -# All checks run on every invocation; the summary report (always-tagged) -# fails the play if any ran check failed, so one run reports everything -# that needs attention. The summary asserts only over the checks that -# ran, so an isolated --tags debug run ends green when the targeted -# check passed. Checks whose target is not configured fail that check -# with a message describing what to set — they do not crash the play. +# All checks run on every invocation; the summary report fails the play +# if any ran check failed, so one run reports everything that needs +# attention. Checks whose target is not configured fail that check with +# a message describing what to set — they do not crash the play. - name: Include pre-validation of required connection variables ansible.builtin.include_tasks: file: pre_validate.yml - apply: - tags: - - always - tags: - - always - name: Run environment validation checks block: - name: Include OpenShift API authentication check ansible.builtin.include_tasks: file: validate_openshift.yml - apply: - tags: - - openshift - - validate - tags: - - openshift - - validate - name: Include OpenShift Virtualization operator check ansible.builtin.include_tasks: file: validate_cnv.yml - apply: - tags: - - cnv - - validate - tags: - - cnv - - validate - name: Include MTV operator check ansible.builtin.include_tasks: file: validate_mtv.yml - apply: - tags: - - mtv - - validate - tags: - - mtv - - validate - name: Include AAP access check ansible.builtin.include_tasks: file: validate_aap.yml - apply: - tags: - - aap - - validate - tags: - - aap - - validate - name: Include vCenter connectivity check ansible.builtin.include_tasks: file: validate_vcenter.yml - apply: - tags: - - vcenter - - validate - tags: - - vcenter - - validate - name: Include VDDK init image check ansible.builtin.include_tasks: file: validate_vddk.yml - apply: - tags: - - vddk - - validate - tags: - - vddk - - validate always: - name: Include the validate_environment summary report ansible.builtin.include_tasks: file: report.yml - apply: - tags: - - always - tags: - - always ... From d6c18d80ed5b33cc6f76bdc648dd8a0d98f2347a Mon Sep 17 00:00:00 2001 From: Vinny Valdez Date: Mon, 26 Oct 2026 08:53:26 -0500 Subject: [PATCH 3/8] docs(validate): drop removed-tag instructions and pre-flight prose MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tag-convention commit removed the task-level tags, but the role's docs still advertised per-check tags and --tags debug runs — update the README, argument_specs, and task comments to describe the one-off CLI run (-e validate_environment_secure_logging=false) instead. Rename the remaining "pre-flight" prose in docs/architecture-v2.md to the "Environment validation" glossary term. Assisted-by: opencode:enmaas/rits/zai-org/glm-5-3 --- docs/architecture-v2.md | 18 +++++++++--------- roles/validate_environment/README.md | 4 ++-- .../meta/argument_specs.yml | 6 +++--- roles/validate_environment/tasks/report.yml | 3 +-- .../tasks/validate_vcenter.yml | 2 +- 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/docs/architecture-v2.md b/docs/architecture-v2.md index 13eee2f..a37cd1d 100644 --- a/docs/architecture-v2.md +++ b/docs/architecture-v2.md @@ -22,9 +22,9 @@ | `aap_cleanup` | **REWRITTEN** | AAP 2.5+ only, simplified dispatch | | `aap_machine_credentials` | **DEFERRED** to Phase 3 | Day 2 scope | | `mtv_management` | **REWRITTEN** | Error handling, provider lifecycle, `provider` var fix | -| `mtv_migrate` | **REWRITTEN** | `failure_strategy`, pre-flight, scheduling, cold migration | +| `mtv_migrate` | **REWRITTEN** | `failure_strategy`, environment validation, scheduling, cold migration | | `network_mgmt` | **REWRITTEN** | Bug fixes (typo), error handling, OVN/UDN prep | -| `validate_migration` | **ENHANCED** | Structured output, pre-flight integration | +| `validate_migration` | **ENHANCED** | Structured output, environment validation integration | | `cluster_healthcheck` | **ENHANCED** | Additional checks for v2 readiness | | `operator_management` | **SIMPLIFIED** | Fewer defaults, cleaner config | | `ocp_cleanup` | **KEPT** | Enhanced scoping | @@ -183,7 +183,7 @@ One primary orchestration workflow: ``` MF - Full Migration Workflow ├── MF - Configure Environment (source + target) -├── MF - Validate (pre-flight) +├── MF - Validate (environment) ├── MF - Migrate └── MF - Validate (post-migration) ``` @@ -407,7 +407,7 @@ environment_manager_environments: {} # same structure as environments.yml **New capabilities:** - `failure_strategy` parameter (MIG-05) -- Pre-flight validation (MIG-08) +- Environment validation (MIG-08) - Cold migration with shutdown/timeout (MIG-07) - Maintenance window scheduling (MIG-09) - Structured migration report output @@ -417,7 +417,7 @@ environment_manager_environments: {} # same structure as environments.yml mtv_migrate_failure_strategy: continue_and_report # continue_and_report | continue_and_retry | halt_on_failure mtv_migrate_max_retries: 3 -mtv_migrate_pre_flight: true +mtv_migrate_environment_validation: true mtv_migrate_shutdown_timeout: 300 mtv_migrate_force_shutdown: false mtv_migrate_cleanup_source: false @@ -430,9 +430,9 @@ mtv_migrate_maintenance_window_end: "" # ISO 8601 ```yaml # tasks/main.yml (conceptual structure) - block: - - name: Pre-flight validation - include_tasks: _pre_flight.yml - when: mtv_migrate_pre_flight + - name: Environment validation + include_tasks: _environment_validation.yml + when: mtv_migrate_environment_validation - name: Wait for maintenance window include_tasks: _schedule.yml @@ -652,7 +652,7 @@ infra.openshift_virtualization_migration/ │ ├── mtv_migrate/ │ │ ├── tasks/ │ │ │ ├── main.yml -│ │ │ ├── _pre_flight.yml +│ │ │ ├── _environment_validation.yml │ │ │ ├── _schedule.yml │ │ │ ├── _plans.yml │ │ │ ├── _execute.yml diff --git a/roles/validate_environment/README.md b/roles/validate_environment/README.md index 53ae8da..5e90f6c 100644 --- a/roles/validate_environment/README.md +++ b/roles/validate_environment/README.md @@ -29,7 +29,7 @@ The AAP access check defaults to the AAP 2.5 platform controller API path (`/api With the sample inventory the connection variables resolve from the target cluster host (`openshift_host`, `openshift_api_key`), the source host (`host`, `username`, `password`, `vddk.image`), and the AAP host (`aap_hostname`, `aap_token`) — selected by `validate_environment_target_name`, `validate_environment_source_name`, and `validate_environment_aap_name`, which default to the `target_name`/`source_name` extra vars (injected by the seeded credentials) or the first host of each group. -All checks run on every invocation, and the summary assert requires every check green — the per-check tags (`openshift`, `cnv`, `mtv`, `aap`, `vcenter`, `vddk`) exist for isolated debugging; the summary asserts only over the checks that ran, so a tagged debug run ends green when the targeted check passed. A source whose `type` is not `vmware` (for example `ovirt`) skips the vCenter and VDDK checks. +All checks run on every invocation, and the summary assert requires every check green. A source whose `type` is not `vmware` (for example `ovirt`) skips the vCenter and VDDK checks. ## Check Mode @@ -122,7 +122,7 @@ Description: Validate the migration environment before seeding AAP — OpenShift * **Required**: False * **Type**: bool * **Default**: True - * **Description**: Whether to enable secure logging for tasks that handle credentials. Set to false to debug failed probes. Prefer a one-off CLI run (--tags ) over flipping the toggle on a job template; if you must, rotate the exposed credential (token or password) afterwards. + * **Description**: Whether to enable secure logging for tasks that handle credentials. Set to false to debug failed probes. Prefer a one-off CLI run (-e validate_environment_secure_logging=false) over flipping the toggle on a job template; if you must, rotate the exposed credential (token or password) afterwards. * **validate_environment_source_name**: * **Required**: False * **Type**: str diff --git a/roles/validate_environment/meta/argument_specs.yml b/roles/validate_environment/meta/argument_specs.yml index 6453ee8..cd8d593 100644 --- a/roles/validate_environment/meta/argument_specs.yml +++ b/roles/validate_environment/meta/argument_specs.yml @@ -26,9 +26,9 @@ argument_specs: description: >- Whether to enable secure logging for tasks that handle credentials. Set to false to debug failed probes. Prefer a - one-off CLI run (--tags ) over flipping the toggle on a - job template; if you must, rotate the exposed credential - (token or password) afterwards. + one-off CLI run (-e validate_environment_secure_logging=false) + over flipping the toggle on a job template; if you must, + rotate the exposed credential (token or password) afterwards. validate_environment_target_name: type: str diff --git a/roles/validate_environment/tasks/report.yml b/roles/validate_environment/tasks/report.yml index 6b12f39..3284a51 100644 --- a/roles/validate_environment/tasks/report.yml +++ b/roles/validate_environment/tasks/report.yml @@ -1,8 +1,7 @@ --- # Collect every check result and fail the play if any ran check failed. # Check files register __validate_environment_result_* facts with ran: true; the -# summary assert only covers checks that ran, so an isolated --tags debug -# run ends green when the targeted check passed. A check that never ran +# summary assert only covers checks that ran. A check that never ran # (unexpected failure in a full run) still shows FAIL with "check did # not run" in the summary, so the report never lies. # diff --git a/roles/validate_environment/tasks/validate_vcenter.yml b/roles/validate_environment/tasks/validate_vcenter.yml index b8dff8f..0ca7277 100644 --- a/roles/validate_environment/tasks/validate_vcenter.yml +++ b/roles/validate_environment/tasks/validate_vcenter.yml @@ -92,7 +92,7 @@ {% else %} vCenter authentication or connectivity failed at {{ validate_environment_vcenter_hostname }} — re-run the vCenter check alone - (--tags vcenter) as a one-off CLI run with + as a one-off CLI run with validate_environment_secure_logging=false to see the fault, then rotate the exposed credential {% endif %} From 7b77b58b8a41506b00680c79ed289c244c05c130 Mon Sep 17 00:00:00 2001 From: Vinny Valdez Date: Mon, 26 Oct 2026 09:04:34 -0500 Subject: [PATCH 4/8] docs(validate): drop stale tagged-run wording from report test The task-level tags are removed; the regression test comment still described an 'isolated tagged run' summary path. Rename it to 'isolated partial run'. Assisted-by: opencode:enmaas/rits/zai-org/glm-5-3 --- .../targets/validate_environment_report/tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/targets/validate_environment_report/tasks/main.yml b/tests/integration/targets/validate_environment_report/tasks/main.yml index b178206..04b0fc0 100644 --- a/tests/integration/targets/validate_environment_report/tasks/main.yml +++ b/tests/integration/targets/validate_environment_report/tasks/main.yml @@ -1,7 +1,7 @@ --- # Regression test for the validate_environment report aggregation. # Runs the report tasks against pre-populated check facts — no real -# endpoints — covering the three summary paths: an isolated tagged run, +# endpoints — covering the three summary paths: an isolated partial run, # an all-passed full run with mixed boolean forms, and a failed full run # whose assert names the failed checks. From a7767e3dc3fbb18cbac135b3ad411f61508051c1 Mon Sep 17 00:00:00 2001 From: Vinny Valdez Date: Mon, 26 Oct 2026 09:35:45 -0500 Subject: [PATCH 5/8] fix(validate): align aap_api_path docs and probe crash tolerance - Document the actual /api/controller/v2/ default in argument_specs.yml (defaults/main.yml already served it; the spec docs claimed /api/v2/) and align the defaults comment, which disagreed with the spec about AWX. - Add ignore_errors to the CNV and AAP probe tasks: a module crash bypasses failed_when and would abort the run, contradicting the documented "checks do not crash the play" claim. Mirrors the existing vCenter/OpenShift probe pattern. - Drop the leftover "check alone" wording from the vCenter failure detail: task tags no longer exist, so a per-check run is not possible. Validated: integration target ok=18/rescued=3 (unchanged), full pre-commit green. Assisted-by: opencode:publishers/prelude-maas/models/glm-53-flash --- roles/validate_environment/README.md | 4 ++-- roles/validate_environment/defaults/main.yml | 6 +++--- roles/validate_environment/meta/argument_specs.yml | 9 +++++---- roles/validate_environment/tasks/validate_aap.yml | 4 ++++ roles/validate_environment/tasks/validate_cnv.yml | 4 ++++ roles/validate_environment/tasks/validate_vcenter.yml | 4 ++-- 6 files changed, 20 insertions(+), 11 deletions(-) diff --git a/roles/validate_environment/README.md b/roles/validate_environment/README.md index 5e90f6c..24e7290 100644 --- a/roles/validate_environment/README.md +++ b/roles/validate_environment/README.md @@ -61,8 +61,8 @@ Description: Validate the migration environment before seeding AAP — OpenShift * **validate_environment_aap_api_path**: * **Required**: False * **Type**: str - * **Default**: /api/v2/ - * **Description**: API base path for the access check. Defaults to /api/v2/ (AWX and AAP 2.4 and earlier); AAP 2.5 platform deployments serve the controller API at /api/controller/v2/. + * **Default**: /api/controller/v2/ + * **Description**: API base path for the access check. Defaults to /api/controller/v2/ (AAP 2.5 platform deployments); AWX and AAP 2.4 and earlier serve the controller API at /api/v2/ — set that value for those environments. * **validate_environment_aap_hostname**: * **Required**: False * **Type**: str diff --git a/roles/validate_environment/defaults/main.yml b/roles/validate_environment/defaults/main.yml index 7afc67f..d2dd49b 100644 --- a/roles/validate_environment/defaults/main.yml +++ b/roles/validate_environment/defaults/main.yml @@ -124,9 +124,9 @@ validate_environment_aap_hostname: >- # required: False # description: >- # API base path appended to the AAP hostname for the access check. -# Defaults to /api/controller/v2/ (AAP 2.5 platform and AWX). AAP 2.4 -# and earlier serve the API at /api/v2/ — set that value for those -# environments. +# Defaults to /api/controller/v2/ (AAP 2.5 platform deployments). AWX +# and AAP 2.4 and earlier serve the API at /api/v2/ — set that value +# for those environments. validate_environment_aap_api_path: /api/controller/v2/ # title: AAP Username diff --git a/roles/validate_environment/meta/argument_specs.yml b/roles/validate_environment/meta/argument_specs.yml index cd8d593..834698e 100644 --- a/roles/validate_environment/meta/argument_specs.yml +++ b/roles/validate_environment/meta/argument_specs.yml @@ -130,11 +130,12 @@ argument_specs: validate_environment_aap_api_path: type: str required: false - default: /api/v2/ + default: /api/controller/v2/ description: >- - API base path for the access check. Defaults to /api/v2/ (AWX - and AAP 2.4 and earlier); AAP 2.5 platform deployments serve - the controller API at /api/controller/v2/. + API base path for the access check. Defaults to + /api/controller/v2/ (AAP 2.5 platform deployments); AWX and + AAP 2.4 and earlier serve the controller API at /api/v2/ — + set that value for those environments. validate_environment_aap_username: type: str diff --git a/roles/validate_environment/tasks/validate_aap.yml b/roles/validate_environment/tasks/validate_aap.yml index 9dd9f9e..39c06b0 100644 --- a/roles/validate_environment/tasks/validate_aap.yml +++ b/roles/validate_environment/tasks/validate_aap.yml @@ -21,6 +21,10 @@ status_code: [200, 401, 403] register: __validate_environment_aap failed_when: false + # A module crash (e.g. aiohttp ContentTypeError when the endpoint answers + # with a non-JSON body) bypasses failed_when and would abort the run; the + # record task below turns the fault into a graceful check result. + ignore_errors: true no_log: "{{ validate_environment_secure_logging }}" - name: validate_aap | Record the AAP access check result diff --git a/roles/validate_environment/tasks/validate_cnv.yml b/roles/validate_environment/tasks/validate_cnv.yml index 03580e7..a2e09e5 100644 --- a/roles/validate_environment/tasks/validate_cnv.yml +++ b/roles/validate_environment/tasks/validate_cnv.yml @@ -13,6 +13,10 @@ namespace: "{{ validate_environment_cnv_namespace }}" register: __validate_environment_cnv_csvs failed_when: false + # A module crash (e.g. an unresolvable host or a malformed kubeconfig) + # bypasses failed_when and would abort the run; the record task below + # turns the fault into a graceful check result. + ignore_errors: true no_log: "{{ validate_environment_secure_logging }}" - name: validate_cnv | Find the OpenShift Virtualization CSV diff --git a/roles/validate_environment/tasks/validate_vcenter.yml b/roles/validate_environment/tasks/validate_vcenter.yml index 0ca7277..7e84f42 100644 --- a/roles/validate_environment/tasks/validate_vcenter.yml +++ b/roles/validate_environment/tasks/validate_vcenter.yml @@ -91,8 +91,8 @@ are visible — a migration source needs at least one {% else %} vCenter authentication or connectivity failed at - {{ validate_environment_vcenter_hostname }} — re-run the vCenter check alone - as a one-off CLI run with + {{ validate_environment_vcenter_hostname }} — re-run the environment + validation as a one-off CLI run with validate_environment_secure_logging=false to see the fault, then rotate the exposed credential {% endif %} From 0e485b6fece249e737ae6f42338698e35cee6b9b Mon Sep 17 00:00:00 2001 From: Vinny Valdez Date: Mon, 26 Oct 2026 10:33:38 -0500 Subject: [PATCH 6/8] feat(validate): add property-based check selection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the fixed six-check include sequence with a loop over the new validate_environment_checks variable (defaults to all six). A one-off run can now limit the pass, e.g. -e validate_environment_checks=[vcenter] to debug a single check — the summary report still runs on every invocation via the always block. Assisted-by: opencode:publishers/prelude-maas/models/glm-53-flash --- roles/validate_environment/README.md | 78 +++++++++++-------- roles/validate_environment/defaults/main.yml | 14 ++++ .../meta/argument_specs.yml | 30 +++++-- roles/validate_environment/tasks/main.yml | 36 +++------ .../tasks/validate_vcenter.yml | 8 +- 5 files changed, 100 insertions(+), 66 deletions(-) diff --git a/roles/validate_environment/README.md b/roles/validate_environment/README.md index 24e7290..4f98337 100644 --- a/roles/validate_environment/README.md +++ b/roles/validate_environment/README.md @@ -56,7 +56,7 @@ Description: Validate the migration environment before seeding AAP — OpenShift #### Key: main -* **Description**: ['Runs every validate_environment check and reports a summary, then fails the play if any check failed. Checks: OpenShift API auth, CNV and MTV operator health, AAP access, vCenter connectivity, and VDDK init image configuration.', 'Designed to run from an AAP job template (credentials inject K8S_AUTH_*, VMWARE_*, CONTROLLER_HOST, CONTROLLER_API_TOKEN) or a controller with the sample inventory. Connection variables cascade from environment variables to inventory host variables.', 'All checks run on every invocation. An unconfigured target fails that check with guidance rather than crashing the play, so one run reports everything that needs attention.'] +* **Description**: ['Runs the selected validate_environment checks and reports a summary, then fails the play if any ran check failed. Checks: OpenShift API auth, CNV and MTV operator health, AAP access, vCenter connectivity, and VDDK init image configuration.', 'Designed to run from an AAP job template (credentials inject K8S_AUTH_*, VMWARE_*, CONTROLLER_HOST, CONTROLLER_API_TOKEN) or a controller with the sample inventory. Connection variables cascade from environment variables to inventory host variables.', 'All checks run by default; validate_environment_checks limits the pass to the named checks. An unconfigured target fails that check with guidance rather than crashing the play, so one run reports everything that needs attention.'] * **Options**: * **validate_environment_aap_api_path**: * **Required**: False @@ -93,6 +93,11 @@ Description: Validate the migration environment before seeding AAP — OpenShift * **Type**: bool * **Default**: True * **Description**: Validate the AAP TLS certificate. + * **validate_environment_checks**: + * **Required**: False + * **Type**: list + * **Default**: ['openshift', 'cnv', 'mtv', 'aap', 'vcenter', 'vddk'] + * **Description**: Which environment validation checks to run, as check-name strings (openshift, cnv, mtv, aap, vcenter, vddk). Defaults to all six. A one-off CLI run can limit the pass, e.g. -e validate_environment_checks=[vcenter] to debug a single check. An unknown name fails the include with a loud file-not-found error — the summary report still runs. * **validate_environment_cnv_namespace**: * **Required**: False * **Type**: str @@ -169,26 +174,33 @@ Description: Validate the migration environment before seeding AAP — OpenShift | Var | Type | Value |Choices |Required | Title | |--------------|--------------|-------------|-------------|-------------|-------------| -| [`validate_environment_aap_api_path`](defaults/main.yml#L130) | str | `/api/controller/v2/` | None | False | AAP API Path | -| [`validate_environment_aap_hostname`](defaults/main.yml#L116) | str | `` | None | False | AAP Hostname | +| [`validate_environment_aap_api_path`](defaults/main.yml#L144) | str | `/api/controller/v2/` | None | False | AAP API Path | +| [`validate_environment_aap_hostname`](defaults/main.yml#L130) | str | `` | None | False | AAP Hostname | | [`validate_environment_aap_name`](defaults/main.yml#L20) | str | `{{ groups['migration_aap'] ¦ default([], true) ¦ first ¦ default('', true) }}` | None | None | None | -| [`validate_environment_aap_password`](defaults/main.yml#L148) | str | `` | None | False | AAP Password | -| [`validate_environment_aap_token`](defaults/main.yml#L161) | str | `` | None | False | AAP Token | -| [`validate_environment_aap_username`](defaults/main.yml#L137) | str | `` | None | False | AAP Username | -| [`validate_environment_aap_validate_certs`](defaults/main.yml#L174) | str | `{{ (lookup('env', 'AAP_VALIDATE_CERTS') ¦ default(hostvars[validate_environment_aap_name]['aap_validate_certs'] ¦ default(true), true)) ¦ bool }}` | None | False | AAP Verify SSL | -| [`validate_environment_cnv_namespace`](defaults/main.yml#L183) | str | `` | None | False | CNV Namespace | -| [`validate_environment_mtv_namespace`](defaults/main.yml#L200) | str | `` | None | False | MTV Namespace | -| [`validate_environment_openshift_api_key`](defaults/main.yml#L46) | str | `` | None | True | OpenShift API Key | -| [`validate_environment_openshift_host`](defaults/main.yml#L33) | str | `` | None | True | OpenShift Host | -| [`validate_environment_openshift_verify_ssl`](defaults/main.yml#L63) | str | `{{ (lookup('env', 'K8S_AUTH_VERIFY_SSL') ¦ default(hostvars[validate_environment_target_name]['openshift_verify_ssl'] ¦ default(true), true)) ¦ bool }}` | None | False | OpenShift Verify SSL | +| [`validate_environment_aap_password`](defaults/main.yml#L162) | str | `` | None | False | AAP Password | +| [`validate_environment_aap_token`](defaults/main.yml#L175) | str | `` | None | False | AAP Token | +| [`validate_environment_aap_username`](defaults/main.yml#L151) | str | `` | None | False | AAP Username | +| [`validate_environment_aap_validate_certs`](defaults/main.yml#L188) | str | `{{ (lookup('env', 'AAP_VALIDATE_CERTS') ¦ default(hostvars[validate_environment_aap_name]['aap_validate_certs'] ¦ default(true), true)) ¦ bool }}` | None | False | AAP Verify SSL | +| [`validate_environment_checks`](defaults/main.yml#L33) | list | `[]` | None | False | Checks | +| [`validate_environment_checks.0`](defaults/main.yml#L34) | str | `openshift` | None | None | None | +| [`validate_environment_checks.1`](defaults/main.yml#L35) | str | `cnv` | None | None | None | +| [`validate_environment_checks.2`](defaults/main.yml#L36) | str | `mtv` | None | None | None | +| [`validate_environment_checks.3`](defaults/main.yml#L37) | str | `aap` | None | None | None | +| [`validate_environment_checks.4`](defaults/main.yml#L38) | str | `vcenter` | None | None | None | +| [`validate_environment_checks.5`](defaults/main.yml#L39) | str | `vddk` | None | None | None | +| [`validate_environment_cnv_namespace`](defaults/main.yml#L197) | str | `` | None | False | CNV Namespace | +| [`validate_environment_mtv_namespace`](defaults/main.yml#L214) | str | `` | None | False | MTV Namespace | +| [`validate_environment_openshift_api_key`](defaults/main.yml#L60) | str | `` | None | True | OpenShift API Key | +| [`validate_environment_openshift_host`](defaults/main.yml#L47) | str | `` | None | True | OpenShift Host | +| [`validate_environment_openshift_verify_ssl`](defaults/main.yml#L77) | str | `{{ (lookup('env', 'K8S_AUTH_VERIFY_SSL') ¦ default(hostvars[validate_environment_target_name]['openshift_verify_ssl'] ¦ default(true), true)) ¦ bool }}` | None | False | OpenShift Verify SSL | | [`validate_environment_secure_logging`](defaults/main.yml#L25) | str | `{{ secure_logging ¦ default(true) }}` | None | None | None | | [`validate_environment_source_name`](defaults/main.yml#L17) | str | `{{ source_name ¦ default(groups['vm_sources'] ¦ default([], true) ¦ first ¦ default('', true), true) }}` | None | None | None | | [`validate_environment_target_name`](defaults/main.yml#L14) | str | `{{ target_name ¦ default(groups['migration_clusters'] ¦ default([], true) ¦ first ¦ default('', true), true) }}` | None | None | None | -| [`validate_environment_vcenter_hostname`](defaults/main.yml#L72) | str | `` | None | False | vCenter Hostname | -| [`validate_environment_vcenter_password`](defaults/main.yml#L94) | str | `` | None | False | vCenter Password | -| [`validate_environment_vcenter_username`](defaults/main.yml#L83) | str | `` | None | False | vCenter Username | -| [`validate_environment_vcenter_validate_certs`](defaults/main.yml#L106) | str | `{{ (lookup('env', 'VMWARE_VALIDATE_CERTS') ¦ default(hostvars[validate_environment_source_name]['validate_certs'] ¦ default(true), true)) ¦ bool }}` | None | False | vCenter Verify SSL | -| [`validate_environment_vddk_image`](defaults/main.yml#L217) | str | `` | None | False | VDDK Init Image | +| [`validate_environment_vcenter_hostname`](defaults/main.yml#L86) | str | `` | None | False | vCenter Hostname | +| [`validate_environment_vcenter_password`](defaults/main.yml#L108) | str | `` | None | False | vCenter Password | +| [`validate_environment_vcenter_username`](defaults/main.yml#L97) | str | `` | None | False | vCenter Username | +| [`validate_environment_vcenter_validate_certs`](defaults/main.yml#L120) | str | `{{ (lookup('env', 'VMWARE_VALIDATE_CERTS') ¦ default(hostvars[validate_environment_source_name]['validate_certs'] ¦ default(true), true)) ¦ bool }}` | None | False | vCenter Verify SSL | +| [`validate_environment_vddk_image`](defaults/main.yml#L231) | str | `` | None | False | VDDK Init Image | 🖇️ Full descriptions for vars in defaults/main.yml
@@ -206,6 +218,20 @@ Description: Validate the migration environment before seeding AAP — OpenShift
`validate_environment_aap_validate_certs`: >-
+`validate_environment_checks`: >- +
+`validate_environment_checks.0`: None +
+`validate_environment_checks.1`: None +
+`validate_environment_checks.2`: None +
+`validate_environment_checks.3`: None +
+`validate_environment_checks.4`: None +
+`validate_environment_checks.5`: None +
`validate_environment_cnv_namespace`: >-
`validate_environment_mtv_namespace`: >- @@ -253,12 +279,7 @@ Description: Validate the migration environment before seeding AAP — OpenShift | ---- | ------ | --------- | | Include pre-validation of required connection variables | `ansible.builtin.include_tasks` | False | | Run environment validation checks | `block` | False | -| Include OpenShift API authentication check | `ansible.builtin.include_tasks` | False | -| Include OpenShift Virtualization operator check | `ansible.builtin.include_tasks` | False | -| Include MTV operator check | `ansible.builtin.include_tasks` | False | -| Include AAP access check | `ansible.builtin.include_tasks` | False | -| Include vCenter connectivity check | `ansible.builtin.include_tasks` | False | -| Include VDDK init image check | `ansible.builtin.include_tasks` | False | +| Include each selected environment validation check | `ansible.builtin.include_tasks` | False | #### File: tasks/pre_validate.yml @@ -339,14 +360,9 @@ classDef rescue stroke:#665352,stroke-width:2px; Start-->|Include task| Include_pre_validation_of_required_connection_variables_pre_validate_yml_0[include pre validation of required connection
variables
include_task: pre validate yml]:::includeTasks Include_pre_validation_of_required_connection_variables_pre_validate_yml_0-->|Block Start| Run_environment_validation_checks1_block_start_0[[run environment validation checks]]:::block - Run_environment_validation_checks1_block_start_0-->|Include task| Include_OpenShift_API_authentication_check_validate_openshift_yml_0[include openshift api authentication check
include_task: validate openshift yml]:::includeTasks - Include_OpenShift_API_authentication_check_validate_openshift_yml_0-->|Include task| Include_OpenShift_Virtualization_operator_check_validate_cnv_yml_1[include openshift virtualization operator check
include_task: validate cnv yml]:::includeTasks - Include_OpenShift_Virtualization_operator_check_validate_cnv_yml_1-->|Include task| Include_MTV_operator_check_validate_mtv_yml_2[include mtv operator check
include_task: validate mtv yml]:::includeTasks - Include_MTV_operator_check_validate_mtv_yml_2-->|Include task| Include_AAP_access_check_validate_aap_yml_3[include aap access check
include_task: validate aap yml]:::includeTasks - Include_AAP_access_check_validate_aap_yml_3-->|Include task| Include_vCenter_connectivity_check_validate_vcenter_yml_4[include vcenter connectivity check
include_task: validate vcenter yml]:::includeTasks - Include_vCenter_connectivity_check_validate_vcenter_yml_4-->|Include task| Include_VDDK_init_image_check_validate_vddk_yml_5[include vddk init image check
include_task: validate vddk yml]:::includeTasks - Include_VDDK_init_image_check_validate_vddk_yml_5-.->|End of Block| Run_environment_validation_checks1_block_start_0 - Include_VDDK_init_image_check_validate_vddk_yml_5-->End + Run_environment_validation_checks1_block_start_0-->|Include task| Include_each_selected_environment_validation_check_validate______validate_environment_check____yml_0[include each selected environment validation check
include_task: validate validate environment check yml]:::includeTasks + Include_each_selected_environment_validation_check_validate______validate_environment_check____yml_0-.->|End of Block| Run_environment_validation_checks1_block_start_0 + Include_each_selected_environment_validation_check_validate______validate_environment_check____yml_0-->End ``` ### Graph for pre_validate.yml diff --git a/roles/validate_environment/defaults/main.yml b/roles/validate_environment/defaults/main.yml index d2dd49b..d0c520e 100644 --- a/roles/validate_environment/defaults/main.yml +++ b/roles/validate_environment/defaults/main.yml @@ -24,6 +24,20 @@ validate_environment_aap_name: "{{ groups['migration_aap'] | default([], true) | # can be debugged with validate_environment_secure_logging=false. validate_environment_secure_logging: "{{ secure_logging | default(true) }}" +# title: Checks +# required: False +# description: >- +# Which environment validation checks to run, as check-name strings. +# Defaults to all six. A one-off run can limit the pass, e.g. +# validate_environment_checks=[vcenter] to debug the vCenter check. +validate_environment_checks: + - openshift + - cnv + - mtv + - aap + - vcenter + - vddk + # title: OpenShift Host # required: True # description: >- diff --git a/roles/validate_environment/meta/argument_specs.yml b/roles/validate_environment/meta/argument_specs.yml index 834698e..ab075fd 100644 --- a/roles/validate_environment/meta/argument_specs.yml +++ b/roles/validate_environment/meta/argument_specs.yml @@ -5,20 +5,40 @@ argument_specs: Validate the migration environment before seeding AAP description: - >- - Runs every validate_environment check and reports a summary, then fails the - play if any check failed. Checks: OpenShift API auth, CNV and - MTV operator health, AAP access, vCenter connectivity, and VDDK - init image configuration. + Runs the selected validate_environment checks and reports a summary, + then fails the play if any ran check failed. Checks: OpenShift + API auth, CNV and MTV operator health, AAP access, vCenter + connectivity, and VDDK init image configuration. - >- Designed to run from an AAP job template (credentials inject K8S_AUTH_*, VMWARE_*, CONTROLLER_HOST, CONTROLLER_API_TOKEN) or a controller with the sample inventory. Connection variables cascade from environment variables to inventory host variables. - >- - All checks run on every invocation. An unconfigured target fails + All checks run by default; validate_environment_checks limits the + pass to the named checks. An unconfigured target fails that check with guidance rather than crashing the play, so one run reports everything that needs attention. options: + validate_environment_checks: + type: list + elements: str + required: false + default: + - openshift + - cnv + - mtv + - aap + - vcenter + - vddk + description: >- + Which environment validation checks to run, as check-name + strings (openshift, cnv, mtv, aap, vcenter, vddk). Defaults to + all six. A one-off CLI run can limit the pass, e.g. + -e validate_environment_checks=[vcenter] to debug a single + check. An unknown name fails the include with a loud + file-not-found error — the summary report still runs. + validate_environment_secure_logging: type: bool required: false diff --git a/roles/validate_environment/tasks/main.yml b/roles/validate_environment/tasks/main.yml index 60d4e62..56b0126 100644 --- a/roles/validate_environment/tasks/main.yml +++ b/roles/validate_environment/tasks/main.yml @@ -1,10 +1,11 @@ --- # The environment validation pass runs before seeding AAP. # -# All checks run on every invocation; the summary report fails the play -# if any ran check failed, so one run reports everything that needs -# attention. Checks whose target is not configured fail that check with -# a message describing what to set — they do not crash the play. +# The checks default to all six; validate_environment_checks limits the +# pass to the named checks for a one-off run. The summary report fails +# the play if any ran check failed, so one run reports everything that +# needs attention. Checks whose target is not configured fail that check +# with a message describing what to set — they do not crash the play. - name: Include pre-validation of required connection variables ansible.builtin.include_tasks: @@ -12,29 +13,12 @@ - name: Run environment validation checks block: - - name: Include OpenShift API authentication check + - name: Include each selected environment validation check ansible.builtin.include_tasks: - file: validate_openshift.yml - - - name: Include OpenShift Virtualization operator check - ansible.builtin.include_tasks: - file: validate_cnv.yml - - - name: Include MTV operator check - ansible.builtin.include_tasks: - file: validate_mtv.yml - - - name: Include AAP access check - ansible.builtin.include_tasks: - file: validate_aap.yml - - - name: Include vCenter connectivity check - ansible.builtin.include_tasks: - file: validate_vcenter.yml - - - name: Include VDDK init image check - ansible.builtin.include_tasks: - file: validate_vddk.yml + file: "validate_{{ __validate_environment_check }}.yml" + loop: "{{ validate_environment_checks }}" + loop_control: + loop_var: __validate_environment_check always: - name: Include the validate_environment summary report diff --git a/roles/validate_environment/tasks/validate_vcenter.yml b/roles/validate_environment/tasks/validate_vcenter.yml index 7e84f42..0eb3847 100644 --- a/roles/validate_environment/tasks/validate_vcenter.yml +++ b/roles/validate_environment/tasks/validate_vcenter.yml @@ -91,9 +91,9 @@ are visible — a migration source needs at least one {% else %} vCenter authentication or connectivity failed at - {{ validate_environment_vcenter_hostname }} — re-run the environment - validation as a one-off CLI run with - validate_environment_secure_logging=false to see the fault, then rotate the - exposed credential + {{ validate_environment_vcenter_hostname }} — re-run the vCenter + check as a one-off CLI run with validate_environment_checks=[vcenter] + and validate_environment_secure_logging=false to see the fault, + then rotate the exposed credential {% endif %} ... From eb1f01c7c00949c2cbf02a6b5540370cb77d4398 Mon Sep 17 00:00:00 2001 From: Vinny Valdez Date: Mon, 26 Oct 2026 10:45:33 -0500 Subject: [PATCH 7/8] fix(validate): accept CLI string form of validate_environment_checks CLI -e passes a string (-e validate_environment_checks=[vddk]) where an inventory var is a real list; loop requires a list and rejected the string. Normalize the loop input to accept a list, a bare check name, or a bracketed comma-separated string. Assisted-by: opencode:publishers/prelude-maas/models/glm-53-flash --- roles/validate_environment/README.md | 48 +++++++++---------- roles/validate_environment/defaults/main.yml | 3 +- .../meta/argument_specs.yml | 3 +- roles/validate_environment/tasks/main.yml | 7 ++- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/roles/validate_environment/README.md b/roles/validate_environment/README.md index 4f98337..f4371a6 100644 --- a/roles/validate_environment/README.md +++ b/roles/validate_environment/README.md @@ -97,7 +97,7 @@ Description: Validate the migration environment before seeding AAP — OpenShift * **Required**: False * **Type**: list * **Default**: ['openshift', 'cnv', 'mtv', 'aap', 'vcenter', 'vddk'] - * **Description**: Which environment validation checks to run, as check-name strings (openshift, cnv, mtv, aap, vcenter, vddk). Defaults to all six. A one-off CLI run can limit the pass, e.g. -e validate_environment_checks=[vcenter] to debug a single check. An unknown name fails the include with a loud file-not-found error — the summary report still runs. + * **Description**: Which environment validation checks to run, as check-name strings (openshift, cnv, mtv, aap, vcenter, vddk). Defaults to all six. Accepts a list, a bare check name, or a bracketed comma-separated string — the CLI -e form, e.g. -e validate_environment_checks=[vcenter] to debug a single check. An unknown name fails the include with a loud file-not-found error — the summary report still runs. * **validate_environment_cnv_namespace**: * **Required**: False * **Type**: str @@ -174,33 +174,33 @@ Description: Validate the migration environment before seeding AAP — OpenShift | Var | Type | Value |Choices |Required | Title | |--------------|--------------|-------------|-------------|-------------|-------------| -| [`validate_environment_aap_api_path`](defaults/main.yml#L144) | str | `/api/controller/v2/` | None | False | AAP API Path | -| [`validate_environment_aap_hostname`](defaults/main.yml#L130) | str | `` | None | False | AAP Hostname | +| [`validate_environment_aap_api_path`](defaults/main.yml#L145) | str | `/api/controller/v2/` | None | False | AAP API Path | +| [`validate_environment_aap_hostname`](defaults/main.yml#L131) | str | `` | None | False | AAP Hostname | | [`validate_environment_aap_name`](defaults/main.yml#L20) | str | `{{ groups['migration_aap'] ¦ default([], true) ¦ first ¦ default('', true) }}` | None | None | None | -| [`validate_environment_aap_password`](defaults/main.yml#L162) | str | `` | None | False | AAP Password | -| [`validate_environment_aap_token`](defaults/main.yml#L175) | str | `` | None | False | AAP Token | -| [`validate_environment_aap_username`](defaults/main.yml#L151) | str | `` | None | False | AAP Username | -| [`validate_environment_aap_validate_certs`](defaults/main.yml#L188) | str | `{{ (lookup('env', 'AAP_VALIDATE_CERTS') ¦ default(hostvars[validate_environment_aap_name]['aap_validate_certs'] ¦ default(true), true)) ¦ bool }}` | None | False | AAP Verify SSL | -| [`validate_environment_checks`](defaults/main.yml#L33) | list | `[]` | None | False | Checks | -| [`validate_environment_checks.0`](defaults/main.yml#L34) | str | `openshift` | None | None | None | -| [`validate_environment_checks.1`](defaults/main.yml#L35) | str | `cnv` | None | None | None | -| [`validate_environment_checks.2`](defaults/main.yml#L36) | str | `mtv` | None | None | None | -| [`validate_environment_checks.3`](defaults/main.yml#L37) | str | `aap` | None | None | None | -| [`validate_environment_checks.4`](defaults/main.yml#L38) | str | `vcenter` | None | None | None | -| [`validate_environment_checks.5`](defaults/main.yml#L39) | str | `vddk` | None | None | None | -| [`validate_environment_cnv_namespace`](defaults/main.yml#L197) | str | `` | None | False | CNV Namespace | -| [`validate_environment_mtv_namespace`](defaults/main.yml#L214) | str | `` | None | False | MTV Namespace | -| [`validate_environment_openshift_api_key`](defaults/main.yml#L60) | str | `` | None | True | OpenShift API Key | -| [`validate_environment_openshift_host`](defaults/main.yml#L47) | str | `` | None | True | OpenShift Host | -| [`validate_environment_openshift_verify_ssl`](defaults/main.yml#L77) | str | `{{ (lookup('env', 'K8S_AUTH_VERIFY_SSL') ¦ default(hostvars[validate_environment_target_name]['openshift_verify_ssl'] ¦ default(true), true)) ¦ bool }}` | None | False | OpenShift Verify SSL | +| [`validate_environment_aap_password`](defaults/main.yml#L163) | str | `` | None | False | AAP Password | +| [`validate_environment_aap_token`](defaults/main.yml#L176) | str | `` | None | False | AAP Token | +| [`validate_environment_aap_username`](defaults/main.yml#L152) | str | `` | None | False | AAP Username | +| [`validate_environment_aap_validate_certs`](defaults/main.yml#L189) | str | `{{ (lookup('env', 'AAP_VALIDATE_CERTS') ¦ default(hostvars[validate_environment_aap_name]['aap_validate_certs'] ¦ default(true), true)) ¦ bool }}` | None | False | AAP Verify SSL | +| [`validate_environment_checks`](defaults/main.yml#L34) | list | `[]` | None | False | Checks | +| [`validate_environment_checks.0`](defaults/main.yml#L35) | str | `openshift` | None | None | None | +| [`validate_environment_checks.1`](defaults/main.yml#L36) | str | `cnv` | None | None | None | +| [`validate_environment_checks.2`](defaults/main.yml#L37) | str | `mtv` | None | None | None | +| [`validate_environment_checks.3`](defaults/main.yml#L38) | str | `aap` | None | None | None | +| [`validate_environment_checks.4`](defaults/main.yml#L39) | str | `vcenter` | None | None | None | +| [`validate_environment_checks.5`](defaults/main.yml#L40) | str | `vddk` | None | None | None | +| [`validate_environment_cnv_namespace`](defaults/main.yml#L198) | str | `` | None | False | CNV Namespace | +| [`validate_environment_mtv_namespace`](defaults/main.yml#L215) | str | `` | None | False | MTV Namespace | +| [`validate_environment_openshift_api_key`](defaults/main.yml#L61) | str | `` | None | True | OpenShift API Key | +| [`validate_environment_openshift_host`](defaults/main.yml#L48) | str | `` | None | True | OpenShift Host | +| [`validate_environment_openshift_verify_ssl`](defaults/main.yml#L78) | str | `{{ (lookup('env', 'K8S_AUTH_VERIFY_SSL') ¦ default(hostvars[validate_environment_target_name]['openshift_verify_ssl'] ¦ default(true), true)) ¦ bool }}` | None | False | OpenShift Verify SSL | | [`validate_environment_secure_logging`](defaults/main.yml#L25) | str | `{{ secure_logging ¦ default(true) }}` | None | None | None | | [`validate_environment_source_name`](defaults/main.yml#L17) | str | `{{ source_name ¦ default(groups['vm_sources'] ¦ default([], true) ¦ first ¦ default('', true), true) }}` | None | None | None | | [`validate_environment_target_name`](defaults/main.yml#L14) | str | `{{ target_name ¦ default(groups['migration_clusters'] ¦ default([], true) ¦ first ¦ default('', true), true) }}` | None | None | None | -| [`validate_environment_vcenter_hostname`](defaults/main.yml#L86) | str | `` | None | False | vCenter Hostname | -| [`validate_environment_vcenter_password`](defaults/main.yml#L108) | str | `` | None | False | vCenter Password | -| [`validate_environment_vcenter_username`](defaults/main.yml#L97) | str | `` | None | False | vCenter Username | -| [`validate_environment_vcenter_validate_certs`](defaults/main.yml#L120) | str | `{{ (lookup('env', 'VMWARE_VALIDATE_CERTS') ¦ default(hostvars[validate_environment_source_name]['validate_certs'] ¦ default(true), true)) ¦ bool }}` | None | False | vCenter Verify SSL | -| [`validate_environment_vddk_image`](defaults/main.yml#L231) | str | `` | None | False | VDDK Init Image | +| [`validate_environment_vcenter_hostname`](defaults/main.yml#L87) | str | `` | None | False | vCenter Hostname | +| [`validate_environment_vcenter_password`](defaults/main.yml#L109) | str | `` | None | False | vCenter Password | +| [`validate_environment_vcenter_username`](defaults/main.yml#L98) | str | `` | None | False | vCenter Username | +| [`validate_environment_vcenter_validate_certs`](defaults/main.yml#L121) | str | `{{ (lookup('env', 'VMWARE_VALIDATE_CERTS') ¦ default(hostvars[validate_environment_source_name]['validate_certs'] ¦ default(true), true)) ¦ bool }}` | None | False | vCenter Verify SSL | +| [`validate_environment_vddk_image`](defaults/main.yml#L232) | str | `` | None | False | VDDK Init Image | 🖇️ Full descriptions for vars in defaults/main.yml
diff --git a/roles/validate_environment/defaults/main.yml b/roles/validate_environment/defaults/main.yml index d0c520e..b998cae 100644 --- a/roles/validate_environment/defaults/main.yml +++ b/roles/validate_environment/defaults/main.yml @@ -28,7 +28,8 @@ validate_environment_secure_logging: "{{ secure_logging | default(true) }}" # required: False # description: >- # Which environment validation checks to run, as check-name strings. -# Defaults to all six. A one-off run can limit the pass, e.g. +# Defaults to all six. Accepts a list, a bare check name, or a +# bracketed comma-separated string — the CLI -e form, e.g. # validate_environment_checks=[vcenter] to debug the vCenter check. validate_environment_checks: - openshift diff --git a/roles/validate_environment/meta/argument_specs.yml b/roles/validate_environment/meta/argument_specs.yml index ab075fd..fd35e61 100644 --- a/roles/validate_environment/meta/argument_specs.yml +++ b/roles/validate_environment/meta/argument_specs.yml @@ -34,7 +34,8 @@ argument_specs: description: >- Which environment validation checks to run, as check-name strings (openshift, cnv, mtv, aap, vcenter, vddk). Defaults to - all six. A one-off CLI run can limit the pass, e.g. + all six. Accepts a list, a bare check name, or a bracketed + comma-separated string — the CLI -e form, e.g. -e validate_environment_checks=[vcenter] to debug a single check. An unknown name fails the include with a loud file-not-found error — the summary report still runs. diff --git a/roles/validate_environment/tasks/main.yml b/roles/validate_environment/tasks/main.yml index 56b0126..15d03d9 100644 --- a/roles/validate_environment/tasks/main.yml +++ b/roles/validate_environment/tasks/main.yml @@ -16,7 +16,12 @@ - name: Include each selected environment validation check ansible.builtin.include_tasks: file: "validate_{{ __validate_environment_check }}.yml" - loop: "{{ validate_environment_checks }}" + # CLI -e passes a string (e.g. -e validate_environment_checks=[vddk]) + # where an inventory var is a real list — normalize both forms here. + loop: "{{ validate_environment_checks + if validate_environment_checks is not string + else (validate_environment_checks | replace('[', '') | replace(']', '') + | split(',') | map('trim') | reject('equalto', '') | list) }}" loop_control: loop_var: __validate_environment_check From e0247391bbb59ed74fc1106ebaa0a86952c435f0 Mon Sep 17 00:00:00 2001 From: Vinny Valdez Date: Mon, 26 Oct 2026 11:39:09 -0500 Subject: [PATCH 8/8] docs(validate_environment): pin-range safety for datacenter_info Issue #121 requires community-module use to document which module, why it is required over a command, and why the pin range is safe. The existing justification covered the first two; add the pin-range note: community.vmware is pinned >=5.5.0 and the task uses only core connection options, unchanged across 5.x. Also note the pyVmomi requirement. Assisted-by: opencode:publishers/prelude-maas/models/glm-53-flash --- changelogs/fragments/121-pin-range-safety.yml | 2 ++ roles/validate_environment/tasks/validate_vcenter.yml | 5 +++++ 2 files changed, 7 insertions(+) create mode 100644 changelogs/fragments/121-pin-range-safety.yml diff --git a/changelogs/fragments/121-pin-range-safety.yml b/changelogs/fragments/121-pin-range-safety.yml new file mode 100644 index 0000000..e22a1e3 --- /dev/null +++ b/changelogs/fragments/121-pin-range-safety.yml @@ -0,0 +1,2 @@ +trivial: + - Add pin-range safety notes to the community.vmware module justification in validate_environment. diff --git a/roles/validate_environment/tasks/validate_vcenter.yml b/roles/validate_environment/tasks/validate_vcenter.yml index 0eb3847..492df3a 100644 --- a/roles/validate_environment/tasks/validate_vcenter.yml +++ b/roles/validate_environment/tasks/validate_vcenter.yml @@ -15,6 +15,11 @@ # .vmware_datacenter_info (pyVmomi, vCenter 6.5+) is the only content that # covers the 6.x path, so the SOAP fallback runs only when the REST probe # cannot return data. +# +# Pin-range safety: community.vmware is pinned >=5.5.0 (galaxy.yml); the +# task uses only the core connection options (hostname, username, password, +# validate_certs), unchanged across 5.x. Requires pyVmomi, which the +# execution environments ship. - name: validate_vcenter | List vCenter datacenters via the REST API (vCenter 7.0+) when: