cloudbridge 4.0.0__tar.gz → 4.2.0__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.
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/PKG-INFO +3 -2
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/__init__.py +9 -6
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/base/helpers.py +25 -40
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/base/middleware.py +7 -3
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/base/provider.py +36 -25
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/base/resources.py +514 -141
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/base/services.py +132 -75
- cloudbridge-4.2.0/cloudbridge/base/subservices.py +249 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/factory.py +14 -10
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/interfaces/exceptions.py +4 -4
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/interfaces/provider.py +34 -18
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/interfaces/resources.py +387 -167
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/interfaces/services.py +290 -117
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/interfaces/subservices.py +57 -34
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/aws/helpers.py +43 -21
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/aws/provider.py +20 -14
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/aws/resources.py +381 -300
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/aws/services.py +455 -273
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/aws/subservices.py +13 -6
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/azure/azure_client.py +224 -136
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/azure/helpers.py +7 -6
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/azure/provider.py +25 -33
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/azure/resources.py +577 -332
- cloudbridge-4.2.0/cloudbridge/providers/azure/services.py +1849 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/azure/subservices.py +19 -5
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/gcp/helpers.py +35 -19
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/gcp/provider.py +52 -41
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/gcp/resources.py +709 -486
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/gcp/services.py +975 -586
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/gcp/subservices.py +12 -6
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/mock/provider.py +5 -3
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/openstack/helpers.py +12 -5
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/openstack/provider.py +82 -60
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/openstack/resources.py +383 -287
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/openstack/services.py +539 -304
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/openstack/subservices.py +14 -6
- cloudbridge-4.2.0/cloudbridge/py.typed +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge.egg-info/PKG-INFO +3 -2
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge.egg-info/SOURCES.txt +2 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge.egg-info/requires.txt +2 -1
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/pyproject.toml +41 -1
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_base_helpers.py +0 -42
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_block_store_service.py +11 -1
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_compute_service.py +12 -23
- cloudbridge-4.2.0/tests/test_multipart_driver.py +223 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_object_store_service.py +206 -0
- cloudbridge-4.0.0/cloudbridge/base/subservices.py +0 -202
- cloudbridge-4.0.0/cloudbridge/providers/azure/services.py +0 -1378
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/LICENSE +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/README.rst +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/base/__init__.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/interfaces/__init__.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/__init__.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/aws/__init__.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/azure/__init__.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/gcp/__init__.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/mock/__init__.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge/providers/openstack/__init__.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge.egg-info/dependency_links.txt +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/cloudbridge.egg-info/top_level.txt +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/setup.cfg +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_cloud_factory.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_cloud_helpers.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_dns_service.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_image_service.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_interface.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_middleware_system.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_network_service.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_object_life_cycle.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_region_service.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_security_service.py +0 -0
- {cloudbridge-4.0.0 → cloudbridge-4.2.0}/tests/test_vm_types_service.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudbridge
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.2.0
|
|
4
4
|
Summary: A simple layer of abstraction over multiple cloud providers.
|
|
5
5
|
Author-email: Galaxy and GVL Projects <help@genome.edu.au>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -22,7 +22,6 @@ Requires-Python: >=3.13
|
|
|
22
22
|
Description-Content-Type: text/x-rst
|
|
23
23
|
License-File: LICENSE
|
|
24
24
|
Requires-Dist: tenacity>=6.0
|
|
25
|
-
Requires-Dist: deprecation>=2.0.7
|
|
26
25
|
Requires-Dist: pyeventsystem<2
|
|
27
26
|
Provides-Extra: aws
|
|
28
27
|
Requires-Dist: boto3<2.0.0,>=1.9.86; extra == "aws"
|
|
@@ -34,6 +33,7 @@ Requires-Dist: azure-mgmt-devtestlabs<10.0.0,>=9.0.0; extra == "azure"
|
|
|
34
33
|
Requires-Dist: azure-mgmt-resource<26.0.0,>=23.0.0; extra == "azure"
|
|
35
34
|
Requires-Dist: azure-mgmt-subscription<4.0.0,>=3.0.0; extra == "azure"
|
|
36
35
|
Requires-Dist: azure-mgmt-compute<39.0.0,>=34.0.0; extra == "azure"
|
|
36
|
+
Requires-Dist: azure-mgmt-dns<10.0.0,>=9.0.0; extra == "azure"
|
|
37
37
|
Requires-Dist: azure-mgmt-network<31.0.0,>=28.0.0; extra == "azure"
|
|
38
38
|
Requires-Dist: azure-mgmt-storage<25.0.0,>=22.0.0; extra == "azure"
|
|
39
39
|
Requires-Dist: azure-storage-blob<13.0.0,>=12.20.0; extra == "azure"
|
|
@@ -59,6 +59,7 @@ Requires-Dist: sphinx>=1.3.1; extra == "dev"
|
|
|
59
59
|
Requires-Dist: pydevd; extra == "dev"
|
|
60
60
|
Requires-Dist: flake8>=3.3.0; extra == "dev"
|
|
61
61
|
Requires-Dist: flake8-import-order>=0.12; extra == "dev"
|
|
62
|
+
Requires-Dist: mypy<3,>=2.1; extra == "dev"
|
|
62
63
|
Dynamic: license-file
|
|
63
64
|
|
|
64
65
|
CloudBridge provides a consistent layer of abstraction over different
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"""Library setup."""
|
|
2
2
|
import logging
|
|
3
|
+
from typing import Any
|
|
3
4
|
|
|
4
5
|
# Current version of the library
|
|
5
|
-
__version__ = '4.
|
|
6
|
+
__version__ = '4.2.0'
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
def get_version():
|
|
9
|
+
def get_version() -> str:
|
|
9
10
|
"""
|
|
10
11
|
Return a string with the current version of the library.
|
|
11
12
|
|
|
@@ -15,7 +16,7 @@ def get_version():
|
|
|
15
16
|
return __version__
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
def init_logging():
|
|
19
|
+
def init_logging() -> None:
|
|
19
20
|
"""
|
|
20
21
|
Initialize logging for testing.
|
|
21
22
|
|
|
@@ -35,7 +36,7 @@ class CBLogger(logging.Logger):
|
|
|
35
36
|
Add a ``trace`` log level, numeric value 5: ``log.trace("Log message")``
|
|
36
37
|
"""
|
|
37
38
|
|
|
38
|
-
def trace(self, msg, *args, **kwargs):
|
|
39
|
+
def trace(self, msg: object, *args: object, **kwargs: Any) -> None:
|
|
39
40
|
"""Add ``trace`` log level."""
|
|
40
41
|
self.log(TRACE, msg, *args, **kwargs)
|
|
41
42
|
|
|
@@ -61,7 +62,8 @@ log.addHandler(logging.NullHandler())
|
|
|
61
62
|
# cloudbridge.set_file_logger(__name__, '/tmp/log')
|
|
62
63
|
|
|
63
64
|
|
|
64
|
-
def set_stream_logger(name, level=TRACE,
|
|
65
|
+
def set_stream_logger(name: str, level: int = TRACE,
|
|
66
|
+
format_string: str | None = None) -> None:
|
|
65
67
|
"""A convenience method to set the global logger to stream."""
|
|
66
68
|
global log
|
|
67
69
|
if not format_string:
|
|
@@ -76,7 +78,8 @@ def set_stream_logger(name, level=TRACE, format_string=None):
|
|
|
76
78
|
log = logger
|
|
77
79
|
|
|
78
80
|
|
|
79
|
-
def set_file_logger(name, filepath, level=logging.INFO,
|
|
81
|
+
def set_file_logger(name: str, filepath: str, level: int = logging.INFO,
|
|
82
|
+
format_string: str | None = None) -> None:
|
|
80
83
|
"""A convenience method to set the global logger to a file."""
|
|
81
84
|
global log
|
|
82
85
|
if not format_string:
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import fnmatch
|
|
2
|
-
import functools
|
|
3
2
|
import logging
|
|
4
3
|
import os
|
|
5
4
|
import re
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
from collections.abc import Iterator
|
|
6
7
|
from contextlib import contextmanager
|
|
8
|
+
from typing import Any
|
|
9
|
+
from typing import TypeVar
|
|
10
|
+
from typing import overload
|
|
7
11
|
|
|
8
12
|
from cryptography.hazmat.backends import default_backend
|
|
9
13
|
from cryptography.hazmat.primitives import serialization as crypt_serialization
|
|
10
14
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
11
15
|
|
|
12
|
-
from deprecation import deprecated
|
|
13
|
-
|
|
14
|
-
import cloudbridge
|
|
15
|
-
|
|
16
16
|
from ..interfaces.exceptions import InvalidParamException
|
|
17
17
|
|
|
18
18
|
log = logging.getLogger(__name__)
|
|
19
19
|
|
|
20
|
+
T = TypeVar("T")
|
|
21
|
+
|
|
20
22
|
|
|
21
|
-
def generate_key_pair():
|
|
23
|
+
def generate_key_pair() -> tuple[str, str]:
|
|
22
24
|
"""
|
|
23
25
|
This method generates a keypair and returns it as a tuple
|
|
24
26
|
of (public, private) keys.
|
|
@@ -38,7 +40,8 @@ def generate_key_pair():
|
|
|
38
40
|
return public_key, private_key
|
|
39
41
|
|
|
40
42
|
|
|
41
|
-
def filter_by(prop_name, kwargs,
|
|
43
|
+
def filter_by(prop_name: str, kwargs: dict[str, Any],
|
|
44
|
+
objs: list[T]) -> list[T]:
|
|
42
45
|
"""
|
|
43
46
|
Utility method for filtering a list of objects by a property.
|
|
44
47
|
If the given property has a non empty value in kwargs, then
|
|
@@ -60,7 +63,8 @@ def filter_by(prop_name, kwargs, objs):
|
|
|
60
63
|
return objs
|
|
61
64
|
|
|
62
65
|
|
|
63
|
-
def generic_find(filter_names, kwargs,
|
|
66
|
+
def generic_find(filter_names: list[str], kwargs: dict[str, Any],
|
|
67
|
+
objs: list[T]) -> list[T]:
|
|
64
68
|
"""
|
|
65
69
|
Utility method for filtering a list of objects by a list of filters.
|
|
66
70
|
"""
|
|
@@ -78,7 +82,7 @@ def generic_find(filter_names, kwargs, objs):
|
|
|
78
82
|
|
|
79
83
|
|
|
80
84
|
@contextmanager
|
|
81
|
-
def cleanup_action(cleanup_func):
|
|
85
|
+
def cleanup_action(cleanup_func: Callable[[], object]) -> Iterator[None]:
|
|
82
86
|
"""
|
|
83
87
|
Context manager to carry out a given
|
|
84
88
|
cleanup action after carrying out a set
|
|
@@ -109,7 +113,17 @@ def cleanup_action(cleanup_func):
|
|
|
109
113
|
log.exception("Error during exception cleanup: ")
|
|
110
114
|
|
|
111
115
|
|
|
112
|
-
|
|
116
|
+
@overload
|
|
117
|
+
def get_env(varname: str) -> str | None:
|
|
118
|
+
...
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@overload
|
|
122
|
+
def get_env(varname: str, default_value: T) -> str | T:
|
|
123
|
+
...
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def get_env(varname: str, default_value: object = None) -> object:
|
|
113
127
|
"""
|
|
114
128
|
Return the value of the environment variable or default_value.
|
|
115
129
|
|
|
@@ -125,39 +139,10 @@ def get_env(varname, default_value=None):
|
|
|
125
139
|
return os.environ.get(varname, default_value)
|
|
126
140
|
|
|
127
141
|
|
|
128
|
-
# Alias deprecation decorator, following:
|
|
129
|
-
# https://stackoverflow.com/questions/49802412/
|
|
130
|
-
# how-to-implement-deprecation-in-python-with-argument-alias
|
|
131
|
-
def deprecated_alias(**aliases):
|
|
132
|
-
def deco(f):
|
|
133
|
-
@functools.wraps(f)
|
|
134
|
-
def wrapper(*args, **kwargs):
|
|
135
|
-
rename_kwargs(f.__name__, kwargs, aliases)
|
|
136
|
-
return f(*args, **kwargs)
|
|
137
|
-
return wrapper
|
|
138
|
-
return deco
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
def rename_kwargs(func_name, kwargs, aliases):
|
|
142
|
-
for alias, new in aliases.items():
|
|
143
|
-
if alias in kwargs:
|
|
144
|
-
if new in kwargs:
|
|
145
|
-
raise InvalidParamException(
|
|
146
|
-
'{} received both {} and {}'.format(func_name, alias, new))
|
|
147
|
-
# Manually invoke the deprecated decorator with an empty lambda
|
|
148
|
-
# to signal deprecation
|
|
149
|
-
deprecated(deprecated_in='1.1',
|
|
150
|
-
removed_in='2.0',
|
|
151
|
-
current_version=cloudbridge.__version__,
|
|
152
|
-
details='{} is deprecated, use {} instead'.format(
|
|
153
|
-
alias, new))(lambda: None)()
|
|
154
|
-
kwargs[new] = kwargs.pop(alias)
|
|
155
|
-
|
|
156
|
-
|
|
157
142
|
NON_ALPHA_NUM = re.compile(r"[^A-Za-z0-9]+")
|
|
158
143
|
|
|
159
144
|
|
|
160
|
-
def to_resource_name(value, replace_with="-"):
|
|
145
|
+
def to_resource_name(value: str, replace_with: str = "-") -> str:
|
|
161
146
|
"""
|
|
162
147
|
Converts a given string to a valid resource name by stripping
|
|
163
148
|
all characters that are not alphanumeric.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from typing import Any
|
|
2
3
|
|
|
3
4
|
from pyeventsystem.middleware import dispatch as pyevent_dispatch
|
|
4
5
|
from pyeventsystem.middleware import intercept
|
|
@@ -19,12 +20,14 @@ class EventDebugLoggingMiddleware(object):
|
|
|
19
20
|
access keys.
|
|
20
21
|
"""
|
|
21
22
|
@observe(event_pattern="*", priority=100)
|
|
22
|
-
def pre_log_event(self, event_args,
|
|
23
|
+
def pre_log_event(self, event_args: dict[str, Any],
|
|
24
|
+
*args: Any, **kwargs: Any) -> None:
|
|
23
25
|
log.debug("Event: {0}, args: {1} kwargs: {2}".format(
|
|
24
26
|
event_args.get("event"), args, kwargs))
|
|
25
27
|
|
|
26
28
|
@observe(event_pattern="*", priority=4900)
|
|
27
|
-
def post_log_event(self, event_args,
|
|
29
|
+
def post_log_event(self, event_args: dict[str, Any],
|
|
30
|
+
*args: Any, **kwargs: Any) -> None:
|
|
28
31
|
log.debug("Event: {0}, result: {1}".format(
|
|
29
32
|
event_args.get("event"), event_args.get("result")))
|
|
30
33
|
|
|
@@ -34,7 +37,8 @@ class ExceptionWrappingMiddleware(object):
|
|
|
34
37
|
Wraps all unhandled exceptions in cloudbridge exceptions.
|
|
35
38
|
"""
|
|
36
39
|
@intercept(event_pattern="*", priority=1050)
|
|
37
|
-
def wrap_exception(self, event_args,
|
|
40
|
+
def wrap_exception(self, event_args: dict[str, Any],
|
|
41
|
+
*args: Any, **kwargs: Any) -> Any:
|
|
38
42
|
next_handler = event_args.pop("next_handler")
|
|
39
43
|
if not next_handler:
|
|
40
44
|
return
|
|
@@ -5,13 +5,17 @@ import logging
|
|
|
5
5
|
import os
|
|
6
6
|
from configparser import ConfigParser
|
|
7
7
|
from os.path import expanduser
|
|
8
|
+
from typing import Any
|
|
9
|
+
from typing import cast
|
|
8
10
|
|
|
11
|
+
from pyeventsystem.middleware import MiddlewareManager
|
|
9
12
|
from pyeventsystem.middleware import SimpleMiddlewareManager
|
|
10
13
|
|
|
11
14
|
from ..base.middleware import ExceptionWrappingMiddleware
|
|
12
15
|
from ..interfaces import CloudProvider
|
|
13
16
|
from ..interfaces.exceptions import ProviderConnectionException
|
|
14
17
|
from ..interfaces.resources import Configuration
|
|
18
|
+
from ..interfaces.resources import PlacementZone
|
|
15
19
|
|
|
16
20
|
log = logging.getLogger(__name__)
|
|
17
21
|
|
|
@@ -28,11 +32,11 @@ CloudBridgeConfigLocations.append(UserConfigPath)
|
|
|
28
32
|
|
|
29
33
|
class BaseConfiguration(Configuration):
|
|
30
34
|
|
|
31
|
-
def __init__(self, user_config):
|
|
35
|
+
def __init__(self, user_config: dict[str, Any]) -> None:
|
|
32
36
|
self.update(user_config)
|
|
33
37
|
|
|
34
38
|
@property
|
|
35
|
-
def default_result_limit(self):
|
|
39
|
+
def default_result_limit(self) -> int:
|
|
36
40
|
"""
|
|
37
41
|
Get the maximum number of results to return for a
|
|
38
42
|
list method
|
|
@@ -42,28 +46,30 @@ class BaseConfiguration(Configuration):
|
|
|
42
46
|
"""
|
|
43
47
|
log.debug("Maximum number of results for list methods %s",
|
|
44
48
|
DEFAULT_RESULT_LIMIT)
|
|
45
|
-
return self.get('default_result_limit', DEFAULT_RESULT_LIMIT)
|
|
49
|
+
return cast(int, self.get('default_result_limit', DEFAULT_RESULT_LIMIT))
|
|
46
50
|
|
|
47
51
|
@property
|
|
48
|
-
def default_wait_timeout(self):
|
|
52
|
+
def default_wait_timeout(self) -> int:
|
|
49
53
|
"""
|
|
50
54
|
Gets the default wait timeout for LifeCycleObjects.
|
|
51
55
|
"""
|
|
52
56
|
log.debug("Default wait timeout for LifeCycleObjects %s",
|
|
53
57
|
DEFAULT_WAIT_TIMEOUT)
|
|
54
|
-
return self.get('default_wait_timeout',
|
|
58
|
+
return cast(int, self.get('default_wait_timeout',
|
|
59
|
+
DEFAULT_WAIT_TIMEOUT))
|
|
55
60
|
|
|
56
61
|
@property
|
|
57
|
-
def default_wait_interval(self):
|
|
62
|
+
def default_wait_interval(self) -> int:
|
|
58
63
|
"""
|
|
59
64
|
Gets the default wait interval for LifeCycleObjects.
|
|
60
65
|
"""
|
|
61
66
|
log.debug("Default wait interfal for LifeCycleObjects %s",
|
|
62
67
|
DEFAULT_WAIT_INTERVAL)
|
|
63
|
-
return self.get('default_wait_interval',
|
|
68
|
+
return cast(int, self.get('default_wait_interval',
|
|
69
|
+
DEFAULT_WAIT_INTERVAL))
|
|
64
70
|
|
|
65
71
|
@property
|
|
66
|
-
def debug_mode(self):
|
|
72
|
+
def debug_mode(self) -> bool:
|
|
67
73
|
"""
|
|
68
74
|
A flag indicating whether CloudBridge is in debug mode. Setting
|
|
69
75
|
this to True will cause the underlying provider's debug
|
|
@@ -75,59 +81,63 @@ class BaseConfiguration(Configuration):
|
|
|
75
81
|
:rtype: ``bool``
|
|
76
82
|
:return: Whether debug mode is on.
|
|
77
83
|
"""
|
|
78
|
-
return
|
|
84
|
+
return cast(bool, self.get('cb_debug',
|
|
85
|
+
os.environ.get('CB_DEBUG', False)))
|
|
79
86
|
|
|
80
87
|
|
|
81
88
|
class BaseCloudProvider(CloudProvider):
|
|
82
|
-
|
|
89
|
+
|
|
90
|
+
PROVIDER_ID: str
|
|
91
|
+
|
|
92
|
+
def __init__(self, config: dict[str, Any]) -> None:
|
|
83
93
|
self._config = BaseConfiguration(config)
|
|
84
94
|
self._config_parser = ConfigParser()
|
|
85
95
|
self._config_parser.read(CloudBridgeConfigLocations)
|
|
86
96
|
self._middleware = SimpleMiddlewareManager()
|
|
87
97
|
self.add_required_middleware()
|
|
88
|
-
self._region_name = None
|
|
89
|
-
self._zone_name = None
|
|
98
|
+
self._region_name: str | None = None
|
|
99
|
+
self._zone_name: str | None = None
|
|
90
100
|
|
|
91
101
|
@property
|
|
92
|
-
def region_name(self):
|
|
102
|
+
def region_name(self) -> str | None:
|
|
93
103
|
return self._region_name
|
|
94
104
|
|
|
95
105
|
@property
|
|
96
|
-
def zone_name(self):
|
|
106
|
+
def zone_name(self) -> str | None:
|
|
97
107
|
if not self._zone_name:
|
|
98
108
|
region = self.compute.regions.current
|
|
99
|
-
zone = region.default_zone
|
|
109
|
+
zone = region.default_zone if region else None
|
|
100
110
|
self._zone_name = zone.name if zone else None
|
|
101
111
|
return self._zone_name
|
|
102
112
|
else:
|
|
103
113
|
try:
|
|
104
114
|
zone_dict = ast.literal_eval(self._zone_name)
|
|
105
115
|
if isinstance(zone_dict, dict):
|
|
106
|
-
return zone_dict
|
|
116
|
+
return cast("str | None", zone_dict)
|
|
107
117
|
except (ValueError, SyntaxError):
|
|
108
118
|
pass
|
|
109
119
|
return self._zone_name
|
|
110
120
|
|
|
111
121
|
@property
|
|
112
|
-
def config(self):
|
|
122
|
+
def config(self) -> Configuration:
|
|
113
123
|
return self._config
|
|
114
124
|
|
|
115
125
|
@property
|
|
116
|
-
def name(self):
|
|
126
|
+
def name(self) -> str:
|
|
117
127
|
return str(self.__class__.__name__)
|
|
118
128
|
|
|
119
129
|
@property
|
|
120
|
-
def middleware(self):
|
|
130
|
+
def middleware(self) -> MiddlewareManager:
|
|
121
131
|
return self._middleware
|
|
122
132
|
|
|
123
|
-
def add_required_middleware(self):
|
|
133
|
+
def add_required_middleware(self) -> None:
|
|
124
134
|
"""
|
|
125
135
|
Adds common middleware that is essential for cloudbridge to function.
|
|
126
136
|
Any other extra middleware can be added through the provider factory.
|
|
127
137
|
"""
|
|
128
138
|
self.middleware.add(ExceptionWrappingMiddleware())
|
|
129
139
|
|
|
130
|
-
def authenticate(self):
|
|
140
|
+
def authenticate(self) -> bool:
|
|
131
141
|
"""
|
|
132
142
|
A basic implementation which simply runs a low impact command to
|
|
133
143
|
check whether cloud credentials work. Providers should override with
|
|
@@ -142,7 +152,7 @@ class BaseCloudProvider(CloudProvider):
|
|
|
142
152
|
raise ProviderConnectionException(
|
|
143
153
|
"Authentication with cloud provider failed: %s" % (e,))
|
|
144
154
|
|
|
145
|
-
def clone(self, zone=None):
|
|
155
|
+
def clone(self, zone: PlacementZone | None = None) -> CloudProvider:
|
|
146
156
|
cloned_config = self.config.copy()
|
|
147
157
|
cloned_provider = self.__class__(cloned_config)
|
|
148
158
|
if zone:
|
|
@@ -150,11 +160,11 @@ class BaseCloudProvider(CloudProvider):
|
|
|
150
160
|
cloned_provider._zone_name = zone.name
|
|
151
161
|
return cloned_provider
|
|
152
162
|
|
|
153
|
-
def _deepgetattr(self, obj, attr):
|
|
163
|
+
def _deepgetattr(self, obj: object, attr: str) -> Any:
|
|
154
164
|
"""Recurses through an attribute chain to get the ultimate value."""
|
|
155
165
|
return functools.reduce(getattr, attr.split('.'), obj)
|
|
156
166
|
|
|
157
|
-
def has_service(self, service_type):
|
|
167
|
+
def has_service(self, service_type: str) -> bool:
|
|
158
168
|
"""
|
|
159
169
|
Checks whether this provider supports a given service.
|
|
160
170
|
|
|
@@ -178,7 +188,8 @@ class BaseCloudProvider(CloudProvider):
|
|
|
178
188
|
service_type)
|
|
179
189
|
return False
|
|
180
190
|
|
|
181
|
-
def _get_config_value(self, key,
|
|
191
|
+
def _get_config_value(self, key: str,
|
|
192
|
+
default_value: Any = None) -> Any:
|
|
182
193
|
"""
|
|
183
194
|
A convenience method to extract a configuration value.
|
|
184
195
|
|