osc-lib 3.2.0__tar.gz → 4.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {osc-lib-3.2.0 → osc_lib-4.0.1}/.pre-commit-config.yaml +17 -2
- {osc-lib-3.2.0 → osc_lib-4.0.1}/ChangeLog +38 -0
- osc_lib-4.0.1/PKG-INFO +94 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/api/api.py +62 -27
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/api/auth.py +36 -21
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/api/utils.py +10 -5
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/cli/client_config.py +53 -32
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/cli/format_columns.py +19 -17
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/cli/identity.py +14 -3
- osc_lib-4.0.1/osc_lib/cli/pagination.py +83 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/cli/parseractions.py +98 -20
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/clientmanager.py +45 -24
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/command/command.py +19 -8
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/command/timing.py +11 -1
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/exceptions.py +12 -2
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/logs.py +17 -8
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/shell.py +64 -44
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/test_shell.py +4 -4
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/utils/__init__.py +0 -19
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/utils/test_tags.py +22 -7
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/utils/test_utils.py +1 -11
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/utils/__init__.py +179 -108
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/utils/columns.py +15 -4
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/utils/tags.py +38 -21
- osc_lib-4.0.1/osc_lib.egg-info/PKG-INFO +94 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib.egg-info/SOURCES.txt +8 -1
- osc_lib-4.0.1/osc_lib.egg-info/pbr.json +1 -0
- osc_lib-4.0.1/pyproject.toml +46 -0
- osc_lib-4.0.1/releasenotes/notes/deprecate-BaseAPI-09abd3cb955c2bb6.yaml +6 -0
- osc_lib-4.0.1/releasenotes/notes/deprecate-clientcache-38c8c9fd4ca6dcdf.yaml +4 -0
- osc_lib-4.0.1/releasenotes/notes/deprecated-legacy-client-helpers-53dde79bd6769d2d.yaml +7 -0
- osc_lib-4.0.1/releasenotes/notes/env-default-e8f2c60f1295d15f.yaml +5 -0
- osc_lib-4.0.1/releasenotes/notes/remove-support-for-legacy-formatters-1240317d801b4336.yaml +8 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/2023.1.rst +1 -1
- osc_lib-4.0.1/releasenotes/source/2025.1.rst +6 -0
- osc_lib-4.0.1/releasenotes/source/_templates/.placeholder +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/index.rst +1 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/requirements.txt +1 -5
- {osc-lib-3.2.0 → osc_lib-4.0.1}/test-requirements.txt +0 -4
- {osc-lib-3.2.0 → osc_lib-4.0.1}/tox.ini +3 -3
- osc-lib-3.2.0/PKG-INFO +0 -87
- osc-lib-3.2.0/doc/Makefile +0 -130
- osc-lib-3.2.0/osc_lib.egg-info/PKG-INFO +0 -87
- osc-lib-3.2.0/osc_lib.egg-info/pbr.json +0 -1
- osc-lib-3.2.0/pyproject.toml +0 -9
- {osc-lib-3.2.0 → osc_lib-4.0.1}/.coveragerc +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/.git-ignore-blame-revs +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/.mailmap +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/.stestr.conf +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/.zuul.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/AUTHORS +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/HACKING.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/LICENSE +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/README.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/doc/ext/__init__.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/doc/ext/apidoc.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/doc/requirements.txt +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/doc/source/conf.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/doc/source/contributor/index.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/doc/source/index.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/doc/source/reference/index.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/doc/source/user/change_log.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/doc/source/user/index.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/doc/source/user/transition.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/__init__.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/api/__init__.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/cli/__init__.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/command/__init__.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/command/commandmanager.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/i18n.py +0 -0
- /osc-lib-3.2.0/osc_lib/tests/__init__.py → /osc_lib-4.0.1/osc_lib/py.typed +0 -0
- {osc-lib-3.2.0/osc_lib/tests/api → osc_lib-4.0.1/osc_lib/tests}/__init__.py +0 -0
- {osc-lib-3.2.0/osc_lib/tests/cli → osc_lib-4.0.1/osc_lib/tests/api}/__init__.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/api/fakes.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/api/test_api.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/api/test_utils.py +0 -0
- {osc-lib-3.2.0/osc_lib/tests/command → osc_lib-4.0.1/osc_lib/tests/cli}/__init__.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/cli/test_client_config.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/cli/test_format_columns.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/cli/test_identity.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/cli/test_parseractions.py +0 -0
- /osc-lib-3.2.0/releasenotes/notes/.placeholder → /osc_lib-4.0.1/osc_lib/tests/command/__init__.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/command/test_command.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/command/test_timing.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/fakes.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/test_clientmanager.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/test_logs.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/tests/utils/test_columns.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib/version.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib.egg-info/dependency_links.txt +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib.egg-info/not-zip-safe +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib.egg-info/requires.txt +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/osc_lib.egg-info/top_level.txt +0 -0
- {osc-lib-3.2.0/releasenotes/source/_static → osc_lib-4.0.1/releasenotes/notes}/.placeholder +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/1.0-summary-47dcce446d6a512b.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/add-KeyValueAppendAction-class-f830e71152d6b91e.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/add-MultiKeyValueCommaAction-class-01dd254a287d70d2.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/add-size-column-5424c40af74688df.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/add_sdk_utils-d0c338eba682f2c8.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/arg-precedence-1ba9fd6929650830.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/auth-type-none-d96760912605f822.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/bug-1558690-1528b637f2c0a449.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/bug-1630822-mask-password-on-debug-20dcdf1c54e84fa1.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/bug-2004898-686577a07e791051.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/bug-2006480-436489d39643e76c.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/direct-openstacksdk-535a179f3c645cc0.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/drop-py2-support-60c93244107d5778.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/find-project-203bf867619c557e.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/keystone-to-keystone-9b2e55b051775322.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/none-auth-cli-48ab0e48d4852941.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/os-profile-as-environment-variable-a5e232e9ca7c5171.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/remove-babel-50abc5b548455bb2.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/remove-group-subclass-82134e6915c7c782.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/save-results-4473cb5731c0c763.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/notes/shell-argv-decode-cdc13dc0c4ec07af.yaml +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/2023.2.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/2024.1.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/2024.2.rst +0 -0
- {osc-lib-3.2.0/releasenotes/source/_templates → osc_lib-4.0.1/releasenotes/source/_static}/.placeholder +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/conf.py +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/newton.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/ocata.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/pike.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/queens.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/rocky.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/stein.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/train.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/unreleased.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/ussuri.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/victoria.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/wallaby.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/xena.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/yoga.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/releasenotes/source/zed.rst +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/setup.cfg +0 -0
- {osc-lib-3.2.0 → osc_lib-4.0.1}/setup.py +0 -0
@@ -4,7 +4,7 @@ default_language_version:
|
|
4
4
|
python: python3
|
5
5
|
repos:
|
6
6
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
7
|
-
rev:
|
7
|
+
rev: v5.0.0
|
8
8
|
hooks:
|
9
9
|
- id: trailing-whitespace
|
10
10
|
- id: mixed-line-ending
|
@@ -22,7 +22,7 @@ repos:
|
|
22
22
|
hooks:
|
23
23
|
- id: doc8
|
24
24
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
25
|
-
rev: v0.6
|
25
|
+
rev: v0.9.6
|
26
26
|
hooks:
|
27
27
|
- id: ruff
|
28
28
|
args: ['--fix', '--unsafe-fixes']
|
@@ -34,3 +34,18 @@ repos:
|
|
34
34
|
additional_dependencies:
|
35
35
|
- flake8-import-order~=0.18.2
|
36
36
|
exclude: '^(doc|releasenotes|tools)/.*$'
|
37
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
38
|
+
rev: v1.13.0
|
39
|
+
hooks:
|
40
|
+
- id: mypy
|
41
|
+
additional_dependencies:
|
42
|
+
- cliff
|
43
|
+
- keystoneauth1
|
44
|
+
- types-requests
|
45
|
+
# keep this in-sync with '[mypy] exclude' in 'setup.cfg'
|
46
|
+
exclude: |
|
47
|
+
(?x)(
|
48
|
+
doc/.*
|
49
|
+
| examples/.*
|
50
|
+
| releasenotes/.*
|
51
|
+
)
|
@@ -1,6 +1,44 @@
|
|
1
1
|
CHANGES
|
2
2
|
=======
|
3
3
|
|
4
|
+
4.0.1
|
5
|
+
-----
|
6
|
+
|
7
|
+
* Temporarily revert dependency bumps
|
8
|
+
* Use Python 3.8-style type hints
|
9
|
+
* Temporarily undrop support for Python 3.8, 3.9
|
10
|
+
* Drop support for Python 3.8, 3.9
|
11
|
+
* Replace UPPER\_CONSTRAINTS\_FILE
|
12
|
+
|
13
|
+
4.0.0
|
14
|
+
-----
|
15
|
+
|
16
|
+
* typing: Enable disallow\_subclassing\_any
|
17
|
+
* tests: Resolve TODO
|
18
|
+
* utils: Deprecate legacy client-specific helpers
|
19
|
+
* utils: Remove support for legacy format functions
|
20
|
+
* utils: Group similar utilities together
|
21
|
+
* utils: Don't warn for partial formatter classes
|
22
|
+
* typing: Add typing to osc\_lib.utils
|
23
|
+
* typing: Add typing to osc\_lib.command
|
24
|
+
* clientmanager: Deprecate ClientCache
|
25
|
+
* typing: Add typing to osc\_lib.clientmanager
|
26
|
+
* typing: Add typing to osc\_lib.shell
|
27
|
+
* typing: Add typing to osc\_lib.logs, osc\_lib.i18n
|
28
|
+
* typing: Add typing to osc\_lib.cli
|
29
|
+
* api: Deprecate BaseAPI
|
30
|
+
* typing: Add typing to osc\_lib.api
|
31
|
+
* Remove unused docs Makefile
|
32
|
+
* typing: Add typing to osc\_lib.exceptions
|
33
|
+
* pre-commit: Enable mypy
|
34
|
+
* typing: Fix initial typing issues
|
35
|
+
* Update master for stable/2025.1
|
36
|
+
* Add pagination helpers
|
37
|
+
* pre-commit: Enable ruff S (bandit) checks
|
38
|
+
* pre-commit: Bump versions
|
39
|
+
* tests: Use consistent output widths
|
40
|
+
* reno: Update master for unmaintained/2023.1
|
41
|
+
|
4
42
|
3.2.0
|
5
43
|
-----
|
6
44
|
|
osc_lib-4.0.1/PKG-INFO
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: osc-lib
|
3
|
+
Version: 4.0.1
|
4
|
+
Summary: OpenStackClient Library
|
5
|
+
Home-page: https://docs.openstack.org/osc-lib/latest/
|
6
|
+
Author: OpenStack
|
7
|
+
Author-email: openstack-discuss@lists.openstack.org
|
8
|
+
Project-URL: Bug Tracker, https://storyboard.openstack.org/#!/project/openstack/osc-lib
|
9
|
+
Project-URL: Documentation, https://docs.openstack.org/osc-lib/latest/
|
10
|
+
Project-URL: Source Code, https://opendev.org/openstack/osc-lib/
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
12
|
+
Classifier: Environment :: OpenStack
|
13
|
+
Classifier: Intended Audience :: Information Technology
|
14
|
+
Classifier: Intended Audience :: System Administrators
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
16
|
+
Classifier: Operating System :: POSIX :: Linux
|
17
|
+
Classifier: Programming Language :: Python
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
19
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
20
|
+
Requires-Python: >=3.8
|
21
|
+
License-File: LICENSE
|
22
|
+
Requires-Dist: cliff>=3.2.0
|
23
|
+
Requires-Dist: keystoneauth1>=3.14.0
|
24
|
+
Requires-Dist: openstacksdk>=0.15.0
|
25
|
+
Requires-Dist: oslo.i18n>=3.15.3
|
26
|
+
Requires-Dist: oslo.utils>=3.33.0
|
27
|
+
Requires-Dist: pbr!=2.1.0,>=2.0.0
|
28
|
+
Requires-Dist: requests>=2.14.2
|
29
|
+
Requires-Dist: stevedore>=1.20.0
|
30
|
+
|
31
|
+
=======
|
32
|
+
osc-lib
|
33
|
+
=======
|
34
|
+
|
35
|
+
.. image:: https://img.shields.io/pypi/v/osc-lib.svg
|
36
|
+
:target: https://pypi.org/project/osc-lib/
|
37
|
+
:alt: Latest Version
|
38
|
+
|
39
|
+
OpenStackClient (aka OSC) is a command-line client for OpenStack. osc-lib
|
40
|
+
is a package of common support modules for writing OSC plugins.
|
41
|
+
|
42
|
+
* `PyPi`_ - package installation
|
43
|
+
* `Online Documentation`_
|
44
|
+
* `Launchpad project`_ - part of OpenStackClient
|
45
|
+
* `Bugs`_ - issue tracking
|
46
|
+
* `Source`_
|
47
|
+
* `Developer` - getting started as a developer
|
48
|
+
* `Contributing` - contributing code
|
49
|
+
* `Testing` - testing code
|
50
|
+
* IRC: #openstack-sdks on OFTC (irc.oftc.net)
|
51
|
+
* License: Apache 2.0
|
52
|
+
|
53
|
+
.. _PyPi: https://pypi.org/project/osc-lib
|
54
|
+
.. _Online Documentation: http://docs.openstack.org/osc-lib/latest/
|
55
|
+
.. _Launchpad project: https://launchpad.net/python-openstackclient
|
56
|
+
.. _Bugs: https://storyboard.openstack.org/#!/project_group/80
|
57
|
+
.. _Source: https://opendev.org/openstack/osc-lib
|
58
|
+
.. _Developer: http://docs.openstack.org/project-team-guide/project-setup/python.html
|
59
|
+
.. _Contributing: http://docs.openstack.org/infra/manual/developers.html
|
60
|
+
.. _Testing: http://docs.openstack.org/osc-lib/latest/contributor/#testing
|
61
|
+
.. _Release Notes: https://docs.openstack.org/releasenotes/osc-lib
|
62
|
+
|
63
|
+
Getting Started
|
64
|
+
===============
|
65
|
+
|
66
|
+
osc-lib can be installed from PyPI using pip::
|
67
|
+
|
68
|
+
pip install osc-lib
|
69
|
+
|
70
|
+
Transition From OpenStackclient
|
71
|
+
===============================
|
72
|
+
|
73
|
+
This library was extracted from the main OSC repo after the OSC 2.4.0 release.
|
74
|
+
The following are the changes to imports that will cover the majority of
|
75
|
+
transition to using osc-lib:
|
76
|
+
|
77
|
+
* openstackclient.api.api -> osc_lib.api.api
|
78
|
+
* openstackclient.api.auth -> osc_lib.api.auth
|
79
|
+
* openstackclient.api.utils -> osc_lib.api.utils
|
80
|
+
* openstackclient.common.command -> osc_lib.command.command
|
81
|
+
* openstackclient.common.commandmanager -> osc_lib.command.commandmanager
|
82
|
+
* openstackclient.common.exceptions -> osc_lib.exceptions
|
83
|
+
* openstackclient.common.logs -> osc_lib.logs
|
84
|
+
* openstackclient.common.parseractions -> osc_lib.cli.parseractions
|
85
|
+
* openstackclient.common.session -> osc_lib.session
|
86
|
+
* openstackclient.common.utils -> osc_lib.utils
|
87
|
+
* openstackclient.i18n -> osc_lib.i18n
|
88
|
+
* openstackclient.shell -> osc_lib.shell
|
89
|
+
|
90
|
+
Also, some of the test fixtures and modules may be used:
|
91
|
+
|
92
|
+
* openstackclient.tests.fakes -> osc_lib.tests.fakes
|
93
|
+
* openstackclient.tests.utils -> osc_lib.tests.utils
|
94
|
+
|
@@ -13,6 +13,9 @@
|
|
13
13
|
|
14
14
|
"""Base API Library"""
|
15
15
|
|
16
|
+
import typing as ty
|
17
|
+
import warnings
|
18
|
+
|
16
19
|
from keystoneauth1 import exceptions as ksa_exceptions
|
17
20
|
from keystoneauth1 import session as ksa_session
|
18
21
|
import requests
|
@@ -42,8 +45,12 @@ class BaseAPI:
|
|
42
45
|
HEADER_NAME = "OpenStack-API-Version"
|
43
46
|
|
44
47
|
def __init__(
|
45
|
-
self,
|
46
|
-
|
48
|
+
self,
|
49
|
+
session: ty.Optional[ksa_session.Session] = None,
|
50
|
+
service_type: ty.Optional[str] = None,
|
51
|
+
endpoint: ty.Optional[str] = None,
|
52
|
+
**kwargs: ty.Any,
|
53
|
+
) -> None:
|
47
54
|
"""Base object that contains some common API objects and methods
|
48
55
|
|
49
56
|
:param keystoneauth1.session.Session session:
|
@@ -58,6 +65,12 @@ class BaseAPI:
|
|
58
65
|
Keyword arguments passed to keystoneauth1.session.Session().
|
59
66
|
"""
|
60
67
|
|
68
|
+
warnings.warn(
|
69
|
+
'The BaseAPI class is deprecated for removal. Consider using '
|
70
|
+
'openstacksdk instead else vendoring this code into your client',
|
71
|
+
category=DeprecationWarning,
|
72
|
+
)
|
73
|
+
|
61
74
|
super().__init__()
|
62
75
|
|
63
76
|
# Create a keystoneauth1.session.Session if one is not supplied
|
@@ -69,7 +82,7 @@ class BaseAPI:
|
|
69
82
|
self.service_type = service_type
|
70
83
|
self.endpoint = self._munge_endpoint(endpoint)
|
71
84
|
|
72
|
-
def _munge_endpoint(self, endpoint):
|
85
|
+
def _munge_endpoint(self, endpoint: ty.Optional[str]) -> ty.Optional[str]:
|
73
86
|
"""Hook to allow subclasses to massage the passed-in endpoint
|
74
87
|
|
75
88
|
Hook to massage passed-in endpoints from arbitrary sources,
|
@@ -90,7 +103,13 @@ class BaseAPI:
|
|
90
103
|
else:
|
91
104
|
return endpoint
|
92
105
|
|
93
|
-
def _request(
|
106
|
+
def _request(
|
107
|
+
self,
|
108
|
+
method: str,
|
109
|
+
url: str,
|
110
|
+
session: ty.Optional[ksa_session.Session] = None,
|
111
|
+
**kwargs: ty.Any,
|
112
|
+
) -> requests.Response:
|
94
113
|
"""Perform call into session
|
95
114
|
|
96
115
|
All API calls are funneled through this method to provide a common
|
@@ -136,7 +155,13 @@ class BaseAPI:
|
|
136
155
|
|
137
156
|
# The basic action methods all take a Session and return dict/lists
|
138
157
|
|
139
|
-
def create(
|
158
|
+
def create(
|
159
|
+
self,
|
160
|
+
url: str,
|
161
|
+
session: ty.Optional[ksa_session.Session] = None,
|
162
|
+
method: ty.Optional[str] = None,
|
163
|
+
**params: ty.Any,
|
164
|
+
) -> ty.Union[requests.Response, ty.Any]:
|
140
165
|
"""Create a new resource
|
141
166
|
|
142
167
|
:param string url:
|
@@ -156,7 +181,12 @@ class BaseAPI:
|
|
156
181
|
except requests.JSONDecodeError:
|
157
182
|
return ret
|
158
183
|
|
159
|
-
def delete(
|
184
|
+
def delete(
|
185
|
+
self,
|
186
|
+
url: str,
|
187
|
+
session: ty.Optional[ksa_session.Session] = None,
|
188
|
+
**params: ty.Any,
|
189
|
+
) -> requests.Response:
|
160
190
|
"""Delete a resource
|
161
191
|
|
162
192
|
:param string url:
|
@@ -169,13 +199,13 @@ class BaseAPI:
|
|
169
199
|
|
170
200
|
def list(
|
171
201
|
self,
|
172
|
-
path,
|
173
|
-
session=None,
|
174
|
-
body=None,
|
175
|
-
detailed=False,
|
176
|
-
headers=None,
|
177
|
-
**params,
|
178
|
-
):
|
202
|
+
path: str,
|
203
|
+
session: ty.Optional[ksa_session.Session] = None,
|
204
|
+
body: ty.Any = None,
|
205
|
+
detailed: bool = False,
|
206
|
+
headers: ty.Optional[ty.Dict[str, str]] = None,
|
207
|
+
**params: ty.Any,
|
208
|
+
) -> ty.Union[requests.Response, ty.Any]:
|
179
209
|
"""Return a list of resources
|
180
210
|
|
181
211
|
GET ${ENDPOINT}/${PATH}?${PARAMS}
|
@@ -226,11 +256,11 @@ class BaseAPI:
|
|
226
256
|
|
227
257
|
def find_attr(
|
228
258
|
self,
|
229
|
-
path,
|
230
|
-
value=None,
|
231
|
-
attr=None,
|
232
|
-
resource=None,
|
233
|
-
):
|
259
|
+
path: str,
|
260
|
+
value: ty.Optional[str] = None,
|
261
|
+
attr: ty.Optional[str] = None,
|
262
|
+
resource: ty.Optional[str] = None,
|
263
|
+
) -> ty.Any:
|
234
264
|
"""Find a resource via attribute or ID
|
235
265
|
|
236
266
|
Most APIs return a list wrapped by a dict with the resource
|
@@ -260,7 +290,7 @@ class BaseAPI:
|
|
260
290
|
if resource is None:
|
261
291
|
resource = path
|
262
292
|
|
263
|
-
def getlist(kw):
|
293
|
+
def getlist(kw: ty.Dict[str, ty.Any]) -> ty.Any:
|
264
294
|
"""Do list call, unwrap resource dict if present"""
|
265
295
|
ret = self.list(path, **kw)
|
266
296
|
if isinstance(ret, dict) and resource in ret:
|
@@ -290,7 +320,12 @@ class BaseAPI:
|
|
290
320
|
msg % {'resource': resource, 'attr': attr, 'value': value}
|
291
321
|
)
|
292
322
|
|
293
|
-
def find_bulk(
|
323
|
+
def find_bulk(
|
324
|
+
self,
|
325
|
+
path: str,
|
326
|
+
headers: ty.Optional[ty.Dict[str, str]] = None,
|
327
|
+
**kwargs: ty.Any,
|
328
|
+
) -> ty.List[ty.Any]:
|
294
329
|
"""Bulk load and filter locally
|
295
330
|
|
296
331
|
:param string path:
|
@@ -318,7 +353,7 @@ class BaseAPI:
|
|
318
353
|
|
319
354
|
return ret
|
320
355
|
|
321
|
-
def find_one(self, path, **kwargs):
|
356
|
+
def find_one(self, path: str, **kwargs: ty.Any) -> ty.Any:
|
322
357
|
"""Find a resource by name or ID
|
323
358
|
|
324
359
|
:param string path:
|
@@ -339,11 +374,11 @@ class BaseAPI:
|
|
339
374
|
|
340
375
|
def find(
|
341
376
|
self,
|
342
|
-
path,
|
343
|
-
value=None,
|
344
|
-
attr=None,
|
345
|
-
headers=None,
|
346
|
-
):
|
377
|
+
path: str,
|
378
|
+
value: ty.Optional[str] = None,
|
379
|
+
attr: ty.Optional[str] = None,
|
380
|
+
headers: ty.Optional[ty.Dict[str, str]] = None,
|
381
|
+
) -> ty.Any:
|
347
382
|
"""Find a single resource by name or ID
|
348
383
|
|
349
384
|
:param string path:
|
@@ -356,7 +391,7 @@ class BaseAPI:
|
|
356
391
|
Headers dictionary to pass to requests
|
357
392
|
"""
|
358
393
|
|
359
|
-
def raise_not_found():
|
394
|
+
def raise_not_found() -> ty.NoReturn:
|
360
395
|
msg = _("%s not found") % value
|
361
396
|
raise exceptions.NotFound(404, msg)
|
362
397
|
|
@@ -14,7 +14,9 @@
|
|
14
14
|
"""Authentication Library"""
|
15
15
|
|
16
16
|
import argparse
|
17
|
+
import typing as ty
|
17
18
|
|
19
|
+
from keystoneauth1.identity import base as identity_base
|
18
20
|
from keystoneauth1.identity.v3 import k2k
|
19
21
|
from keystoneauth1.loading import base
|
20
22
|
|
@@ -22,16 +24,25 @@ from osc_lib import exceptions as exc
|
|
22
24
|
from osc_lib.i18n import _
|
23
25
|
from osc_lib import utils
|
24
26
|
|
27
|
+
if ty.TYPE_CHECKING:
|
28
|
+
from openstack import connection
|
29
|
+
|
25
30
|
|
26
31
|
# Initialize the list of Authentication plugins early in order
|
27
32
|
# to get the command-line options
|
28
33
|
PLUGIN_LIST = None
|
29
34
|
|
35
|
+
|
36
|
+
class _OptionDict(ty.TypedDict):
|
37
|
+
env: str
|
38
|
+
help: str
|
39
|
+
|
40
|
+
|
30
41
|
# List of plugin command line options
|
31
|
-
OPTIONS_LIST = {}
|
42
|
+
OPTIONS_LIST: ty.Dict[str, _OptionDict] = {}
|
32
43
|
|
33
44
|
|
34
|
-
def get_plugin_list():
|
45
|
+
def get_plugin_list() -> ty.FrozenSet[str]:
|
35
46
|
"""Gather plugin list and cache it"""
|
36
47
|
|
37
48
|
global PLUGIN_LIST
|
@@ -41,7 +52,7 @@ def get_plugin_list():
|
|
41
52
|
return PLUGIN_LIST
|
42
53
|
|
43
54
|
|
44
|
-
def get_options_list():
|
55
|
+
def get_options_list() -> ty.Dict[str, _OptionDict]:
|
45
56
|
"""Gather plugin options so the help action has them available"""
|
46
57
|
|
47
58
|
global OPTIONS_LIST
|
@@ -65,7 +76,10 @@ def get_options_list():
|
|
65
76
|
return OPTIONS_LIST
|
66
77
|
|
67
78
|
|
68
|
-
def check_valid_authorization_options(
|
79
|
+
def check_valid_authorization_options(
|
80
|
+
options: 'connection.Connection',
|
81
|
+
auth_plugin_name: str,
|
82
|
+
) -> None:
|
69
83
|
"""Validate authorization options, and provide helpful error messages."""
|
70
84
|
if (
|
71
85
|
options.auth.get('project_id')
|
@@ -86,16 +100,15 @@ def check_valid_authorization_options(options, auth_plugin_name):
|
|
86
100
|
)
|
87
101
|
|
88
102
|
|
89
|
-
def check_valid_authentication_options(
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
"""
|
95
|
-
|
103
|
+
def check_valid_authentication_options(
|
104
|
+
options: 'connection.Connection',
|
105
|
+
auth_plugin_name: str,
|
106
|
+
) -> None:
|
107
|
+
"""Validate authentication options, and provide helpful error messages."""
|
96
108
|
# Get all the options defined within the plugin.
|
97
|
-
plugin_opts =
|
98
|
-
|
109
|
+
plugin_opts = {
|
110
|
+
opt.dest: opt for opt in base.get_plugin_options(auth_plugin_name)
|
111
|
+
}
|
99
112
|
|
100
113
|
# NOTE(aloga): this is an horrible hack. We need a way to specify the
|
101
114
|
# required options in the plugins. Using the "required" argument for
|
@@ -141,7 +154,9 @@ def check_valid_authentication_options(options, auth_plugin_name):
|
|
141
154
|
)
|
142
155
|
|
143
156
|
|
144
|
-
def build_auth_plugins_option_parser(
|
157
|
+
def build_auth_plugins_option_parser(
|
158
|
+
parser: argparse.ArgumentParser,
|
159
|
+
) -> argparse.ArgumentParser:
|
145
160
|
"""Auth plugins options builder
|
146
161
|
|
147
162
|
Builds dynamically the list of options expected by each available
|
@@ -206,13 +221,13 @@ def build_auth_plugins_option_parser(parser):
|
|
206
221
|
|
207
222
|
|
208
223
|
def get_keystone2keystone_auth(
|
209
|
-
local_auth,
|
210
|
-
service_provider,
|
211
|
-
project_id=None,
|
212
|
-
project_name=None,
|
213
|
-
project_domain_id=None,
|
214
|
-
project_domain_name=None,
|
215
|
-
):
|
224
|
+
local_auth: identity_base.BaseIdentityPlugin,
|
225
|
+
service_provider: str,
|
226
|
+
project_id: ty.Optional[str] = None,
|
227
|
+
project_name: ty.Optional[str] = None,
|
228
|
+
project_domain_id: ty.Optional[str] = None,
|
229
|
+
project_domain_name: ty.Optional[str] = None,
|
230
|
+
) -> k2k.Keystone2Keystone:
|
216
231
|
"""Return Keystone 2 Keystone authentication for service provider.
|
217
232
|
|
218
233
|
:param local_auth: authentication to use with the local Keystone
|
@@ -13,13 +13,18 @@
|
|
13
13
|
|
14
14
|
"""API Utilities Library"""
|
15
15
|
|
16
|
+
import typing as ty
|
17
|
+
|
18
|
+
|
19
|
+
_T = ty.TypeVar('_T', bound=ty.List[ty.Any])
|
20
|
+
|
16
21
|
|
17
22
|
def simple_filter(
|
18
|
-
data=None,
|
19
|
-
attr=None,
|
20
|
-
value=None,
|
21
|
-
property_field=None,
|
22
|
-
):
|
23
|
+
data: ty.Optional[_T] = None,
|
24
|
+
attr: ty.Optional[str] = None,
|
25
|
+
value: ty.Optional[str] = None,
|
26
|
+
property_field: ty.Optional[str] = None,
|
27
|
+
) -> ty.Optional[_T]:
|
23
28
|
"""Filter a list of dicts
|
24
29
|
|
25
30
|
:param list data:
|
@@ -14,7 +14,9 @@
|
|
14
14
|
"""OpenStackConfig subclass for argument compatibility"""
|
15
15
|
|
16
16
|
import logging
|
17
|
+
import typing as ty
|
17
18
|
|
19
|
+
from keystoneauth1.loading import identity as ksa_loading
|
18
20
|
from openstack.config import exceptions as sdk_exceptions
|
19
21
|
from openstack.config import loader as config
|
20
22
|
from oslo_utils import strutils
|
@@ -23,10 +25,12 @@ from oslo_utils import strutils
|
|
23
25
|
LOG = logging.getLogger(__name__)
|
24
26
|
|
25
27
|
|
26
|
-
#
|
28
|
+
# Subclass OpenStackConfig in order to munge config values
|
27
29
|
# before auth plugins are loaded
|
28
|
-
class OSC_Config(config.OpenStackConfig):
|
29
|
-
def _auth_select_default_plugin(
|
30
|
+
class OSC_Config(config.OpenStackConfig): # type: ignore
|
31
|
+
def _auth_select_default_plugin(
|
32
|
+
self, config: ty.Dict[str, ty.Any]
|
33
|
+
) -> ty.Dict[str, ty.Any]:
|
30
34
|
"""Select a default plugin based on supplied arguments
|
31
35
|
|
32
36
|
Migrated from auth.select_auth_plugin()
|
@@ -59,7 +63,9 @@ class OSC_Config(config.OpenStackConfig):
|
|
59
63
|
LOG.debug("Auth plugin {} selected".format(config['auth_type']))
|
60
64
|
return config
|
61
65
|
|
62
|
-
def _auth_v2_arguments(
|
66
|
+
def _auth_v2_arguments(
|
67
|
+
self, config: ty.Dict[str, ty.Any]
|
68
|
+
) -> ty.Dict[str, ty.Any]:
|
63
69
|
"""Set up v2-required arguments from v3 info
|
64
70
|
|
65
71
|
Migrated from auth.build_auth_params()
|
@@ -72,41 +78,49 @@ class OSC_Config(config.OpenStackConfig):
|
|
72
78
|
config['auth']['tenant_name'] = config['auth']['project_name']
|
73
79
|
return config
|
74
80
|
|
75
|
-
def _auth_v2_ignore_v3(
|
81
|
+
def _auth_v2_ignore_v3(
|
82
|
+
self, config: ty.Dict[str, ty.Any]
|
83
|
+
) -> ty.Dict[str, ty.Any]:
|
76
84
|
"""Remove v3 arguments if present for v2 plugin
|
77
85
|
|
78
86
|
Migrated from clientmanager.setup_auth()
|
79
87
|
"""
|
80
|
-
|
81
88
|
# NOTE(hieulq): If USER_DOMAIN_NAME, USER_DOMAIN_ID, PROJECT_DOMAIN_ID
|
82
89
|
# or PROJECT_DOMAIN_NAME is present and API_VERSION is 2.0, then
|
83
90
|
# ignore all domain related configs.
|
84
|
-
if str(config.get('identity_api_version', '')).startswith(
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
" identity API version is 2.0"
|
91
|
+
if not str(config.get('identity_api_version', '')).startswith('2'):
|
92
|
+
return config
|
93
|
+
|
94
|
+
if not config.get('auth_type') or not config['auth_type'].endswith(
|
95
|
+
'password'
|
96
|
+
):
|
97
|
+
return config
|
98
|
+
|
99
|
+
domain_props = [
|
100
|
+
'project_domain_id',
|
101
|
+
'project_domain_name',
|
102
|
+
'user_domain_id',
|
103
|
+
'user_domain_name',
|
104
|
+
]
|
105
|
+
for prop in domain_props:
|
106
|
+
if config['auth'].pop(prop, None) is not None:
|
107
|
+
if config.get('cloud'):
|
108
|
+
LOG.warning(
|
109
|
+
"Ignoring domain related config {} for {}"
|
110
|
+
"because identity API version is 2.0".format(
|
111
|
+
prop, config['cloud']
|
106
112
|
)
|
113
|
+
)
|
114
|
+
else:
|
115
|
+
LOG.warning(
|
116
|
+
f"Ignoring domain related config {prop} because"
|
117
|
+
" identity API version is 2.0"
|
118
|
+
)
|
107
119
|
return config
|
108
120
|
|
109
|
-
def _auth_default_domain(
|
121
|
+
def _auth_default_domain(
|
122
|
+
self, config: ty.Dict[str, ty.Any]
|
123
|
+
) -> ty.Dict[str, ty.Any]:
|
110
124
|
"""Set a default domain from available arguments
|
111
125
|
|
112
126
|
Migrated from clientmanager.setup_auth()
|
@@ -147,7 +161,9 @@ class OSC_Config(config.OpenStackConfig):
|
|
147
161
|
config['auth']['user_domain_id'] = default_domain
|
148
162
|
return config
|
149
163
|
|
150
|
-
def auth_config_hook(
|
164
|
+
def auth_config_hook(
|
165
|
+
self, config: ty.Dict[str, ty.Any]
|
166
|
+
) -> ty.Dict[str, ty.Any]:
|
151
167
|
"""Allow examination of config values before loading auth plugin
|
152
168
|
|
153
169
|
OpenStackClient will override this to perform additional checks
|
@@ -165,7 +181,11 @@ class OSC_Config(config.OpenStackConfig):
|
|
165
181
|
)
|
166
182
|
return config
|
167
183
|
|
168
|
-
def _validate_auth(
|
184
|
+
def _validate_auth(
|
185
|
+
self,
|
186
|
+
config: ty.Dict[str, ty.Any],
|
187
|
+
loader: ksa_loading.BaseIdentityLoader, # type: ignore
|
188
|
+
) -> ty.Dict[str, ty.Any]:
|
169
189
|
"""Validate auth plugin arguments"""
|
170
190
|
# May throw a keystoneauth1.exceptions.NoMatchingPlugin
|
171
191
|
|
@@ -229,7 +249,8 @@ class OSC_Config(config.OpenStackConfig):
|
|
229
249
|
|
230
250
|
return config
|
231
251
|
|
232
|
-
|
252
|
+
# TODO(stephenfin): Add type once we have typing for SDK
|
253
|
+
def load_auth_plugin(self, config: ty.Dict[str, ty.Any]) -> ty.Any:
|
233
254
|
"""Get auth plugin and validate args"""
|
234
255
|
|
235
256
|
loader = self._get_auth_loader(config)
|