Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Inventory data plugin #888

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

ubaumann
Copy link
Contributor

This pull request is a quick and incomplete implementation of adding an Inventory Data Plugin. The idea is to have a base to discuss this idea and what would be needed to accept such a change.

At the moment, the inventory data is stored in a Python dictionary. This works great. However, I found myself in a situation where I would like to replace the dictionary with objects. More specifically, I would like to use a pydantic model for the data structure. Firstly, to have input validation and, secondly, to be able to add functions to the pedantic objects to reduce logic in templates.

This PR adds a new plugin type called InventoryDataPlugin. The idea is to allow the default dict object to be replaced with another object. For now, I implemented it in a way that does not break any tests, as the new datatype used to store the data needs to provide methods similar to a dictionary. The code and plugin are most likely more complex because of this.

To use pydantic I would try to implement a plugin to use a model similar to this (just "random" pseudocode, untested):

from typing import (
    Any,
    ItemsView,
    KeysView,
    ValuesView,
)

from pydantic import BaseModel, ConfigDict
from pydantic.networks import IPvAnyAddress

class User(BaseModel):
    model_config = ConfigDict(
        strict=True
    )
    name: str
    age: int
    is_active: bool
    ip: IPvAnyAddress

    def __getitem__(self, key: str) -> Any:
        return getattr(self, key)
    
    def get(self, key: str, default: Any = None) -> Any:
        try:
            return self.__getitem__(key)
        except AttributeError:
            return default
    
    def __setitem__(self, key: str, value: Any):
        self.model_validate({**self.__dict__, **{key: value}})
        setattr(self, key, value)
    
    def keys(self) -> KeysView[str]:
        return self.__dict__.keys()
    
    def values(self) -> ValuesView[Any]:
        return self.__dict__.values()
    
    def items(self) -> ItemsView[str, Any]:
        return self.__dict__.items()

The model, of course, would be much more complex with nested models. What already works well is to store multiple models in the data dictionary. So, in this case, only the first level would be a dictionary.

inv = inventory_plugin(**config.inventory.options).load()
inventory_plugin_params = config.inventory.options.copy()

init_params = inspect.signature(inventory_plugin).parameters
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This code is most likely not working yet. The idea would be to detect if the Inventory plugin allows passing down the configuration settings to the Host, Group and Defaults Inventory objects. This would allow us to avoid breaking existing inventory plugins.

@ubaumann ubaumann marked this pull request as draft December 20, 2023 16:12
@ubaumann
Copy link
Contributor Author

PS: The tests are failing as the package is not installed again in the pipeline because of cashing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant