Airflow and Openstack modules upgrade

This PS upgrades Airflow to 2.10.4 and Openstack
modules to 2024.1 Caracal versions

Change-Id: I66aa7acfdaa5ffa6947856691dd69219be54976c
This commit is contained in:
Sergiy Markin
2024-12-17 14:59:29 +00:00
parent ce595ec149
commit 54c3ebd63e
43 changed files with 185 additions and 171 deletions

View File

@@ -201,7 +201,7 @@
commit: true commit: true
static: static:
- latest - latest
- airflow_2.10.2 - airflow_2.10.4
- secret: - secret:

View File

@@ -6,5 +6,5 @@ blank_line_before_nested_class_or_def = false
blank_line_before_module_docstring = true blank_line_before_module_docstring = true
split_before_logical_operator = true split_before_logical_operator = true
split_before_first_argument = true split_before_first_argument = true
allow_split_before_dict_value = false allow_split_before_dict_value = true
split_before_arithmetic_operator = true split_before_arithmetic_operator = true

View File

@@ -30,7 +30,6 @@ class Apply(api.BaseResource):
"""Controller for installing and updating charts defined in an Armada """Controller for installing and updating charts defined in an Armada
manifest file. manifest file.
""" """
@policy.enforce('armada:create_endpoints') @policy.enforce('armada:create_endpoints')
def on_post(self, req, resp): def on_post(self, req, resp):
# Load data from request and get options # Load data from request and get options

View File

@@ -20,7 +20,6 @@ class Health(api.BaseResource):
""" """
Return empty response/body to show that Armada is healthy. Return empty response/body to show that Armada is healthy.
""" """
def on_get(self, req, resp): def on_get(self, req, resp):
""" """
It really does nothing right now. It may do more later. It really does nothing right now. It may do more later.

View File

@@ -22,7 +22,6 @@ from armada.handlers import metrics
class Metrics(api.BaseResource): class Metrics(api.BaseResource):
'''Controller for exporting prometheus metrics. '''Controller for exporting prometheus metrics.
''' '''
def on_get(self, req, resp): def on_get(self, req, resp):
encoder, content_type = prometheus_client.exposition.choose_encoder( encoder, content_type = prometheus_client.exposition.choose_encoder(
req.get_header('Accept')) req.get_header('Accept'))

View File

