moto/tests/test_ecr/test_ecr_policy_validation.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

378 lines
11 KiB
Python
Raw Permalink Normal View History

import json
import pytest
from moto.ecr.exceptions import InvalidParameterException
from moto.ecr.policy_validation import EcrLifecyclePolicyValidator
def test_validate():
# given
policy = {
"rules": [
{
"rulePriority": 1,
"description": "test policy",
"selection": {
"tagStatus": "untagged",
"countType": "imageCountMoreThan",
"countNumber": 30,
},
"action": {"type": "expire"},
},
{
"rulePriority": 2,
"description": "test policy",
"selection": {
"tagStatus": "tagged",
"tagPrefixList": ["3.9"],
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 30,
},
"action": {"type": "expire"},
},
]
}
# when/then
validator = EcrLifecyclePolicyValidator(json.dumps(policy))
validator.validate()
@pytest.mark.parametrize(
"policy",
[
"some invalid input",
[
{
"rulePriority": 1,
"description": "test policy",
"selection": {
"tagStatus": "untagged",
"countType": "imageCountMoreThan",
"countNumber": 30,
},
"action": {"type": "expire"},
}
],
],
ids=["not_json", "not_dict"],
)
def test_validate_error_parse(policy):
# given
# when
with pytest.raises(InvalidParameterException) as e:
validator = EcrLifecyclePolicyValidator(json.dumps(policy))
validator.validate()
# then
ex = e.value
assert ex.code == 400
assert ex.error_type == "InvalidParameterException"
assert (
ex.message
== "Invalid parameter at 'LifecyclePolicyText' failed to satisfy constraint: 'Lifecycle policy validation failure: Could not map policyString into LifecyclePolicy.'"
)
@pytest.mark.parametrize(
"policy",
[
{"no_rules": "test"},
{
"rules": {
"rulePriority": 1,
"description": "test policy",
"selection": {
"tagStatus": "untagged",
"countType": "imageCountMoreThan",
"countNumber": 30,
},
"action": {"type": "expire"},
},
},
],
ids=["no_rules", "not_list"],
)
def test_validate_error_extract_rules(policy):
# given
# when
with pytest.raises(InvalidParameterException) as e:
validator = EcrLifecyclePolicyValidator(json.dumps(policy))
validator.validate()
# then
ex = e.value
assert ex.code == 400
assert ex.error_type == "InvalidParameterException"
assert (
ex.message
== "Invalid parameter at 'LifecyclePolicyText' failed to satisfy constraint: 'Lifecycle policy validation failure: object has missing required properties ([\"rules\"])'"
)
@pytest.mark.parametrize("rule", ["not_dict"], ids=["not_dict"])
def test_validate_error_rule_type(rule):
# given
# when
with pytest.raises(InvalidParameterException) as e:
validator = EcrLifecyclePolicyValidator(json.dumps({"rules": [rule]}))
validator.validate()
# then
ex = e.value
assert ex.code == 400
assert ex.error_type == "InvalidParameterException"
assert ex.message == (
"Invalid parameter at 'LifecyclePolicyText' failed to satisfy constraint: "
"'Lifecycle policy validation failure: "
f'instance type ({type(rule)}) does not match any allowed primitive type (allowed: ["object"])\''
)
@pytest.mark.parametrize(
["rule", "error_msg"],
[
[
{
"description": "test policy",
"selection": {
"tagStatus": "untagged",
"countType": "imageCountMoreThan",
"countNumber": 30,
},
"action": {"type": "expire"},
},
'object has missing required properties (["rulePriority"])\'',
],
[
{
"rulePriority": 1,
"description": "test policy",
"action": {"type": "expire"},
},
'object has missing required properties (["selection"])\'',
],
[
{
"rulePriority": 1,
"description": "test policy",
"selection": {
"tagStatus": "untagged",
"countType": "imageCountMoreThan",
"countNumber": 30,
},
},
'object has missing required properties (["action"])\'',
],
[
{
"rulePriority": 1,
"selection": {
"tagStatus": "untagged",
"countType": "imageCountMoreThan",
"countNumber": 30,
},
"action": {"type": "expire"},
"unknown": 123,
},
'object instance has properties which are not allowed by the schema: (["unknown"])\'',
],
],
ids=["missing_rulePriority", "missing_selection", "missing_action", "unknown"],
)
def test_validate_error_rule_properties(rule, error_msg):
# given
# when
with pytest.raises(InvalidParameterException) as e:
validator = EcrLifecyclePolicyValidator(json.dumps({"rules": [rule]}))
validator.validate()
# then
ex = e.value
assert ex.code == 400
assert ex.error_type == "InvalidParameterException"
assert (
ex.message
== f"Invalid parameter at 'LifecyclePolicyText' failed to satisfy constraint: 'Lifecycle policy validation failure: {error_msg}"
)
@pytest.mark.parametrize(
["action", "error_msg"],
[
[{}, 'object has missing required properties (["type"])\''],
[
{"type": "expire", "unknown": 123},
(
"object instance has properties "
'which are not allowed by the schema: (["unknown"])\''
),
],
[
{"type": "keep"},
(
"instance value (keep) not found in enum "
':(possible values: ["expire"])\''
),
],
],
ids=["missing_type", "unknown", "unknown_type_value"],
)
def test_validate_error_action_properties(action, error_msg):
# given
# when
with pytest.raises(InvalidParameterException) as e:
validator = EcrLifecyclePolicyValidator(
json.dumps(
{
"rules": [
{
"rulePriority": 1,
"selection": {
"tagStatus": "untagged",
"countType": "imageCountMoreThan",
"countNumber": 30,
},
"action": action,
}
]
}
)
)
validator.validate()
# then
ex = e.value
assert ex.code == 400
assert ex.error_type == "InvalidParameterException"
assert (
ex.message
== f"Invalid parameter at 'LifecyclePolicyText' failed to satisfy constraint: 'Lifecycle policy validation failure: {error_msg}"
)
@pytest.mark.parametrize(
["selection", "error_msg"],
[
[
{"countType": "imageCountMoreThan", "countNumber": 30},
'object has missing required properties (["tagStatus"])\'',
],
[
{"tagStatus": "untagged", "countNumber": 30},
'object has missing required properties (["countType"])\'',
],
[
{"tagStatus": "untagged", "countType": "imageCountMoreThan"},
'object has missing required properties (["countNumber"])\'',
],
[
{
"tagStatus": "untagged",
"countType": "imageCountMoreThan",
"countNumber": 30,
"unknown": 123,
},
(
"object instance has properties "
'which are not allowed by the schema: (["unknown"])\''
),
],
[
{
"tagStatus": "unknown",
"countType": "imageCountMoreThan",
"countNumber": 30,
},
(
"instance value (unknown) not found in enum "
':(possible values: ["any", "tagged", "untagged"])\''
),
],
[
{"tagStatus": "untagged", "countType": "unknown", "countNumber": 30},
"instance failed to match exactly one schema (matched 0 out of 2)",
],
[
{
"tagStatus": "untagged",
"countType": "sinceImagePushed",
"countUnit": "unknown",
"countNumber": 30,
},
(
"instance value (unknown) not found in enum "
':(possible values: ["days"])\''
),
],
[
{
"tagStatus": "untagged",
"countType": "imageCountMoreThan",
"countNumber": 0,
},
(
"numeric instance is lower than the required minimum "
2022-04-27 11:58:59 +00:00
"(minimum: 1, found: 0)"
),
],
[
{
"tagStatus": "untagged",
"countType": "imageCountMoreThan",
"countNumber": -1,
},
(
"numeric instance is lower than the required minimum "
2022-04-27 11:58:59 +00:00
"(minimum: 1, found: -1)"
),
],
],
ids=[
"missing_tagStatus",
"missing_countType",
"missing_countNumber",
"unknown",
"unknown_tagStatus_value",
"unknown_countType_value",
"unknown_countUnit_value",
"zero_countNumber_value",
"negative_countNumber_value",
],
)
def test_validate_error_selection_properties(selection, error_msg):
# given
# when
with pytest.raises(InvalidParameterException) as e:
validator = EcrLifecyclePolicyValidator(
json.dumps(
{
"rules": [
{
"rulePriority": 1,
"selection": selection,
"action": {"type": "expire"},
}
]
}
)
)
validator.validate()
# then
ex = e.value
assert ex.code == 400
assert ex.error_type == "InvalidParameterException"
assert (
ex.message
== f"Invalid parameter at 'LifecyclePolicyText' failed to satisfy constraint: 'Lifecycle policy validation failure: {error_msg}"
)