From 86b7d034032e4399c5fc4a901c59616ebeaaae62 Mon Sep 17 00:00:00 2001 From: Sergiy Markin <smarkin@mirantis.com> Date: Mon, 23 Dec 2024 06:03:19 +0000 Subject: [PATCH] Fix deprecated code This PS replaces deprecared module pkg_resources, also fixes some unit tests and fixes the schema validation by adding specific schema draft to choose in order to prevent the processor to fall back to use the latest draft that may potentially cause issues. Also this PS bumps kubectl version to 1.32.0 due to CVE and switched base ubuntu image repo to quay.io/airshipit Change-Id: Ie40f179eac83fde4d828e6f63a9c03e473eb3b15 --- images/airflow/Dockerfile.ubuntu_jammy | 4 +- images/shipyard/Dockerfile.ubuntu_jammy | 2 +- .../shipyard_airflow/requirements-direct.txt | 8 +- .../shipyard_airflow/requirements-frozen.txt | 8 +- .../schemas/deploymentConfiguration.yaml | 2 +- .../schemas/deploymentStrategy.yaml | 2 +- .../test_armada_test_releases_operator.py | 150 ++++++++++-------- .../unit/schemas/base_schema_validation.py | 5 +- 8 files changed, 96 insertions(+), 85 deletions(-) diff --git a/images/airflow/Dockerfile.ubuntu_jammy b/images/airflow/Dockerfile.ubuntu_jammy index 62a40cd3..d2257cb0 100644 --- a/images/airflow/Dockerfile.ubuntu_jammy +++ b/images/airflow/Dockerfile.ubuntu_jammy @@ -19,7 +19,7 @@ # 429 Too Many Requests - Server message: too many requests: # You have reached your pull rate limit. # You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit -ARG FROM=public.ecr.aws/docker/library/ubuntu:jammy +ARG FROM=quay.io/airshipit/ubuntu:jammy FROM ${FROM} LABEL org.opencontainers.image.authors='airship-discuss@lists.airshipit.org, irc://#airshipit@freenode' \ @@ -55,7 +55,7 @@ ARG DEBIAN_FRONTEND=noninteractive ARG ctx_base=src/bin # Kubectl version -ARG KUBECTL_VERSION=1.31.0 +ARG KUBECTL_VERSION=1.32.0 # Needed from apache-airflow 1.10.2, since core.airflow_home config is deprecated ENV AIRFLOW_HOME=${AIRFLOW_HOME} diff --git a/images/shipyard/Dockerfile.ubuntu_jammy b/images/shipyard/Dockerfile.ubuntu_jammy index 99d0e524..fc7b33bd 100644 --- a/images/shipyard/Dockerfile.ubuntu_jammy +++ b/images/shipyard/Dockerfile.ubuntu_jammy @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -ARG FROM=ubuntu:jammy +ARG FROM=quay.io/airshipit/ubuntu:jammy FROM ${FROM} LABEL org.opencontainers.image.authors='airship-discuss@lists.airshipit.org, irc://#airshipit@freenode' \ diff --git a/src/bin/shipyard_airflow/requirements-direct.txt b/src/bin/shipyard_airflow/requirements-direct.txt index f792be04..2ae43580 100644 --- a/src/bin/shipyard_airflow/requirements-direct.txt +++ b/src/bin/shipyard_airflow/requirements-direct.txt @@ -59,7 +59,7 @@ oslo.versionedobjects==3.3.0 # Airship dependencies -git+https://opendev.org/airship/deckhand.git@4d500e48e880ea7f9a3582324c55c61373a855ea#egg=deckhand -git+https://opendev.org/airship/drydock.git@ffcd51e00249198f1e2d40f3e83c8c1c338df3ad#egg=drydock_provisioner&subdirectory=python -git+https://opendev.org/airship/armada.git@af4bf814f3a44e9ccee7c9fd8e4be34d943e013d#egg=armada -git+https://opendev.org/airship/promenade.git@817ead27e991ff3fbed99ea1cb08aad5674d7167#egg=promenade +git+https://opendev.org/airship/deckhand.git@211b2d20c080ec806d196f3ec6b0d0472b00fa1b#egg=deckhand +git+https://opendev.org/airship/drydock.git@108a3c1ee4666df3a6fb4439df245525a870d1d9#egg=drydock_provisioner&subdirectory=python +git+https://opendev.org/airship/armada.git@963e23bb9323ea30472c54adc32e5c9eb7bf0506#egg=armada +git+https://opendev.org/airship/promenade.git@40fd108fd976c19bc142d10cc52b24d48de37100#egg=promenade diff --git a/src/bin/shipyard_airflow/requirements-frozen.txt b/src/bin/shipyard_airflow/requirements-frozen.txt index 8ec69613..8eb87c04 100644 --- a/src/bin/shipyard_airflow/requirements-frozen.txt +++ b/src/bin/shipyard_airflow/requirements-frozen.txt @@ -21,7 +21,7 @@ apache-airflow-providers-smtp==1.8.1 apache-airflow-providers-sqlite==3.9.1 apispec==6.8.0 argcomplete==3.5.2 -Armada @ git+https://opendev.org/airship/armada.git@af4bf814f3a44e9ccee7c9fd8e4be34d943e013d +Armada @ git+https://opendev.org/airship/armada.git@963e23bb9323ea30472c54adc32e5c9eb7bf0506 arrow==1.3.0 asgiref==3.8.1 async-timeout==5.0.1 @@ -55,7 +55,7 @@ cron-descriptor==1.4.5 croniter==5.0.1 cryptography==42.0.8 debtcollector==3.0.0 -Deckhand @ git+https://opendev.org/airship/deckhand.git@4d500e48e880ea7f9a3582324c55c61373a855ea +Deckhand @ git+https://opendev.org/airship/deckhand.git@211b2d20c080ec806d196f3ec6b0d0472b00fa1b decorator==5.1.1 deepdiff==8.1.1 Deprecated==1.2.15 @@ -63,7 +63,7 @@ dill==0.3.1.1 dnspython==2.7.0 docopt==0.6.2 dogpile.cache==1.3.3 -drydock_provisioner @ git+https://opendev.org/airship/drydock.git@ffcd51e00249198f1e2d40f3e83c8c1c338df3ad#subdirectory=python +drydock_provisioner @ git+https://opendev.org/airship/drydock.git@108a3c1ee4666df3a6fb4439df245525a870d1d9#subdirectory=python email_validator==2.2.0 eventlet==0.38.1 exceptiongroup==1.2.2 @@ -188,7 +188,7 @@ pluggy==1.5.0 ply==3.11 prettytable==3.12.0 prison==0.2.1 -promenade @ git+https://opendev.org/airship/promenade.git@817ead27e991ff3fbed99ea1cb08aad5674d7167 +promenade @ git+https://opendev.org/airship/promenade.git@40fd108fd976c19bc142d10cc52b24d48de37100 prometheus_client==0.21.1 prompt_toolkit==3.0.48 propcache==0.2.1 diff --git a/src/bin/shipyard_airflow/shipyard_airflow/schemas/deploymentConfiguration.yaml b/src/bin/shipyard_airflow/shipyard_airflow/schemas/deploymentConfiguration.yaml index d79d313a..d6c94180 100644 --- a/src/bin/shipyard_airflow/shipyard_airflow/schemas/deploymentConfiguration.yaml +++ b/src/bin/shipyard_airflow/shipyard_airflow/schemas/deploymentConfiguration.yaml @@ -6,7 +6,7 @@ metadata: labels: application: shipyard data: - $schema: 'http://json-schema.org/schema#' + $schema: 'http://json-schema.org/draft-04/schema#' id: 'https://github.com/openstack/airship-shipyard/blob/master/src/bin/shipyard_airflow/shipyard_airflow/schemas/deploymentConfiguration.yaml' type: 'object' properties: diff --git a/src/bin/shipyard_airflow/shipyard_airflow/schemas/deploymentStrategy.yaml b/src/bin/shipyard_airflow/shipyard_airflow/schemas/deploymentStrategy.yaml index c51e40cd..234dbd00 100644 --- a/src/bin/shipyard_airflow/shipyard_airflow/schemas/deploymentStrategy.yaml +++ b/src/bin/shipyard_airflow/shipyard_airflow/schemas/deploymentStrategy.yaml @@ -6,7 +6,7 @@ metadata: labels: application: shipyard data: - $schema: 'http://json-schema.org/schema#' + $schema: 'http://json-schema.org/draft-04/schema#' id: 'https://github.com/openstack/airship-shipyard/blob/master/src/bin/shipyard_airflow/shipyard_airflow/schemas/deploymentStrategy.yaml' type: 'object' required: diff --git a/src/bin/shipyard_airflow/tests/unit/plugins/test_armada_test_releases_operator.py b/src/bin/shipyard_airflow/tests/unit/plugins/test_armada_test_releases_operator.py index e965af39..6dc5a336 100644 --- a/src/bin/shipyard_airflow/tests/unit/plugins/test_armada_test_releases_operator.py +++ b/src/bin/shipyard_airflow/tests/unit/plugins/test_armada_test_releases_operator.py @@ -12,20 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. """Tests ArmadaTestReleasesOperator functionality""" + import os from unittest import mock - -from airflow.exceptions import AirflowException import pytest +from airflow.exceptions import AirflowException -from shipyard_airflow.plugins.armada_base_operator import \ - ArmadaBaseOperator -from shipyard_airflow.plugins.armada_test_releases import \ - ArmadaTestReleasesOperator -from shipyard_airflow.plugins.ucp_base_operator import \ - UcpBaseOperator - - +from shipyard_airflow.plugins.armada_base_operator import ArmadaBaseOperator +from shipyard_airflow.plugins.armada_test_releases import ArmadaTestReleasesOperator +from shipyard_airflow.plugins.ucp_base_operator import UcpBaseOperator CONF_FILE = os.path.join(os.path.dirname(__file__), 'test.conf') @@ -38,64 +33,81 @@ RELEASES = { 'openstack': ['glance', 'heat', 'horizon', 'keystone'] } +@pytest.fixture +def setup_armada_operator(): + """Fixture to setup the ArmadaTestReleasesOperator with default params""" + op = ArmadaTestReleasesOperator(main_dag_name='main', + shipyard_conf=CONF_FILE, + task_id='t1') + op.action_params = dict() + return op -class TestArmadaTestReleasesOperator(ArmadaTestReleasesOperator): - @mock.patch('shipyard_airflow.plugins.armada_test_releases.LOG.info') - @mock.patch.object(ArmadaBaseOperator, 'armada_client', create=True) - @mock.patch.object(ArmadaBaseOperator, 'get_releases', - return_value=RELEASES) - def test_do_execute(self, mock_releases, mock_client, - mock_logs): - op = ArmadaTestReleasesOperator(main_dag_name='main', - shipyard_conf=CONF_FILE, - task_id='t1') - op.action_params = dict() +@pytest.fixture +def setup_operator_with_params(): + """Fixture to setup the ArmadaTestReleasesOperator with action params""" + op = ArmadaTestReleasesOperator(main_dag_name='main', + shipyard_conf=CONF_FILE, + task_id='t1') + op.action_params = ACTION_PARAMS + return op + +@pytest.fixture +def mock_releases(): + """Fixture to mock releases""" + with mock.patch.object(ArmadaBaseOperator, 'get_releases', return_value=RELEASES): + yield + +@pytest.fixture +def mock_client(): + """Fixture to mock Armada client""" + with mock.patch.object(ArmadaBaseOperator, 'armada_client', create=True) as mock_client: + yield mock_client + +@pytest.fixture +def mock_logs(): + """Fixture to mock logging""" + with mock.patch('shipyard_airflow.plugins.armada_test_releases.LOG.info') as mock_logs: + yield mock_logs + +@pytest.fixture +def mock_k8s_logs(): + """Fixture to mock k8s logs""" + with mock.patch.object(UcpBaseOperator, 'get_k8s_logs') as mock_k8s_logs: + yield mock_k8s_logs + +def test_do_execute(setup_armada_operator, mock_releases, mock_client, mock_logs): + """Test ArmadaTestReleasesOperator execute functionality""" + op = setup_armada_operator + op.do_execute() + + # Verify Armada client called to test every release + calls = [mock.call(release=release, timeout=None) for release_list in RELEASES.values() for release in release_list] + mock_client.get_test_release.assert_has_calls(calls, any_order=True) + + # Verify test results logged + mock_logs.assert_called_with(mock_client.get_test_release.return_value) + + +def test_do_execute_with_params(setup_operator_with_params, mock_client, mock_logs): + """Test ArmadaTestReleasesOperator execute functionality with action params""" + op = setup_operator_with_params + op.do_execute() + + # Verify Armada client called for single release with action params + release = ACTION_PARAMS['release'] + mock_client.get_test_release.assert_called_once_with(release=release, timeout=None) + + # Verify test results logged + mock_logs.assert_called_with(mock_client.get_test_release.return_value) + + +def test_do_execute_fail(setup_armada_operator, mock_releases, mock_client, mock_k8s_logs): + """Test failure scenario for ArmadaTestReleasesOperator""" + mock_client.get_test_release.return_value = None + + op = setup_armada_operator + + # Verify errors logged to pods + with pytest.raises(AirflowException): op.do_execute() - - # Verify Armada client called to test every release - calls = list() - for release_list in RELEASES.values(): - for release in release_list: - calls.append(mock.call( - release=release, - timeout=None)) - mock_client.get_test_release.assert_has_calls(calls, any_order=True) - - # Verify test results logged - mock_logs.assert_called_with(mock_client.get_test_release.return_value) - - @mock.patch('shipyard_airflow.plugins.armada_test_releases.LOG.info') - @mock.patch.object(ArmadaBaseOperator, 'armada_client', create=True) - def test_do_execute_with_params(self, mock_client, mock_logs): - op = ArmadaTestReleasesOperator(main_dag_name='main', - shipyard_conf=CONF_FILE, - task_id='t1') - op.action_params = ACTION_PARAMS - op.do_execute() - - # Verify Armada client called for single release with action params - release = ACTION_PARAMS['release'] - mock_client.get_test_release.assert_called_once_with( - release=release, - timeout=None) - - # Verify test results logged - mock_logs.assert_called_with(mock_client.get_test_release.return_value) - - @mock.patch.object(ArmadaBaseOperator, 'armada_client', create=True) - @mock.patch.object(ArmadaBaseOperator, 'get_releases', - return_value=RELEASES) - @mock.patch.object(UcpBaseOperator, 'get_k8s_logs') - def test_do_execute_fail(self, mock_k8s_logs, - mock_releases, mock_client): - mock_client.get_test_release.return_value = None - - op = ArmadaTestReleasesOperator(main_dag_name='main', - shipyard_conf=CONF_FILE, - task_id='t1') - op.action_params = dict() - - # Verify errors logged to pods - with pytest.raises(AirflowException): - op.do_execute() - mock_k8s_logs.assert_called_once() + mock_k8s_logs.assert_called_once() diff --git a/src/bin/shipyard_airflow/tests/unit/schemas/base_schema_validation.py b/src/bin/shipyard_airflow/tests/unit/schemas/base_schema_validation.py index 13685769..2d68967b 100644 --- a/src/bin/shipyard_airflow/tests/unit/schemas/base_schema_validation.py +++ b/src/bin/shipyard_airflow/tests/unit/schemas/base_schema_validation.py @@ -16,7 +16,7 @@ import os import yaml import jsonschema -import pkg_resources +from importlib.resources import files import pytest from jsonschema.exceptions import ValidationError @@ -31,8 +31,7 @@ class BaseSchemaValidationTest(object): :param expect_failure: should the validation pass or fail. :param input_files: pytest fixture used to access the test input files :param input: test input yaml doc filename""" - schema_dir = pkg_resources.resource_filename('shipyard_airflow', - 'schemas') + schema_dir = str(files('shipyard_airflow') / 'schemas') schema_filename = os.path.join(schema_dir, schema) schema_file = open(schema_filename, 'r') schema = yaml.safe_load(schema_file)