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

Feat/hw tool state pattern #134

Closed

Conversation

jneo8
Copy link
Contributor

@jneo8 jneo8 commented Dec 11, 2023

Draft PR without unit test.


  • Store status in the charm _stored and use it for conditional expression
  • Instead of re-call the hw_white_list, use the hw_white_list stored in _stored

[EC] this PR should cover

  • Fix infinite event loop (remove defer)
  • Should not regenerate hardware list after 1st installation
  • Missing logic before refactor

@jneo8 jneo8 changed the base branch from master to feat/life-cycle December 11, 2023 10:58
Copy link
Member

@gabrielcocenza gabrielcocenza left a comment

Choose a reason for hiding this comment

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

Hi, I left some comments that I think it can be improved.

I also would like to know why we are using # type: ignore in a lot of places of the code.

import logging
from time import sleep
from typing import Any, Dict, Optional, Tuple
from typing import Any, Dict, List, Optional, Tuple
Copy link
Member

Choose a reason for hiding this comment

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

typing Dict and List are deprecated. It's recommendable using plain list and dict

Comment on lines +91 to +93
if len(self._stored.missing_resources) == 0: # type: ignore
return False
return True
Copy link
Member

Choose a reason for hiding this comment

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

Maybe this would be equivalent?

Suggested change
if len(self._stored.missing_resources) == 0: # type: ignore
return False
return True
return len(self._stored.missing_resources) > 0

Comment on lines +98 to +100
if len(self._stored.failed_strategies) == 0: # type: ignore
return False
return True
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if len(self._stored.failed_strategies) == 0: # type: ignore
return False
return True
return len(self._stored.failed_strategies) > 0

Comment on lines +81 to +86
if (
len(self._stored.missing_resources) > 0 # type: ignore
or len(self._stored.failed_strategies) > 0 # type: ignore
):
return False
return True
Copy link
Member

Choose a reason for hiding this comment

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

I think we can use state_missing_resource and state_failed_install_strategies and not repeat the logic

Suggested change
if (
len(self._stored.missing_resources) > 0 # type: ignore
or len(self._stored.failed_strategies) > 0 # type: ignore
):
return False
return True
return self.state_missing_resource or self.state_failed_install_strategies

Copy link
Contributor Author

@jneo8 jneo8 Dec 12, 2023

Choose a reason for hiding this comment

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

I believe the meaning is different here, but I know what you want.

Comment on lines +110 to +113
health = self.exporter.check_health()
if not health:
logger.warning("Exporter health check - failed.")
return health
Copy link
Member

Choose a reason for hiding this comment

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

We can use walrus notation

Suggested change
health = self.exporter.check_health()
if not health:
logger.warning("Exporter health check - failed.")
return health
if not health := self.exporter.check_health():
logger.warning("Exporter health check - failed.")
return health

config={},
exporter_installed=False,
installed=False,
hw_white_list=[],
Copy link
Member

Choose a reason for hiding this comment

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

nit: I think it's preferable using accept_list or allow_list than white_list

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 terms is been used in whole project now. We can use another PR to replace it.


if not installed:
logger.error(msg)
self._log_stored()
Copy link
Member

Choose a reason for hiding this comment

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

Why here we don't have the same pattern of generating the message and logging as it happens on state_msg_missing_resources and state_msg_failed_install_strategies?

@property
def state_msg_missing_resources(self) -> str:
"""Message for missing resources."""
return f"Missing resources: {list(self._stored.missing_resources)}" # type: ignore
Copy link
Member

Choose a reason for hiding this comment

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

Maybe using .join as the comment bellow

if len(failed_checks) > 0:
return False, f"Fail strategy checks: {failed_checks}"
return True, ""
if ok:
Copy link
Member

Choose a reason for hiding this comment

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

ok it's not a good variable name and it's not used on other places. I prefer checking directly like if strategy.check():

"""Install the exporter."""
logger.info("Installing %s.", EXPORTER_NAME)
success = self.template.render_config(port=port, level=level, redfish_creds=redfish_creds)
success = self.template.render_config(
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand why we are using twice and overriding the variable success. If this fails it will not be checked and logged

Copy link
Contributor

@rgildein rgildein left a comment

Choose a reason for hiding this comment

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

Couple of small comments, but for functionality point of view it looks good to me.

def _log_stored(self) -> None:
"""Logger print _stored information."""
msg = (
"Hw tool state: " # type: ignore
Copy link
Contributor

Choose a reason for hiding this comment

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

Why we need to use type: ignore here?

"""Logger print _stored information."""
msg = (
"Hw tool state: " # type: ignore
f"hw_white_list: {list(self._stored.hw_white_list)}"
Copy link
Contributor

Choose a reason for hiding this comment

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

It's really needed to convert list to list?

>>> a = [1, 2, 3]
>>> f"without: {a} and with {list(a)}"
'without: [1, 2, 3] and with [1, 2, 3]'

f" installed_strategies: {list(self._stored.installed_strategies)}"
f" failed_strategies: {list(self._stored.failed_strategies)}"
)
logger.info(msg)
Copy link
Contributor

Choose a reason for hiding this comment

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

I will suggest to use lazy formatting instead of f-string, e.g. logger.log("some list: %s", some_list).

Comment on lines +82 to +83
len(self._stored.missing_resources) > 0 # type: ignore
or len(self._stored.failed_strategies) > 0 # type: ignore
Copy link
Contributor

Choose a reason for hiding this comment

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

Why we need to have this type ignore again? The StoredState is not providing type hinting? If yes, could we report an issue about it (I check there is none).

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, StoredState is not providing type hinting.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would be good to report an issue. Those type: ignore are enjoying :).

Comment on lines +81 to +86
if (
len(self._stored.missing_resources) > 0 # type: ignore
or len(self._stored.failed_strategies) > 0 # type: ignore
):
return False
return True
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if (
len(self._stored.missing_resources) > 0 # type: ignore
or len(self._stored.failed_strategies) > 0 # type: ignore
):
return False
return True
return not (
len(self._stored.missing_resources) > 0 # type: ignore
or len(self._stored.failed_strategies) > 0 # type: ignore
)

Comment on lines +91 to +93
if len(self._stored.missing_resources) == 0: # type: ignore
return False
return True
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if len(self._stored.missing_resources) == 0: # type: ignore
return False
return True
return not len(self._stored.missing_resources) == 0 # type: ignore

Comment on lines 573 to 574
if strategy.name not in hw_white_list:
continue
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO we should provide some log message for skipped strategy, same in install function.

return

port = self.model.config.get("exporter-port", "10000")
level = self.model.config.get("exporter-log-level", "INFO")
logger.info("Get redfish creds." "")
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
logger.info("Get redfish creds." "")
logger.info("Get redfish creds.")

@jneo8 jneo8 closed this Dec 12, 2023
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.

3 participants