Skip to content
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
1 change: 1 addition & 0 deletions docs/dictionary/en-custom.txt
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ networkattachmentdefinition
networkconfig
networkmanager
networktype
networker
nfs
nftables
nhc
Expand Down
150 changes: 150 additions & 0 deletions roles/edpm_ssh_info/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# edpm_ssh_info

This Ansible role retrieves EDPM (External Data Plane Management) SSH connectivity information.

## Description

The role performs the following tasks:

1. Queries OpenShift for OpenStackDataPlaneNodeSet resources
2. Retrieves the dataplane SSH private key from OpenShift secrets (if not already present locally)
3. Extracts compute node names and their control plane IP addresses
4. Returns all information in a structured format for use in subsequent plays

## Requirements

- Ansible collection `kubernetes.core` must be installed
- Ansible collection `community.okd` must be installed
- Valid kubeconfig file at `{{ ansible_user_dir }}/.kube/config`
- Access to the OpenShift/Kubernetes namespace containing EDPM resources
- Appropriate permissions to read OpenStackDataPlaneNodeSet resources and secrets

## Variables

### Role Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `cifmw_edpm_ssh_info_openstack_namespace` | `openstack` | OpenShift namespace where EDPM resources are deployed |
| `cifmw_edpm_ssh_info_kubeconfig_path` | `{{ ansible_user_dir }}/.kube/config` | Path to kubeconfig file |
| `cifmw_edpm_ssh_info_oc_auth_required` | `true` | Whether to authenticate to OpenShift cluster before querying resources |
| `cifmw_edpm_ssh_info_oc_username` | `kubeadmin` | OpenShift username for authentication |
| `cifmw_edpm_ssh_info_oc_password_file` | `{{ ansible_user_dir }}/.kube/kubeadmin-password` | Path to file containing OpenShift password |
| `cifmw_edpm_ssh_info_oc_api_url` | `https://api.ocp.openstack.lab:6443/` | OpenShift API URL |
| `cifmw_edpm_ssh_info_oc_validate_certs` | `false` | Whether to validate SSL certificates when connecting to OpenShift API |
| `cifmw_edpm_ssh_info_node_prefix` | `compute-` | Node name prefix to filter (e.g., 'compute-', 'networker-') |
| `cifmw_edpm_ssh_info_ssh_secret_name` | `dataplane-ansible-ssh-private-key-secret` | Name of the secret containing SSH private key |
| `cifmw_edpm_ssh_info_ssh_key_path` | `{{ ansible_user_dir }}/.ssh/compute_id` | Destination path for SSH private key |

## Output

### Facts Set

The role sets a fact named `cifmw_edpm_ssh_info` with the following structure:

```yaml
cifmw_edpm_ssh_info:
ssh_key_path: "/path/to/ssh/key"
nodes:
- name: compute-0
host: 192.168.122.100
- name: compute-1
host: 192.168.122.101
```

**Fields:**
- `ssh_key_path` (string): Path to the SSH private key file
- `nodes` (list): List of discovered dataplane nodes
- `name` (string): Node name (e.g., "compute-0")
- `host` (string): Control plane IP address

## Usage

### Basic Usage (with defaults)

```yaml
- name: Get EDPM SSH information
hosts: localhost
gather_facts: false
tasks:
- name: Retrieve dataplane info
ansible.builtin.include_role:
name: edpm_ssh_info

- name: Display discovered nodes
ansible.builtin.debug:
msg: "Found {{ cifmw_edpm_ssh_info.nodes | length }} nodes"
```

### Custom Configuration

```yaml
- name: Get EDPM SSH information
hosts: localhost
gather_facts: false
tasks:
- name: Retrieve dataplane info
ansible.builtin.include_role:
name: edpm_ssh_info
vars:
cifmw_edpm_ssh_info_openstack_namespace: my-openstack
cifmw_edpm_ssh_info_node_prefix: networker-
cifmw_edpm_ssh_info_ssh_key_path: /custom/path/to/key
```

### Custom Password File

```yaml
- name: Get EDPM SSH information with custom password file
hosts: localhost
gather_facts: false
tasks:
- name: Retrieve dataplane info
ansible.builtin.include_role:
name: edpm_ssh_info
vars:
cifmw_edpm_ssh_info_oc_password_file: /custom/path/to/password-file
```

### Using with Dynamic Inventory

```yaml
- name: Get EDPM SSH information
hosts: localhost
gather_facts: false
tasks:
- name: Retrieve dataplane info
ansible.builtin.include_role:
name: edpm_ssh_info

- name: Add nodes to inventory
hosts: localhost
gather_facts: false
tasks:
- name: Add compute nodes to dynamic inventory
ansible.builtin.add_host:
name: "{{ item.name }}"
ansible_host: "{{ item.host }}"
ansible_ssh_private_key_file: "{{ cifmw_edpm_ssh_info.ssh_key_path }}"
groups:
- compute_nodes
loop: "{{ cifmw_edpm_ssh_info.nodes }}"

- name: Configure compute nodes
hosts: compute_nodes
tasks:
- name: Run configuration tasks
ansible.builtin.debug:
msg: "Configuring {{ inventory_hostname }}"
```

## Notes

- If your kubeconfig is already authenticated, set `cifmw_edpm_ssh_info_oc_auth_required: false` to skip the `oc login` step
- The OpenShift password is read from the file specified in `cifmw_edpm_ssh_info_oc_password_file` (defaults to `~/.kube/kubeadmin-password`)
- You can set a custom password file path via `cifmw_edpm_ssh_info_oc_password_file` if your password is stored elsewhere
- The role will fail if no OpenStackDataPlaneNodeSet resources are found
- SSH key retrieval is skipped if the key file already exists at the destination path
- SSH key is saved with `0600` permissions for security
- The role is idempotent - it can be run multiple times safely
- Only nodes matching the specified prefix and having a control plane IP are included
22 changes: 22 additions & 0 deletions roles/edpm_ssh_info/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
# OpenShift/Kubernetes namespace for EDPM resources
cifmw_edpm_ssh_info_openstack_namespace: openstack

# Kubeconfig file path
cifmw_edpm_ssh_info_kubeconfig_path: "{{ ansible_user_dir }}/.kube/config"

# OpenShift authentication required
cifmw_edpm_ssh_info_oc_auth_required: true

# OpenShift login credentials
cifmw_edpm_ssh_info_oc_username: kubeadmin
cifmw_edpm_ssh_info_oc_password_file: "{{ ansible_user_dir }}/.kube/kubeadmin-password"
cifmw_edpm_ssh_info_oc_api_url: https://api.ocp.openstack.lab:6443/
cifmw_edpm_ssh_info_oc_validate_certs: false

# Node name prefix to filter (e.g., 'compute-', 'networker-')
cifmw_edpm_ssh_info_node_prefix: compute-

# SSH private key retrieval settings
cifmw_edpm_ssh_info_ssh_secret_name: dataplane-ansible-ssh-private-key-secret
cifmw_edpm_ssh_info_ssh_key_path: "{{ ansible_user_dir }}/.ssh/compute_id"
4 changes: 4 additions & 0 deletions roles/edpm_ssh_info/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
collections:
- kubernetes.core
- community.okd
84 changes: 84 additions & 0 deletions roles/edpm_ssh_info/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
- name: Read OpenShift password from file
ansible.builtin.slurp:
src: "{{ cifmw_edpm_ssh_info_oc_password_file }}"
register: _oc_password_content
no_log: "{{ cifmw_nolog | default(true) | bool }}"
when: cifmw_edpm_ssh_info_oc_auth_required

- name: Authenticate to OpenShift cluster
community.okd.openshift_auth:
host: "{{ cifmw_edpm_ssh_info_oc_api_url }}"
username: "{{ cifmw_edpm_ssh_info_oc_username }}"
password: "{{ _oc_password_content.content | b64decode | trim }}"
validate_certs: "{{ cifmw_edpm_ssh_info_oc_validate_certs }}"
register: _openshift_auth_result
no_log: "{{ cifmw_nolog | default(true) | bool }}"
when: cifmw_edpm_ssh_info_oc_auth_required

- name: Get OpenShift DataPlane NodeSets
kubernetes.core.k8s_info:
api_version: dataplane.openstack.org/v1beta1
kind: OpenStackDataPlaneNodeSet
namespace: "{{ cifmw_edpm_ssh_info_openstack_namespace }}"
host: "{{ cifmw_edpm_ssh_info_oc_api_url if cifmw_edpm_ssh_info_oc_auth_required else omit }}"
api_key: "{{ _openshift_auth_result.openshift_auth.api_key if cifmw_edpm_ssh_info_oc_auth_required else omit }}"
kubeconfig: "{{ cifmw_edpm_ssh_info_kubeconfig_path if not cifmw_edpm_ssh_info_oc_auth_required else omit }}"
validate_certs: "{{ cifmw_edpm_ssh_info_oc_validate_certs }}"
register: osdpns_info
failed_when: osdpns_info.resources | length == 0

- name: Check if SSH private key already exists
ansible.builtin.stat:
path: "{{ cifmw_edpm_ssh_info_ssh_key_path }}"
register: ssh_key_stat

- name: Retrieve SSH private key from OpenShift
when: not ssh_key_stat.stat.exists
block:
- name: Get dataplane SSH secret from OpenShift
kubernetes.core.k8s_info:
api_version: v1
kind: Secret
name: "{{ cifmw_edpm_ssh_info_ssh_secret_name }}"
namespace: "{{ cifmw_edpm_ssh_info_openstack_namespace }}"
host: "{{ cifmw_edpm_ssh_info_oc_api_url if cifmw_edpm_ssh_info_oc_auth_required else omit }}"
api_key: "{{ _openshift_auth_result.openshift_auth.api_key if cifmw_edpm_ssh_info_oc_auth_required else omit }}"
kubeconfig: "{{ cifmw_edpm_ssh_info_kubeconfig_path if not cifmw_edpm_ssh_info_oc_auth_required else omit }}"
validate_certs: "{{ cifmw_edpm_ssh_info_oc_validate_certs }}"
register: secret_info
failed_when: secret_info.resources | length == 0

- name: Ensure SSH directory exists
ansible.builtin.file:
path: "{{ cifmw_edpm_ssh_info_ssh_key_path | dirname }}"
state: directory
mode: '0700'

- name: Save SSH private key
ansible.builtin.copy:
content: "{{ secret_info.resources[0].data['ssh-privatekey'] | b64decode }}"
dest: "{{ cifmw_edpm_ssh_info_ssh_key_path }}"
mode: '0600'
no_log: "{{ cifmw_nolog | default(true) | bool }}"

- name: Build dataplane information with nodes and SSH key
ansible.builtin.set_fact:
cifmw_edpm_ssh_info:
ssh_key_path: "{{ cifmw_edpm_ssh_info_ssh_key_path }}"
nodes: >-
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: consider to change variable name to something different, that would be helpful to recognize place, where it has been set.
In other words, other people might think that the nodes var comes from CI (Zuul), but we set the fact here. More, the var is common, so changing var to other name might be helpful in future when debug is needed.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a bit confused by this comment. nodes is a member of the cifmw_edpm_ssh_info dict that is being set as a fact here. Seems clear enough to me where this comes from. Am I misunderstanding something?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree with you @michburk, considering that @danpawlik also approved it, could you approve it too?

{%- set nodes = [] -%}
{%- for nodeset in osdpns_info.resources -%}
{%- if nodeset.status.allHostnames is defined and nodeset.status.allIPs is defined -%}
{%- for fqdn in nodeset.status.allHostnames.keys() -%}
{%- set node_name = fqdn.split('.')[0] -%}
{%- if node_name.startswith(cifmw_edpm_ssh_info_node_prefix) and fqdn in nodeset.status.allIPs -%}
{%- set ctlplane_ip = nodeset.status.allIPs[fqdn].ctlplane | default(None) -%}
{%- if ctlplane_ip -%}
{%- set _ = nodes.append({'name': node_name, 'host': ctlplane_ip}) -%}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endfor -%}
{{ nodes }}
9 changes: 9 additions & 0 deletions zuul.d/molecule.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,15 @@
- ^.config/molecule/.*
name: cifmw-molecule-cleanup_openstack
parent: cifmw-molecule-noop
- job:
files:
- ^common-requirements.txt
- ^test-requirements.txt
- ^roles/edpm_ssh_info/.*
- ^ci/playbooks/molecule.*
- ^.config/molecule/.*
name: cifmw-molecule-edpm_ssh_info
parent: cifmw-molecule-noop
- job:
files:
- ^common-requirements.txt
Expand Down
1 change: 1 addition & 0 deletions zuul.d/projects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
- cifmw-molecule-edpm_deploy_baremetal
- cifmw-molecule-edpm_kustomize
- cifmw-molecule-edpm_prepare
- cifmw-molecule-edpm_ssh_info
- cifmw-molecule-env_op_images
- cifmw-molecule-fdp_update_container_images
- cifmw-molecule-fdp_update_edpm
Expand Down