Commit a93a415e authored by Sergio Gimenez's avatar Sergio Gimenez
Browse files

Refactor federation-manager roles to follow standard pattern

- Create role-template/ with standard structure and documentation
- Refactor federation-manager role:
  - Split monolithic 95-line main.yml into deploy/undeploy tasks
  - Add state-based routing (federation_manager_state)
  - Organize defaults with clear section headers
  - Convert kubectl commands to kubernetes.core.k8s module
- Refactor federation-manager-remote role:
  - Apply same pattern as federation-manager
  - Add state-based routing (remote_federation_manager_state)
  - Add explanatory comments about simulating partner OP
- Add ROLE_REFACTORING.md documenting progress and standards

Benefits:
- Self-documenting: Clear where deploy/undeploy logic lives
- Consistent: Same pattern across roles
- Maintainable: Separated concerns, DRY principles
- Flexible: Can toggle components with state variable
parent 0e329628
Loading
Loading
Loading
Loading

ROLE_REFACTORING.md

0 → 100644
+139 −0
Original line number Diff line number Diff line
# Role Refactoring Progress

## Goal
Standardize all OOP roles to follow a consistent, self-documenting pattern.

## Standard Pattern

```
roles/component-name/
├── defaults/main.yml      # All config with clear section comments
├── tasks/
│   ├── main.yml           # Entry point with state-based routing
│   ├── deploy.yml         # All deployment logic
│   ├── undeploy.yml       # All cleanup logic
│   └── verify.yml         # Health checks (optional)
└── templates/             # K8s manifests
```

### Key Principles
1. **State-based**: All roles support `<component>_state: present|absent`
2. **Separation**: Deploy/undeploy logic in separate files
3. **Self-documenting**: Clear section headers and comments
4. **Consistent**: Same pattern across all roles

## Completed Refactoring

### ✅ Role Template (`ansible/role-template/`)
- Created standard template for new roles
- Includes README with usage instructions
- Template files for defaults, tasks (main, deploy, undeploy, verify)

### ✅ federation-manager
**Before**: 95-line monolithic `main.yml`
**After**: 
- `defaults/main.yml`: Organized with clear sections (88 lines)
- `tasks/main.yml`: Simple 9-line dispatcher
- `tasks/deploy.yml`: All deployment logic (118 lines)
- `tasks/undeploy.yml`: All cleanup logic (68 lines)

**Changes**:
- Added `federation_manager_state` variable support
- Organized defaults into logical sections with headers
- Converted kubectl commands to kubernetes.core.k8s module
- Added timeout configuration variable
- Clear comments explaining each component

### ✅ federation-manager-remote
**Before**: 95-line monolithic `main.yml`
**After**:
- `defaults/main.yml`: Organized with clear sections (95 lines)
- `tasks/main.yml`: Simple 9-line dispatcher
- `tasks/deploy.yml`: All deployment logic (118 lines)
- `tasks/undeploy.yml`: All cleanup logic (68 lines)

**Changes**:
- Added `remote_federation_manager_state` variable support
- Organized defaults with explanatory comments
- Added note explaining this simulates a partner operator
- Clarified that it shares ECP with local FM

## Roles Already Following Pattern

These roles already follow (or mostly follow) the standard pattern:

### ✅ oeg (Open Exposure Gateway)
- ✓ State-based (`oeg_state`)
- ✓ Separate deploy.yml/undeploy.yml
- ✓ Clean structure

### ✅ srm (Service Resource Manager)
- ✓ State-based (`srm_state`)
- ✓ Separate deploy.yml/undeploy.yml
- ✓ Clean structure

### ✅ lite2edge
- ✓ State-based (`lite2edge_state`)
- ✓ Separate deploy.yml/undeploy.yml
- ✓ Clean structure

### ✅ i2edge (Mostly compliant)
- ✓ Separate task files (deploy, undeploy, verify, prerequisites)
- ✓ State-based (`i2edge_state`)
- ⚠️ More complex due to local build requirements
- Recommendation: Keep as-is, it's well-structured

## Roles Needing Refactoring

### 🔲 artefact-manager
- Current: Monolithic 35-line main.yml
- Needs: Split into deploy/undeploy, add state variable

### 🔲 homer
- Current: Monolithic 60-line main.yml  
- Needs: Split into deploy/undeploy, add state variable

### 🔲 prometheus
- Current: Has install.yml and verify.yml
- Needs: Rename install.yml → deploy.yml, add undeploy.yml, add state variable

### 🔲 zot
- Current: Has install.yml and verify.yml
- Needs: Rename install.yml → deploy.yml, add undeploy.yml, add state variable

### 🔲 node-feature-discovery
- Current: Has install.yml
- Needs: Rename install.yml → deploy.yml, add undeploy.yml, add state variable

### 🔲 kind-cluster
- Special case: Infrastructure role, different pattern is OK
- Recommendation: Document as infrastructure exception

### 🔲 helm
- Special case: Tool installation role
- Recommendation: Document as utility exception

## Next Steps

1. **Test current changes**: Verify federation-manager and remote work correctly
2. **Refactor remaining roles**: artefact-manager, homer, prometheus, zot, nfd
3. **Update playbooks**: Ensure all playbooks work with new state-based roles
4. **Documentation**: Add role-specific README.md files
5. **Validation**: Run ansible-lint on refactored roles

## Benefits Achieved

