Developing network resource modules

    The resource module builder has the following capabilities:

    • Uses a defined model to scaffold a resource module directory layout and initial class files.
    • Scaffolds either an Ansible role or a collection.
    • Subsequent uses of the resource module builder will only replace the module arspec and file containing the module docstring.
    • Allows you to store complex examples along side the model in the same directory.
    • Maintains the model as the source of truth for the module and use resource module builder to update the source files as needed.
    • Generates working sample modules for both and <network_os>_facts.

    To access the resource module builder:

    • clone the github repository:
    • Install the requirements:

    Creating a model

    You must create a model for your new resource. The resource module builder uses this model to create:

    • The scaffold for a new module
    • The argspec for the new module
    • The docstring for the new module

    The model is then the single source of truth for both the argspec and docstring, keeping them in sync. Use the resource module builder to generate this scaffolding. For any subsequent updates to the module, update the model first and use the resource module builder to update the module argspec and docstring.

    1. ---
    2. GENERATOR_VERSION: '1.0'
    3. ANSIBLE_METADATA: |
    4. {
    5. 'metadata_version': '1.1',
    6. 'status': ['preview'],
    7. 'supported_by': '<support_group>'
    8. }
    9. NETWORK_OS: myos
    10. RESOURCE: interfaces
    11. COPYRIGHT: Copyright 2019 Red Hat
    12. LICENSE: gpl-3.0.txt
    13.  
    14. DOCUMENTATION: |
    15. module: myos_interfaces
    16. version_added: 2.9
    17. short_description: 'Manages <xxxx> attributes of <network_os> <resource>'
    18. description: 'Manages <xxxx> attributes of <network_os> <resource>.'
    19. author: Ansible Network Engineer
    20. notes:
    21. - 'Tested against <network_os> <version>'
    22. options:
    23. config:
    24. description: The provided configuration
    25. type: list
    26. elements: dict
    27. suboptions:
    28. name:
    29. type: str
    30. description: The name of the <resource>
    31. some_string:
    32. type: str
    33. description:
    34. - The some_string_01
    35. choices:
    36. - choice_a
    37. - choice_b
    38. - choice_c
    39. default: choice_a
    40. description:
    41. - The some_bool.
    42. type: bool
    43. some_int:
    44. description:
    45. - The some_int.
    46. type: int
    47. version_added: '1.1'
    48. some_dict:
    49. type: dict
    50. description:
    51. - The some_dict.
    52. suboptions:
    53. property_01:
    54. description:
    55. - The property_01
    56. type: str
    57. state:
    58. description:
    59. - The state of the configuration after module completion.
    60. type: str
    61. choices:
    62. - merged
    63. - replaced
    64. - overridden
    65. - deleted
    66. default: merged
    67. EXAMPLES:
    68. - deleted_example_01.txt
    69. - merged_example_01.txt
    70. - overridden_example_01.txt
    71. - replaced_example_01.txt

    Notice that you should include examples for each of the states that the resource supports. The resource module builder also includes these in the sample model.

    See for more examples.

    To use the resource module builder to create a collection scaffold from your resource model:

    1. ansible-playbook -e rm_dest=<destination for modules and module utils> \
    2. -e structure=collection \
    3. -e collection_org=<collection_org> \
    4. -e collection_name=<collection_name> \
    5. -e model=<model> \
    6. site.yml

    Where the parameters are as follows:

    • rm_dest: The directory where the resource module builder places the files and directories for the resource module and facts modules.
    • structure: The directory layout type (role or collection)
      • role: Generate a role directory layout.
      • collection: Generate a collection directory layout.
    • collectionorg: The organization of the collection, required when _structure=collection.
    • collectionname: The name of the collection, required when _structure=collection.
    • model: The path to the model file.

    Examples

    This example shows the directory layout for the following:

    • : myos
    • resource: interfaces
    1. ansible-playbook -e rm_dest=~/github/rm_example \
    2. -e structure=collection \
    3. -e collection_org=cidrblock \
    4. -e collection_name=my_collection \
    5. -e model=models/myos/interfaces/myos_interfaces.yml \
    6. site.yml
    1. ├── docs
    2. ├── LICENSE.txt
    3. ├── playbooks
    4. ├── plugins
    5. | ├── action
    6. | ├── filter
    7. | ├── inventory
    8. | ├── modules
    9. | | ├── __init__.py
    10. | | ├── myos_facts.py
    11. | | └── myos_interfaces.py
    12. | └── module_utils
    13. | ├── __init__.py
    14. | └── network
    15. | ├── __init__.py
    16. | └── myos
    17. | ├── argspec
    18. | | ├── facts
    19. | | | └── __init__.py
    20. | | ├── __init__.py
    21. | | └── interfaces
    22. | | ├── __init__.py
    23. | | └── interfaces.py
    24. | ├── config
    25. | | ├── __init__.py
    26. | | └── interfaces
    27. | | ├── __init__.py
    28. | | └── interfaces.py
    29. | ├── facts
    30. | | ├── facts.py
    31. | | ├── __init__.py
    32. | | └── interfaces
    33. | | ├── __init__.py
    34. | | └── interfaces.py
    35. | ├── __init__.py
    36. | └── utils
    37. | ├── __init__.py
    38. | └── utils.py
    39. ├── README.md
    40. └── roles

    This example displays the role directory layout for the following:

    • network_os: myos
    • resource: interfaces
    1. ansible-playbook -e rm_dest=~/github/rm_example/roles/my_role \
    2. -e structure=role \
    3. -e model=models/myos/interfaces/myos_interfaces.yml \
    4. site.yml

    This example shows how to use the generated collection in a playbook:

    This example shows how to use the generated role in a playbook:

    1. - hosts: myos101
    2. gather_facts: False
    3. roles:
    4. - my_role
    5.  
    6. - hosts: myos101
    7. gather_facts: False
    8. tasks:
    9. - myos_interfaces:
    10. register: result
    11. - debug:
    12. var: result
    13. - myos_facts:
    14. - debug:
    15. var: ansible_network_resources
    • Module
      • library/<ansiblenetwork_os><resource>.py.
      • Imports the module_utils resource package and calls execute_module API
    1. def main():
    2. result = <resource_package>(module).execute_module()
    • Module argspec
      • module_utils/<ansible_network_os>/argspec/<resource>/.
      • Argspec for the resource.
    • Facts
      • module_utils/<ansible_network_os>/facts/<resource>/.
      • Populate facts for the resource.
      • Entry in module_utils/<ansible_network_os>/facts/facts.py for get_facts API to keep module and facts gathered for the resource module in sync for every subset.
      • Entry of Resource subset in FACTS_RESOURCE_SUBSETS list in module_utils/<ansible_network_os>/facts/facts.py to make facts collection work.
    • Module package in module_utils
      • module_utils/<ansible_network_os>/<config>/<resource>/.
      • Implement execute_module API that loads the configuration to device and generates the result with changed, commands, before and after keys.
      • Call get_facts API that returns the <resource> configuration facts or return the difference if the device has onbox diff support.
      • Compare facts gathered and given key-values if diff is not supported.
      • Generate final configuration.
    • Utils
      • module_utils/<ansible_network_os>/utils.
      • Utilities for the platform.

    Developer notes

    The tests rely on a role generated by the resource module builder. After changes to the resource module builder, the role should be regenerated and the tests modified and run as needed. To generate the role after changes: