Skip to content
This repository was archived by the owner on Sep 9, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
gateway_settings:

Check warning on line 2 in collections/ansible_collections/osac/config_as_code/roles/aap/vars/controller.yml

View workflow job for this annotation

GitHub Actions / ansible-lint

var-naming[no-role-prefix]

Variables names from within roles should use aap_ as a prefix. (vars: gateway_settings)
gateway_access_token_expiration: 7200

# Create a project from the specified git repo
Expand Down Expand Up @@ -171,6 +171,30 @@
allow_simultaneous: true
ask_variables_on_launch: true
verbosity: 0
- name: "{{ aap_prefix }}-create-public-ip-pool"
project: "{{ aap_prefix }}"
organization: "{{ aap_organization_name }}"
job_type: run
playbook: "playbook_osac_create_public_ip_pool.yml"
inventory: "{{ aap_prefix }}-networking-operations"
execution_environment: "{{ aap_prefix }}-ee"
instance_groups:
- "{{ aap_prefix }}-networking-operations-ig"
allow_simultaneous: true
ask_variables_on_launch: true
verbosity: 0
- name: "{{ aap_prefix }}-delete-public-ip-pool"
project: "{{ aap_prefix }}"
organization: "{{ aap_organization_name }}"
job_type: run
playbook: "playbook_osac_delete_public_ip_pool.yml"
inventory: "{{ aap_prefix }}-networking-operations"
execution_environment: "{{ aap_prefix }}-ee"
instance_groups:
- "{{ aap_prefix }}-networking-operations-ig"
allow_simultaneous: true
ask_variables_on_launch: true
verbosity: 0

controller_job_template_surveys: # noqa: var-naming[no-role-prefix]
- name: "{{ aap_prefix }}-create-hosted-cluster-post-install"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
# Defaults for metallb_l2 role
# Labels are defined inline in the task files alongside resource definitions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
argument_specs:
create_public_ip_pool:
options:
public_ip_pool:
type: dict
required: true
description: PublicIPPool CR from fulfillment-api via EDA payload
public_ip_pool_name:
type: str
required: true
description: Name of the PublicIPPool resource
template_parameters:
type: dict
description: Template-specific parameters (reserved for future use)
options: {}
default: {}

delete_public_ip_pool:
options:
public_ip_pool:
type: dict
required: true
description: PublicIPPool CR from fulfillment-api via EDA payload
public_ip_pool_name:
type: str
required: true
description: Name of the PublicIPPool resource
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: MetalLB L2 Implementation
description: >
Provisions MetalLB IPAddressPool and L2Advertisement resources for PublicIPPool.
Handles L2-based IP address advertisement on bare-metal clusters.

template_type: network

# PublicIPPool registration fields
implementation_strategy: metallb-l2
capabilities:
supports_ipv4: true
supports_ipv6: true
supports_dual_stack: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
# Create MetalLB IPAddressPool and L2Advertisement for PublicIPPool
# 1. Creates IPAddressPool with autoAssign: false and addresses from CR spec.cidrs
# 2. Creates L2Advertisement referencing the IPAddressPool by name

- name: Include get remote cluster kubeconfig
ansible.builtin.include_role:
name: osac.service.common
tasks_from: get_remote_cluster_kubeconfig

- name: Extract PublicIPPool configuration
ansible.builtin.set_fact:
pool_name: "{{ public_ip_pool.metadata.name }}"
pool_cidrs: "{{ public_ip_pool.spec.cidrs }}"

- name: Display PublicIPPool information
ansible.builtin.debug:
msg:
- "Creating MetalLB resources for PublicIPPool '{{ pool_name }}'"
- "CIDRs: {{ pool_cidrs }}"

- name: Create IPAddressPool
kubernetes.core.k8s:
kubeconfig: "{{ remote_cluster_kubeconfig | default(omit) }}"
state: present
definition:
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: "{{ pool_name }}"
namespace: metallb-system
labels:
osac.openshift.io/publicippool: "{{ pool_name }}"
osac.io/managed-by: osac-fulfillment
spec:
autoAssign: false
addresses: "{{ pool_cidrs }}"
register: ipaddresspool_result

# MetalLB webhook may not be ready yet after operator install
# Retry once every 10 seconds for 10 minutes
retries: 60
delay: 10
until: ipaddresspool_result is successful

- name: Display IPAddressPool creation result
ansible.builtin.debug:
msg:
- "IPAddressPool '{{ pool_name }}' created successfully"
- "Changed: {{ ipaddresspool_result.changed | default(false) }}"

- name: Create L2Advertisement
kubernetes.core.k8s:
kubeconfig: "{{ remote_cluster_kubeconfig | default(omit) }}"
state: present
definition:
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: "{{ pool_name }}-l2adv"
namespace: metallb-system
labels:
osac.openshift.io/publicippool: "{{ pool_name }}"
osac.io/managed-by: osac-fulfillment
spec:
ipAddressPools:
- "{{ pool_name }}"
register: l2advertisement_result

# MetalLB webhook may not be ready yet after operator install
retries: 60
delay: 10
until: l2advertisement_result is successful

- name: Display L2Advertisement creation result
ansible.builtin.debug:
msg:
- "L2Advertisement '{{ pool_name }}-l2adv' created successfully"
- "Changed: {{ l2advertisement_result.changed | default(false) }}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
# Delete MetalLB L2Advertisement and IPAddressPool for PublicIPPool
# 1. Deletes L2Advertisement first (must be removed before pool)
# 2. Deletes IPAddressPool
# Handles "not found" errors gracefully for both resources

