From c51ff9bb5f39f15c09473b56948c44f819e37fb3 Mon Sep 17 00:00:00 2001 From: Jonas Date: Tue, 26 Jul 2022 03:26:30 +0200 Subject: [PATCH] IOT: fix increment policy version ids (#5296) --- moto/iot/models.py | 18 ++++++++++--- tests/test_iot/test_iot_policies.py | 39 +++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/moto/iot/models.py b/moto/iot/models.py index 46d37c62e..c3593cebc 100644 --- a/moto/iot/models.py +++ b/moto/iot/models.py @@ -216,6 +216,7 @@ class FakePolicy(BaseModel): self.arn = f"arn:aws:iot:{region_name}:{get_account_id()}:policy/{name}" self.default_version_id = default_version_id self.versions = [FakePolicyVersion(self.name, document, True, region_name)] + self._max_version_id = self.versions[0]._version_id def to_get_dict(self): return { @@ -238,16 +239,20 @@ class FakePolicy(BaseModel): class FakePolicyVersion(object): - def __init__(self, policy_name, document, is_default, region_name): + def __init__(self, policy_name, document, is_default, region_name, version_id=1): self.name = policy_name self.arn = f"arn:aws:iot:{region_name}:{get_account_id()}:policy/{policy_name}" self.document = document or {} self.is_default = is_default - self.version_id = "1" + self._version_id = version_id self.create_datetime = time.mktime(datetime(2015, 1, 1).timetuple()) self.last_modified_datetime = time.mktime(datetime(2015, 1, 2).timetuple()) + @property + def version_id(self): + return str(self._version_id) + def to_get_dict(self): return { "policyName": self.name, @@ -1047,11 +1052,16 @@ class IoTBackend(BaseBackend): raise ResourceNotFoundException() if len(policy.versions) >= 5: raise VersionsLimitExceededException(policy_name) + + policy._max_version_id += 1 version = FakePolicyVersion( - policy_name, policy_document, set_as_default, self.region_name + policy_name, + policy_document, + set_as_default, + self.region_name, + version_id=policy._max_version_id, ) policy.versions.append(version) - version.version_id = "{0}".format(len(policy.versions)) if set_as_default: self.set_default_policy_version(policy_name, version.version_id) return version diff --git a/tests/test_iot/test_iot_policies.py b/tests/test_iot/test_iot_policies.py index 662bce869..7021c701e 100644 --- a/tests/test_iot/test_iot_policies.py +++ b/tests/test_iot/test_iot_policies.py @@ -241,6 +241,45 @@ def test_policy_versions(iot_client): err["Message"].should.equal("Cannot delete the default version of a policy") +def test_policy_versions_increment_beyond_5(iot_client, policy): + """ + Version ids increment by one each time. + + Previously there was a bug where the version id was not incremented beyond 5. + This prevents a regression. + """ + policy_name = policy["policyName"] + + for v in range(2, 11): + new_version = iot_client.create_policy_version( + policyName=policy_name, + policyDocument=json.dumps({"version": f"version_{v}"}), + setAsDefault=True, + ) + new_version.should.have.key("policyVersionId").which.should.equal(str(v)) + iot_client.delete_policy_version( + policyName=policy_name, policyVersionId=str(v - 1) + ) + + +def test_policy_versions_increment_even_after_version_delete(iot_client, policy): + """Version ids increment even if the max version was deleted.""" + + policy_name = policy["policyName"] + + new_version = iot_client.create_policy_version( + policyName=policy_name, + policyDocument=json.dumps({"version": "version_2"}), + ) + new_version.should.have.key("policyVersionId").which.should.equal("2") + iot_client.delete_policy_version(policyName=policy_name, policyVersionId="2") + third_version = iot_client.create_policy_version( + policyName=policy_name, + policyDocument=json.dumps({"version": "version_3"}), + ) + third_version.should.have.key("policyVersionId").which.should.equal("3") + + def test_delete_policy_validation(iot_client): doc = """{ "Version": "2012-10-17",