Contributing Code
As an open source project, OS Migrate welcomes contributions from the community at large. The following guide provides information on how to add a new role to the project and where additional testing or documentation artifacts should be added. This isn’t an exhaustive reference and is a living document subject to change as needed when the project formalizes any practice or pattern.
Adding a New Role
The most common contribution to OS Migrate is adding a new role to support the export or import of resources. The construction of the roles will likely follow a similar pattern. Each role also has specific unit and functional test requirements. The most common pattern for adding a new role will follow these steps:
Add a resource class to
os_migrate/plugins/module_utils
that inherits fromansible_collections.os_migrate.os_migrate.plugins.module_utils.resource.Resource
Add a unit test to
os_migrate/tests/unit
to test serializing and de-serializing data, and any other functionality your class may have.Create a new module in
os_migrate/plugins/modules
to facilitate the import or export of the resource.Add a new playbook to
os_migrate/playbooks
.Add a new role to
os_migrate/roles
.Add functional tests to
tests/func
that test primary use, idempotency, and updates as a minimum. Additional tests as necessary.Add documentation within classes and roles/playbooks as required. Update developer or user documentation as needed.
Creating the role skeleton automatically
Adding roles into os-migrate can be easily achieved by creating the role structure skeleton automatically.
From the repository root directory execute:
ansible-playbook \
-i 'localhost,' \
./scripts/role-addition.yml \
-e ansible_connection=local \
-e role_name=import_example_resource
This command will generate the role, the default variables file, and the documentation stub.
Resources
Resources are the primary data structures that are exported from and
imported to clouds. In
os_migrate/plugins/module_utils/resource.py
, there is a
Resource
class provided for your new resource to inherit from. It
provides a way to quickly build an organized class that uses
openstacksdk to retrieve, create and update data within a connected
OpenStack tenant. See how other classes in the module_utils
directory inherit from Resource
for inspiration.
Two very important properties are the ‘params’ and ‘_info’, as these are the primary data fields that will be exported and imported. At a minimum, the name property of any resource should be in params_from_sdk, and most likely addresses should be there too. The difference between info and params is:
A property that would be an ‘_info’ type is something that we don’t want or cannot “make the same” in the destination cloud. For example, typically UUIDs can’t be the same between two tenants so an ‘id’ property should remain in info.
A property that would be in a ‘params’ type are things that we do want to copy to the destination cloud. These typically also get looked at when we’re making sure the import behavior is idempotent. I.e. when we re-run import playbooks, things that already got imported before are not attempted to be imported again.
Export Roles
In the defaults/main.yml
file, at a minimum you will need to
define the os_migrate_[resource]_filter
variable to support
filtering of resources by the name property.
In the meta/main.yml
file you will likely just need to add the
following default content:
---
galaxy_info:
author: os-migrate
description: os-migrate resource
company: Red Hat
license: Apache-2.0
min_ansible_version: "2.9"
platforms:
- name: Fedora
versions:
- "34"
galaxy_tags: ["osmigrate"]
dependencies:
- role: os_migrate.os_migrate.prelude_src
In the tasks/main.yml
file, add your Ansible tasks for exporting the
data. A common pattern is retrieving data from an OpenStack tenant via a
cloud
module
, creating a collection of name/id pairs for export, filtering the names
for specific resources, and then calling the module you created for
export.
Import Roles
In the defaults/main.yml
file, at a minimum you will need to
define the same os_migrate_[resource]_filter
variable as with
export, and import_[resource]_validate_file: true
variable to set
whether or not the import data file should be validated for this
role. In most cases, it should be set to true
.
In the meta/main.yml
file you will likely just need to add the
following default content:
---
galaxy_info:
author: os-migrate
description: os-migrate resource
company: Red Hat
license: Apache-2.0
min_ansible_version: "2.9"
platforms:
- name: Fedora
versions:
- "34"
galaxy_tags: ["osmigrate"]
dependencies:
- role: os_migrate.os_migrate.prelude_dst
In the tasks/main.yml
file, add your Ansible tasks for importing the
data. A common pattern is validating the data file created by the
associated export role, reading the data file and then calling the
module you created for import.
Writing Tests
For newly implemented resources, ensure comprehensive test coverage by following this checklist:
Functional Tests
Ensure both import and export functionalities are tested, not just idempotency.
Include tests for admin-only resources, ensuring they are renamed before import.
Test resources as a tenant whenever possible to ensure broader coverage.
For resources with special properties like
links
orextra_specs
, write detailed tests inspecting these properties closely.
Unit Tests
Write unit tests for each new module created, focusing on the logic within the module.
Ensure that edge cases and error handling paths are covered in unit tests.
Integration Tests
Add integration tests that cover the entire process of exporting and then importing the resource, verifying the integrity and consistency of the data.
Verify that the resource behaves as expected in the context of the os-migrate ecosystem.
Documentation and Examples
In the
DOCUMENTATION
constant of each module, include examples of how to use the module in a playbook.Ensure that the
README.md
file for the new role is comprehensive, covering the role’s purpose, usage, and any dependencies.
Test Execution in CI
Confirm that all tests are executed in the Continuous Integration (CI) environment before merging.
If a feature is merged without proper tests due to specific circumstances, create a technical debt tracking card to follow up.
Review and Inspection
Conduct thorough reviews, especially when introducing new resources, to catch potential issues early.
Implement policies or checklists in development documentation to ensure test soundness and coverage.
Location of Tests
Place functional and integration tests in the
tests/e2e
ortests/func
directory respectively, following the existing structure for similar resources.Unit tests should reside alongside the modules they are testing, in the
os_migrate/tests/
directory.
Special Considerations
For resources that are only accessible by admin users, ensure tests reflect this by running them with appropriate permissions.
Address any known issues from previous retrospectives, such as fixing the handling of Nova keypairs or ensuring resources are tested in tenant context.
Necessary Documentation
If this is your first time adding a pull request to the os-migrate
repository, add your author information to galaxy.yml
.
In each Ansible module in os_migrate/plugins/modules
, there is a
DOCUMENTATION
constant where you must provide standard
documentation on what the module does and an example of how you would
use it in a playbook.
Each new role must have a README.md
file as a requirement for
Ansible Galaxy publishing.