-**Discoverability**: "Where's the deployment logic?" → "Look in tasks/deploy.yml"
-**Consistency**: All roles work the same way
-**Maintainability**: Changes in one place, clear separation of concerns
-**Self-documenting**: Structure and comments make purpose clear
-**Reusability**: Template makes adding new roles easy
-**State management**: Can toggle components on/off easily

## Testing Checklist

- [ ] Deploy single OOP with refactored federation-manager
- [ ] Undeploy works correctly
- [ ] Remote federation manager deploys independently
- [ ] No regressions in existing scenarios
- [ ] ansible-lint passes
+63 −0
Original line number Diff line number Diff line
# Role Template

This is the standard structure for all OP_Automation roles.

## Structure

```
role-name/
├── defaults/
│   └── main.yml          # All role variables with descriptions
├── tasks/
│   ├── main.yml          # Entry point with state-based routing
│   ├── deploy.yml        # Deployment logic
│   ├── undeploy.yml      # Cleanup logic
│   └── verify.yml        # Health checks (optional)
├── templates/            # Jinja2 templates for K8s manifests
└── README.md             # Role documentation (optional)
```

## Usage

To create a new role:

```bash
cp -r ansible/role-template ansible/roles/new-component
cd ansible/roles/new-component
# Edit files and replace placeholders
```

## Standard Pattern

### defaults/main.yml
- Define ALL configurable variables
- Include clear comments for each variable
- Group related variables together
- Set sensible defaults

### tasks/main.yml
- Simple state-based dispatcher
- Calls deploy.yml, undeploy.yml, or verify.yml based on state

### tasks/deploy.yml
- All deployment logic
- Create namespace, secrets, deployments, services
- Wait for resources to be ready

### tasks/undeploy.yml
- All cleanup logic
- Delete resources in reverse order
- Handle errors gracefully

### tasks/verify.yml (optional)
- Health checks
- Validate deployment succeeded
- Check service endpoints

## State Variable

All roles MUST support the `<component>_state` variable:
- `present`: Deploy the component
- `absent`: Remove the component

Example: `federation_manager_state: present`
+36 −0
Original line number Diff line number Diff line
---
# Component Name Configuration
# Replace 'component' with actual component name (e.g., federation_manager, oeg, srm)

# Component namespace
component_namespace: "{{ oop_namespace | default('oop') }}"

# Component state (present/absent)
component_state: present

# Kubeconfig settings
component_kubeconfig: "{{ kubeconfig_output_dir }}/{{ kubeconfig_filename }}"

# Component image settings
component_image_repository: "labs.etsi.org:5050/oop/code/component-name"
component_image_tag: "latest"
component_image_pull_policy: Always

# Service configuration
component_service_name: component
component_service_type: NodePort
component_service_port: 80
component_service_target_port: 8080
component_service_node_port: 30000

# Resource limits
component_resources_limits_cpu: 1000m
component_resources_limits_memory: 1Gi
component_resources_requests_cpu: 500m
component_resources_requests_memory: 512Mi

# Deployment settings
component_replicas: 1
component_ready_timeout: 300

# Additional component-specific variables go here
+51 −0
Original line number Diff line number Diff line
---
# Deployment tasks for component
# All logic for deploying the component goes here

- name: Create component namespace
  kubernetes.core.k8s:
    state: present
    definition:
      apiVersion: v1
      kind: Namespace
      metadata:
        name: "{{ component_namespace }}"
    kubeconfig: "{{ component_kubeconfig }}"

- name: Create image pull secret (if registry token provided)
  kubernetes.core.k8s:
    state: present
    definition:
      apiVersion: v1
      kind: Secret
      metadata:
        name: registry-secret
        namespace: "{{ component_namespace }}"
      type: kubernetes.io/dockerconfigjson
      data:
        .dockerconfigjson: "{{ {'auths': {docker_registry: {'username': docker_registry_username, 'password': gitlab_token, 'email': '', 'auth': (docker_registry_username + ':' + gitlab_token) | b64encode }}} | to_json | b64encode }}"
    kubeconfig: "{{ component_kubeconfig }}"
  when: gitlab_token is defined

- name: Generate component deployment manifest
  ansible.builtin.template:
    src: deployment.yaml.j2
    dest: "/tmp/component-deployment.yaml"
    mode: "0644"

- name: Apply component deployment
  kubernetes.core.k8s:
    state: present
    src: "/tmp/component-deployment.yaml"
    kubeconfig: "{{ component_kubeconfig }}"

- name: Wait for component to be ready
  ansible.builtin.command: >
    kubectl wait
    --namespace {{ component_namespace }}
    --for=condition=available
    deployment/{{ component_service_name }}
    --timeout={{ component_ready_timeout }}s
  changed_when: false
  environment:
    KUBECONFIG: "{{ component_kubeconfig }}"
+18 −0
Original line number Diff line number Diff line
---
# Entry point for component role
# Routes to deploy, undeploy, or verify based on state

- name: Deploy component
  ansible.builtin.include_tasks: deploy.yml
  when: component_state == 'present'

- name: Undeploy component
  ansible.builtin.include_tasks: undeploy.yml
  when: component_state == 'absent'

# Optional: Verify after deployment
# - name: Verify component deployment
#   ansible.builtin.include_tasks: verify.yml
#   when:
#     - component_state == 'present'
#     - component_verify_deployment | default(false)
Loading