From c1cc663be0b10414a62b7ab3a58a3da6893e02f1 Mon Sep 17 00:00:00 2001 From: Pavlina Bortlova Date: Thu, 15 Oct 2020 17:44:56 +0200 Subject: [PATCH 1/3] Add models specific to request_type --- iiblib/iib_build_details_model.py | 184 +++++++++----------------- tests/test_iib_build_details_model.py | 117 +++++++++++++--- tests/test_iib_build_details_pager.py | 43 +++--- 3 files changed, 181 insertions(+), 163 deletions(-) diff --git a/iiblib/iib_build_details_model.py b/iiblib/iib_build_details_model.py index cf41b41..17283f2 100644 --- a/iiblib/iib_build_details_model.py +++ b/iiblib/iib_build_details_model.py @@ -1,135 +1,69 @@ class IIBBuildDetailsModel(object): """Model class handling data about index build task""" - def __init__( - self, - _id, - state, - reason, - state_history, - from_index, - from_index_resolved, - bundles, - removed_operators, - organization, - binary_image, - binary_image_resolved, - index_image, - request_type, - arches, - bundle_mapping, - omps_operator_version, - ): - """ - Args: - _id (int) - Id of build - state (str) - State of build - state (str) - Reason for state change - from_index (str) - Reference of index image used as source for rebuild - from_index_resolved (str) - Reference of new index image - bundles (list) - List of bundles to be added to index image - removed_operators (list) - List of operators to be removed from index image - organization (str) - Name of organization to push to in the legacy app registry - binary_image (str) - Reference of binary image used for rebuilding - binary_image_resolved (str) - Checksum reference of binary image that was used for rebuilding - index_image (str) - Reference of index image to rebuild - request_type (str) - Type of iib build task (add or remove) - arches (list) - List of architectures supported in new index image - bundle_mapping (dict) - Operator names in "bundles" map to: list of "bundles" which - map to the operator key - omps_operator_version (dict) - Operator version returned from OMPS API call used for Add request - """ - self.id = _id - self.state = state - self.reason = reason - self.state_history = state_history - self.from_index = from_index - self.from_index_resolved = from_index_resolved - self.bundles = bundles - self.removed_operators = removed_operators - self.organization = organization - self.binary_image = binary_image - self.binary_image_resolved = binary_image_resolved - self.index_image = index_image - self.request_type = request_type - self.arches = arches - self.bundle_mapping = bundle_mapping - self.omps_operator_version = omps_operator_version + _data_attrs = [] + _kwattrs = [] + + def __init__(self, *args, **kwargs): + self.data = {} + for attr, attr_val in zip(args, self._data_attrs): + self.data[attr_val] = attr + for key, value in kwargs.items(): + self.data[key] = value @classmethod def from_dict(cls, data): - return cls( - data["id"], - data["state"], - data["state_reason"], - data.get("state_history", []), - data["from_index"], - data["from_index_resolved"], - data.get("bundles", []), - data.get("removed_operators", []), - data.get("organization"), - data["binary_image"], - data["binary_image_resolved"], - data["index_image"], - data["request_type"], - data["arches"], - data["bundle_mapping"], - data.get("omps_operator_version", {}), - ) + if data['request_type'] == "add": + return AddModel._from_dict(data) + elif data['request_type'] == "rm": + return RmModel._from_dict(data) + elif data['request_type'] == "regenerate-bundle": + return RegenerateBundleModel._from_dict(data) + raise KeyError("Unsupported request type: %s" % data['request_type']) + + @classmethod + def _from_dict(cls, data): + args = [] + kwargs = {} + for attr in cls._data_attrs: + args.append(data[attr]) + for kwattr in cls._kwattrs: + kwargs[kwattr] = data[kwattr] + return cls(*args, **kwargs) def to_dict(self): - return { - "id": self.id, - "state": self.state, - "state_reason": self.reason, - "state_history": self.state_history, - "from_index": self.from_index, - "from_index_resolved": self.from_index, - "bundles": self.bundles, - "removed_operators": self.removed_operators, - "organization": self.organization, - "binary_image": self.binary_image, - "binary_image_resolved": self.binary_image_resolved, - "index_image": self.index_image, - "request_type": self.request_type, - "arches": self.arches, - "bundle_mapping": self.bundle_mapping, - "omps_operator_version": self.omps_operator_version, - } + result = {} + for key in self._data_attrs: + result[key] = self.data[key] + for key in self._kwattrs: + result[key] = self.data[key] + return result def __eq__(self, other): - if ( - self.id == other.id - and self.state == other.state - and self.reason == other.reason - and self.state_history == other.state_history - and self.from_index == other.from_index - and self.from_index_resolved == other.from_index_resolved - and self.bundles == other.bundles - and self.removed_operators == other.removed_operators - and self.organization == other.organization - and self.binary_image == other.binary_image - and self.binary_image_resolved == other.binary_image_resolved - and self.index_image == other.index_image - and self.request_type == other.request_type - and self.arches == other.arches - and self.bundle_mapping == other.bundle_mapping - and self.omps_operator_version == other.omps_operator_version - ): - return True - return False + return isinstance(other, IIBBuildDetailsModel) and self.data == other.data + + +class AddModel(IIBBuildDetailsModel): + + # TODO if there are always the same _data_attrs we can put it to the class _data_attrs + _data_attrs = ["id", "arches", "state", "state_reason", "request_type", "state_history", + "batch", "batch_annotations", "logs", "updated", "user"] + _kwattrs = ["binary_image", "binary_image_resolved", "bundles", "bundle_mapping", + "from_index", "from_index_resolved", "index_image", "removed_operators", + "organization", "omps_operator_version", "distribution_scope"] + + +class RmModel(IIBBuildDetailsModel): + + _data_attrs = ["arches", "id", "state", "state_reason", "request_type", "state_history", + "batch", "batch_annotations", "logs", "updated", "user"] + _kwattrs = ["binary_image", "binary_image_resolved", "bundles", "bundle_mapping", + "from_index", "from_index_resolved", "index_image", "removed_operators", + "organization", "distribution_scope"] + + +class RegenerateBundleModel(IIBBuildDetailsModel): + + _data_attrs = ["arches", "id", "state", "state_reason", "request_type", "state_history", + "batch", "batch_annotations", "logs", "updated", "user"] + _kwattrs = ["bundle_image", "from_bundle_image", "from_bundle_image_resolved", "organization"] diff --git a/tests/test_iib_build_details_model.py b/tests/test_iib_build_details_model.py index 33868e9..4f6a493 100644 --- a/tests/test_iib_build_details_model.py +++ b/tests/test_iib_build_details_model.py @@ -1,10 +1,66 @@ import pytest -from iiblib.iib_build_details_model import IIBBuildDetailsModel +from iiblib.iib_build_details_model import IIBBuildDetailsModel, AddModel @pytest.fixture -def fixture_build_details_json(): +def fixture_add_build_details_model(): + json = { + "id": 1, + "arches": ["x86_64"], + "state": "in_progress", + "state_reason": "state_reason", + "request_type": "add", + "state_history": [], + "batch": 1, + "batch_annotations": {"batch_annotations": 1}, + "logs": {}, + "updated": "updated", + "user": "user@example.com", + "binary_image": "binary_image", + "binary_image_resolved": "binary_image_resolved", + "bundles": ["bundles1"], + "bundle_mapping": {"bundle_mapping": "map"}, + "from_index": "from_index", + "from_index_resolved": "from_index_resolved", + "index_image": "index_image", + "removed_operators": ["operator1"], + "organization": "organization", + "omps_operator_version": {"operator": "1.0"}, + "distribution_scope": "null", + } + return json + +@pytest.fixture +def fixture_rm_build_details_model(): + json = { + "id": 1, + "arches": ["x86_64"], + "state": "in_progress", + "state_reason": "state_reason", + "request_type": "rm", + "state_history": [], + "batch": 1, + "batch_annotations": {"batch_annotations": 1}, + "logs": {}, + "updated": "updated", + "user": "user@example.com", + "binary_image": "binary_image", + "binary_image_resolved": "binary_image_resolved", + "bundles": ["bundles1"], + "bundle_mapping": {"bundle_mapping": "map"}, + "from_index": "from_index", + "from_index_resolved": "from_index_resolved", + "index_image": "index_image", + "removed_operators": ["operator1"], + "organization": "organization", + "omps_operator_version": {"operator": "1.0"}, + "distribution_scope": "null", + } + return json + +@pytest.fixture +def fixture_regenerate_bundle_build_details_model(): json = { "id": 1, "state": "in_progress", @@ -18,55 +74,72 @@ def fixture_build_details_json(): "binary_image": "binary_image", "binary_image_resolved": "binary_image_resolved", "index_image": "index_image", - "request_type": "request_type", + "request_type": "regenerate-bundle", "arches": ["x86_64"], "bundle_mapping": {"bundle_mapping": "map"}, "omps_operator_version": {"operator": "1.0"}, + "batch": 1, + "batch_annotations": {"batch_annotations": 1}, + "logs": {}, + "updated": "updated", + "user": "user@example.com", } return json -def test_iibbuilddetailsmodel(fixture_build_details_json): - unexpected_model = IIBBuildDetailsModel( +def test_iib_build_details_model_add_request_type(fixture_add_build_details_model): + unexpected_model = AddModel( 1, + ["x86_64"], "finished", "state_reason", + "add", [], + 1, + {"batch_annotations": 1}, + {}, + "updated", + "user@example.com", + "binary_image", + "binary_image_resolved", + ["bundles1"], + {"bundle_mapping": "map"}, "from_index", "from_index_resolved", - ["bundles1"], + "index_image", ["operator1"], "organization", - "binary_image", - "binary_image_resolved", - "index_image", - "request_type", - ["x86_64"], - {"bundle_mapping": "map"}, {"operator": "1.0"}, + "null", ) - expected_model = IIBBuildDetailsModel( + expected_model = AddModel( 1, + ["x86_64"], "in_progress", "state_reason", + "add", [], + 1, + {"batch_annotations": 1}, + {}, + "updated", + "user@example.com", + "binary_image", + "binary_image_resolved", + ["bundles1"], + {"bundle_mapping": "map"}, "from_index", "from_index_resolved", - ["bundles1"], + "index_image", ["operator1"], "organization", - "binary_image", - "binary_image_resolved", - "index_image", - "request_type", - ["x86_64"], - {"bundle_mapping": "map"}, {"operator": "1.0"}, + "null", ) - model = IIBBuildDetailsModel.from_dict(fixture_build_details_json) + model = IIBBuildDetailsModel.from_dict(fixture_add_build_details_model) assert model == expected_model assert model != unexpected_model - model = IIBBuildDetailsModel.from_dict(fixture_build_details_json).to_dict() + model = IIBBuildDetailsModel.from_dict(fixture_add_build_details_model).to_dict() assert model == expected_model.to_dict() assert model != unexpected_model.to_dict() diff --git a/tests/test_iib_build_details_pager.py b/tests/test_iib_build_details_pager.py index fc843a4..eb6271f 100644 --- a/tests/test_iib_build_details_pager.py +++ b/tests/test_iib_build_details_pager.py @@ -10,44 +10,55 @@ def fixture_build_details_json(): json = { "id": 1, + "arches": ["x86_64"], "state": "in_progress", "state_reason": "state_reason", + "request_type": "add", "state_history": [], + "batch": 1, + "batch_annotations": {"batch_annotations": 1}, + "logs": {}, + "updated": "updated", + "user": "user@example.com", + "binary_image": "binary_image", + "binary_image_resolved": "binary_image_resolved", + "bundles": ["bundles1"], + "bundle_mapping": {"bundle_mapping": "map"}, "from_index": "from_index", "from_index_resolved": "from_index_resolved", - "bundles": ["bundles1"], + "index_image": "index_image", "removed_operators": ["operator1"], "organization": "organization", - "binary_image": "binary_image", - "binary_image_resolved": "binary_image_resolved", - "index_image": "index_image", - "request_type": "request_type", - "arches": ["x86_64"], - "bundle_mapping": {"bundle_mapping": "map"}, "omps_operator_version": {"operator": "1.0"}, + "distribution_scope": "null" } return json - @pytest.fixture def fixture_build_details_json2(): json = { "id": 2, + "arches": ["x86_64"], "state": "in_progress", "state_reason": "state_reason", + "request_type": "add", "state_history": [], + "batch": 2, + "batch_annotations": {"batch_annotations": 2}, + "logs": {}, + "updated": "updated", + "user": "user@example.com", + "binary_image": "binary_image", + "binary_image_resolved": "binary_image_resolved", + "bundles": ["bundles1"], + "bundle_mapping": {"bundle_mapping": "map"}, "from_index": "from_index", "from_index_resolved": "from_index_resolved", - "bundles": ["bundles1"], + "index_image": "index_image", "removed_operators": ["operator1"], "organization": "organization", - "binary_image": "binary_image", - "binary_image_resolved": "binary_image_resolved", - "index_image": "index_image", - "request_type": "request_type", - "arches": ["x86_64"], - "bundle_mapping": {"bundle_mapping": "map"}, "omps_operator_version": {"operator": "1.0"}, + "distribution_scope": "null" } return json @@ -88,7 +99,7 @@ def fixture_builds_page2_json(fixture_build_details_json2): return json -def test_iibbuilddetails_pager( +def test_iib_build_details_pager( fixture_builds_page1_json, fixture_builds_page2_json, fixture_build_details_json, From fb070bc543ad6d851486f43f06931d9ac77aaa46 Mon Sep 17 00:00:00 2001 From: Pavlina Bortlova Date: Tue, 20 Oct 2020 15:27:38 +0200 Subject: [PATCH 2/3] Modify tests --- iiblib/iib_build_details_model.py | 95 ++++++++--- iiblib/iib_client.py | 6 +- tests/test_iib_build_details_model.py | 190 ++++++++++++++++----- tests/test_iib_build_details_pager.py | 21 +-- tests/test_iib_client.py | 236 ++++++++++++++------------ 5 files changed, 361 insertions(+), 187 deletions(-) diff --git a/iiblib/iib_build_details_model.py b/iiblib/iib_build_details_model.py index 17283f2..d7eb52e 100644 --- a/iiblib/iib_build_details_model.py +++ b/iiblib/iib_build_details_model.py @@ -6,20 +6,20 @@ class IIBBuildDetailsModel(object): def __init__(self, *args, **kwargs): self.data = {} - for attr, attr_val in zip(args, self._data_attrs): - self.data[attr_val] = attr + for attr_val, attr in zip(args, self._data_attrs): + self.data[attr] = attr_val for key, value in kwargs.items(): self.data[key] = value @classmethod def from_dict(cls, data): - if data['request_type'] == "add": + if data["request_type"] == "add": return AddModel._from_dict(data) - elif data['request_type'] == "rm": + elif data["request_type"] == "rm": return RmModel._from_dict(data) - elif data['request_type'] == "regenerate-bundle": + elif data["request_type"] == "regenerate-bundle": return RegenerateBundleModel._from_dict(data) - raise KeyError("Unsupported request type: %s" % data['request_type']) + raise KeyError("Unsupported request type: %s" % data["request_type"]) @classmethod def _from_dict(cls, data): @@ -46,24 +46,81 @@ def __eq__(self, other): class AddModel(IIBBuildDetailsModel): # TODO if there are always the same _data_attrs we can put it to the class _data_attrs - _data_attrs = ["id", "arches", "state", "state_reason", "request_type", "state_history", - "batch", "batch_annotations", "logs", "updated", "user"] - _kwattrs = ["binary_image", "binary_image_resolved", "bundles", "bundle_mapping", - "from_index", "from_index_resolved", "index_image", "removed_operators", - "organization", "omps_operator_version", "distribution_scope"] + _data_attrs = [ + "id", + "arches", + "state", + "state_reason", + "request_type", + "state_history", + "batch", + "batch_annotations", + "logs", + "updated", + "user", + ] + _kwattrs = [ + "binary_image", + "binary_image_resolved", + "bundles", + "bundle_mapping", + "from_index", + "from_index_resolved", + "index_image", + "removed_operators", + "organization", + "omps_operator_version", + "distribution_scope", + ] class RmModel(IIBBuildDetailsModel): - _data_attrs = ["arches", "id", "state", "state_reason", "request_type", "state_history", - "batch", "batch_annotations", "logs", "updated", "user"] - _kwattrs = ["binary_image", "binary_image_resolved", "bundles", "bundle_mapping", - "from_index", "from_index_resolved", "index_image", "removed_operators", - "organization", "distribution_scope"] + _data_attrs = [ + "id", + "arches", + "state", + "state_reason", + "request_type", + "state_history", + "batch", + "batch_annotations", + "logs", + "updated", + "user", + ] + _kwattrs = [ + "binary_image", + "binary_image_resolved", + "bundles", + "bundle_mapping", + "from_index", + "from_index_resolved", + "index_image", + "removed_operators", + "organization", + "distribution_scope", + ] class RegenerateBundleModel(IIBBuildDetailsModel): - _data_attrs = ["arches", "id", "state", "state_reason", "request_type", "state_history", - "batch", "batch_annotations", "logs", "updated", "user"] - _kwattrs = ["bundle_image", "from_bundle_image", "from_bundle_image_resolved", "organization"] + _data_attrs = [ + "id", + "arches", + "state", + "state_reason", + "request_type", + "state_history", + "batch", + "batch_annotations", + "logs", + "updated", + "user", + ] + _kwattrs = [ + "bundle_image", + "from_bundle_image", + "from_bundle_image_resolved", + "organization", + ] diff --git a/iiblib/iib_client.py b/iiblib/iib_client.py index 5a33231..c1b9a31 100644 --- a/iiblib/iib_client.py +++ b/iiblib/iib_client.py @@ -282,13 +282,13 @@ def wait_for_build(self, build): """ timeout = time.time() + self.wait_for_build_timeout while True: - build_details = self.get_build(build.id) - if build_details.state in ("complete", "failed"): + build_details = self.get_build(build.data["id"]) + if build_details.data["state"] in ("complete", "failed"): return build_details if time.time() >= timeout: raise IIBException( "Timeout reached. Build request %s was not processed in %d seconds." - % (build.id, self.wait_for_build_timeout), + % (build.data["id"], self.wait_for_build_timeout), ) time.sleep(self.poll_interval) diff --git a/tests/test_iib_build_details_model.py b/tests/test_iib_build_details_model.py index 4f6a493..77150b0 100644 --- a/tests/test_iib_build_details_model.py +++ b/tests/test_iib_build_details_model.py @@ -1,10 +1,15 @@ import pytest -from iiblib.iib_build_details_model import IIBBuildDetailsModel, AddModel +from iiblib.iib_build_details_model import ( + IIBBuildDetailsModel, + AddModel, + RmModel, + RegenerateBundleModel, +) @pytest.fixture -def fixture_add_build_details_model(): +def fixture_add_build_details_json(): json = { "id": 1, "arches": ["x86_64"], @@ -31,10 +36,11 @@ def fixture_add_build_details_model(): } return json + @pytest.fixture -def fixture_rm_build_details_model(): +def fixture_rm_build_details_json(): json = { - "id": 1, + "id": 2, "arches": ["x86_64"], "state": "in_progress", "state_reason": "state_reason", @@ -54,40 +60,34 @@ def fixture_rm_build_details_model(): "index_image": "index_image", "removed_operators": ["operator1"], "organization": "organization", - "omps_operator_version": {"operator": "1.0"}, "distribution_scope": "null", } return json + @pytest.fixture -def fixture_regenerate_bundle_build_details_model(): +def fixture_regenerate_bundle_build_details_json(): json = { - "id": 1, + "id": 3, + "arches": ["x86_64"], "state": "in_progress", "state_reason": "state_reason", - "state_history": [], - "from_index": "from_index", - "from_index_resolved": "from_index_resolved", - "bundles": ["bundles1"], - "removed_operators": ["operator1"], - "organization": "organization", - "binary_image": "binary_image", - "binary_image_resolved": "binary_image_resolved", - "index_image": "index_image", "request_type": "regenerate-bundle", - "arches": ["x86_64"], - "bundle_mapping": {"bundle_mapping": "map"}, - "omps_operator_version": {"operator": "1.0"}, + "state_history": [], "batch": 1, "batch_annotations": {"batch_annotations": 1}, "logs": {}, "updated": "updated", "user": "user@example.com", + "bundle_image": "bundle_image", + "from_bundle_image": "from_bundle_image", + "from_bundle_image_resolved": "from_bundle_image_resolved", + "organization": "organization", } return json -def test_iib_build_details_model_add_request_type(fixture_add_build_details_model): +def test_add_model(fixture_add_build_details_json): unexpected_model = AddModel( 1, ["x86_64"], @@ -100,17 +100,17 @@ def test_iib_build_details_model_add_request_type(fixture_add_build_details_mode {}, "updated", "user@example.com", - "binary_image", - "binary_image_resolved", - ["bundles1"], - {"bundle_mapping": "map"}, - "from_index", - "from_index_resolved", - "index_image", - ["operator1"], - "organization", - {"operator": "1.0"}, - "null", + binary_image="binary_image", + binary_image_resolved="binary_image_resolved", + bundles=["bundles1"], + bundle_mapping={"bundle_mapping": "map"}, + from_index="from_index", + from_index_resolved="from_index_resolved", + index_image="index_image", + removed_operators=["operator1"], + organization="organization", + omps_operator_version={"operator": "1.0"}, + distribution_scope="null", ) expected_model = AddModel( 1, @@ -124,22 +124,124 @@ def test_iib_build_details_model_add_request_type(fixture_add_build_details_mode {}, "updated", "user@example.com", - "binary_image", - "binary_image_resolved", - ["bundles1"], - {"bundle_mapping": "map"}, - "from_index", - "from_index_resolved", - "index_image", - ["operator1"], - "organization", - {"operator": "1.0"}, - "null", + binary_image="binary_image", + binary_image_resolved="binary_image_resolved", + bundles=["bundles1"], + bundle_mapping={"bundle_mapping": "map"}, + from_index="from_index", + from_index_resolved="from_index_resolved", + index_image="index_image", + removed_operators=["operator1"], + organization="organization", + omps_operator_version={"operator": "1.0"}, + distribution_scope="null", + ) + model = IIBBuildDetailsModel.from_dict(fixture_add_build_details_json) + assert model == expected_model + assert model != unexpected_model + + model = IIBBuildDetailsModel.from_dict(fixture_add_build_details_json).to_dict() + assert model == expected_model.to_dict() + assert model != unexpected_model.to_dict() + + +def test_rm_model(fixture_rm_build_details_json): + unexpected_model = RmModel( + 2, + ["x86_64"], + "finished", + "state_reason", + "rm", + [], + 1, + {"batch_annotations": 1}, + {}, + "updated", + "user@example.com", + binary_image="binary_image", + binary_image_resolved="binary_image_resolved", + bundles=["bundles1"], + bundle_mapping={"bundle_mapping": "map"}, + from_index="from_index", + from_index_resolved="from_index_resolved", + index_image="index_image", + removed_operators=["operator1"], + organization="organization", + distribution_scope="null", + ) + expected_model = RmModel( + 2, + ["x86_64"], + "in_progress", + "state_reason", + "rm", + [], + 1, + {"batch_annotations": 1}, + {}, + "updated", + "user@example.com", + binary_image="binary_image", + binary_image_resolved="binary_image_resolved", + bundles=["bundles1"], + bundle_mapping={"bundle_mapping": "map"}, + from_index="from_index", + from_index_resolved="from_index_resolved", + index_image="index_image", + removed_operators=["operator1"], + organization="organization", + distribution_scope="null", + ) + model = IIBBuildDetailsModel.from_dict(fixture_rm_build_details_json) + assert model == expected_model + assert model != unexpected_model + + model = IIBBuildDetailsModel.from_dict(fixture_rm_build_details_json).to_dict() + assert model == expected_model.to_dict() + assert model != unexpected_model.to_dict() + + +def test_regenerate_bundle_model(fixture_regenerate_bundle_build_details_json): + unexpected_model = RegenerateBundleModel( + 3, + ["x86_64"], + "finished", + "state_reason", + "regenerate-bundle", + [], + 1, + {"batch_annotations": 1}, + {}, + "updated", + "user@example.com", + bundle_image="bundle_image", + from_bundle_image="from_bundle_image", + from_bundle_image_resolved="from_bundle_image_resolved", + organization="organization", + ) + expected_model = RegenerateBundleModel( + 3, + ["x86_64"], + "in_progress", + "state_reason", + "regenerate-bundle", + [], + 1, + {"batch_annotations": 1}, + {}, + "updated", + "user@example.com", + bundle_image="bundle_image", + from_bundle_image="from_bundle_image", + from_bundle_image_resolved="from_bundle_image_resolved", + organization="organization", ) - model = IIBBuildDetailsModel.from_dict(fixture_add_build_details_model) + model = IIBBuildDetailsModel.from_dict(fixture_regenerate_bundle_build_details_json) assert model == expected_model assert model != unexpected_model - model = IIBBuildDetailsModel.from_dict(fixture_add_build_details_model).to_dict() + model = IIBBuildDetailsModel.from_dict( + fixture_regenerate_bundle_build_details_json + ).to_dict() assert model == expected_model.to_dict() assert model != unexpected_model.to_dict() diff --git a/tests/test_iib_build_details_pager.py b/tests/test_iib_build_details_pager.py index eb6271f..afe13b2 100644 --- a/tests/test_iib_build_details_pager.py +++ b/tests/test_iib_build_details_pager.py @@ -7,7 +7,7 @@ @pytest.fixture -def fixture_build_details_json(): +def fixture_add_build_details_json(): json = { "id": 1, "arches": ["x86_64"], @@ -30,12 +30,13 @@ def fixture_build_details_json(): "removed_operators": ["operator1"], "organization": "organization", "omps_operator_version": {"operator": "1.0"}, - "distribution_scope": "null" + "distribution_scope": "null", } return json + @pytest.fixture -def fixture_build_details_json2(): +def fixture_add_build_details_json2(): json = { "id": 2, "arches": ["x86_64"], @@ -58,15 +59,15 @@ def fixture_build_details_json2(): "removed_operators": ["operator1"], "organization": "organization", "omps_operator_version": {"operator": "1.0"}, - "distribution_scope": "null" + "distribution_scope": "null", } return json @pytest.fixture -def fixture_builds_page1_json(fixture_build_details_json): +def fixture_builds_page1_json(fixture_add_build_details_json): json = { - "items": [fixture_build_details_json], + "items": [fixture_add_build_details_json], "meta": { "first": "", "last": "", @@ -82,9 +83,9 @@ def fixture_builds_page1_json(fixture_build_details_json): @pytest.fixture -def fixture_builds_page2_json(fixture_build_details_json2): +def fixture_builds_page2_json(fixture_add_build_details_json2): json = { - "items": [fixture_build_details_json2], + "items": [fixture_add_build_details_json2], "meta": { "first": "", "last": "", @@ -102,8 +103,8 @@ def fixture_builds_page2_json(fixture_build_details_json2): def test_iib_build_details_pager( fixture_builds_page1_json, fixture_builds_page2_json, - fixture_build_details_json, - fixture_build_details_json2, + fixture_add_build_details_json, + fixture_add_build_details_json2, ): with requests_mock.Mocker() as m: m.register_uri( diff --git a/tests/test_iib_client.py b/tests/test_iib_client.py index 70d7d3f..1a4cba6 100644 --- a/tests/test_iib_client.py +++ b/tests/test_iib_client.py @@ -13,78 +13,88 @@ @pytest.fixture -def fixture_build_details_json(): +def fixture_add_build_details_json(): json = { "id": 1, + "arches": ["x86_64"], "state": "in_progress", "state_reason": "state_reason", + "request_type": "add", "state_history": [], + "batch": 1, + "batch_annotations": {"batch_annotations": 1}, + "logs": {}, + "updated": "updated", + "user": "user@example.com", + "binary_image": "binary_image", + "binary_image_resolved": "binary_image_resolved", + "bundles": ["bundles1"], + "bundle_mapping": {"bundle_mapping": "map"}, "from_index": "from_index", "from_index_resolved": "from_index_resolved", - "bundles": ["bundles1"], + "index_image": "index_image", "removed_operators": ["operator1"], "organization": "organization", - "binary_image": "binary_image", - "binary_image_resolved": "binary_image_resolved", - "index_image": "index_image", - "request_type": "request_type", - "arches": ["x86_64"], - "bundle_mapping": {"bundle_mapping": "map"}, "omps_operator_version": {"operator": "1.0"}, + "distribution_scope": "null", } return json @pytest.fixture -def fixture_build_details_json2(): +def fixture_rm_build_details_json(): json = { "id": 2, + "arches": ["x86_64"], "state": "in_progress", "state_reason": "state_reason", + "request_type": "rm", "state_history": [], + "batch": 1, + "batch_annotations": {"batch_annotations": 1}, + "logs": {}, + "updated": "updated", + "user": "user@example.com", + "binary_image": "binary_image", + "binary_image_resolved": "binary_image_resolved", + "bundles": ["bundles1"], + "bundle_mapping": {"bundle_mapping": "map"}, "from_index": "from_index", "from_index_resolved": "from_index_resolved", - "bundles": ["bundles1"], + "index_image": "index_image", "removed_operators": ["operator1"], "organization": "organization", - "binary_image": "binary_image", - "binary_image_resolved": "binary_image_resolved", - "index_image": "index_image", - "request_type": "request_type", - "arches": ["x86_64"], - "bundle_mapping": {"bundle_mapping": "map"}, - "omps_operator_version": {"operator": "1.0"}, + "distribution_scope": "null", } return json @pytest.fixture -def fixture_build_details_json3(): +def fixture_regenerate_bundle_build_details_json(): json = { - "id": 1, + "id": 3, + "arches": ["x86_64"], "state": "in_progress", "state_reason": "state_reason", + "request_type": "regenerate-bundle", "state_history": [], - "from_index": "from_index", - "from_index_resolved": "from_index_resolved", - "bundles": ["bundles1"], - "removed_operators": ["operator1"], + "batch": 1, + "batch_annotations": {"batch_annotations": 1}, + "logs": {}, + "updated": "updated", + "user": "user@example.com", + "bundle_image": "bundle_image", + "from_bundle_image": "from_bundle_image", + "from_bundle_image_resolved": "from_bundle_image_resolved", "organization": "organization", - "binary_image": "mapped_binary_image", - "binary_image_resolved": "mapped_binary_image_resolved", - "index_image": "index_image", - "request_type": "request_type", - "arches": ["x86_64"], - "bundle_mapping": {"bundle_mapping": "map"}, - "omps_operator_version": {"operator": "1.0"}, } return json @pytest.fixture -def fixture_builds_page1_json(fixture_build_details_json): +def fixture_builds_page1_json(fixture_add_build_details_json): json = { - "items": [fixture_build_details_json], + "items": [fixture_add_build_details_json], "meta": { "first": "", "last": "", @@ -100,9 +110,9 @@ def fixture_builds_page1_json(fixture_build_details_json): @pytest.fixture -def fixture_builds_page2_json(fixture_build_details_json2): +def fixture_builds_page2_json(fixture_rm_build_details_json): json = { - "items": [fixture_build_details_json2], + "items": [fixture_rm_build_details_json], "meta": { "first": "", "last": "", @@ -117,31 +127,59 @@ def fixture_builds_page2_json(fixture_build_details_json2): return json -def test_iib_client(fixture_build_details_json, fixture_builds_page1_json): +def test_iib_client( + fixture_add_build_details_json, + fixture_rm_build_details_json, + fixture_regenerate_bundle_build_details_json, + fixture_builds_page1_json, +): with requests_mock.Mocker() as m: m.register_uri( "POST", "/api/v1/builds/add", status_code=200, - json=fixture_build_details_json, + json=fixture_add_build_details_json, ) m.register_uri( "POST", "/api/v1/builds/rm", status_code=200, - json=fixture_build_details_json, + json=fixture_rm_build_details_json, + ) + # TODO add other request types + + m.register_uri( + "POST", + "/api/v1/builds/regenerate-bundle", + status_code=200, + json=fixture_regenerate_bundle_build_details_json, ) m.register_uri( "GET", "/api/v1/builds", status_code=200, json=fixture_builds_page1_json ) m.register_uri( - "GET", "/api/v1/builds/1", status_code=200, json=fixture_build_details_json + "GET", + "/api/v1/builds/1", + status_code=200, + json=fixture_add_build_details_json, + ) + m.register_uri( + "GET", + "/api/v1/builds/2", + status_code=200, + json=fixture_rm_build_details_json, + ) + m.register_uri( + "GET", + "/api/v1/builds/3", + status_code=200, + json=fixture_regenerate_bundle_build_details_json, ) iibc = IIBClient("fake-host") assert iibc.add_bundles( "index-image", ["bundles-map"], [], binary_image="binary" - ) == IIBBuildDetailsModel.from_dict(fixture_build_details_json) + ) == IIBBuildDetailsModel.from_dict(fixture_add_build_details_json) assert ( iibc.add_bundles( "index-image", @@ -153,13 +191,13 @@ def test_iib_client(fixture_build_details_json, fixture_builds_page1_json): overwrite_from_index=True, overwrite_from_index_token="str", ) - == IIBBuildDetailsModel.from_dict(fixture_build_details_json) + == IIBBuildDetailsModel.from_dict(fixture_add_build_details_json) ) assert ( iibc.add_bundles( "index-image", ["bundles-map"], [], binary_image="binary", raw=True ) - == fixture_build_details_json + == fixture_add_build_details_json ) assert ( iibc.remove_operators( @@ -170,18 +208,34 @@ def test_iib_client(fixture_build_details_json, fixture_builds_page1_json): overwrite_from_index=True, overwrite_from_index_token="str", ) - == IIBBuildDetailsModel.from_dict(fixture_build_details_json) + == IIBBuildDetailsModel.from_dict(fixture_rm_build_details_json) ) assert ( iibc.remove_operators( "index-image", ["operator1"], [], binary_image="binary", raw=True ) - == fixture_build_details_json + == fixture_rm_build_details_json ) + + # get_builds - request_type is "add" assert iibc.get_build(1) == IIBBuildDetailsModel.from_dict( - fixture_build_details_json + fixture_add_build_details_json + ) + assert iibc.get_build(1, raw=True) == fixture_add_build_details_json + + # get_builds - request_type is "rm" + assert iibc.get_build(2) == IIBBuildDetailsModel.from_dict( + fixture_rm_build_details_json + ) + assert iibc.get_build(2, raw=True) == fixture_rm_build_details_json + + # get_builds - request_type is "regenerate-bundle" + assert iibc.get_build(3) == IIBBuildDetailsModel.from_dict( + fixture_regenerate_bundle_build_details_json + ) + assert ( + iibc.get_build(3, raw=True) == fixture_regenerate_bundle_build_details_json ) - assert iibc.get_build(1, raw=True) == fixture_build_details_json assert iibc.get_builds() == IIBBuildDetailsPager.from_dict( iibc, fixture_builds_page1_json @@ -189,7 +243,9 @@ def test_iib_client(fixture_build_details_json, fixture_builds_page1_json): assert iibc.get_builds(raw=True) == fixture_builds_page1_json -def test_iib_client_failure(fixture_build_details_json): +def test_iib_client_no_overwrite_from_index_or_token( + fixture_add_build_details_json, fixture_rm_build_details_json +): error_msg = ( "Either both or neither of overwrite-from-index " "and overwrite-from-index-token should be specified." @@ -199,13 +255,13 @@ def test_iib_client_failure(fixture_build_details_json): "POST", "/api/v1/builds/add", status_code=200, - json=fixture_build_details_json, + json=fixture_add_build_details_json, ) m.register_uri( "POST", "/api/v1/builds/rm", status_code=200, - json=fixture_build_details_json, + json=fixture_rm_build_details_json, ) iibc = IIBClient("fake-host") with pytest.raises(ValueError, match=error_msg): @@ -246,71 +302,23 @@ def test_iib_client_failure(fixture_build_details_json): ) -def test_iib_client_no_binary_image(fixture_build_details_json3): - with requests_mock.Mocker() as m: - m.register_uri( - "POST", - "/api/v1/builds/add", - status_code=200, - json=fixture_build_details_json3, - ) - m.register_uri( - "POST", - "/api/v1/builds/rm", - status_code=200, - json=fixture_build_details_json3, - ) - - iibc = IIBClient("fake-host") - assert iibc.add_bundles( - "index-image", ["bundles-map"], [] - ) == IIBBuildDetailsModel.from_dict(fixture_build_details_json3) - assert ( - iibc.add_bundles( - "index-image", - ["bundles-map"], - [], - cnr_token="cnr", - organization="org", - overwrite_from_index=True, - overwrite_from_index_token="str", - ) - == IIBBuildDetailsModel.from_dict(fixture_build_details_json3) - ) - assert ( - iibc.add_bundles("index-image", ["bundles-map"], [], raw=True) - == fixture_build_details_json3 - ) - assert ( - iibc.remove_operators( - "index-image", - ["operator1"], - [], - overwrite_from_index=True, - overwrite_from_index_token="str", - ) - == IIBBuildDetailsModel.from_dict(fixture_build_details_json3) - ) - assert ( - iibc.remove_operators("index-image", ["operator1"], [], raw=True) - == fixture_build_details_json3 - ) - - -def test_client_wait_for_build(fixture_build_details_json): +# there add model used +def test_client_wait_for_build(fixture_add_build_details_json): iibc = IIBClient("fake-host", poll_interval=1) - bdetails_finished = copy.copy(fixture_build_details_json) + bdetails_finished = copy.copy(fixture_add_build_details_json) bdetails_finished["state"] = "complete" with requests_mock.Mocker() as m: m.register_uri( "GET", "/api/v1/builds/1", [ - {"json": fixture_build_details_json, "status_code": 200}, + {"json": fixture_add_build_details_json, "status_code": 200}, {"json": bdetails_finished, "status_code": 200}, ], ) - iibc.wait_for_build(IIBBuildDetailsModel.from_dict(fixture_build_details_json)) + iibc.wait_for_build( + IIBBuildDetailsModel.from_dict(fixture_add_build_details_json) + ) bdetails_finished["state"] = "failed" with requests_mock.Mocker() as m: @@ -318,37 +326,43 @@ def test_client_wait_for_build(fixture_build_details_json): "GET", "/api/v1/builds/1", [ - {"json": fixture_build_details_json, "status_code": 200}, + {"json": fixture_add_build_details_json, "status_code": 200}, {"json": bdetails_finished, "status_code": 200}, ], ) - iibc.wait_for_build(IIBBuildDetailsModel.from_dict(fixture_build_details_json)) + iibc.wait_for_build( + IIBBuildDetailsModel.from_dict(fixture_add_build_details_json) + ) -def test_client_wait_for_build_retry(fixture_build_details_json): +# add model used +def test_client_wait_for_build_retry(fixture_add_build_details_json): iibc = IIBClient("fake-host.test", poll_interval=1, retries=10, backoff_factor=0) with pytest.raises( requests.exceptions.RequestException, match=".*Max retries exceeded*." ): - iibc.wait_for_build(IIBBuildDetailsModel.from_dict(fixture_build_details_json)) + iibc.wait_for_build( + IIBBuildDetailsModel.from_dict(fixture_add_build_details_json) + ) -def test_client_wait_for_build_timeout(fixture_build_details_json): +# add model used +def test_client_wait_for_build_timeout(fixture_add_build_details_json): # set wait timeout for 2 seconds iibc = IIBClient("fake-host.test", poll_interval=1, wait_for_build_timeout=2) with requests_mock.Mocker() as m: m.register_uri( "GET", - "/api/v1/builds/{}".format(fixture_build_details_json["id"]), + "/api/v1/builds/{}".format(fixture_add_build_details_json["id"]), status_code=200, - json=fixture_build_details_json, + json=fixture_add_build_details_json, ) with pytest.raises(IIBException, match="Timeout*."): iibc.wait_for_build( - IIBBuildDetailsModel.from_dict(fixture_build_details_json) + IIBBuildDetailsModel.from_dict(fixture_add_build_details_json) ) From ffac7e289a495eb3be8837389c100f91377755b3 Mon Sep 17 00:00:00 2001 From: Pavlina Bortlova Date: Mon, 26 Oct 2020 14:43:41 +0100 Subject: [PATCH 3/3] Add properties for each model --- iiblib/iib_build_details_model.py | 198 +++++++++++++++++++++++------- 1 file changed, 157 insertions(+), 41 deletions(-) diff --git a/iiblib/iib_build_details_model.py b/iiblib/iib_build_details_model.py index d7eb52e..d8bacf6 100644 --- a/iiblib/iib_build_details_model.py +++ b/iiblib/iib_build_details_model.py @@ -1,7 +1,20 @@ class IIBBuildDetailsModel(object): """Model class handling data about index build task""" - _data_attrs = [] + _data_attrs = [ + "id", + "arches", + "state", + "state_reason", + "request_type", + "state_history", + "batch", + "batch_annotations", + "logs", + "updated", + "user" + ] + _kwattrs = [] def __init__(self, *args, **kwargs): @@ -42,23 +55,53 @@ def to_dict(self): def __eq__(self, other): return isinstance(other, IIBBuildDetailsModel) and self.data == other.data + @property + def id(self): + return self.data["id"] + + @property + def arches(self): + return self.data["arches"] + + @property + def state(self): + return self.data["state"] + + @property + def state_reason(self): + return self.data["state_reason"] + + @property + def request_type(self): + return self.data["request_type"] + + @property + def state_history(self): + return self.data["state_history"] + + @property + def batch(self): + return self.data["batch"] + + @property + def batch_annotations(self): + return self.data["batch_annotations"] + + @property + def logs(self): + return self.data["logs"] + + @property + def updated(self): + return self.data["updated"] + + @property + def user(self): + return self.data["user"] + class AddModel(IIBBuildDetailsModel): - # TODO if there are always the same _data_attrs we can put it to the class _data_attrs - _data_attrs = [ - "id", - "arches", - "state", - "state_reason", - "request_type", - "state_history", - "batch", - "batch_annotations", - "logs", - "updated", - "user", - ] _kwattrs = [ "binary_image", "binary_image_resolved", @@ -73,22 +116,53 @@ class AddModel(IIBBuildDetailsModel): "distribution_scope", ] + @property + def binary_image(self): + return self.data["binary_image"] + + @property + def binary_image_resolved(self): + return self.data["binary_image_resolved"] + + @property + def bundles(self): + return self.data["bundles"] + + @property + def bundle_mapping(self): + return self.data["bundle_mapping"] + + @property + def from_index(self): + return self.data["from_index"] + + @property + def from_index_resolved(self): + return self.data["from_index_resolved"] + + @property + def index_image(self): + return self.data["index_image"] + + @property + def removed_operators(self): + return self.data["removed_operators"] + + @property + def organization(self): + return self.data["organization"] + + @property + def omps_operator_version(self): + return self.data["omps_operator_version"] + + @property + def distribution_scope(self): + return self.data["distribution_scope"] + class RmModel(IIBBuildDetailsModel): - _data_attrs = [ - "id", - "arches", - "state", - "state_reason", - "request_type", - "state_history", - "batch", - "batch_annotations", - "logs", - "updated", - "user", - ] _kwattrs = [ "binary_image", "binary_image_resolved", @@ -102,25 +176,67 @@ class RmModel(IIBBuildDetailsModel): "distribution_scope", ] + @property + def binary_image(self): + return self.data["binary_image"] + + @property + def binary_image_resolved(self): + return self.data["binary_image_resolved"] + + @property + def bundles(self): + return self.data["bundles"] + + @property + def bundle_mapping(self): + return self.data["bundle_mapping"] + + @property + def from_index(self): + return self.data["from_index"] + + @property + def from_index_resolved(self): + return self.data["from_index_resolved"] + + @property + def index_image(self): + return self.data["index_image"] + + @property + def removed_operators(self): + return self.data["removed_operators"] + + @property + def organization(self): + return self.data["organization"] + + @property + def distribution_scope(self): + return self.data["distribution_scope"] + class RegenerateBundleModel(IIBBuildDetailsModel): - _data_attrs = [ - "id", - "arches", - "state", - "state_reason", - "request_type", - "state_history", - "batch", - "batch_annotations", - "logs", - "updated", - "user", - ] _kwattrs = [ "bundle_image", "from_bundle_image", "from_bundle_image_resolved", "organization", ] + @property + def bundle_image(self): + return self.data["bundle_image"] + + @property + def from_bundle_image(self): + return self.data["from_bundle_image"] + + @property + def from_bundle_image_resolved(self): + return self.data["from_bundle_image_resolved"] + + @property + def organization(self): + return self.data["organization"]