Skip to content
This repository was archived by the owner on Sep 9, 2026. It is now read-only.

Add osac.workflows collection with override support and integration tests - #220

Merged
avishayt merged 27 commits into
osac-project:mainfrom
avishayt:overrides-and-tests
Mar 26, 2026
Merged

avishayt merged 27 commits into
osac-project:mainfrom
avishayt:overrides-and-tests

Conversation

@avishayt

@avishayt avishayt commented Mar 15, 2026

Copy link
Copy Markdown
Contributor

Add osac.workflows collection with override support and integration tests

Summary

This PR introduces the osac.workflows collection, which provides reusable workflow playbooks with built-in customization points. This enables deployments like MOC (Mass Open Cloud) to customize infrastructure integration, networking, and templates without duplicating workflow code.

All 11 OSAC workflows are now available as importable playbooks with override support:

  • Cluster workflows: create, delete, post_install
  • Compute instance workflows: create, delete
  • Hostpool workflows: create, delete
  • Reporting workflows: cluster_status, hostpool_status
  • Maintenance workflows: cleanup_stale_network_resources
  • Config workflows: config_as_code

Key Changes

Workflow Collection Structure

collections/ansible_collections/osac/workflows/
├── playbooks/
│   ├── cluster/create.yml, delete.yml, post_install.yml
│   ├── compute_instance/create.yml, delete.yml
│   ├── hostpool/create.yml, delete.yml
│   ├── reporting/cluster_status.yml, hostpool_status.yml
│   ├── maintenance/cleanup_stale_network_resources.yml
│   └── config_as_code.yml
└── roles/workflow_helpers/

Override Pattern

All workflows support customization via override variables:

# Import workflow with overrides
- name: Create cluster with custom infrastructure
  ansible.builtin.import_playbook: osac.workflows.cluster.create
  vars:
    # Override infrastructure provisioning step
    install_step_cluster_infra_override:
      name: moc.custom.esi_infrastructure
      tasks_from: main.yml

Three levels of customization:

  1. Workflow hooks: hook_workflow_start, hook_workflow_complete (all workflows)
  2. Step overrides: Replace major workflow phases (e.g., step_hostpool_infra_override)
  3. Template hooks: Customize template internals (e.g., create_step_modify_vm_spec_override)

Template Enhancements

Templates now support override patterns:

VM Template (ocp_virt_vm):

  • 7 overrideable steps: validate, secrets, modify_vm_spec, pre/post hooks, resources, wait_annotate
  • build_spec is NOT overrideable (use modify_vm_spec hook instead)

Cluster Template (ocp_4_17_small):

  • 6 install steps: pre_install hook, hosted_cluster, cluster_infra, external_access, retrieve_kubeconfig, post_install hook
  • 5 delete steps: pre_delete hook, hosted_cluster, external_access, cluster_infra, post_delete hook
  • All steps overrideable for MOC's ESI integration

Hostpool Workflows:

  • Infrastructure step made overrideable (step_hostpool_infra_override)
  • Enables non-OpenStack/ESI deployments to skip MOC-specific infrastructure

Integration Tests

Complete test suite with 20 passing tests (10 workflows × 2 tests each):

make test              # Run full test cycle
make test-setup        # Create kind cluster + CRDs
make test-run          # Run all tests
make test-teardown     # Cleanup

Test structure:

  • Baseline tests: Use real templates with infrastructure steps mocked
  • Override tests: Verify all override points execute correctly
  • Test collection: osac.test_overrides provides hook implementations that log execution

Test coverage:

  • ✅ All cluster workflows (create, delete, post_install)
  • ✅ All compute_instance workflows (create, delete)
  • ✅ All hostpool workflows (create, delete)
  • ✅ All reporting workflows (cluster_status, hostpool_status)
  • ✅ Maintenance cleanup workflow

Benefits

For MOC:

  • Override infrastructure steps to integrate ESI (Elastic Secure Infrastructure)
  • Override networking to use OpenStack Neutron
  • Customize templates without forking playbooks
  • Stay in sync with upstream osac-aap changes

For other deployments:

  • Use baseline workflows without OpenStack/ESI dependencies
  • Customize infrastructure integration for their environment
  • Override only what's needed, inherit the rest

For maintainers:

  • Single source of truth for workflow logic
  • No code duplication across repositories
  • Easier to add new features and fix bugs

Testing

All integration tests pass:

