Skip to content

Add infrahubctl menu load command to load menu items from a file #73

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

Merged
merged 3 commits into from
Oct 14, 2024

Conversation

dgarros
Copy link
Contributor

@dgarros dgarros commented Oct 12, 2024

This PR adds a new cli command infrahubctl menu load to load menu items from one or multiple files

This effort is part of the upcoming release of Infrahub and it is required to load the new menu items

The menu file need to have the following format.

in Summary

  • The first 4 lines are mandatory
  • The format under data must be compatible with CoreMenuItem
  • If kind is provided, the path will be automatically generated to /objects/<kind>
---
apiVersion: infrahub.app/v1
kind: Menu
spec:
  data:
  - namespace: Location
    name: MainMenu
    label: Location
    icon: "mingcute:location-line"
    children:
      data:
      - namespace: Location
        name: ContinentMenu
        label: Continent
        kind: LocationContinent
        icon: "jam:world"
        order_weight: 1000

More than just the menu

Because, it felt silly to create yet another specific command for the menu, I tried to make it as generic as possible.
With a tiny difference, this format should work for all type of objects in the near future.
I've also added the command infrahubctl object load (hidden for now) to explore this feature.

I was able to successfully load this file with location data but more work is required to properly support all types of relationships

---
apiVersion: infrahub.app/v1
kind: Object
spec:
  kind: LocationContinent
  data:
  - name: North America
    children:
      kind: LocationCountry
      data:
      - name: "United States of America"
      - name: "Canada"
  - name: South America
    children:
      kind: LocationCountry
      data:
      - name: "Mexico"
      - name: "Brazil"

Copy link

codecov bot commented Oct 13, 2024

Codecov Report

Attention: Patch coverage is 54.54545% with 105 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
infrahub_sdk/spec/object.py 24.28% 53 Missing ⚠️
infrahub_sdk/yaml.py 68.51% 16 Missing and 1 partial ⚠️
infrahub_sdk/spec/menu.py 50.00% 12 Missing ⚠️
infrahub_sdk/ctl/menu.py 65.38% 9 Missing ⚠️
infrahub_sdk/ctl/object.py 65.38% 9 Missing ⚠️
infrahub_sdk/ctl/utils.py 84.21% 3 Missing ⚠️
infrahub_sdk/ctl/cli_commands.py 85.71% 1 Missing ⚠️
infrahub_sdk/ctl/schema.py 66.66% 1 Missing ⚠️
@@            Coverage Diff             @@
##             develop      #73   +/-   ##
==========================================
  Coverage           ?   43.30%           
==========================================
  Files              ?       74           
  Lines              ?     6844           
  Branches           ?     1353           
==========================================
  Hits               ?     2964           
  Misses             ?     3611           
  Partials           ?      269           
Flag Coverage Δ
python-3.10 43.30% <54.54%> (?)
python-3.11 43.30% <54.54%> (?)
python-3.12 43.30% <54.54%> (?)
python-3.9 43.24% <54.54%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
infrahub_sdk/protocols.py 100.00% <100.00%> (ø)
infrahub_sdk/ctl/cli_commands.py 37.05% <85.71%> (ø)
infrahub_sdk/ctl/schema.py 55.83% <66.66%> (ø)
infrahub_sdk/ctl/utils.py 60.90% <84.21%> (ø)
infrahub_sdk/ctl/menu.py 65.38% <65.38%> (ø)
infrahub_sdk/ctl/object.py 65.38% <65.38%> (ø)
infrahub_sdk/spec/menu.py 50.00% <50.00%> (ø)
infrahub_sdk/yaml.py 70.83% <68.51%> (ø)
infrahub_sdk/spec/object.py 24.28% <24.28%> (ø)

Copy link
Contributor

@ogenstad ogenstad left a comment

Choose a reason for hiding this comment

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

LGTM. Added some comments which is mostly me just thinking out loud.

for file in files:
file.validate_content()
if not file.spec.kind:
raise FileNotValidError(name=str(file.location), message="kind must be specified.")
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we have this happen within .validate_content() instead?

return data

@classmethod
async def create_node(
Copy link
Contributor

Choose a reason for hiding this comment

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

In what way has this been used? I think it might be fine to create the menu but I'm wondering if we need to rethink the structure for other object types where the object we create is related to other objects. If those objects doesn't yet exist I think we'd need to create them first before creating the "base" object. Should be doable by looking at the relationships and which side if any is mandatory. Though it would also be nice if we could just feed everything to the backend as a "fix this in a single transaction" type of way. Not a blocker here and it could be that I don't completely understand how this gets used but I see some situations where it seems problematic now depending on how the relationships are defined.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes I fully agree, this is not the final implementation
My end goal is to be able to create all these objects in memory and to have a engine that will know in which order they need to be created based on the schema.
This is very similar to what we need to build better generators.

_spec: Optional[InfrahubObjectFileData] = None

@property
def spec(self) -> InfrahubObjectFileData:
Copy link
Contributor

Choose a reason for hiding this comment

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

Just thinking out loud here if we're later adding a spec property to other object types and want to look at the spec for a generic InfrahubFile object it might get problematic if we always need to override the returned data in a different way for each given subclass (in this case ObjectFile which would return an InfrahubObjectFileData. Depending on what we do in the future it might not be a problem, alternatively we could look at generics and see if we could fix it with that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, not a fan of this implementation as well, happy to consider a better/cleaner solution in the future

pass

@classmethod
def load_from_disk(cls, paths: list[Path]) -> list[Self]:
Copy link
Contributor

Choose a reason for hiding this comment

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

We currently read most of the data from disk as a sync function, i.e. the jinja2 templates when used from within the git-agent and also even the loading of .infrahub.yml files. I see this being used within the git-agents as well. Even though we don't have the file loaders as async now I'm wondering if this should be an async function from the start, or if we just introduce a new one that is async once we actually read the files from disk in an async way.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since it's sync for now, my vote is to keep it as a sync function but it would be good to start using anyio.Path to properly support Async for all disk access. I'll open an issue to track that

@dgarros dgarros marked this pull request as ready for review October 14, 2024 19:57
@dgarros dgarros merged commit 8222579 into develop Oct 14, 2024
12 checks passed
@dgarros dgarros deleted the dga-20241012-menu branch October 14, 2024 19:58
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.

2 participants