-
Notifications
You must be signed in to change notification settings - Fork 127
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: add PyHPS CLI #3091
Closed
Closed
feat: add PyHPS CLI #3091
Changes from all commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
85d371e
First iteration
germa89 1da9ca4
Adding logging
germa89 4f32315
fixes to the CLI help
germa89 08d2055
Fix codacy issues
germa89 08731de
Merge branch 'main' into feat/pyhps-support
germa89 d70b090
Apply suggestions from code review
germa89 aa8a23c
Apply suggestions from code review
germa89 660e717
Adding suggestions
germa89 33ac15a
Removing warnings.
germa89 4055c60
Adding inputs and outputs (#3112)
germa89 f23da00
Adding APDL jobs support (#3111)
germa89 0f80a47
Refactoring PyHPS implementation (#3117)
germa89 a7adf0b
Merge branch 'main' into feat/pyhps-support
germa89 dff728d
Apply suggestions from Kathy's code review
germa89 a9eb0e8
Merge branch 'main' into feat/pyhps-support
germa89 445949a
Adding changelog entry: 3091.miscellaneous.md
pyansys-ci-bot 4556c49
Adding changelog entry: 3091.miscellaneous.md
pyansys-ci-bot ac875f1
Renaming argument ``to_json``.
germa89 1911729
rewriting docstring
germa89 9bc7612
Merge branch 'main' into feat/pyhps-support
germa89 0279ffc
Adding changelog entry: 3091.added.md
pyansys-ci-bot dd0cb4b
Merge branch 'main' into feat/pyhps-support
germa89 4145688
feat: Detaching logging from main logic (#3205)
germa89 6807934
fix: codecov suggestions
germa89 1b53047
feat: renaming PyMAPDLJobSubmissionDefinition class
germa89 a29589d
docs: improved docstring
germa89 b9a6c98
feat: renaming to submission.
germa89 e1b85b8
fix: doc example
germa89 e0bd844
docs:improve docstring examples
germa89 6cfa2eb
feat: rename file to match main function 'submit'
germa89 3b55c89
feat: adding option to pass token to CLI.
germa89 ef24249
docs: adding API docs
germa89 82e3209
chore: Merge branch 'main' into feat/pyhps-support
germa89 7af9298
docs: using other type of reference
germa89 a78aa4c
feat: adding imports to hpc.__init__
germa89 79615f8
Merge branch 'main' into feat/pyhps-support
germa89 72c309c
ci: auto fixes from pre-commit.com hooks.
pre-commit-ci[bot] File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
feat: add PyHPS CLI |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
feat: Detaching logging from main logic |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
.. _ref_hpc_api: | ||
|
||
.. currentmodule:: ansys.mapdl.core.hpc.pyhps | ||
|
||
HPC Submissions | ||
=============== | ||
|
||
.. autosummary:: | ||
:toctree: _autosummary | ||
|
||
SubmissionDefinition | ||
|
||
|
||
|
||
.. currentmodule:: ansys.mapdl.core.hpc.login | ||
|
||
HPC login | ||
========= | ||
|
||
.. autosummary:: | ||
:toctree: _autosummary | ||
|
||
get_token_access | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ PyMAPDL, see :ref:`ref_mapdl_commands`. | |
database | ||
geometry | ||
helper | ||
hpc | ||
information | ||
inline | ||
krylov | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,284 @@ | ||
# Copyright (C) 2016 - 2025 ANSYS, Inc. and/or its affiliates. | ||
# SPDX-License-Identifier: MIT | ||
# | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining a copy | ||
# of this software and associated documentation files (the "Software"), to deal | ||
# in the Software without restriction, including without limitation the rights | ||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
# copies of the Software, and to permit persons to whom the Software is | ||
# furnished to do so, subject to the following conditions: | ||
# | ||
# The above copyright notice and this permission notice shall be included in all | ||
# copies or substantial portions of the Software. | ||
# | ||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
# SOFTWARE. | ||
|
||
"""Login into a PyHPS cluster""" | ||
from getpass import getpass | ||
import logging | ||
from typing import Optional | ||
|
||
import click | ||
|
||
logging.basicConfig( | ||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", | ||
) | ||
logger = logging.getLogger() | ||
|
||
|
||
@click.command( | ||
name="login", | ||
short_help="Login into an HPS cluster.", | ||
help="""Login into an HPS cluster. | ||
|
||
It does store credentials (cluster url, password and username) in the OS credential manager. | ||
If you want to change any credential, just issue the command again with the new values. | ||
|
||
Examples | ||
-------- | ||
|
||
Prompt the values for user, password and HPC cluster URL: | ||
|
||
$ pymapdl login | ||
Username: myuser | ||
Password: mypassword | ||
HPS cluster URL: https://123.456.789.1:3000/hps | ||
Stored credentials: | ||
User : 'user' | ||
Cluster URL : 'https://123.456.789.1:3000/hps' | ||
|
||
Use the CLI arguments to supply the values | ||
|
||
$ pymapdl login --user myuser --password mypassword --url "https://123.456.789.1:3000/hps" | ||
Stored credentials: | ||
User : 'user' | ||
Cluster URL : 'https://123.456.789.1:3000/hps' | ||
|
||
Set the defaults user, password and URL. They will be used when one of them is | ||
missing. | ||
|
||
$ pymapdl login --default --user myuser --password mypassword --url "https://123.456.789.1:3000/hps" | ||
Stored default credentials. | ||
|
||
It is possible to input some arguments using the CLI arguments, and other using | ||
the prompt: | ||
|
||
$ pymapdl login --user myuser --url "https://123.456.789.1:3000/hps" | ||
Password: mypassword | ||
Stored credentials: | ||
User : 'user' | ||
Cluster URL : 'https://123.456.789.1:3000/hps' | ||
|
||
""", | ||
) | ||
@click.option("--user", default=None, type=str, help="The username to login.") | ||
@click.option("--password", default=None, type=str, help="The password to login.") | ||
@click.option( | ||
"--url", | ||
default=None, | ||
type=str, | ||
help="The HPS cluster URL. For instance 'https://123.456.789.1:3000/hps'.", | ||
) | ||
@click.option( | ||
"--default", | ||
default=False, | ||
type=bool, | ||
is_flag=False, | ||
flag_value=True, | ||
help="""Set the default user, password and URL. These credentials are not tested against any HPC.""", | ||
) | ||
@click.option( | ||
"--test_token", | ||
default=False, | ||
type=bool, | ||
is_flag=False, | ||
flag_value=True, | ||
help="""Test if the token is valid. This argument is ignored if '--default' argument is ``True``.""", | ||
) | ||
@click.option( | ||
"--quiet", | ||
default=False, | ||
type=bool, | ||
is_flag=False, | ||
flag_value=True, | ||
help="""Suppress all console printout.""", | ||
) | ||
@click.option( | ||
"--debug", | ||
default=False, | ||
type=bool, | ||
is_flag=False, | ||
flag_value=True, | ||
help="""Activate debugging printout. It might show the input password!""", | ||
) | ||
def login( | ||
user: Optional[str] = None, | ||
password: Optional[str] = None, | ||
url: Optional[str] = None, | ||
default: bool = False, | ||
test_token: bool = False, | ||
quiet: bool = False, | ||
debug: bool = False, | ||
): | ||
from ansys.mapdl.core.hpc.login import login_in_cluster, store_credentials | ||
|
||
if debug: | ||
logger.setLevel(logging.DEBUG) | ||
|
||
if quiet: | ||
import urllib3 | ||
|
||
urllib3.disable_warnings() | ||
|
||
logger.debug("Storing non-default credentials.") | ||
if not user: | ||
user = click.prompt("Username") | ||
|
||
if not user: | ||
raise ValueError("No user was provided.") | ||
|
||
if not password: | ||
password = getpass("Password: ") | ||
if not password: | ||
raise ValueError("No password was provided.") | ||
|
||
if not default and not url: | ||
url = click.prompt("HPS cluster URL") | ||
if not url: | ||
raise ValueError("No password was provided.") | ||
|
||
token = login_in_cluster(user, password, url) | ||
logger.debug("Login successful") | ||
|
||
if test_token: | ||
logger.debug("Testing token") | ||
from requests import ConnectionError | ||
|
||
from ansys.mapdl.core.hpc.login import token_is_valid | ||
|
||
if not token_is_valid(url, token): | ||
raise ConnectionError("The retrieved token is not valid.") | ||
else: | ||
if not quiet: | ||
click.echo("Token has been verified with the HPC cluster.") | ||
|
||
logger.info(f"Stored credentials: {user}, {password}, {url}") | ||
store_credentials(user, password, url, default=default) | ||
|
||
if not quiet: | ||
if default: | ||
click.echo("Stored default credentials.") | ||
else: | ||
click.echo( | ||
f"Stored credentials:\n User : '{user}'\n Cluster URL : '{url}'" | ||
) | ||
|
||
|
||
@click.command( | ||
short_help="Logout from an HPS cluster.", | ||
help="""Logout from an HPS cluster. | ||
|
||
It deletes credentials stored on the system. | ||
|
||
Examples | ||
-------- | ||
|
||
Delete the credentials associated to an specific URL | ||
|
||
$ pymapdl logout --url "https://123.456.789.1:3000/hps" | ||
The HPS cluster 'https://123.456.789.1:3000/hps' credentials have been deleted. | ||
|
||
Delete the default credentials. | ||
|
||
$ pymapdl logout --default | ||
The default credentials have been deleted. | ||
|
||
Notes | ||
----- | ||
- If the credentials do not exist, the CLI notifies and exits cleanly. | ||
No exception is raised. If you want to raise an exception (exit 1), then pass | ||
the argument ``--strict``. | ||
""", | ||
) | ||
@click.option( | ||
"--url", | ||
default=None, | ||
type=str, | ||
help="The HPS cluster URL. For instance 'https://10.231.106.1:3000/hps'.", | ||
) | ||
@click.option( | ||
"--default", | ||
default=False, | ||
type=bool, | ||
is_flag=False, | ||
flag_value=True, | ||
help="""Deletes the default login configuration.""", | ||
) | ||
@click.option( | ||
"--quiet", | ||
default=False, | ||
type=bool, | ||
is_flag=False, | ||
flag_value=True, | ||
help="""Suppress all console printout.""", | ||
) | ||
@click.option( | ||
"--debug", | ||
default=False, | ||
type=bool, | ||
is_flag=False, | ||
flag_value=True, | ||
help="""Activate debugging printout.""", | ||
) | ||
@click.option( | ||
"--strict", | ||
default=False, | ||
type=bool, | ||
is_flag=False, | ||
flag_value=True, | ||
help="""Raise an issue if the credentials do not exist.""", | ||
) | ||
def logout(url, default, quiet, debug, strict): | ||
|
||
# TODO: keyrings library seems to not being able to list the credentials | ||
# under a service name. We might need to keep track of those in a file or | ||
# something. | ||
|
||
import keyring | ||
|
||
from ansys.mapdl.core.hpc.login import delete_credentials | ||
|
||
if debug: | ||
logger.setLevel(logging.DEBUG) | ||
|
||
if not url and not default: | ||
raise ValueError("An URL needs to be used.") | ||
|
||
if url and default: | ||
raise ValueError("The argument '--default' cannot be used with an URL.") | ||
|
||
if default: | ||
logger.debug("Deleting credentials for the default profile.") | ||
url = None | ||
|
||
try: | ||
delete_credentials(url) | ||
success_message = "The {0} credentials have been deleted.".format( | ||
"default" if default else f"HPS cluster '{url}'" | ||
) | ||
except keyring.errors.PasswordDeleteError: | ||
success_message = "The {0} credentials do not exist.".format( | ||
"default" if default else f"HPS cluster '{url}'" | ||
) | ||
if strict: | ||
raise keyring.errors.PasswordDeleteError(success_message) | ||
|
||
if not quiet: | ||
click.echo(success_message) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
Copilot Autofix AI about 1 month ago
To fix the problem, we need to ensure that sensitive information such as passwords is not logged. Instead of logging the password, we can log a placeholder or omit it entirely from the log message. This change should be made on line 172 where the sensitive information is being logged.
The best way to fix this without changing existing functionality is to modify the log message to exclude the password. We can log the user and URL while omitting the password. This change will be made in the
login
function in the filesrc/ansys/mapdl/core/cli/login.py
.