- name: Include get remote cluster kubeconfig
ansible.builtin.include_role:
name: osac.service.common
tasks_from: get_remote_cluster_kubeconfig

- name: Extract PublicIPPool configuration
ansible.builtin.set_fact:
pool_name: "{{ public_ip_pool.metadata.name }}"

- name: Display deletion information
ansible.builtin.debug:
msg:
- "Deleting MetalLB resources for PublicIPPool '{{ pool_name }}'"

- name: Delete L2Advertisement
kubernetes.core.k8s:
kubeconfig: "{{ remote_cluster_kubeconfig | default(omit) }}"
state: absent
api_version: metallb.io/v1beta1
kind: L2Advertisement
name: "{{ pool_name }}-l2adv"
namespace: metallb-system
wait: true
wait_timeout: 300
register: l2adv_delete_result
retries: 3
delay: 10
until: >-
l2adv_delete_result is successful
or ('NotFound' in (l2adv_delete_result.msg | default('')))
failed_when:
- l2adv_delete_result.failed | default(false)
- "'NotFound' not in (l2adv_delete_result.msg | default(''))"

- name: Display L2Advertisement deletion result
ansible.builtin.debug:
msg:
- "L2Advertisement '{{ pool_name }}-l2adv' deletion completed"
- "Changed: {{ l2adv_delete_result.changed | default(false) }}"

- name: Delete IPAddressPool
kubernetes.core.k8s:
kubeconfig: "{{ remote_cluster_kubeconfig | default(omit) }}"
state: absent
api_version: metallb.io/v1beta1
kind: IPAddressPool
name: "{{ pool_name }}"
namespace: metallb-system
wait: true
wait_timeout: 300
register: ipaddresspool_delete_result
retries: 3
delay: 10
until: >-
ipaddresspool_delete_result is successful
or ('NotFound' in (ipaddresspool_delete_result.msg | default('')))
failed_when:
- ipaddresspool_delete_result.failed | default(false)
- "'NotFound' not in (ipaddresspool_delete_result.msg | default(''))"

- name: Display IPAddressPool deletion result
ansible.builtin.debug:
msg:
- "IPAddressPool '{{ pool_name }}' deletion completed"
- "Changed: {{ ipaddresspool_delete_result.changed | default(false) }}"
36 changes: 36 additions & 0 deletions playbook_osac_create_public_ip_pool.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
- name: Create a PublicIPPool resource
hosts: localhost
gather_facts: false

vars:
public_ip_pool: "{{ ansible_eda.event.payload }}"
public_ip_pool_name: "{{ ansible_eda.event.payload.metadata.name }}"
# Implementation strategy set by osac-operator from PublicIPPool spec
implementation_strategy: >-
{{ (ansible_eda.event.payload.metadata.annotations | default({}))
.get('osac.openshift.io/implementation-strategy', '') }}
template_parameters: {}

pre_tasks:
- name: Show EDA Event
ansible.builtin.debug:
var: ansible_eda.event.payload

- name: Validate implementation strategy is set
ansible.builtin.fail:
msg: "Missing required annotation 'osac.openshift.io/implementation-strategy'"
when: implementation_strategy | length == 0

tasks:
- name: Display PublicIPPool information
ansible.builtin.debug:
msg:
- "PublicIPPool name: {{ public_ip_pool_name }}"
- "Implementation strategy: {{ implementation_strategy }}"
- "Template parameters: {{ template_parameters }}"

- name: Call the selected PublicIPPool role
ansible.builtin.include_role:
name: "osac.templates.{{ implementation_strategy | replace('-', '_') }}"
tasks_from: create_public_ip_pool
35 changes: 35 additions & 0 deletions playbook_osac_delete_public_ip_pool.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
- name: Delete a PublicIPPool resource
hosts: localhost
gather_facts: false

vars:
public_ip_pool: "{{ ansible_eda.event.payload }}"
public_ip_pool_name: "{{ ansible_eda.event.payload.metadata.name }}"
# Implementation strategy set by osac-operator from PublicIPPool spec
implementation_strategy: >-
{{ (ansible_eda.event.payload.metadata.annotations | default({}))
.get('osac.openshift.io/implementation-strategy', '') }}
template_parameters: {}

pre_tasks:
- name: Show EDA Event
ansible.builtin.debug:
var: ansible_eda.event.payload

- name: Validate implementation strategy is set
ansible.builtin.fail:
msg: "Missing required annotation 'osac.openshift.io/implementation-strategy'"
when: implementation_strategy | length == 0

tasks:
- name: Display PublicIPPool information
ansible.builtin.debug:
msg:
- "Deleting PublicIPPool: {{ public_ip_pool_name }}"
- "Implementation strategy: {{ implementation_strategy }}"

- name: Call the selected PublicIPPool role
ansible.builtin.include_role:
name: "osac.templates.{{ implementation_strategy | replace('-', '_') }}"
tasks_from: delete_public_ip_pool
14 changes: 14 additions & 0 deletions rulebooks/cluster_fulfillment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,17 @@
run_job_template:
name: "{{ job_template_prefix }}-delete-subnet"
organization: "{{ job_template_organization }}"

- name: Create public IP pool
condition: event.meta.endpoint == "create-public-ip-pool"
action:
run_job_template:
name: "{{ job_template_prefix }}-create-public-ip-pool"
organization: "{{ job_template_organization }}"

- name: Delete public IP pool
condition: event.meta.endpoint == "delete-public-ip-pool"
action:
run_job_template:
name: "{{ job_template_prefix }}-delete-public-ip-pool"
organization: "{{ job_template_organization }}"
Loading