Passed: 20/20 (100%)
- cluster_create: baseline ✓, overrides ✓
- cluster_delete: baseline ✓, overrides ✓
- cluster_post_install: baseline ✓, overrides ✓
- compute_instance_create: baseline ✓, overrides ✓
- compute_instance_delete: baseline ✓, overrides ✓
- hostpool_create: baseline ✓, overrides ✓
- hostpool_delete: baseline ✓, overrides ✓
- cluster_status_reporting: baseline ✓, overrides ✓
- hostpool_status_reporting: baseline ✓, overrides ✓
- maintenance_cleanup: baseline ✓, overrides ✓

Documentation

  • collections/ansible_collections/osac/workflows/README.md - Collection overview and usage
  • collections/ansible_collections/osac/workflows/docs/override_guide.md - Complete override reference
  • tests/integration/README.md - Test setup and execution guide
  • tests/integration/TEMPLATE_OVERRIDES.md - Template override patterns

Migration Impact

For existing osac-aap users:

  • No changes required - top-level playbooks still exist and work as before
  • Can migrate to collection workflows when ready

For osac-aap-moc:

  • Can now import workflows and pass overrides instead of duplicating playbooks
  • Infrastructure integration becomes configuration, not code

Follow-up Work

MOC-specific Ansible to separate repository:

  • The osac-aap-moc repository should be restructured to use this collection
  • MOC override roles and playbooks should be moved to a dedicated repository
  • This will eliminate code duplication and simplify maintenance
  • Tracked in follow-up issue/PR

Summary by CodeRabbit

  • New Features

    • Added workflow extension points and safe no-op hook defaults plus new importable workflow playbooks and template hook support.
  • Tests

    • Added a comprehensive integration test suite: fixtures, setup/run/teardown scripts, inventory/config, and a Makefile target to run it.
  • Documentation

    • Added workflows README and a detailed override guide with examples.
  • Chores

    • Updated ignore rules, lint configuration, and collection metadata/checksum records for test and workflow artifacts.

@eranco74 eranco74 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Comments

1. Finalizer override safety concern

In the cluster delete workflow, the override guide lists step_remove_finalizer_override as a phase override. Is removing finalizers really safe to override? If someone overrides this and skips it, the resource will be stuck with a dangling finalizer. Consider making finalizer removal CRITICAL (not overrideable), consistent with how it's handled in the compute_instance workflows.

2. Vendor directory sync with osac-templates

This PR modifies files under vendor/ansible_collections/osac/templates/ (ocp_virt_vm, ocp_4_17_small). These vendored templates are also in osac-templates. Are these changes in sync with osac-templates PR #14? If both PRs land, we need to make sure the vendored copy matches what's in the templates repo.

3. ocp_virt_vm refactoring scope

The create.yaml went from 338 lines of inline logic to 67 lines dispatching to 7 sub-task files. The logic looks preserved, but this is a significant refactor hidden inside a "workflow collection" PR. Would it make sense to split the template refactoring into a separate PR in osac-templates first, then vendor it here? That would make each PR easier to review and bisect if issues arise.

4. Naming inconsistency across layers

Workflow-level overrides use hook_workflow_start, template install steps use install_step_*_override, and VM create steps use create_step_*_override. The prefixes differ across layers — this makes sense conceptually but could be confusing for consumers. The override_guide.md documents it well, but is a more uniform naming scheme feasible?

5. template_parameters: {} in compute_instance/create.yml

This hardcodes an empty dict for template_parameters. The existing compute instance playbook passes template parameters from the CRD. Is this intentional, or should it be populated from the ComputeInstance spec?

6. No error handling on hook failures

If a hook (e.g., hook_workflow_start) fails, the workflow will fail but won't clean up any partial state (e.g., finalizer already added, partial infrastructure created). The existing workflows have the same limitation so this isn't a regression, but worth tracking as follow-up work — especially now that external code (overrides) can inject failures into the workflow.

@adriengentil adriengentil left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

few comments, I mainly reviewed the compute instance part, I think it's going to the right direction overall

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these files are vendored form osac.templates collections here: https://github.com/osac-project/osac-templates. you'll need to open a PR there, and re-vendor the dependencies here in osac-aap repo.

But I think we can consider these templates generic now, and should be part of osac-aap, and collections specific to an infrastructure (e.g.: MOC/ESI), should live in their own repo.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not use ansible end-to-end?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

config-as-code is not launched by osac-operator, not sure we need it as part of a workflow as I don't think we want the service provider to customize the "osac" configuration of AAP.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right - undoing the changes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I know it's ugly, but I find it easier to navigate when files are ordered in the workflow order, so have create_01_ , create_02_...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion! I prefer semantic names since the orchestration file already defines the execution order. Numbering would require renaming files whenever steps are reordered or inserted. Happy to reconsider if there's strong preference for it though.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if this stuff should be part of the workflow

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right - removed

@akshaynadkarni

akshaynadkarni commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

Disclaimer:
@avishayt
First of all, thanks for attempting to make our ansible code more modular. It's a huge task! I'm still learning ansible through this project. TBH, it would perhaps take me days to review all the changes 😅 .

However, I wanted to try one of the AI review tools - Qodo - which was made available to developers at RedHat. I used this PR as a guinea pig for setting up and running Qodo locally. Below I'm capturing what Qodo provided me. You are obviously much more familiar with the ansible code than I am. So, perhaps these suggestions will make more sense to you.

Please feel to completely discard as well . I hope you don't mind me sharing the output here.

If you think this was helpful, please do lmk, mainly to understand if Qodo is a good enough review tool in addition to human reviews. Thanks for indulging me 🙏 .


Summary

This PR adds an osac.workflows collection with override support, refactors template roles, and adds integration tests. The override pattern and test approach are sound. Several regressions and test gaps need attention before merge.

High-severity Issues

  1. cleanup_stale_network_resources workflow defaults to noop (behavioral regression)
  • Files:
    • collections/ansible_collections/osac/workflows/playbooks/maintenance/cleanup_stale_network_resources.yml
    • playbook_osac_cleanup_stale_network_resources.yml (existing main playbook)
    • collections/ansible_collections/osac/service/roles/cleanup_stale_network_resources/*
  • Evidence:
    • The existing top-level playbook (playbook_osac_cleanup_stale_network_resources.yml) directly calls osac.service.cleanup_stale_network_resources with namespace var.
    • The new workflow uses a noop as default for the maintenance step; therefore importing the workflow without override will do nothing.
  • Recommendation:
    • Make the default call the cleanup role (osac.service.cleanup_stale_network_resources with cleanup_stale_network_resources_namespace: "{{ lookup('env','POD_NAMESPACE') }}") and keep override available for callers to replace or skip.
  1. Debug diagnostic tasks left in cluster/create.yml (remove before merge)
  • File and evidence:
    • collections/ansible_collections/osac/workflows/playbooks/cluster/create.yml contains three debug/pre_tasks:
      • Debug - Show K8S_AUTH_KUBECONFIG (ansible.builtin.debug)
      • Debug - Test cluster connectivity (ansible.builtin.command: kubectl cluster-info)
      • Debug - Show cluster info result (ansible.builtin.debug var=cluster_info_result)
    • These run kubectl on every invocation and leak information to logs.
  • Recommendation:
    • Remove these diagnostic tasks. If needed, expose them behind an optional pre_tasks hook that callers opt into.
  1. Vendored ocp_4_17_small template now hard-depends on osac.workflows.workflow_helpers
  • Files and evidence:
    • vendor template location referenced in tests and fixtures (fixtures reference osac.templates.ocp_4_17_small).
    • The template's install/delete tasks set defaults using osac.workflows.workflow_helpers/noop.yml, creating a collection dependency for a vendored external template.
  • Recommendation:
    • Replace the reference to the workflows collection with a self-contained noop (e.g., inline debug or meta:no-op) or add a tasks/noop.yml inside the template role so the template remains standalone.

Medium-severity Issues

  1. config_as_code workflow missing integration test
  • Files:
    • collections/ansible_collections/osac/workflows/playbooks/config_as_code.yml exists.
    • tests/integration/run_tests.sh — WORKFLOWS array lists 10 workflows; config_as_code is absent.
  • Recommendation:
    • Add a test target for config_as_code (baseline + overrides) or document/explain why it is excluded and update PR claim of "All 11" to reflect reality.
  1. Hostpool override tests don't verify infra step override executed
  • Files:
    • tests/integration/targets/hostpool_create/tasks/overrides.yml
    • tests/integration/targets/hostpool_delete/tasks/overrides.yml
  • Evidence:
    • Tests set step_hostpool_infra_override to osac.workflows.workflow_helpers/noop.yml, which doesn't write the override log. Assertions check only workflow_start and workflow_complete strings.
  • Recommendation:
    • Use a logging override (e.g., osac.test_overrides.workflow_hooks/maintenance.yml) for infra step override and assert the infra override log entry is present.
  1. workflow_helpers contains unused utility tasks (dead code)
  • Files:
    • collections/ansible_collections/osac/workflows/roles/workflow_helpers/tasks/set_cluster_order_name.yml
    • collections/ansible_collections/osac/workflows/roles/workflow_helpers/tasks/set_lock_holder_id.yml
  • Evidence:
    • Workflows use inline set_fact calls instead of including these utility tasks; the files appear unused.
  • Recommendation:
    • Either remove these files or update workflows to include them for consistency. Pick one approach and apply across playbooks.

Low-severity Issues

  1. step_apply_defaults_default inconsistent tasks_from usage
  • Files:
    • collections/ansible_collections/osac/workflows/playbooks/cluster/create.yml (explicit tasks_from: main.yml)
    • cluster/delete.yml and cluster/post_install.yml (omit tasks_from)
  • Recommendation:
    • Add tasks_from: main.yml to delete.yml and post_install.yml for reader symmetry (no runtime difference, just clarity).

What this PR does well

  • Override pattern _override | default(_default) applied consistently.
  • Clear comments marking CRITICAL vs overrideable steps.
  • Correct switch to include_role to enable dynamic role names.
  • Ocp_virt_vm template refactor into focused task files increases maintainability.
  • Test override infrastructure using logging roles is a sound test pattern.
  • Baseline tests correctly stub infrastructure via noop overrides.
  • Documentation and override guide comprehensive.

Suggested Action Items (priority order)

  1. Fix cleanup_stale_network_resources default to call the cleanup role (High).
  2. Remove the kubectl/debug tasks from cluster/create.yml (High).
  3. Restore vendored template independence by removing hard reference to osac.workflows in ocp_4_17_small (High).
  4. Add or document config_as_code integration test status (Medium).
  5. Update hostpool override tests to assert infra override execution (Medium).
  6. Remove or use the unused workflow_helpers task files (Medium).
  7. Normalize tasks_from usage for apply_defaults steps (Low).

Appendix — Evidence locations (selected)

  • cleanup workflow:
    • collections/ansible_collections/osac/workflows/playbooks/maintenance/cleanup_stale_network_resources.yml
    • playbook_osac_cleanup_stale_network_resources.yml
    • collections/ansible_collections/osac/service/roles/cleanup_stale_network_resources/tasks/cleanup.yaml
  • cluster create diagnostics:
    • collections/ansible_collections/osac/workflows/playbooks/cluster/create.yml (contains kubectl cluster-info and debug tasks)
  • vendored template references:
    • tests/integration/fixtures/clusterorder-test.yaml (templateID: osac.templates.ocp_4_17_small)
    • tests/integration/TEMPLATE_OVERRIDES.md
  • tests list:
    • tests/integration/run_tests.sh (WORKFLOWS array — 10 entries; config_as_code missing)
  • hostpool tests:
    • tests/integration/targets/hostpool_create/tasks/overrides.yml
    • tests/integration/targets/hostpool_delete/tasks/overrides.yml
  • unused helper task files:
    • collections/ansible_collections/osac/workflows/roles/workflow_helpers/tasks/set_cluster_order_name.yml
    • collections/ansible_collections/osac/workflows/roles/workflow_helpers/tasks/set_lock_holder_id.yml
  • tasks_from inconsistency:
    • cluster/create.yml, cluster/delete.yml, cluster/post_install.yml under collections/ansible_collections/osac/workflows/playbooks/cluster/

Developer guidance: why these are problems and better approaches

  1. cleanup_stale_network_resources workflow defaults to noop
  • Why this is a problem:
    • Users expect a playbook named cleanup_stale_network_resources to perform cleanup by default. A noop default creates a silent failure mode where resources are not reclaimed and alerts/tests won't surface the omission.
    • In automation pipelines (CI/CD, scheduled AAP jobs), a missing default leads to resource leakage over time, increasing operational burden.
  • Better approach:
    • Make the cleanup role the default implementation (osac.service.cleanup_stale_network_resources) and keep the _override variable to allow replacement or skipping.
    • Keep the namespace variable defaulted to lookup('env','POD_NAMESPACE') so the workflow mirrors previous behavior.
  1. Debug diagnostic tasks left in cluster/create.yml
  • Why this is a problem:
    • Executing kubectl in every workflow run introduces an external dependency and can fail unpredictably (network issues, auth missing), increasing job flakiness.
    • Printing auth/kubeconfig details into logs risks leaking sensitive information in shared CI/AAP logs.
  • Better approach:
    • Remove these tasks from production code. If retained for troubleshooting, gate them behind an opt-in variable or a test-only playbook so they only run when explicitly enabled.
  1. Vendored ocp_4_17_small template now hard-depends on osac.workflows.workflow_helpers
  • Why this is a problem:
    • Vendored templates are intended to be usable standalone. Referencing a collection from the same repo as a default introduces coupling and will break downstream consumers who expect the vendor artifact to be self-contained.
    • This circular dependency increases friction for reuse and packaging (e.g., publishing the template separately or using it in other contexts).
  • Better approach:
    • Provide an internal noop inside the template role (tasks/noop.yml) or use an inline ansible.builtin.debug/meta:no-op for defaults. Allow callers to override to osac.workflows.workflow_helpers when they use the workflows collection, but do not require it.
  1. config_as_code workflow missing integration test
  • Why this is a problem:
    • A claimed coverage of "All 11" workflows is inaccurate; untested workflows can harbour regressions or structural issues (the split-play structure here) which CI won't catch.
    • Lack of test coverage reduces confidence in refactors and in future changes.
  • Better approach:
    • Add config_as_code to the test matrix with a baseline and an override test using the same noop/logging pattern, or explicitly document why the workflow is excluded and adjust the PR messaging.
  1. Hostpool override tests don't verify infra step override executed
  • Why this is a problem:
    • Tests are giving a false positive signal: they pass even if the infra override mechanism is broken because the infra override itself is a noop that doesn't record execution.
    • This undermines the purpose of the override tests and hides regressions.
  • Better approach:
    • In override tests, use a logging override role that appends a known string to the override log. Update assertions to check for that string so each declared override point is asserted.
  1. workflow_helpers contains unused utility tasks (dead code)
  • Why this is a problem:
    • Dead files confuse maintainers about the intended architecture (centralized helpers vs inline facts) and increase the surface area for future bugs.
    • Inconsistency increases cognitive load when editing workflows.
  • Better approach:
    • Decide on one pattern: either remove these unused helper files (if inline facts are preferred) or update workflows to call the helper tasks so logic is centralized and easier to change.
  1. step_apply_defaults_default inconsistent tasks_from usage
  • Why this is a problem:
    • This is a readability/consistency issue rather than a runtime bug; inconsistent patterns slow reviewers and newcomers and can hide copy-paste mistakes.
  • Better approach:
    • Make the tasks_from usage consistent across create/delete/post_install playbooks (explicitly set tasks_from: main.yml) to improve clarity.

Alternative design notes (high-level)

  • Defaults should be opinionated and perform the core advertised behavior; let overrides opt out or replace.
  • Vendored templates must remain self-contained to preserve portability.
  • Continue using the three-level override model — it supports fine-grained extensibility — but ensure defaults and tests align so that behavior is predictable.

@avishayt
avishayt requested a review from danmanor March 22, 2026 10:56
Comment on lines +41 to 49
- name: Step - Create cluster infrastructure
ansible.builtin.include_role:
name: "{{ (install_step_cluster_infra_override | default(install_step_cluster_infra_default)).name }}"
tasks_from: "{{ (install_step_cluster_infra_override | default(install_step_cluster_infra_default)).tasks_from }}"
vars:
cluster_infra_state: present
cluster_infra_name: "{{ cluster_order.metadata.name }}"
cluster_infra_namespace: "{{ cluster_working_namespace }}"
cluster_infra_node_requests: "{{ cluster_order.spec.nodeRequests | unique(attribute='resourceClass') }}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the user's override step needs different vars ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The vars block is the interface contract, not a restriction. Override roles receive these vars but can ignore them and use their own logic. They also have access to all workflow-level variables. This documents what's available while allowing flexibility.

Comment on lines +68 to +72

- name: Step - Post-install hook
ansible.builtin.include_role:
name: "{{ (install_step_post_install_hook_override | default(install_step_post_install_hook_default)).name }}"
tasks_from: "{{ (install_step_post_install_hook_override | default(install_step_post_install_hook_default)).tasks_from }}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need post create hook and also post template hook ? they are executed right after the other no ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, different layers:

  • Template hook (install_step_post_install_hook) - Runs at end of template execution, for template-specific customization
  • Workflow hook (hook_workflow_complete) - Runs at end of entire workflow (after template + finalizers), for workflow-wide concerns like notifications

They serve different purposes: template hook for infrastructure-specific logic, workflow hook for cross-cutting concerns.

@danmanor danmanor left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@avishayt So if I understand correctly OSAC operator will trigger the workflows from the new collection instead of the global playbooks. Few questions:

  • You didn't remove them because of backward compatibility ?
  • Lets say a user wants to override a step in the template - you wrote they need to import the role and set the var to the their step instead. How exactly they should be doing it ? where should they define the step ?

@avishayt

Copy link
Copy Markdown
Contributor Author

@avishayt So if I understand correctly OSAC operator will trigger the workflows from the new collection instead of the global playbooks. Few questions:

  • You didn't remove them because of backward compatibility ?
  • Lets say a user wants to override a step in the template - you wrote they need to import the role and set the var to the their step instead. How exactly they should be doing it ? where should they define the step ?

Backwards compatibility: Yes, global playbooks remain as thin wrappers calling osac.workflows. Existing AAP jobs/rulebooks keep working.

How to use overrides: Users create their own playbooks that import the workflow collection and pass override vars:

# User's playbook (in their own repo)
- name: Create cluster with custom infra
  ansible.builtin.import_playbook: osac.workflows.cluster.create
  vars:
    cluster_order: "{{ ansible_eda.event.payload }}"
    install_step_cluster_infra_override:
      name: my_company.custom_infra
      tasks_from: main.yml

Then point their AAP job template to their playbook. Full examples in override_guide.md.

@avishayt

avishayt commented Mar 24, 2026

Copy link
Copy Markdown
Contributor Author

Addressed all @eranco74 review comments:

  1. ✅ Finalizer override safety - Already correct (NOT overrideable)
  2. ✅ Vendor sync - Fixed in osac-templates PR Use explicit fqdn in api service publishing configuration #19
  3. ✅ Refactoring scope - Done in osac-templates first ✓
  4. ✅ Naming inconsistency - Intentional design (different layers)
  5. ✅ template_parameters hardcoded - Fixed (extract from spec)
  6. ⏸️ Error handling on hook failures - Acknowledged as future work

Addressed all @adriengentil review comments:

  1. ✅ Vendored templates - Fixed in osac-templates PR Use explicit fqdn in api service publishing configuration #19
  2. ✅ config_as_code.yml - Removed from workflows collection
  3. ✅ cleanup_stale_network_resources.yml - Removed from workflows collection
  4. ✅ File numbering - Already discussed/declined (semantic names preferred)
  5. ⏸️ "Why not ansible end-to-end for tests?" - Addressed via Slack

Addressed all @akshaynadkarni review comments:

  1. ✅ cleanup_stale_network_resources - Removed
  2. ✅ Debug tasks in cluster/create.yml - Removed
  3. ✅ Vendored template dependency - Fixed (added noop.yml)
  4. ✅ config_as_code missing test - Removed the workflow
  5. ✅ Hostpool override tests - Added logging override + assertions
  6. ✅ workflow_helpers dead code - Removed unused files
  7. ✅ tasks_from inconsistency - Normalized across workflows

avishayt added 13 commits March 25, 2026 16:58
Add osac.workflows collection with cluster/create.yml workflow. Enables
customization via generic hooks (workflow start/complete), modification
hooks (HostedCluster/NodePool YAML), and phase overrides.

Update osac.service.hosted_cluster to use build→hook→apply pattern for
HostedCluster and NodePool resource creation.
Add cluster/delete.yml workflow with same customization pattern as create
workflow. Provides generic hooks (workflow start/complete) and phase
overrides for defaults, namespace, template execution, and finalizer removal.
Add cluster/post_install.yml workflow for post-installation cluster
configuration. Provides generic hooks and phase overrides. Sets KUBECONFIG
environment from admin_kubeconfig variable for cluster access.
Add hostpool/create.yml and hostpool/delete.yml workflows for host pool
infrastructure management. Provides only generic hooks (workflow_start,
workflow_complete) as extension points. All other steps are critical.
Add reporting/cluster_status.yml and reporting/hostpool_status.yml workflows
for annotating CRDs with workflow status. Provides only generic hooks as
extension points. All status reporting is critical.
Wraps osac.config_as_code.subscription and osac.config_as_code.configure playbooks with generic workflow hooks at boundaries.

Extension points:
- hook_workflow_start: Custom pre-workflow tasks
- hook_workflow_complete: Custom post-workflow tasks
Add maintenance/cleanup_stale_network_resources.yml workflow for cleaning up
orphaned network resources. Provides generic hooks as extension points.
Add osac.test_overrides collection containing hook roles for testing workflow
override mechanisms. Includes roles for workflow hooks, cluster hooks, VM
create/delete hooks, and a test template.

All hooks log execution to /tmp/osac_test_overrides.log for verification.
Add complete integration test suite for osac.workflows collection:

- Test targets for all workflows (cluster, compute_instance, hostpool, reporting, maintenance)
- Each target has baseline and override tests
- Test fixtures for ClusterOrder, ComputeInstance, and HostPool CRDs
- Test environment setup script (kind cluster, KubeVirt/CDI CRDs)
- Test runner script with summary reporting
- Documentation for template override patterns

Tests use real templates with selective overrides to prevent actual
infrastructure provisioning while validating workflow logic.
Add Makefile with targets for running integration tests:
- test-setup: Create kind cluster and install CRDs
- test-run: Run all integration tests
- test-teardown: Delete kind cluster
- test: Run complete test cycle
These workflows don't belong in the workflows collection:
- config_as_code is for AAP platform configuration, not tenant provisioning
- cleanup_stale_network_resources is a maintenance task, not a provisioning workflow

The workflows collection should only contain tenant resource provisioning
workflows (cluster, compute_instance, hostpool). Config-as-code and maintenance
tasks are called separately, not triggered by osac-operator.
Removed diagnostic tasks that run kubectl and print sensitive information:
- kubectl cluster-info execution (external dependency, flaky)
- K8S_AUTH_KUBECONFIG logging (potential credential leak)
- Cluster order debug output before/after defaults

These tasks were left over from development and should not run in production.
Added local noop.yml to the template and updated install.yaml and delete.yaml
to reference it instead of osac.workflows.workflow_helpers. This removes the
circular dependency where a vendored template required the workflows collection
from the same repository.

Vendored templates should be standalone and not depend on other collections
in the same repo. This allows them to be used independently.

TODO: Apply this fix upstream in osac-templates repository

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
.ansible-lint-ignore (2)

31-33: Track workflows collection metadata completion.

The comment indicates changelog and runtime metadata will be added when the workflows collection is published. Since osac.workflows is production code (unlike test_overrides), ensure there's a tracking mechanism (issue, checklist, or milestone) to complete this metadata before the collection is released or consumed by downstream users.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.ansible-lint-ignore around lines 31 - 33, Add a formal tracking item to
ensure the workflows collection's missing metadata (changelog and runtime
entries referenced for
collections/ansible_collections/osac/workflows/galaxy.yml) is completed before
release: create a ticket/issue or milestone titled e.g. "osac.workflows
galaxy.yml metadata" and attach a small checklist (add changelog, add runtime
metadata, verify schema) and link that ticket from the comment or repo release
checklist so maintainers must close it before publishing/consuming the
collection.

11-30: Extensive risky-file-permissions suppressions for test logging.

While the 19 suppressions are justified for test-only logging code, consider adding explicit mode: parameters (e.g., mode: '0644') to the lineinfile tasks for consistency with security best practices, even in test code. This would eliminate the need for these suppressions and maintain uniform standards across the codebase.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.ansible-lint-ignore around lines 11 - 30, The PR adds many
"risky-file-permissions" suppressions for test-only lineinfile tasks; instead
edit each affected lineinfile task (names include apply_defaults,
modify_hosted_cluster, modify_nodepool, delete, install, post_install,
modify_vm_spec, post_create_hook, pre_create_hook, resources, secrets,
wait_annotate, post_delete_hook, pre_delete_hook, hostpool_infra, maintenance,
workflow_complete, workflow_start) to explicitly set a secure file mode (e.g.,
mode: '0644') on the target file operations so the tasks convey intended
permissions and you can remove the ansible-lint suppressions. Ensure the mode
field is added under the same task that uses the lineinfile module and follow
Ansible YAML formatting for the mode string.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.ansible-lint-ignore:
- Around line 31-33: Add a formal tracking item to ensure the workflows
collection's missing metadata (changelog and runtime entries referenced for
collections/ansible_collections/osac/workflows/galaxy.yml) is completed before
release: create a ticket/issue or milestone titled e.g. "osac.workflows
galaxy.yml metadata" and attach a small checklist (add changelog, add runtime
metadata, verify schema) and link that ticket from the comment or repo release
checklist so maintainers must close it before publishing/consuming the
collection.
- Around line 11-30: The PR adds many "risky-file-permissions" suppressions for
test-only lineinfile tasks; instead edit each affected lineinfile task (names
include apply_defaults, modify_hosted_cluster, modify_nodepool, delete, install,
post_install, modify_vm_spec, post_create_hook, pre_create_hook, resources,
secrets, wait_annotate, post_delete_hook, pre_delete_hook, hostpool_infra,
maintenance, workflow_complete, workflow_start) to explicitly set a secure file
mode (e.g., mode: '0644') on the target file operations so the tasks convey
intended permissions and you can remove the ansible-lint suppressions. Ensure
the mode field is added under the same task that uses the lineinfile module and
follow Ansible YAML formatting for the mode string.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9634e355-a234-4b46-b293-b93e3e75e978

📥 Commits

Reviewing files that changed from the base of the PR and between 7d51e69 and 25049ac.

📒 Files selected for processing (2)
  • .ansible-lint-ignore
  • .ansible-lint.yml
✅ Files skipped from review due to trivial changes (1)
  • .ansible-lint.yml

1. Exclude massopencloud/esi collection (third-party code)
2. Skip parser-error globally (false positive on multi-play test playbooks)
3. Skip fqcn[keyword] (workflows intentionally use collections: for resolution)
4. Downgrade risky-file-permissions to warning (test logging uses lineinfile)
5. Configure kinds mapping for integration test playbooks
6. Add ignore entries for test-only galaxy.yml and workflows galaxy.yml metadata

Production code in osac.workflows and osac.service still gets full linting.
Test code gets meaningful checks but problematic test-specific patterns downgraded.

Note: 62 var-naming violations remain in osac.service roles (pre-existing code).
These should be addressed in a separate PR to avoid scope creep.
@avishayt

Copy link
Copy Markdown
Contributor Author

Fixed CodeRabbit comments:

  • ✅ #2988885244: Added kubernetes.core dependency to workflows/galaxy.yml
  • ✅ #2988885256: Fixed kubeconfig fallback with default(..., true) in cluster/create.yml
  • ✅ #2988885265: Added POD_NAMESPACE fallback in cluster/create.yml
  • ✅ #2988885301: Fixed kubeconfig fallback with default(..., true) in hostpool/create.yml
  • ✅ #2988885356: Added POD_NAMESPACE fallback in hostpool/create.yml
  • ✅ #2988885378: Made workflow_helpers/tasks/main.yml executable by importing noop.yml

@avishayt

Copy link
Copy Markdown
Contributor Author

Fixed additional CodeRabbit comments:

  • ✅ #2989179945: hostpool/delete.yml already has default(..., true) for kubeconfig
  • ✅ #2989180046: Removed stale config_as_code references from TEMPLATE_OVERRIDES.md
  • ✅ #2993159322: Fixed TEMPLATE_OVERRIDES.md build_spec contradiction - removed from override example as it's not overrideable

@avishayt
avishayt force-pushed the overrides-and-tests branch from 6e2c5f9 to 06b5dd2 Compare March 26, 2026 09:46
@adriengentil

Copy link
Copy Markdown
Contributor

@avishayt some of these fixes are in the vendor directory, right? do you plan to open a PR in osac-templates, and re-vendor?

1. Add kubernetes.core dependency to workflows/galaxy.yml
2. Fix kubeconfig fallback to handle empty env vars with default(..., true)
   - Applied to all 9 workflow playbooks
3. Add POD_NAMESPACE fallbacks in cluster/create.yml and hostpool/create.yml
4. Make workflow_helpers/tasks/main.yml executable by importing noop.yml
5. Remove stale config_as_code references from documentation
6. Reduce logging verbosity in hostpool/create.yml

All 18 integration tests pass.

Note: Timestamp comparison issue in vendored create_resources.yaml needs to be
fixed in upstream osac-templates repository, not here.
Re-vendored osac.templates after merging upstream PR osac-project#21 which fixes timestamp
comparison in create_resources.yaml to use to_datetime filter.

Upstream fix: osac-project/osac-templates#21
@avishayt
avishayt force-pushed the overrides-and-tests branch from 06b5dd2 to 28e9777 Compare March 26, 2026 11:14
@avishayt

Copy link
Copy Markdown
Contributor Author

Re-vendored osac.templates with timestamp comparison fix:

  1. Created PR osac-project/osac-templates#21 to fix timestamp comparison in create_resources.yaml
  2. PR was merged to osac-templates main
  3. Re-vendored osac.templates collection with the fix
  4. All 18 integration tests pass ✅

The timestamp comparison now properly uses Jinja's to_datetime filter instead of string comparison.

@openshift-ci

openshift-ci Bot commented Mar 26, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: adriengentil, avishayt

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants