Collections for the EDA Applications#
Note
Beta version. Collections content may change.
Nokia EDA is an extensible infrastructure automation framework. Its extensibility is powered by the EDA Applications that can be developed by anyone, installed anytime, and used by everyone.
Applications extend EDA's functionality by adding new abstracted resources, dashboards, workflows, alarms. Given that the EDA Applications are pluggable and can be added/removed at any time, we offer Ansible Collections per each application to match the extensibility of the API layer. An Ansible user would install the collections for the apps they plan to use via Ansible and use the relevant module plugins provided by the collections.
Nokia provides Ansible collections for the applications available in Nokia's EDA built in apps catalog that EDA users get by default when they install the platform. For custom, user-provided applications, we will offer the instrumentation to generate the Ansible modules based on the application's OpenAPI specification in the future.
Installation#
Installation instructions provided in the main readme and are universal for all collections.
Collection structure#
Each application collection contains module plugins that are designed to manage the lifecycle of the resources offered by the application. In a nutshell, the app collection provides the modules for the following tasks:
- list metadata information about the available API versions and the resources the given application provides
- create, update, query, and delete the resources offered by the application
- list the revision history of a given resource and fetch the info about the deleted instances of the resource
We will explain the typical modules you will see in each collection based on the Siteinfo collection and the modules it provides.
Module Name | Example | Description |
---|---|---|
appgroup | nokia.eda_siteinfo_v1alpha1.appgroup | lists available API versions the given API group provides |
resourcelist | nokia.eda_siteinfo_v1alpha1.resourcelist | lists the resources the given application provides |
<resource-name> | nokia.eda_siteinfo_v1alpha1.banner | create, update, query, and delete the resources offered by the application |
<resource-name>list | nokia.eda_siteinfo_v1alpha1.bannerlist | fetch all instance of a given resource type from all or a given namespace |
<resource-name>_deleted | nokia.eda_siteinfo_v1alpha1.banner_deleted | list deleted instances of a given resource |
<resource-name>_revisions | nokia.eda_siteinfo_v1alpha1.banner_revisions | list revision history of a given resource |
Metadata information#
Each application collection provides two modules to extract the metadata about the supported api versions and resources offered by the application:
nokia.eda_<app-name>_<app-api-version>.appgroup
: lists available API versions the given API group providesnokia.eda_<app-name>_<app-api-version>.resourcelist
: lists the API resources the given API group/version provides
API group, App name and API version
EDA adheres to the Kubernetes Resource Model when defining its own resources, the groups they belong to, and the version of the API. This warrants some familiarity with the terms being used in the documentation.
In the FQCN like nokia.eda_siteinfo_v1alpha1
you have:
- siteinfo.eda.nokia.com - the API group. For Nokia-provided apps, the API Group is a combination of the app name and eda.nokia.com string that, when combined, provides a DNS-like name.
- v1alpha1 - the API version in that group
API versions#
In future EDA will support multiple API versions of the same app to interact with the resources offered by the application. This is especially useful during the transition period where a new API has been announced, but the old API is still in use and allows users to transition gradually.
To lay the foundation for this, an appgroup
module cab used to list the available API versions for the application. For example, to see what API versions of the Siteinfo application group are available:
- name: Get Banner appgroup
hosts: all
gather_facts: false
tasks:
- name: Fetch EDA access token
nokia.eda_utils_v1.get_token:
base_url: "{{ eda_api_url }}"
client_secret: "{{ client_secret }}"
username: admin
password: "{{ eda_password }}"
register: token
- name: Get Banner app group
nokia.eda_siteinfo_v1alpha1.appgroup:
base_url: "{{ eda_api_url }}"
auth_token: "Bearer {{ token.result.access_token }}"
register: response
- name: print response
ansible.builtin.debug:
var: response
The output shows that the Siteinfo application provides only one group/version - siteinfo.eda.nokia.com/v1alpha1
:
Available resources#
To list the available resources that an application provides, you would use the resourcelist
module from the collection.
- name: Get Siteinfo resource list
hosts: all
gather_facts: false
tasks:
- name: Fetch EDA access token
nokia.eda_utils_v1.get_token:
base_url: "{{ eda_api_url }}"
client_secret: "{{ client_secret }}"
username: admin
password: "{{ eda_password }}"
register: token
- name: Get Siteinfo resource list
nokia.eda_siteinfo_v1alpha1.resourcelist:
base_url: "{{ eda_api_url }}"
auth_token: "Bearer {{ token.result.access_token }}"
register: response
- name: print response
ansible.builtin.debug:
var: response
As per the output, the Siteinfo application identified by the group/version siteinfo.eda.nokia.com/v1alpha1
provides a single resource - Banner
that is namespaced and can be found in the UI under the Site Profiles category.
Resources and CRUD operations#
Most often you will find yourself using app collections to perform Create/Read/Update/Delete (CRUD) operations on the resources provided by the application. Like creating an interface, getting the configured fabrics, removing a banner and so on.
Transaction API vs CRUD operations
Creating, Updating and Deleting resources via the modules provided by each application collection is done by using the REST API endpoint that each application exposes for their resources. This results in every create/update/delete action to become a transaction with an individual change of a resource.
While using the individual modules from the collection to manage resources is not wrong, you miss on features that the Transaction API brings such as combining multiple resources in an atomic transaction, running the dry-run and collecting the diffs.
Learn how to use Transaction module from the Core collection to fully leverage Nokia EDA powers.
For each resource in the application group, the collection provides the following modules:
<resource-name>
, e.g.banner
: to manage the lifecycle of a singular resource. Supports create, update, query (read), and delete operations<resource-name>list
, e.g.bannerlist
: to fetch a several instances of the resource in a namespace or across all namespaces. Supports only query/read operation.
For example, if you take a look at the Siteinfo application and the modules it provides, you will see the following entries in the table:
nokia.eda_siteinfo_v1alpha1.banner
nokia.eda_siteinfo_v1alpha1.bannerlist
These modules allow you to perform CRUD operations on the resource, Banner
in this case. Let us cover these operations in detail in the next section.
Create#
To create a resource, use the nokia.eda_<app-name>_<app-api-version>.<resource-name>
module. In case of the Siteinfo application, you would use the nokia.eda_siteinfo_v1alpha1.banner
module to create an abstracted Banner.
The argument specification for every application module is the same and follows the pattern depicted below:
- name: Create a resource
nokia.eda_<app-name>_<app-api-version>.<resource-name>:
base_url: "{{ eda_api_url }}"
auth_token: "Bearer {{ eda_access_token }}"
resource:
metadata:
name:
namespace:
# other optional resource metadata
spec:
# resource spec
state: present
As you can see, the module argument specification simply embeds the resource body with its metadata
and spec
fields1 under the .resource
block. A user can simply copy the YAML from the EDA UI and paste it in the playbook, or craft the payload manually based on the OpenAPI spec or Resource Browser of a given resource.
The state: present
in the module argspec instructs the module to ensure the resource is created or updated to match the desired state defined in the playbook.
- name: Create a Banner
hosts: all
gather_facts: false
tasks:
- name: Fetch EDA access token
nokia.eda_utils_v1.get_token:
base_url: "{{ eda_api_url }}"
client_secret: "{{ client_secret }}"
username: admin
password: "{{ eda_password }}"
register: token
- name: Create a banner
nokia.eda_siteinfo_v1alpha1.banner:
base_url: "{{ eda_api_url }}"
auth_token: "Bearer {{ token.result.access_token }}"
resource:
metadata:
labels:
some-label: ansible-demo
namespace: eda
name: demo-banner
spec:
loginBanner: "This is a demo banner provisioned by Ansible"
nodeSelector:
- eda.nokia.com/role=leaf
- eda.nokia.com/role=spine
state: present
register: response
- name: print response
ansible.builtin.debug:
var: response
When creating a resource you can omit the
apiVersion
andKind
under the resource block, as this information is automatically populated by the module.
Read#
Single resource#
To read (aka query/get) the particular resource in a namespace you need to provide the name
and namespace
in the module specification along with the state: query
argument.
- name: Get a banner
hosts: all
gather_facts: false
tasks:
- name: Fetch EDA access token
nokia.eda_utils_v1.get_token:
base_url: "{{ eda_api_url }}"
client_secret: "{{ client_secret }}"
username: admin
password: "{{ eda_password }}"
register: token
- name: Get a banner
nokia.eda_siteinfo_v1alpha1.banner:
base_url: "{{ eda_api_url }}"
auth_token: "Bearer {{ token.result.access_token }}"
namespace: eda
name: demo-banner
state: query
register: response
- name: print response
ansible.builtin.debug:
var: response
response:
changed: false
failed: false
result:
apiVersion: siteinfo.eda.nokia.com/v1alpha1
kind: Banner
metadata:
labels:
some-label: ansible-demo
name: demo-banner
namespace: eda
spec:
loginBanner: This is a demo banner provisioned by Ansible
nodeSelector:
- eda.nokia.com/role=leaf
- eda.nokia.com/role=spine
status:
nodes:
- leaf2
- leaf1
- spine1
status: 200
All in a namespace#
To get all resources of the same kind from a namespace, use the ***list
as in bannerlist
module and provide the namespace
argument:
- name: Get banners
hosts: all
gather_facts: false
tasks:
- name: Fetch EDA access token
nokia.eda_utils_v1.get_token:
base_url: "{{ eda_api_url }}"
client_secret: "{{ client_secret }}"
username: admin
password: "{{ eda_password }}"
register: token
- name: Get banners
nokia.eda_siteinfo_v1alpha1.bannerlist:
base_url: "{{ eda_api_url }}"
auth_token: "Bearer {{ token.result.access_token }}"
namespace: eda
state: query
register: response
- name: print response
ansible.builtin.debug:
var: response
response:
changed: false
failed: false
result:
apiVersion: siteinfo.eda.nokia.com/v1alpha1
items:
- apiVersion: siteinfo.eda.nokia.com/v1alpha1
kind: Banner
metadata:
labels:
some-label: ansible-demo
name: demo-banner
namespace: eda
spec:
loginBanner: This is a demo banner provisioned by Ansible
nodeSelector:
- eda.nokia.com/role=leaf
- eda.nokia.com/role=spine
status:
nodes:
- leaf2
- leaf1
- spine1
kind: BannerList
status: 200
All in a cluster#
To get all Banner resources from all namespaces, use the bannerlist
module without providing a namespace:
- name: List banners in all namespaces
hosts: all
gather_facts: false
tasks:
- name: Fetch EDA access token
nokia.eda_utils_v1.get_token:
base_url: "{{ eda_api_url }}"
client_secret: "{{ client_secret }}"
username: admin
password: "{{ eda_password }}"
register: token
- name: List banners in all namespaces
nokia.eda_siteinfo_v1alpha1.bannerlist:
base_url: "{{ eda_api_url }}"
auth_token: "Bearer {{ token.result.access_token }}"
state: query
register: response
- name: print response
ansible.builtin.debug:
var: response
response:
changed: false
failed: false
result:
apiVersion: siteinfo.eda.nokia.com/v1alpha1
items:
- apiVersion: siteinfo.eda.nokia.com/v1alpha1
kind: Banner
metadata:
labels:
some-label: ansible-demo
name: demo-banner
namespace: eda
spec:
loginBanner: This is a demo banner provisioned by Ansible
nodeSelector:
- eda.nokia.com/role=leaf
- eda.nokia.com/role=spine
status:
nodes:
- leaf2
- leaf1
- spine1
kind: BannerList
status: 200
By label#
To get resources with a specific label, use the ***list
module and provide the label-selector
argument with a label-selector string value in it. If you add namespace
you will get the resources with the label from a namespace, and without the namespace you will get the resources from all namespaces.
- name: List banners in all namespaces
hosts: all
gather_facts: false
tasks:
- name: Fetch EDA access token
nokia.eda_utils_v1.get_token:
base_url: "{{ eda_api_url }}"
client_secret: "{{ client_secret }}"
username: admin
password: "{{ eda_password }}"
register: token
- name: List banners with a label
nokia.eda_siteinfo_v1alpha1.bannerlist:
base_url: "{{ eda_api_url }}"
auth_token: "Bearer {{ token.result.access_token }}"
label-selector: "some-label=ansible-demo"
state: query
register: response
- name: print response
ansible.builtin.debug:
var: response
response:
changed: false
failed: false
result:
apiVersion: siteinfo.eda.nokia.com/v1alpha1
items:
- apiVersion: siteinfo.eda.nokia.com/v1alpha1
kind: Banner
metadata:
labels:
some-label: ansible-demo
name: demo-banner
namespace: eda
spec:
loginBanner: This is a demo banner provisioned by Ansible
nodeSelector:
- eda.nokia.com/role=leaf
- eda.nokia.com/role=spine
status:
nodes:
- leaf2
- leaf1
- spine1
kind: BannerList
status: 200
Update#
The update workflow reuses the module argument specification of the create operation with the same state: present
argument. The module's logic checks if the resource by this name (and in the same namespace, if applicable) already exists and if its metadata and spec match the provided ones. If they do not match, the existing resource is replaced with the new one.
For instance, if we start with the Banner resource created as in the create section above and we were to update the nodeSelector
field to remove spine nodes, we would use the following playbook:
- name: Update a Banner
hosts: all
gather_facts: false
tasks:
- name: Fetch EDA access token
nokia.eda_utils_v1.get_token:
base_url: "{{ eda_api_url }}"
client_secret: "{{ client_secret }}"
username: admin
password: "{{ eda_password }}"
register: token
- name: Update a banner
nokia.eda_siteinfo_v1alpha1.banner:
base_url: "{{ eda_api_url }}"
auth_token: "Bearer {{ token.result.access_token }}"
resource:
metadata:
labels:
some-label: ansible-demo
namespace: eda
name: demo-banner
spec:
loginBanner: "This is a CHANGED demo banner provisioned by Ansible"
nodeSelector:
- eda.nokia.com/role=leaf
state: present
register: response
- name: print response
ansible.builtin.debug:
var: response
response:
changed: true
failed: false
result:
apiVersion: siteinfo.eda.nokia.com/v1alpha1
kind: Banner
metadata:
labels:
some-label: ansible-demo
name: demo-banner
namespace: eda
spec:
loginBanner: This is a CHANGED demo banner provisioned by Ansible
nodeSelector:
- eda.nokia.com/role=leaf
status: 200
The update response includes the full resource representation of the updated banner (minus the status field). If we would run the get-banner playbook, we would see that our changes (the login banner message and the selected nodes) are all respected:
ansible-playbook apps/siteinfo_v1alpha1/docs/examples/get-banner.yaml
PLAY [Get a banner] *********************************************************************************************
TASK [Fetch EDA access token] ***********************************************************************************
[WARNING]: Platform linux on host localhost is using the discovered Python interpreter at /home/roman/nokia-
eda/ansible/.venv/bin/python3.12, but future installation of another Python interpreter could change the meaning
of that path. See https://docs.ansible.com/ansible-core/2.17/reference_appendices/interpreter_discovery.html for
more information.
ok: [localhost]
TASK [Get a banner] *********************************************************************************************
ok: [localhost]
TASK [print response] *******************************************************************************************
ok: [localhost] =>
response:
changed: false
failed: false
result:
apiVersion: siteinfo.eda.nokia.com/v1alpha1
kind: Banner
metadata:
labels:
some-label: ansible-demo
name: demo-banner
namespace: eda
spec:
loginBanner: This is a CHANGED demo banner provisioned by Ansible
nodeSelector:
- eda.nokia.com/role=leaf
status:
nodes:
- leaf1
- leaf2
status: 200
Revisions#
Thanks to the Git used by EDA as its resource database, every modifications to the resources are tracked, can be listed and reverted if needed. The history of changes to the resources can be fetched using the _revisions
module.
If you have been following the examples in this section and modified the banner resource, running the revisions module will show you the history of changes made to it.
- name: Get a banner revision history
hosts: all
gather_facts: false
tasks:
- name: Fetch EDA access token
nokia.eda_utils_v1.get_token:
base_url: "{{ eda_api_url }}"
client_secret: "{{ client_secret }}"
username: admin
password: "{{ eda_password }}"
register: token
- name: Get a banner revision history
nokia.eda_siteinfo_v1alpha1.banners_revisions:
base_url: "{{ eda_api_url }}"
auth_token: "Bearer {{ token.result.access_token }}"
namespace: eda
name: demo-banner
state: query
register: response
- name: print response
ansible.builtin.debug:
var: response
response:
changed: false
failed: false
result:
- author: admin
changeType: MODIFIED
commitTime: "2025-08-25T13:21:21+00:00"
hash: 05655f0e61890d972537622f3278eef811125609
message: REST
transactionId: 76
- author: admin
changeType: ADDED
commitTime: "2025-08-25T09:27:28+00:00"
hash: b7dd27e1e56fd157d0a9703dfe8047cb803434e1
message: REST
transactionId: 75
status: 200
The revision history shows the changes made to the demo-banner
resource in the eda
namespace. First it was created in transaction 75 and then modified in transaction 76.
Delete#
To delete a resource, use the resource module with the namespace
and name
arguments provided and state: absent
set:
- name: Delete a Banner
hosts: all
gather_facts: false
tasks:
- name: Fetch EDA access token
nokia.eda_utils_v1.get_token:
base_url: "{{ eda_api_url }}"
client_secret: "{{ client_secret }}"
username: admin
password: "{{ eda_password }}"
register: token
- name: Delete a banner
nokia.eda_siteinfo_v1alpha1.banner:
base_url: "{{ eda_api_url }}"
auth_token: "Bearer {{ token.result.access_token }}"
namespace: eda
name: demo-banner
state: absent
register: response
- name: print response
ansible.builtin.debug:
var: response
Delete history#
Similar to the revision history of the existing resource, the deletion history of all instances of the resource can be tracked using the _deleted
module. This module lists the deleted instances of a given resource type along with the transaction ID when it was deleted.
- name: Get a banner revision history
hosts: all
gather_facts: false
tasks:
- name: Fetch EDA access token
nokia.eda_utils_v1.get_token:
base_url: "{{ eda_api_url }}"
client_secret: "{{ client_secret }}"
username: admin
password: "{{ eda_password }}"
register: token
- name: Get a banner revision history
nokia.eda_siteinfo_v1alpha1.banner_deleted:
base_url: "{{ eda_api_url }}"
auth_token: "Bearer {{ token.result.access_token }}"
namespace: eda
state: query
register: response
- name: print response
ansible.builtin.debug:
var: response
response:
changed: false
failed: false
result:
- commitTime: "2025-08-25T15:01:52.466829+00:00"
hash: 10ce977ce091bbedabb33eeec5121242392d5a02
name: demo-banner
namespace: eda
transactionId: 77
status: 200
The response shows that an instance of the Banner resource with the name demo-banner
was deleted in transaction 77.
-
There is no need to provide
apiVersion
andkind
fields in the argspec of a module, as these are implied by the module. ↩