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

[apiclient] restructure models and managers #982

Merged
merged 6 commits into from
Nov 23, 2023
Merged

Conversation

lanfon72
Copy link
Member

@lanfon72 lanfon72 commented Nov 9, 2023

Changes

  • UPDATE restructure managers.py
    • add folder managers
    • add __init__.py for the folder as a module
    • add base.py for BaseManager and constants
    • add files for related managers (hosts, images, volumes, keypairs, settings, networks, templates, supportbundles, storageclasses, clusternetworks, volumesnapshots, virtualmachines), backups for BackupManager and VirtualMachineSnapshotManager, internal and longhorn for those operations not available in harvester dashboard. (managers would be imported in __init__.py)
  • UPDATE restructure models.py
    • add folder models
    • add __init__.py for the folder as a module
    • add base.py for constants
    • add files for related Specs (backups, settings, virtualmachines, volumes)
  • NEW type stub files
    • add .pyi files into managers folder for related managers
    • add .pyi files into models folder for related specs
    • add api.pyi for api.py
    • add py.typed to mark the lib having type information1
  • NEW unit tests
    • add test_load_managers to test api.load_managers
    • add test_for_version to test manager.for_version

The restructure is necessary that we are going to support multiple cluster version in the API with new introduced method api.load_managers, for implement new api operations, we can simply inherit old managers to overwrite old version. (you can check the tests/test_managers.py::test_for_version for more details.

Footnotes

  1. PEP561 https://peps.python.org/pep-0561/

@lanfon72 lanfon72 requested a review from a team November 13, 2023 16:02
@lanfon72 lanfon72 changed the title restructure models and managers [apiclient] restructure models and managers Nov 13, 2023
@albinsun
Copy link
Contributor

albinsun commented Nov 14, 2023

Do we have test runs/reports on restructured suites?

@lanfon72
Copy link
Member Author

Do we have test runs/reports on restructured suites?

This change will not affect to existing test cases, so I didn't trigger any CI build for it.
The change might affect to existing import related to apiclient, and I had confirmed that this will compatible with old one by executing pytest --collect-only harvester_e2e_tests/

Copy link
Contributor

@albinsun albinsun left a comment

Choose a reason for hiding this comment

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

Test will fail when import typing.Final, which is new in python 3.8 and not compatible to our current env.
Ref. harvester-runtests#410

...
'/var/harvester_test_410_harvester-runtests/.tox/py36/lib64/python3.6/site-packages/yaml/__init__.py'>
apiclient/harvester_api/models/base.py:1: in <module>
    from typing import Final
E   ImportError: cannot import name 'Final'
...

@lanfon72
Copy link
Member Author

lanfon72 commented Nov 15, 2023

As we are leaving python 3.6 (#970), I will add a temporarily fix to let it compatible with 3.6, then we can revert the commit when we change to use 3.10+

(Executed on harvester-runtests#412, and #411 is the run before the fix)

@lanfon72 lanfon72 requested a review from albinsun November 15, 2023 16:27
@albinsun
Copy link
Contributor

As we are leaving python 3.6 (#970), I will add a temporarily fix to let it compatible with 3.6, then we can revert the commit when we change to use 3.10+

(Executed on harvester-runtests#412, and #411 is the run before the fix)

Hi, could you help to confirm #412 test result?
They both error with UserWarning: conflicting basepython version (set 3.6, should be 3.8) for env 'py38';....

And the 412 report looks empty.
image

411

TASK [tests : Run the functional tests] ****************************************
Wednesday 15 November 2023  15:58:31 +0000 (0:00:00.057)       0:01:18.644 **** 
fatal: [pcloud003]: FAILED! => changed=true 
  cmd: tox -e py36 --result-json=test_result.json -- -vvl `cat run_filters/all.txt`  --json-report --html=test_report/test_result.html -m 'not delete_host and not upgrade' -k 'apis2' > test_result.txt
  delta: '0:00:32.544962'
  end: '2023-11-15 08:23:59.325522'
  msg: non-zero return code
  rc: 1
  start: '2023-11-15 08:23:26.780560'
  stderr: |-
    /usr/lib/python3.6/site-packages/tox/config/__init__.py:672: UserWarning: conflicting basepython version (set 3.6, should be 3.8) for env 'py38';resolve conflict or set ignore_basepython_conflict
      testenv_config.envname,
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>
...ignoring

412

TASK [tests : debug] ***********************************************************
Wednesday 15 November 2023  16:22:33 +0000 (0:00:00.046)       0:01:08.614 **** 
ok: [pcloud003] => 
  msg: tox -e py36 --result-json=test_result.json -- -vvl `cat run_filters/all.txt`  --json-report --html=test_report/test_result.html -m 'not delete_host and not upgrade' -k 'apis2'

TASK [tests : Run the functional tests] ****************************************
Wednesday 15 November 2023  16:22:33 +0000 (0:00:00.068)       0:01:08.683 **** 
fatal: [pcloud003]: FAILED! => changed=true 
  cmd: tox -e py36 --result-json=test_result.json -- -vvl `cat run_filters/all.txt`  --json-report --html=test_report/test_result.html -m 'not delete_host and not upgrade' -k 'apis2' > test_result.txt
  delta: '0:00:27.348655'
  end: '2023-11-15 08:47:55.727753'
  msg: non-zero return code
  rc: 1
  start: '2023-11-15 08:47:28.379098'
  stderr: |-
    /usr/lib/python3.6/site-packages/tox/config/__init__.py:672: UserWarning: conflicting basepython version (set 3.6, should be 3.8) for env 'py38';resolve conflict or set ignore_basepython_conflict
      testenv_config.envname,
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>
...ignoring

@lanfon72
Copy link
Member Author

412 will not have test results is expected, it is targeting to execute test cases not existing (then it would be same as —collect-only)
Base version conflicts is expected which is existing issue but will not affect to test execution

@albinsun albinsun requested a review from a team November 21, 2023 02:07
Copy link
Contributor

@albinsun albinsun left a comment

Choose a reason for hiding this comment

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

As comments, please help to add comment on key properties and some more unittests to increase readability, it will be helpful.

self.assertEqual(B0.for_version('1.2.0'), B120)
self.assertEqual(B0.for_version('1.1.3'), B113)
self.assertEqual(B0.for_version('1.3.0'), B130)
self.assertEqual(B0.for_version('1.1.4'), B114)
Copy link
Contributor

@albinsun albinsun Nov 22, 2023

Choose a reason for hiding this comment

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

Better to have multi-manager inheritance case which are more close to real usage in code.

for example

>>> from testo import BaseManager
>>> class AManager(BaseManager):
...     pass
... 
>>> class AManager_110(AManager):
...     support_to = '1.1.0'
... 
>>> class BManager(BaseManager):
...     pass
... 
>>> class BManager_110(BManager):
...     support_to = '1.1.0'
... 


>>> BManager.for_version('1.1.0') == BManager_110
True
>>> BManager.for_version('1.2.0') == BManager_110
True
>>> BManager.for_version('1.0.0') != BManager_110
True
>>> BManager.for_version('1.1.0') != AManager_110
True
>>> AManager.for_version('1.1.0') == AManager_110
True
...

Copy link
Member Author

@lanfon72 lanfon72 Nov 22, 2023

Choose a reason for hiding this comment

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

The unit test is focusing on test class method for_version, it is designed to seeking the most fit sub-class.

For multiple managers inherited from the BaseManager, is the flexibility of the class method, so it would not be included in unit test. (out of scope)

It is very general that we will not test inherited class behavior, because it's the contract of inheritance, derived class should follow parents signature and it's parents methods should always able to be used in derived.

apiclient/harvester_api/managers/base.py Show resolved Hide resolved
@lanfon72
Copy link
Member Author

lanfon72 commented Nov 22, 2023

The code snippet will help you to understand how to leverage the inheritance to support multiple version:

(venv) lanfon@lanfonsuse:~/dev_src/tests> python
Python 3.10.2 (main, Jan 19 2022, 22:05:06) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from harvester_api.managers import HostManager as hm, ImageManager as im
>>> hm._sub_classes[hm]  # the attribute `_sub_classes` inherited from BaseManager
[<class 'harvester_api.managers.hosts.HostManager'>]
>>> im._sub_classes[im]
[<class 'harvester_api.managers.images.ImageManager'>]
>>> class H2(hm):
...   support_to = '1.1.0'
... 
>>> hm._sub_classes[hm]  # when new class derived, it would be added into the dict by `__init_sub_classes__`
[<class 'harvester_api.managers.hosts.HostManager'>, <class '__main__.H2'>]
>>> hm._sub_classes[H2]  # The list for derived class `H2` would also be added
[<class '__main__.H2'>]
>>> 
>>> class H3(H2):
...   support_to = '1.2.0'
... 
>>> hm._sub_classes[hm]
[<class 'harvester_api.managers.hosts.HostManager'>, <class '__main__.H2'>, <class '__main__.H3'>]
>>> hm._sub_classes[H2]   # when H3 inherited from H2, all its parents will have it
[<class '__main__.H2'>, <class '__main__.H3'>]
>>> hm.for_version('1.2.0')  # the `for_version` is going to the target version in the class' sub classes (by using `is_support`)
<class '__main__.H3'>
>>> H3.for_version('1.1.0')  # so if its sub class don't have any suitable version, we will return itself
<class '__main__.H3'>

In the api.py, we add new method load_managers(version) to adjust supported managers for api authorized cluster. (when use api.Login to do authorization, managers will be load with the cluster's version.

You can check #979 for the similar case (inheritance and seeking) be used in terraform provider version.

Copy link
Contributor

@albinsun albinsun left a comment

Choose a reason for hiding this comment

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

LGTM

@albinsun albinsun requested a review from a team November 23, 2023 00:57
@lanfon72 lanfon72 merged commit db1a87e into harvester:main Nov 23, 2023
1 check passed
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