@@ -35,7 +35,6 @@ class TestReleasesReleaseNameController(api.BaseResource):
''' '''
Test Helm releases via release name. Test Helm releases via release name.
''' '''
@policy.enforce('armada:test_release') @policy.enforce('armada:test_release')
def on_get(self, req, resp, namespace, release): def on_get(self, req, resp, namespace, release):
try: try:
@@ -71,7 +70,6 @@ class TestReleasesManifestController(api.BaseResource):
''' '''
Test Helm releases via a Manifest. Test Helm releases via a Manifest.
''' '''
def _format_validation_response(self, req, resp, result, details): def _format_validation_response(self, req, resp, result, details):
resp.content_type = 'application/json' resp.content_type = 'application/json'
resp_body = { resp_body = {

View File

@@ -26,7 +26,6 @@ from armada.handlers.document import ReferenceResolver
class Validate(api.BaseResource): class Validate(api.BaseResource):
'''Controller for validating an Armada manifest. '''Controller for validating an Armada manifest.
''' '''
@policy.enforce('armada:validate_manifest') @policy.enforce('armada:validate_manifest')
def on_post(self, req, resp): def on_post(self, req, resp):
try: try:

View File

@@ -24,7 +24,6 @@ class Versions(api.BaseResource):
Returns the list of supported versions of the Armada API. Returns the list of supported versions of the Armada API.
""" """
def on_get(self, req, resp): def on_get(self, req, resp):
resp.status = falcon.HTTP_200 resp.status = falcon.HTTP_200
resp.text = json.dumps( resp.text = json.dumps(

View File

@@ -37,7 +37,6 @@ class ArmadaSession(object):
value may also be supplied instead of a tuple to indicate only the value may also be supplied instead of a tuple to indicate only the
read timeout to use read timeout to use
""" """
def __init__( def __init__(
self, self,
host, host,
@@ -186,7 +185,6 @@ class ArmadaSession(object):
class TcpKeepaliveAdapter(requests.adapters.HTTPAdapter): class TcpKeepaliveAdapter(requests.adapters.HTTPAdapter):
""""Transport adapter" that enables TCP keepalives.""" """"Transport adapter" that enables TCP keepalives."""
def init_poolmanager(self, connections, maxsize, block=False): def init_poolmanager(self, connections, maxsize, block=False):
options = HTTPConnection.default_socket_options + [ options = HTTPConnection.default_socket_options + [
(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),

View File

@@ -84,7 +84,6 @@ class ChartDeployAwareLogger(logging.Logger):
"""Includes name of chart currently being deployed (if any) in log """Includes name of chart currently being deployed (if any) in log
messages. messages.
""" """
def _log(self, level, msg, *args, **kwargs): def _log(self, level, msg, *args, **kwargs):
chart = get_current_chart() chart = get_current_chart()
if chart: if chart:

View File

@@ -116,7 +116,8 @@ def register_opts(conf):
def list_opts(): def list_opts():
return { return {
'DEFAULT': default_options, 'DEFAULT':
default_options,
'keystone_authtoken': ( 'keystone_authtoken': (
ks_loading.get_session_conf_options() ks_loading.get_session_conf_options()
+ ks_loading.get_auth_common_conf_options() + ks_loading.get_auth_common_conf_options()

View File

@@ -23,7 +23,6 @@ class ArmadaException(base_exception.ArmadaBaseException):
class ArmadaTimeoutException(ArmadaException): class ArmadaTimeoutException(ArmadaException):
'''Exception that occurs when Armada times out while processing.''' '''Exception that occurs when Armada times out while processing.'''
def __init__(self, reason): def __init__(self, reason):
self._message = 'Armada timed out waiting on: %s' % (reason) self._message = 'Armada timed out waiting on: %s' % (reason)
super(ArmadaTimeoutException, self).__init__(self._message) super(ArmadaTimeoutException, self).__init__(self._message)
@@ -35,7 +34,6 @@ class ProtectedReleaseException(ArmadaException):
than DEPLOYED that is designated `protected` in the Chart and than DEPLOYED that is designated `protected` in the Chart and
`continue_processing` is False. `continue_processing` is False.
''' '''
def __init__(self, release_id, status): def __init__(self, release_id, status):
self._message = ( self._message = (
'Armada encountered protected release {} in {} status'.format( 'Armada encountered protected release {} in {} status'.format(
@@ -48,7 +46,6 @@ class InvalidValuesYamlException(ArmadaException):
Exception that occurs when Armada encounters invalid values.yaml content in Exception that occurs when Armada encounters invalid values.yaml content in
a helm chart. a helm chart.
''' '''
def __init__(self, chart_description): def __init__(self, chart_description):
self._message = ( self._message = (
'Armada encountered invalid values.yaml in helm chart: %s' 'Armada encountered invalid values.yaml in helm chart: %s'
@@ -61,7 +58,6 @@ class InvalidOverrideValuesYamlException(ArmadaException):
Exception that occurs when Armada encounters invalid override yaml in Exception that occurs when Armada encounters invalid override yaml in
helm chart. helm chart.
''' '''
def __init__(self, chart_description): def __init__(self, chart_description):
self._message = ( self._message = (
'Armada encountered invalid values.yaml in helm chart: %s' 'Armada encountered invalid values.yaml in helm chart: %s'
@@ -73,7 +69,6 @@ class ChartDeployException(ArmadaException):
''' '''
Exception that occurs while deploying charts. Exception that occurs while deploying charts.
''' '''
def __init__(self, chart_names): def __init__(self, chart_names):
self._message = ('Exception deploying charts: %s' % chart_names) self._message = ('Exception deploying charts: %s' % chart_names)
super(ChartDeployException, self).__init__(self._message) super(ChartDeployException, self).__init__(self._message)
@@ -83,7 +78,6 @@ class WaitException(ArmadaException):
''' '''
Exception that occurs while waiting for resources to become ready. Exception that occurs while waiting for resources to become ready.
''' '''
def __init__(self, message): def __init__(self, message):
self._message = message self._message = message
super(WaitException, self).__init__(message) super(WaitException, self).__init__(message)
@@ -94,7 +88,6 @@ class DeploymentLikelyPendingException(ArmadaException):
Exception that occurs when it is detected that an existing release Exception that occurs when it is detected that an existing release
operation (e.g. install, update, delete) is likely still pending. operation (e.g. install, update, delete) is likely still pending.
''' '''
def __init__(self, release_id, status, last_deployment_age, timeout): def __init__(self, release_id, status, last_deployment_age, timeout):
self._message = ( self._message = (
'Existing deployment likely pending ' 'Existing deployment likely pending '
@@ -111,7 +104,6 @@ class PreUpdateJobDeleteException(ArmadaException):
**Troubleshoot:** **Troubleshoot:**
*Coming Soon* *Coming Soon*
''' '''
def __init__(self, name, namespace): def __init__(self, name, namespace):
message = 'Failed to delete k8s job {} in {}'.format(name, namespace) message = 'Failed to delete k8s job {} in {}'.format(name, namespace)

View File

@@ -158,7 +158,7 @@ def default_error_serializer(req, resp, exception):
info_list=None) info_list=None)
def default_exception_handler(ex, req, resp, params): def default_exception_handler(req, resp, ex, params):
""" """
Catch-all exception handler for standardized output. Catch-all exception handler for standardized output.
If this is a standard falcon HTTPError, rethrow it for handling If this is a standard falcon HTTPError, rethrow it for handling
@@ -186,13 +186,13 @@ class ArmadaAPIException(falcon.HTTPError):
status = falcon.HTTP_500 status = falcon.HTTP_500
def __init__( def __init__(
self, self,
title=None, title=None,
description=None, description=None,
error_list=None, error_list=None,
info_list=None, info_list=None,
status=None, status=None,
retry=False, retry=False,
): ):
""" """
:param description: The internal error description :param description: The internal error description
@@ -206,34 +206,30 @@ class ArmadaAPIException(falcon.HTTPError):
:param retry: Optional retry directive for the consumer :param retry: Optional retry directive for the consumer
""" """
if title is None: # Use default title and status if none provided
self.title = self.__class__.title status = status or self.__class__.status
else: title = title or self.__class__.title
self.title = title
if status is None: # Call falcon.HTTPError's constructor
self.status = self.__class__.status super().__init__(status, title=title)
else:
self.status = status
# Store custom fields as instance attributes
self.description = description self.description = description
self.error_list = massage_error_list(error_list, description) self.error_list = massage_error_list(error_list, description)
self.info_list = info_list self.info_list = info_list
self.retry = retry self.retry = retry
super().__init__(
self.status, self.title,
self._gen_ex_message(self.title, self.description))
@staticmethod @staticmethod
def _gen_ex_message(title, description): def _gen_ex_message(title, description):
"""Generate an exception message."""
ttl = title or 'Exception' ttl = title or 'Exception'
dsc = description or 'No additional description' dsc = description or 'No additional description'
return '{} : {}'.format(ttl, dsc) return f'{ttl} : {dsc}'
@staticmethod @staticmethod
def handle(ex, req, resp, params): def handle(req, resp, ex, params):
""" """
The handler used for app errors and child classes The handler used for app errors and child classes.
""" """
format_error_resp( format_error_resp(
req, req,
@@ -249,7 +245,6 @@ class ArmadaAPIException(falcon.HTTPError):
class ArmadaBaseException(Exception): class ArmadaBaseException(Exception):
'''Base class for Armada exception and error handling.''' '''Base class for Armada exception and error handling.'''
def __init__(self, message=None, **kwargs): def __init__(self, message=None, **kwargs):
self.message = message or self.message self.message = message or self.message
# replacing try-except-pass block with suppress # replacing try-except-pass block with suppress

View File

@@ -25,7 +25,6 @@ class HelmChartBuildException(ChartBuilderException):
''' '''
Exception that occurs when Helm Chart fails to build. Exception that occurs when Helm Chart fails to build.
''' '''
def __init__(self, chart_name, details): def __init__(self, chart_name, details):
self._chart_name = chart_name self._chart_name = chart_name
self._message = ( self._message = (

View File

@@ -19,7 +19,6 @@ class HelmCommandException(ex):
''' '''
Exception that occurs when a helm command fails. Exception that occurs when a helm command fails.
''' '''
def __init__(self, called_process_error): def __init__(self, called_process_error):
self.called_process_error = called_process_error self.called_process_error = called_process_error
message = 'helm command failed: {}'.format( message = 'helm command failed: {}'.format(

View File

@@ -28,7 +28,6 @@ class InvalidOverrideTypeException(OverrideException):
Exception that occurs when an invalid override type is used with the Exception that occurs when an invalid override type is used with the
set flag. set flag.
''' '''
def __init__(self, override_type): def __init__(self, override_type):
self._message = 'Override type "{}" is invalid'.format(override_type) self._message = 'Override type "{}" is invalid'.format(override_type)
@@ -42,7 +41,6 @@ class InvalidOverrideFileException(OverrideException):
**Troubleshoot:** **Troubleshoot:**
*Coming Soon* *Coming Soon*
''' '''
def __init__(self, filename): def __init__(self, filename):
self._message = '{} is not a valid override file.'.format(filename) self._message = '{} is not a valid override file.'.format(filename)
@@ -56,7 +54,6 @@ class InvalidOverrideValueException(OverrideException):
**Troubleshoot:** **Troubleshoot:**
*Coming Soon* *Coming Soon*
''' '''
def __init__(self, override_command): def __init__(self, override_command):
self._message = '{} is not a valid override statement.'.format( self._message = '{} is not a valid override statement.'.format(
override_command) override_command)
@@ -71,7 +68,6 @@ class UnknownDocumentOverrideException(OverrideException):
**Troubleshoot:** **Troubleshoot:**
*Coming Soon* *Coming Soon*
''' '''
def __init__(self, doc_type, doc_name): def __init__(self, doc_type, doc_name):
self._message = 'Unable to find {1} document schema: {0} '.format( self._message = 'Unable to find {1} document schema: {0} '.format(
doc_type, doc_name) doc_type, doc_name)

View File

@@ -28,7 +28,6 @@ class GitException(SourceException):
**Troubleshoot:** **Troubleshoot:**
*Coming Soon* *Coming Soon*
''' '''
def __init__(self, location): def __init__(self, location):
self._location = location self._location = location
self._message = ( self._message = (
@@ -40,7 +39,6 @@ class GitException(SourceException):
class GitAuthException(SourceException): class GitAuthException(SourceException):
'''Exception that occurs when authentication fails for cloning a repo.''' '''Exception that occurs when authentication fails for cloning a repo.'''
def __init__(self, repo_url, ssh_key_path): def __init__(self, repo_url, ssh_key_path):
self._repo_url = repo_url self._repo_url = repo_url
self._ssh_key_path = ssh_key_path self._ssh_key_path = ssh_key_path
@@ -57,7 +55,6 @@ class GitAuthException(SourceException):
class GitProxyException(SourceException): class GitProxyException(SourceException):
'''Exception when an error occurs cloning a Git repository '''Exception when an error occurs cloning a Git repository
through a proxy.''' through a proxy.'''
def __init__(self, location): def __init__(self, location):
self._location = location self._location = location
self._message = ('Could not resolve proxy [', self._location, '].') self._message = ('Could not resolve proxy [', self._location, '].')
@@ -67,7 +64,6 @@ class GitProxyException(SourceException):
class GitSSHException(SourceException): class GitSSHException(SourceException):
'''Exception that occurs when an SSH key could not be found.''' '''Exception that occurs when an SSH key could not be found.'''
def __init__(self, ssh_key_path): def __init__(self, ssh_key_path):
self._ssh_key_path = ssh_key_path self._ssh_key_path = ssh_key_path
@@ -79,7 +75,6 @@ class GitSSHException(SourceException):
class SourceCleanupException(SourceException): class SourceCleanupException(SourceException):
'''Exception that occurs for an invalid dir.''' '''Exception that occurs for an invalid dir.'''
def __init__(self, target_dir): def __init__(self, target_dir):
self._target_dir = target_dir self._target_dir = target_dir
self._message = self._target_dir + ' is not a valid directory.' self._message = self._target_dir + ' is not a valid directory.'
@@ -95,7 +90,6 @@ class TarballDownloadException(SourceException):
**Troubleshoot:** **Troubleshoot:**
*Coming Soon* *Coming Soon*
''' '''
def __init__(self, tarball_url): def __init__(self, tarball_url):
self._tarball_url = tarball_url self._tarball_url = tarball_url
self._message = 'Unable to download from ' + self._tarball_url self._message = 'Unable to download from ' + self._tarball_url
@@ -110,7 +104,6 @@ class TarballExtractException(SourceException):
**Troubleshoot:** **Troubleshoot:**
*Coming Soon* *Coming Soon*
''' '''
def __init__(self, tarball_dir): def __init__(self, tarball_dir):
self._tarball_dir = tarball_dir self._tarball_dir = tarball_dir
self._message = 'Unable to extract ' + self._tarball_dir self._message = 'Unable to extract ' + self._tarball_dir
@@ -125,7 +118,6 @@ class InvalidPathException(SourceException):
**Troubleshoot:** **Troubleshoot:**
*Coming Soon* *Coming Soon*
''' '''
def __init__(self, path): def __init__(self, path):
self._path = path self._path = path
self._message = 'Unable to access path ' + self._path self._message = 'Unable to access path ' + self._path
@@ -140,7 +132,6 @@ class ChartSourceException(SourceException):
**Troubleshoot:** **Troubleshoot:**
*Coming Soon* *Coming Soon*
''' '''
def __init__(self, chart_name, source_type): def __init__(self, chart_name, source_type):
self._chart_name = chart_name self._chart_name = chart_name
self._source_type = source_type self._source_type = source_type

View File

@@ -42,7 +42,6 @@ class Armada(object):
This is the main Armada class handling the Armada This is the main Armada class handling the Armada
workflows workflows
''' '''
def __init__( def __init__(
self, self,
documents, documents,

View File

@@ -32,7 +32,6 @@ class ChartBuilder(object):
This class handles taking chart intentions as a parameter and turning those This class handles taking chart intentions as a parameter and turning those
into proper Helm chart metadata. into proper Helm chart metadata.
''' '''
@classmethod @classmethod
def from_chart_doc(cls, chart, helm): def from_chart_doc(cls, chart, helm):
''' '''

View File

@@ -28,7 +28,6 @@ LOG = logging.getLogger(__name__)
class ReferenceResolver(object): class ReferenceResolver(object):
"""Class for handling different data references to resolve the data.""" """Class for handling different data references to resolve the data."""
@classmethod @classmethod
def resolve_reference(cls, design_ref): def resolve_reference(cls, design_ref):
"""Resolve a reference to a design document. """Resolve a reference to a design document.

View File

@@ -40,7 +40,6 @@ class Helm(object):
''' '''
Helm CLI handler Helm CLI handler
''' '''
def __init__(self, bearer_token=None): def __init__(self, bearer_token=None):
self.bearer_token = bearer_token self.bearer_token = bearer_token
@@ -57,8 +56,11 @@ class Helm(object):
LOG.info('Running command=%s', command) LOG.info('Running command=%s', command)
try: try:
result = subprocess.run( # nosec result = subprocess.run( # nosec
command, check=True, universal_newlines=True, command,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True,
universal_newlines=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
timeout=timeout) timeout=timeout)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
raise HelmCommandException(e) raise HelmCommandException(e)

View File

@@ -33,7 +33,6 @@ class K8s(object):
''' '''
Object to obtain the local kube config file Object to obtain the local kube config file
''' '''
def __init__(self, bearer_token=None): def __init__(self, bearer_token=None):
''' '''
Initialize connection to Kubernetes Initialize connection to Kubernetes

View File

@@ -49,14 +49,13 @@ def lock_and_thread(lock_name="lock"):
:param lock_name: name of the lock to create :param lock_name: name of the lock to create
""" """
def lock_decorator(func): def lock_decorator(func):
@functools.wraps(func) @functools.wraps(func)
def func_wrapper(*args, **kwargs): def func_wrapper(*args, **kwargs):
bearer_token = None bearer_token = None
found_helm = False found_helm = False
for arg in args: for arg in args:
if type(arg) == Helm: if type(arg) is Helm:
bearer_token = arg.bearer_token bearer_token = arg.bearer_token
found_helm = True found_helm = True

View File

@@ -42,7 +42,6 @@ class ReleaseDiff(object):
:param new_values: The chart override values to deploy. :param new_values: The chart override values to deploy.
:type new_values: dict :type new_values: dict
''' '''
def __init__(self, old_chart, old_values, new_chart, new_values): def __init__(self, old_chart, old_values, new_chart, new_values):
self.old_chart = old_chart self.old_chart = old_chart
self.old_values = old_values self.old_values = old_values

View File

@@ -25,7 +25,11 @@ LOG = logging.getLogger(__name__)
class Test(object): class Test(object):
def __init__( def __init__(
self, chart, release_id, helm, cg_test_charts=None, self,
chart,
release_id,
helm,
cg_test_charts=None,
enable_all=False): enable_all=False):
"""Initialize a test handler to run Helm tests corresponding to a """Initialize a test handler to run Helm tests corresponding to a
release. release.
@@ -62,7 +66,7 @@ class Test(object):
self.test_enabled = True self.test_enabled = True
# TODO: Remove when v1 doc support is removed. # TODO: Remove when v1 doc support is removed.
if (type(test_values) == bool): if (type(test_values) is bool):
LOG.warn( LOG.warn(
'Boolean value for chart `test` key is deprecated and ' 'Boolean value for chart `test` key is deprecated and '
'will be removed. Use `test.enabled` instead.') 'will be removed. Use `test.enabled` instead.')

View File

@@ -215,7 +215,11 @@ class ChartWait():
class ResourceWait(ABC): class ResourceWait(ABC):
def __init__( def __init__(
self, resource_type, chart_wait, labels, get_resources, self,
resource_type,
chart_wait,
labels,
get_resources,
required=True): required=True):
self.resource_type = resource_type self.resource_type = resource_type
self.chart_wait = chart_wait self.chart_wait = chart_wait

View File

@@ -96,7 +96,6 @@ def attr(**kwargs):
This decorator applies the testtools.testcase.attr if it is in the list of This decorator applies the testtools.testcase.attr if it is in the list of
attributes to testtools we want to apply. attributes to testtools we want to apply.
""" """
def decorator(f): def decorator(f):
if 'type' in kwargs and isinstance(kwargs['type'], str): if 'type' in kwargs and isinstance(kwargs['type'], str):
f = testtools.testcase.attr(kwargs['type'])(f) f = testtools.testcase.attr(kwargs['type'])(f)
@@ -112,7 +111,6 @@ class AttrDict(dict):
"""Allows defining objects with attributes without defining a class """Allows defining objects with attributes without defining a class
""" """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs) super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self self.__dict__ = self

View File

@@ -25,7 +25,6 @@ from armada.tests.unit import fixtures
class BaseControllerTest(test_base.ArmadaTestCase): class BaseControllerTest(test_base.ArmadaTestCase):
"""Base class for unit testing falcon controllers.""" """Base class for unit testing falcon controllers."""
def setUp(self): def setUp(self):
super(BaseControllerTest, self).setUp() super(BaseControllerTest, self).setUp()
# Override the default configuration file lookup with references to # Override the default configuration file lookup with references to

View File

@@ -157,10 +157,14 @@ class TestReleasesManifestControllerNegativeTest(base.BaseControllerTest):
'An error occurred while building chart group: ' 'An error occurred while building chart group: '
'Could not build ChartGroup named ' 'Could not build ChartGroup named '
'"keystone-infra-services".'), '"keystone-infra-services".'),
'error': True, 'error':
'kind': 'ValidationMessage', True,
'level': 'Error', 'kind':
'name': 'ARM001', 'ValidationMessage',
'level':
'Error',
'name':
'ARM001',
'documents': [] 'documents': []
}, resp_body['details']['messageList']) }, resp_body['details']['messageList'])
self.assertEqual( self.assertEqual(
@@ -196,13 +200,16 @@ class TestReleasesManifestControllerNegativeTest(base.BaseControllerTest):
self.assertEqual( self.assertEqual(
[ [
{ {
'message': ( 'message':
'An error occurred while generating the manifest: foo.' ('An error occurred while generating the manifest: foo.'),
), 'error':
'error': True, True,
'kind': 'ValidationMessage', 'kind':
'level': 'Error', 'ValidationMessage',
'name': 'ARM001', 'level':
'Error',
'name':
'ARM001',
'documents': [] 'documents': []
} }
], resp_body['details']['messageList']) ], resp_body['details']['messageList'])

View File

@@ -41,7 +41,6 @@ class ConfPatcher(fixtures.Fixture):
it's teardown. it's teardown.
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
"""Constructor """Constructor
@@ -69,7 +68,6 @@ class RealPolicyFixture(fixtures.Fixture):
like to load and enforce the shipped default policy in tests. like to load and enforce the shipped default policy in tests.
""" """
def __init__(self, verify=True, *args, **kwargs): def __init__(self, verify=True, *args, **kwargs):
"""Constructor for ``RealPolicyFixture``. """Constructor for ``RealPolicyFixture``.

View File

@@ -348,7 +348,6 @@ class ArmadaHandlerTestCase(base.ArmadaTestCase):
expected_last_test_result=None, expected_last_test_result=None,
diff={'some_key': {'some diff'}}): diff={'some_key': {'some diff'}}):
"""Test install functionality from the sync() method.""" """Test install functionality from the sync() method."""
@mock.patch.object(armada.Armada, 'post_flight_ops') @mock.patch.object(armada.Armada, 'post_flight_ops')
@mock.patch.object(armada, 'ChartDownload') @mock.patch.object(armada, 'ChartDownload')
@mock.patch('armada.handlers.chart_deploy.ChartBuilder.from_chart_doc') @mock.patch('armada.handlers.chart_deploy.ChartBuilder.from_chart_doc')
@@ -650,7 +649,7 @@ class ArmadaNegativeHandlerTestCase(base.ArmadaTestCase):
"""Test armada handling with invalid manifest.""" """Test armada handling with invalid manifest."""
yaml_documents = list(yaml.safe_load_all(TEST_YAML)) yaml_documents = list(yaml.safe_load_all(TEST_YAML))
error_re = ('.*Documents must include at least one of each of .*') error_re = ('.*Documents must include at least one of each of .*')
self.assertRaisesRegexp( self.assertRaisesRegex(
ManifestException, error_re, armada.Armada, yaml_documents[:1], ManifestException, error_re, armada.Armada, yaml_documents[:1],
mock.MagicMock()) mock.MagicMock())
@@ -658,10 +657,11 @@ class ArmadaNegativeHandlerTestCase(base.ArmadaTestCase):
def test_armada_override_exception(self, MockChartDownload): def test_armada_override_exception(self, MockChartDownload):
"""Test Armada checks with invalid chart override.""" """Test Armada checks with invalid chart override."""
yaml_documents = list(yaml.safe_load_all(TEST_YAML)) yaml_documents = list(yaml.safe_load_all(TEST_YAML))
override = ('chart:example-chart-2:name=' 'overridden', ) override = ('chart:example-chart-2:name='
'overridden', )
error_re = ('is not a valid override statement') error_re = ('is not a valid override statement')
with self.assertRaisesRegexp(InvalidOverrideValueException, error_re): with self.assertRaisesRegex(InvalidOverrideValueException, error_re):
armada.Armada(yaml_documents, mock.MagicMock(), set_ovr=override) armada.Armada(yaml_documents, mock.MagicMock(), set_ovr=override)
@mock.patch.object(armada, 'ChartDownload') @mock.patch.object(armada, 'ChartDownload')
@@ -675,5 +675,5 @@ class ArmadaNegativeHandlerTestCase(base.ArmadaTestCase):
del example_document['data']['release'] del example_document['data']['release']
error_re = ('Invalid document .*') error_re = ('Invalid document .*')
with self.assertRaisesRegexp(InvalidManifestException, error_re): with self.assertRaisesRegex(InvalidManifestException, error_re):
armada.Armada(yaml_documents, mock.MagicMock(), set_ovr=None) armada.Armada(yaml_documents, mock.MagicMock(), set_ovr=None)

View File

@@ -15,7 +15,7 @@
import copy import copy
import os import os
import testtools import testtools
import yaml import yaml
from armada import exceptions from armada import exceptions
@@ -345,7 +345,7 @@ class ManifestNegativeTestCase(testtools.TestCase):
documents.append(documents[-1]) # Copy the last manifest. documents.append(documents[-1]) # Copy the last manifest.
error_re = r'Multiple manifests are not supported.*' error_re = r'Multiple manifests are not supported.*'
self.assertRaisesRegexp( self.assertRaisesRegex(
exceptions.ManifestException, error_re, manifest.Manifest, exceptions.ManifestException, error_re, manifest.Manifest,
documents) documents)
@@ -356,7 +356,7 @@ class ManifestNegativeTestCase(testtools.TestCase):
documents.append(documents[-1]) # Copy the last manifest. documents.append(documents[-1]) # Copy the last manifest.
error_re = r'Multiple manifests are not supported.*' error_re = r'Multiple manifests are not supported.*'
self.assertRaisesRegexp( self.assertRaisesRegex(
exceptions.ManifestException, exceptions.ManifestException,
error_re, error_re,
manifest.Manifest, manifest.Manifest,
@@ -367,7 +367,7 @@ class ManifestNegativeTestCase(testtools.TestCase):
error_re = ( error_re = (
'.*Documents must include at least one of each of .* and ' '.*Documents must include at least one of each of .* and '
'only one .*') 'only one .*')
self.assertRaisesRegexp( self.assertRaisesRegex(
exceptions.ManifestException, error_re, manifest.Manifest, exceptions.ManifestException, error_re, manifest.Manifest,
documents) documents)
@@ -391,7 +391,7 @@ class ManifestNegativeTestCase(testtools.TestCase):
armada_manifest = manifest.Manifest(self.documents) armada_manifest = manifest.Manifest(self.documents)
error_re = r'.*Could not find %s named "%s"' % ( error_re = r'.*Could not find %s named "%s"' % (
schema.TYPE_CHART, 'invalid') schema.TYPE_CHART, 'invalid')
self.assertRaisesRegexp( self.assertRaisesRegex(
exceptions.BuildChartException, error_re, exceptions.BuildChartException, error_re,
armada_manifest.find_chart_document, 'invalid') armada_manifest.find_chart_document, 'invalid')
@@ -399,7 +399,7 @@ class ManifestNegativeTestCase(testtools.TestCase):
armada_manifest = manifest.Manifest(self.documents) armada_manifest = manifest.Manifest(self.documents)
error_re = r'.*Could not find %s named "%s"' % ( error_re = r'.*Could not find %s named "%s"' % (
schema.TYPE_CHARTGROUP, 'invalid') schema.TYPE_CHARTGROUP, 'invalid')
self.assertRaisesRegexp( self.assertRaisesRegex(
exceptions.BuildChartGroupException, error_re, exceptions.BuildChartGroupException, error_re,
armada_manifest.find_chart_group_document, 'invalid') armada_manifest.find_chart_group_document, 'invalid')

View File

@@ -64,7 +64,8 @@ class OverrideTestCase(testtools.TestCase):
documents_copy = copy.deepcopy(original_documents) documents_copy = copy.deepcopy(original_documents)
values_documents = list(yaml.safe_load_all(g.read())) values_documents = list(yaml.safe_load_all(g.read()))
override = ('manifest:simple-armada:release_prefix=' 'overridden', ) override = ('manifest:simple-armada:release_prefix='
'overridden', )
# Case 1: Checking if primitive gets updated. # Case 1: Checking if primitive gets updated.
ovr = Override(original_documents, override, [values_yaml]) ovr = Override(original_documents, override, [values_yaml])
ovr.update_manifests() ovr.update_manifests()
@@ -102,7 +103,8 @@ class OverrideTestCase(testtools.TestCase):
original_documents = list(yaml.safe_load_all(f.read())) original_documents = list(yaml.safe_load_all(f.read()))
original_documents[-1]['data']['test'] = {'foo': 'bar'} original_documents[-1]['data']['test'] = {'foo': 'bar'}
override = ('manifest:simple-armada:test=' '{"foo": "bar"}', ) override = ('manifest:simple-armada:test='
'{"foo": "bar"}', )
ovr = Override(original_documents, override, []) ovr = Override(original_documents, override, [])
self.assertRaises(json.decoder.JSONDecodeError, ovr.update_manifests) self.assertRaises(json.decoder.JSONDecodeError, ovr.update_manifests)
@@ -346,7 +348,8 @@ class OverrideNegativeTestCase(testtools.TestCase):
with open(self.base_manifest) as f: with open(self.base_manifest) as f:
original_documents = list(yaml.safe_load_all(f.read())) original_documents = list(yaml.safe_load_all(f.read()))
override = ('manifest:simple-armada:name=' 'overridden', ) override = ('manifest:simple-armada:name='
'overridden', )
ovr = Override(original_documents, override) ovr = Override(original_documents, override)
self.assertRaises( self.assertRaises(
override_exceptions.InvalidOverrideValueException, override_exceptions.InvalidOverrideValueException,

View File

@@ -32,6 +32,6 @@ class SchemaTestCase(unittest.TestCase):
import, and importing the schemas again in manually results in import, and importing the schemas again in manually results in
duplicates. duplicates.
""" """
with self.assertRaisesRegexp(RuntimeError, with self.assertRaisesRegex(RuntimeError,
'Duplicate schema specified for: .*'): 'Duplicate schema specified for: .*'):
schema._load_schemas() schema._load_schemas()

View File

@@ -80,7 +80,6 @@ class ValidateOwnExamplesTestCase(BaseValidateTest):
``armada/examples`` passes internal Armada schema validation. ``armada/examples`` passes internal Armada schema validation.
""" """
def test_own_document_examples(self): def test_own_document_examples(self):
examples_path = os.path.join(os.getcwd(), 'examples') examples_path = os.path.join(os.getcwd(), 'examples')
example_files = [ example_files = [
@@ -215,7 +214,7 @@ data:
class ValidateNegativeTestCase(BaseValidateTest): class ValidateNegativeTestCase(BaseValidateTest):
def test_validate_no_dictionary_expect_type_error(self): def test_validate_no_dictionary_expect_type_error(self):
expected_error = 'The provided input "invalid" must be a dictionary.' expected_error = 'The provided input "invalid" must be a dictionary.'
self.assertRaisesRegexp( self.assertRaisesRegex(
TypeError, expected_error, validate.validate_armada_documents, TypeError, expected_error, validate.validate_armada_documents,
['invalid']) ['invalid'])

View File

@@ -31,7 +31,6 @@ class ValidationMessage(object):
:param string diagnostic: Information about what lead to the message, :param string diagnostic: Information about what lead to the message,
or details for resolution. or details for resolution.
""" """
def __init__( def __init__(
self, self,
message='Document validation error.', message='Document validation error.',

View File

@@ -69,9 +69,9 @@ author = 'The Airship Authors'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
#version = u'0.2.0' # version = u'0.2.0'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
#release = u'0.2.0' # release = u'0.2.0'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View File

@@ -21,20 +21,29 @@ testtools
urllib3 urllib3
uWSGI uWSGI
# Openstack Antelope 2023.1 # Openstack Caracal 2024.1
# https://releases.openstack.org/antelope/index.html # https://releases.openstack.org/caracal/index.html
python-keystoneclient==5.1.0 barbican==18.0.0
keystoneauth1==5.1.2 python-barbicanclient==5.7.0
keystonemiddleware==10.2.0 python-keystoneclient==5.4.0
oslo.cache==3.3.1 keystoneauth1==5.6.0
oslo.config==9.1.1 keystonemiddleware==10.6.0
oslo.context==5.1.1
oslo.db==12.3.1 oslo.cache==3.7.0
oslo.i18n==6.0.0 oslo.concurrency==6.0.0
oslo.log==5.2.0 oslo.config==9.4.0
oslo.middleware==5.1.1 oslo.context==5.5.0
oslo.policy==4.1.1 oslo.db==15.0.0
oslo.serialization==5.1.1 oslo.i18n==6.3.0
oslo.utils==6.1.0 oslo.log==5.5.1
oslo.messaging==14.7.2
oslo.metrics==0.8.0
oslo.middleware==6.1.0
oslo.policy==4.3.0
oslo.serialization==5.4.1
oslo.service==3.4.1
oslo.upgradecheck==2.3.0
oslo.utils==7.1.0
oslo.versionedobjects==3.3.0

View File

@@ -1,87 +1,119 @@
alembic==1.13.2 alembic==1.14.0
amqp==5.3.1
attrs==24.2.0 attrs==24.2.0
bcrypt==4.2.0 autopage==0.5.2
barbican==18.0.0
bcrypt==4.2.1
cachetools==5.5.0 cachetools==5.5.0
castellan==5.2.0
certifi==2024.8.30 certifi==2024.8.30
charset-normalizer==3.3.2 cffi==1.17.1
charset-normalizer==3.4.0
click==8.1.7 click==8.1.7
cliff==4.8.0
cmd2==2.5.8
cryptography==42.0.8
debtcollector==3.0.0 debtcollector==3.0.0
decorator==5.1.1 decorator==5.1.1
deepdiff==8.0.1 deepdiff==8.1.1
dnspython==2.7.0
dogpile.cache==1.3.3 dogpile.cache==1.3.3
falcon==3.1.3 eventlet==0.38.1
falcon==4.0.2
fasteners==0.19
futurist==3.0.0
gitdb==4.0.11 gitdb==4.0.11
GitPython==3.1.43 GitPython==3.1.43
google-auth==2.34.0 google-auth==2.36.0
greenlet==3.1.0 greenlet==3.1.1
idna==3.10 idna==3.10
iso8601==2.1.0 iso8601==2.1.0
Jinja2==3.1.4 Jinja2==3.1.4
jsonschema==4.23.0 jsonschema==4.23.0
jsonschema-specifications==2023.12.1 jsonschema-specifications==2023.12.1
keystoneauth1==5.1.2 keystoneauth1==5.6.0
keystonemiddleware==10.2.0 keystonemiddleware==10.6.0
kombu==5.4.2
kubernetes==30.1.0 kubernetes==30.1.0
Mako==1.3.5 ldap3==2.9.1
MarkupSafe==2.1.5 logutils==0.3.5
Mako==1.3.8
MarkupSafe==3.0.2
microversion-parse==2.0.0
mock==5.1.0 mock==5.1.0
msgpack==1.1.0 msgpack==1.1.0
netaddr==1.3.0 netaddr==1.3.0
netifaces==0.11.0 netifaces==0.11.0
oauthlib==3.2.2 oauthlib==3.2.2
orderly-set==5.2.2 orderly-set==5.2.3
os-service-types==1.7.0 os-service-types==1.7.0
oslo.cache==3.3.1 oslo.cache==3.7.0
oslo.config==9.1.1 oslo.concurrency==6.0.0
oslo.context==5.1.1 oslo.config==9.4.0
oslo.db==12.3.1 oslo.context==5.5.0
oslo.i18n==6.0.0 oslo.db==15.0.0
oslo.log==5.2.0 oslo.i18n==6.3.0
oslo.middleware==5.1.1 oslo.log==5.5.1
oslo.policy==4.1.1 oslo.messaging==14.7.2
oslo.serialization==5.1.1 oslo.metrics==0.8.0
oslo.utils==6.1.0 oslo.middleware==6.1.0
packaging==24.1 oslo.policy==4.3.0
oslo.serialization==5.4.1
oslo.service==3.4.1
oslo.upgradecheck==2.3.0
oslo.utils==7.1.0
oslo.versionedobjects==3.3.0
packaging==24.2
Paste==3.10.1 Paste==3.10.1
PasteDeploy==3.1.0 PasteDeploy==3.1.0
pbr==6.1.0 pbr==6.1.0
pecan==1.5.1
pip==24.1 pip==24.1
prometheus_client==0.20.0 prettytable==3.12.0
prometheus_client==0.21.1
py==1.11.0 py==1.11.0
pyasn1==0.6.1 pyasn1==0.6.1
pyasn1_modules==0.4.0 pyasn1_modules==0.4.0
pycadf==3.1.1 pycadf==4.0.0
pycparser==2.22
PyJWT==2.10.1
pylibyaml==0.1.0 pylibyaml==0.1.0
pyparsing==3.1.4 pyOpenSSL==24.3.0
pyparsing==3.2.0
pyperclip==1.9.0
python-barbicanclient==5.7.0
python-dateutil==2.9.0.post0 python-dateutil==2.9.0.post0
python-keystoneclient==5.1.0 python-keystoneclient==5.4.0
python-memcached==1.62 python-memcached==1.62
pytz==2024.2 pytz==2024.2
PyYAML==6.0.2 PyYAML==6.0.2
referencing==0.35.1 referencing==0.35.1
repoze.lru==0.7
requests==2.32.3 requests==2.32.3
requests-oauthlib==1.3.1 requests-oauthlib==1.3.1
responses==0.25.3 responses==0.25.3
retry==0.9.2 retry==0.9.2
rfc3986==2.0.0 rfc3986==2.0.0
rpds-py==0.20.0 Routes==2.5.1
rpds-py==0.22.3
rsa==4.9 rsa==4.9
setuptools==70.1.0 setuptools==70.1.0
six==1.16.0 six==1.17.0
smmap==5.0.1 smmap==5.0.1
SQLAlchemy==1.4.54 SQLAlchemy==1.4.54
sqlalchemy-migrate==0.13.0
sqlparse==0.5.1
statsd==4.0.1 statsd==4.0.1
stevedore==5.3.0 stevedore==5.4.0
Tempita==0.5.2
testresources==2.0.1 testresources==2.0.1
testscenarios==0.5.0 testscenarios==0.5.0
testtools==2.7.2 testtools==2.7.2
typing_extensions==4.12.2 typing_extensions==4.12.2
urllib3==2.2.2 tzdata==2024.2
uWSGI==2.0.27 urllib3==2.2.3
WebOb==1.8.8 uWSGI==2.0.28
vine==5.1.0
wcwidth==0.2.13
WebOb==1.8.9
websocket-client==1.8.0 websocket-client==1.8.0
wheel==0.43.0 wheel==0.43.0
wrapt==1.16.0 wrapt==1.17.0
yappi==1.6.10

View File

@@ -54,6 +54,7 @@ with-doctest=1
[yapf] [yapf]
based_on_style = pep8 based_on_style = pep8
column_limit = 79
blank_line_before_nested_class_or_def = true blank_line_before_nested_class_or_def = true
blank_line_before_module_docstring = true blank_line_before_module_docstring = true
split_before_logical_operator = false split_before_logical_operator = false

View File

@@ -5,8 +5,7 @@ try:
except ImportError: except ImportError:
pass pass
setuptools.setup( setuptools.setup(package_data={'armada': ['schemas/*.yaml']},
package_data={'armada': ['schemas/*.yaml']}, include_package_data=True,
include_package_data=True, setup_requires=['pbr>=2.0.0'],
setup_requires=['pbr>=2.0.0'], pbr=True)
pbr=True)

View File

@@ -1,11 +1,12 @@
bandit==1.6.0 bandit==1.6.0
# cmd2>=1.5.0 # cmd2>=1.5.0
coverage==5.3 coverage==5.3
flake8-import-order>=0.18.1 flake8-import-order
flake8==3.8.4 importlib-metadata
flake8 >= 6.0.0
grpcio-tools>=1.16.0 grpcio-tools>=1.16.0
os-testr>=1.0.0 # Apache-2.0 os-testr>=1.0.0 # Apache-2.0
pyflakes==2.2.0 pyflakes
sphinx-rtd-theme==0.5.0 sphinx-rtd-theme==0.5.0
stestr==4.1.0 stestr==4.1.0
testrepository==0.0.20 testrepository==0.0.20
@@ -14,4 +15,5 @@ testscenarios==0.5.0
# testtools==2.5.0 # testtools==2.5.0
# tox>=3.28.0, <4.0.0 # tox>=3.28.0, <4.0.0
# typing-extensions>=3.7.2 # typing-extensions>=3.7.2
yapf==0.27.0 yapf

View File

@@ -38,7 +38,7 @@ allowlist_externals=
sh sh
deps= deps=
-r{toxinidir}/requirements-direct.txt -r{toxinidir}/requirements-direct.txt
-c https://raw.githubusercontent.com/apache/airflow/constraints-2.10.2/constraints-3.10.txt -c https://raw.githubusercontent.com/apache/airflow/constraints-2.10.4/constraints-3.10.txt
commands= commands=
rm -f requirements-frozen.txt rm -f requirements-frozen.txt
sh -c "pip freeze --all | grep -vE 'armada|pyinotify|pkg-resources==0.0.0' > requirements-frozen.txt" sh -c "pip freeze --all | grep -vE 'armada|pyinotify|pkg-resources==0.0.0' > requirements-frozen.txt"
@@ -118,5 +118,6 @@ enable-extensions = H106,H201,H904
ignore = W503,B202,B113 ignore = W503,B202,B113
exclude = .git,.tox,dist,*lib/python*,*egg,build,releasenotes,doc/*,venv exclude = .git,.tox,dist,*lib/python*,*egg,build,releasenotes,doc/*,venv
max-complexity = 24 max-complexity = 24
max-line-length = 79
application-import-names = armada application-import-names = armada
import-order-style = pep8 import-order-style = pep8