moto/tests/test_ecr/test_ecr_policy_validation.py
2021-10-18 19:44:29 +00:00

398 lines
12 KiB
Python

import json
import pytest
import sure # noqa # pylint: disable=unused-import
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
ex.code.should.equal(400)
ex.error_type.should.equal("InvalidParameterException")
ex.message.should.equal(
"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
ex.code.should.equal(400)
ex.error_type.should.equal("InvalidParameterException")
ex.message.should.equal(
"Invalid parameter at 'LifecyclePolicyText' failed to satisfy constraint: "
"'Lifecycle policy validation failure: "
'object has missing required properties (["rules"])\''
)
@pytest.mark.parametrize(
["rule", "rule_type"], [["not_dict", "string"]], ids=["not_dict"],
)
def test_validate_error_rule_type(rule, rule_type):
# given
# when
with pytest.raises(InvalidParameterException) as e:
validator = EcrLifecyclePolicyValidator(json.dumps({"rules": [rule]}))
validator.validate()
# then
ex = e.value
ex.code.should.equal(400)
ex.error_type.should.equal("InvalidParameterException")
ex.message.should.equal(
"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
ex.code.should.equal(400)
ex.error_type.should.equal("InvalidParameterException")
ex.message.should.equal(
"".join(
[
"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
ex.code.should.equal(400)
ex.error_type.should.equal("InvalidParameterException")
ex.message.should.equal(
"".join(
[
"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 "
f"(minimum: 1, found: 0)"
),
],
[
{
"tagStatus": "untagged",
"countType": "imageCountMoreThan",
"countNumber": -1,
},
(
"numeric instance is lower than the required minimum "
f"(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
ex.code.should.equal(400)
ex.error_type.should.equal("InvalidParameterException")
ex.message.should.equal(
"".join(
[
"Invalid parameter at 'LifecyclePolicyText' failed to satisfy constraint: "
"'Lifecycle policy validation failure: ",
error_msg,
]
)
)