Config - implement Organization Conformance Pack functionality (#3116)
* Add config.put_organization_conformance_pack * Add config.describe_organization_conformance_packs * Add config.get_organization_conformance_pack_detailed_status * Add config.describe_organization_conformance_pack_statuses * Add config.delete_organization_conformance_pack * Add an update method to OrganizationConformancePack
This commit is contained in:
parent
c5de56ce70
commit
55bb4eb08d
@ -376,3 +376,19 @@ class InvalidResultTokenException(JsonRESTError):
|
|||||||
super(InvalidResultTokenException, self).__init__(
|
super(InvalidResultTokenException, self).__init__(
|
||||||
"InvalidResultTokenException", message
|
"InvalidResultTokenException", message
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ValidationException(JsonRESTError):
|
||||||
|
code = 400
|
||||||
|
|
||||||
|
def __init__(self, message):
|
||||||
|
super(ValidationException, self).__init__("ValidationException", message)
|
||||||
|
|
||||||
|
|
||||||
|
class NoSuchOrganizationConformancePackException(JsonRESTError):
|
||||||
|
code = 400
|
||||||
|
|
||||||
|
def __init__(self, message):
|
||||||
|
super(NoSuchOrganizationConformancePackException, self).__init__(
|
||||||
|
"NoSuchOrganizationConformancePackException", message
|
||||||
|
)
|
||||||
|
@ -41,6 +41,8 @@ from moto.config.exceptions import (
|
|||||||
ResourceNotDiscoveredException,
|
ResourceNotDiscoveredException,
|
||||||
TooManyResourceKeys,
|
TooManyResourceKeys,
|
||||||
InvalidResultTokenException,
|
InvalidResultTokenException,
|
||||||
|
ValidationException,
|
||||||
|
NoSuchOrganizationConformancePackException,
|
||||||
)
|
)
|
||||||
|
|
||||||
from moto.core import BaseBackend, BaseModel
|
from moto.core import BaseBackend, BaseModel
|
||||||
@ -159,7 +161,8 @@ class ConfigEmptyDictable(BaseModel):
|
|||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
data = {}
|
data = {}
|
||||||
for item, value in self.__dict__.items():
|
for item, value in self.__dict__.items():
|
||||||
if value is not None:
|
# ignore private attributes
|
||||||
|
if not item.startswith("_") and value is not None:
|
||||||
if isinstance(value, ConfigEmptyDictable):
|
if isinstance(value, ConfigEmptyDictable):
|
||||||
data[
|
data[
|
||||||
snake_to_camels(
|
snake_to_camels(
|
||||||
@ -367,12 +370,56 @@ class ConfigAggregationAuthorization(ConfigEmptyDictable):
|
|||||||
self.tags = tags or {}
|
self.tags = tags or {}
|
||||||
|
|
||||||
|
|
||||||
|
class OrganizationConformancePack(ConfigEmptyDictable):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
region,
|
||||||
|
name,
|
||||||
|
delivery_s3_bucket,
|
||||||
|
delivery_s3_key_prefix=None,
|
||||||
|
input_parameters=None,
|
||||||
|
excluded_accounts=None,
|
||||||
|
):
|
||||||
|
super(OrganizationConformancePack, self).__init__(
|
||||||
|
capitalize_start=True, capitalize_arn=False
|
||||||
|
)
|
||||||
|
|
||||||
|
self._status = "CREATE_SUCCESSFUL"
|
||||||
|
self._unique_pack_name = "{0}-{1}".format(name, random_string())
|
||||||
|
|
||||||
|
self.conformance_pack_input_parameters = input_parameters or []
|
||||||
|
self.delivery_s3_bucket = delivery_s3_bucket
|
||||||
|
self.delivery_s3_key_prefix = delivery_s3_key_prefix
|
||||||
|
self.excluded_accounts = excluded_accounts or []
|
||||||
|
self.last_update_time = datetime2int(datetime.utcnow())
|
||||||
|
self.organization_conformance_pack_arn = "arn:aws:config:{0}:{1}:organization-conformance-pack/{2}".format(
|
||||||
|
region, DEFAULT_ACCOUNT_ID, self._unique_pack_name
|
||||||
|
)
|
||||||
|
self.organization_conformance_pack_name = name
|
||||||
|
|
||||||
|
def update(
|
||||||
|
self,
|
||||||
|
delivery_s3_bucket,
|
||||||
|
delivery_s3_key_prefix,
|
||||||
|
input_parameters,
|
||||||
|
excluded_accounts,
|
||||||
|
):
|
||||||
|
self._status = "UPDATE_SUCCESSFUL"
|
||||||
|
|
||||||
|
self.conformance_pack_input_parameters = input_parameters
|
||||||
|
self.delivery_s3_bucket = delivery_s3_bucket
|
||||||
|
self.delivery_s3_key_prefix = delivery_s3_key_prefix
|
||||||
|
self.excluded_accounts = excluded_accounts
|
||||||
|
self.last_update_time = datetime2int(datetime.utcnow())
|
||||||
|
|
||||||
|
|
||||||
class ConfigBackend(BaseBackend):
|
class ConfigBackend(BaseBackend):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.recorders = {}
|
self.recorders = {}
|
||||||
self.delivery_channels = {}
|
self.delivery_channels = {}
|
||||||
self.config_aggregators = {}
|
self.config_aggregators = {}
|
||||||
self.aggregation_authorizations = {}
|
self.aggregation_authorizations = {}
|
||||||
|
self.organization_conformance_packs = {}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _validate_resource_types(resource_list):
|
def _validate_resource_types(resource_list):
|
||||||
@ -1110,6 +1157,134 @@ class ConfigBackend(BaseBackend):
|
|||||||
"FailedEvaluations": [],
|
"FailedEvaluations": [],
|
||||||
} # At this time, moto is not adding failed evaluations.
|
} # At this time, moto is not adding failed evaluations.
|
||||||
|
|
||||||
|
def put_organization_conformance_pack(
|
||||||
|
self,
|
||||||
|
region,
|
||||||
|
name,
|
||||||
|
template_s3_uri,
|
||||||
|
template_body,
|
||||||
|
delivery_s3_bucket,
|
||||||
|
delivery_s3_key_prefix,
|
||||||
|
input_parameters,
|
||||||
|
excluded_accounts,
|
||||||
|
):
|
||||||
|
# a real validation of the content of the template is missing at the moment
|
||||||
|
if not template_s3_uri and not template_body:
|
||||||
|
raise ValidationException("Template body is invalid")
|
||||||
|
|
||||||
|
if not re.match(r"s3://.*", template_s3_uri):
|
||||||
|
raise ValidationException(
|
||||||
|
"1 validation error detected: "
|
||||||
|
"Value '{}' at 'templateS3Uri' failed to satisfy constraint: "
|
||||||
|
"Member must satisfy regular expression pattern: "
|
||||||
|
"s3://.*".format(template_s3_uri)
|
||||||
|
)
|
||||||
|
|
||||||
|
pack = self.organization_conformance_packs.get(name)
|
||||||
|
|
||||||
|
if pack:
|
||||||
|
pack.update(
|
||||||
|
delivery_s3_bucket=delivery_s3_bucket,
|
||||||
|
delivery_s3_key_prefix=delivery_s3_key_prefix,
|
||||||
|
input_parameters=input_parameters,
|
||||||
|
excluded_accounts=excluded_accounts,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
pack = OrganizationConformancePack(
|
||||||
|
region=region,
|
||||||
|
name=name,
|
||||||
|
delivery_s3_bucket=delivery_s3_bucket,
|
||||||
|
delivery_s3_key_prefix=delivery_s3_key_prefix,
|
||||||
|
input_parameters=input_parameters,
|
||||||
|
excluded_accounts=excluded_accounts,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.organization_conformance_packs[name] = pack
|
||||||
|
|
||||||
|
return {
|
||||||
|
"OrganizationConformancePackArn": pack.organization_conformance_pack_arn
|
||||||
|
}
|
||||||
|
|
||||||
|
def describe_organization_conformance_packs(self, names):
|
||||||
|
packs = []
|
||||||
|
|
||||||
|
for name in names:
|
||||||
|
pack = self.organization_conformance_packs.get(name)
|
||||||
|
|
||||||
|
if not pack:
|
||||||
|
raise NoSuchOrganizationConformancePackException(
|
||||||
|
"One or more organization conformance packs with specified names are not present. "
|
||||||
|
"Ensure your names are correct and try your request again later."
|
||||||
|
)
|
||||||
|
|
||||||
|
packs.append(pack.to_dict())
|
||||||
|
|
||||||
|
return {"OrganizationConformancePacks": packs}
|
||||||
|
|
||||||
|
def describe_organization_conformance_pack_statuses(self, names):
|
||||||
|
packs = []
|
||||||
|
statuses = []
|
||||||
|
|
||||||
|
if names:
|
||||||
|
for name in names:
|
||||||
|
pack = self.organization_conformance_packs.get(name)
|
||||||
|
|
||||||
|
if not pack:
|
||||||
|
raise NoSuchOrganizationConformancePackException(
|
||||||
|
"One or more organization conformance packs with specified names are not present. "
|
||||||
|
"Ensure your names are correct and try your request again later."
|
||||||
|
)
|
||||||
|
|
||||||
|
packs.append(pack)
|
||||||
|
else:
|
||||||
|
packs = list(self.organization_conformance_packs.values())
|
||||||
|
|
||||||
|
for pack in packs:
|
||||||
|
statuses.append(
|
||||||
|
{
|
||||||
|
"OrganizationConformancePackName": pack.organization_conformance_pack_name,
|
||||||
|
"Status": pack._status,
|
||||||
|
"LastUpdateTime": pack.last_update_time,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return {"OrganizationConformancePackStatuses": statuses}
|
||||||
|
|
||||||
|
def get_organization_conformance_pack_detailed_status(self, name):
|
||||||
|
pack = self.organization_conformance_packs.get(name)
|
||||||
|
|
||||||
|
if not pack:
|
||||||
|
raise NoSuchOrganizationConformancePackException(
|
||||||
|
"One or more organization conformance packs with specified names are not present. "
|
||||||
|
"Ensure your names are correct and try your request again later."
|
||||||
|
)
|
||||||
|
|
||||||
|
# actually here would be a list of all accounts in the organization
|
||||||
|
statuses = [
|
||||||
|
{
|
||||||
|
"AccountId": DEFAULT_ACCOUNT_ID,
|
||||||
|
"ConformancePackName": "OrgConformsPack-{0}".format(
|
||||||
|
pack._unique_pack_name
|
||||||
|
),
|
||||||
|
"Status": pack._status,
|
||||||
|
"LastUpdateTime": datetime2int(datetime.utcnow()),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
return {"OrganizationConformancePackDetailedStatuses": statuses}
|
||||||
|
|
||||||
|
def delete_organization_conformance_pack(self, name):
|
||||||
|
pack = self.organization_conformance_packs.get(name)
|
||||||
|
|
||||||
|
if not pack:
|
||||||
|
raise NoSuchOrganizationConformancePackException(
|
||||||
|
"Could not find an OrganizationConformancePack for given request with resourceName {}".format(
|
||||||
|
name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.organization_conformance_packs.pop(name)
|
||||||
|
|
||||||
|
|
||||||
config_backends = {}
|
config_backends = {}
|
||||||
for region in Session().get_available_regions("config"):
|
for region in Session().get_available_regions("config"):
|
||||||
|
@ -159,3 +159,46 @@ class ConfigResponse(BaseResponse):
|
|||||||
self._get_param("TestMode"),
|
self._get_param("TestMode"),
|
||||||
)
|
)
|
||||||
return json.dumps(evaluations)
|
return json.dumps(evaluations)
|
||||||
|
|
||||||
|
def put_organization_conformance_pack(self):
|
||||||
|
conformance_pack = self.config_backend.put_organization_conformance_pack(
|
||||||
|
region=self.region,
|
||||||
|
name=self._get_param("OrganizationConformancePackName"),
|
||||||
|
template_s3_uri=self._get_param("TemplateS3Uri"),
|
||||||
|
template_body=self._get_param("TemplateBody"),
|
||||||
|
delivery_s3_bucket=self._get_param("DeliveryS3Bucket"),
|
||||||
|
delivery_s3_key_prefix=self._get_param("DeliveryS3KeyPrefix"),
|
||||||
|
input_parameters=self._get_param("ConformancePackInputParameters"),
|
||||||
|
excluded_accounts=self._get_param("ExcludedAccounts"),
|
||||||
|
)
|
||||||
|
|
||||||
|
return json.dumps(conformance_pack)
|
||||||
|
|
||||||
|
def describe_organization_conformance_packs(self):
|
||||||
|
conformance_packs = self.config_backend.describe_organization_conformance_packs(
|
||||||
|
self._get_param("OrganizationConformancePackNames")
|
||||||
|
)
|
||||||
|
|
||||||
|
return json.dumps(conformance_packs)
|
||||||
|
|
||||||
|
def describe_organization_conformance_pack_statuses(self):
|
||||||
|
statuses = self.config_backend.describe_organization_conformance_pack_statuses(
|
||||||
|
self._get_param("OrganizationConformancePackNames")
|
||||||
|
)
|
||||||
|
|
||||||
|
return json.dumps(statuses)
|
||||||
|
|
||||||
|
def get_organization_conformance_pack_detailed_status(self):
|
||||||
|
# 'Filters' parameter is not implemented yet
|
||||||
|
statuses = self.config_backend.get_organization_conformance_pack_detailed_status(
|
||||||
|
self._get_param("OrganizationConformancePackName")
|
||||||
|
)
|
||||||
|
|
||||||
|
return json.dumps(statuses)
|
||||||
|
|
||||||
|
def delete_organization_conformance_pack(self):
|
||||||
|
self.config_backend.delete_organization_conformance_pack(
|
||||||
|
self._get_param("OrganizationConformancePackName")
|
||||||
|
)
|
||||||
|
|
||||||
|
return ""
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
import boto3
|
import boto3
|
||||||
@ -1874,3 +1875,314 @@ def test_put_evaluations():
|
|||||||
response.should.equal(
|
response.should.equal(
|
||||||
{"FailedEvaluations": [], "ResponseMetadata": {"HTTPStatusCode": 200,},}
|
{"FailedEvaluations": [], "ResponseMetadata": {"HTTPStatusCode": 200,},}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_config
|
||||||
|
def test_put_organization_conformance_pack():
|
||||||
|
# given
|
||||||
|
client = boto3.client("config", region_name="us-east-1")
|
||||||
|
|
||||||
|
# when
|
||||||
|
response = client.put_organization_conformance_pack(
|
||||||
|
DeliveryS3Bucket="awsconfigconforms-test-bucket",
|
||||||
|
OrganizationConformancePackName="test-pack",
|
||||||
|
TemplateS3Uri="s3://test-bucket/test-pack.yaml",
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
arn = response["OrganizationConformancePackArn"]
|
||||||
|
arn.should.match(
|
||||||
|
r"arn:aws:config:us-east-1:\d{12}:organization-conformance-pack/test-pack-\w{8}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# putting an organization conformance pack with the same name should result in an update
|
||||||
|
# when
|
||||||
|
response = client.put_organization_conformance_pack(
|
||||||
|
DeliveryS3Bucket="awsconfigconforms-test-bucket",
|
||||||
|
OrganizationConformancePackName="test-pack",
|
||||||
|
TemplateS3Uri="s3://test-bucket/test-pack-2.yaml",
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
response["OrganizationConformancePackArn"].should.equal(arn)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_config
|
||||||
|
def test_put_organization_conformance_pack_errors():
|
||||||
|
# given
|
||||||
|
client = boto3.client("config", region_name="us-east-1")
|
||||||
|
|
||||||
|
# when
|
||||||
|
with assert_raises(ClientError) as e:
|
||||||
|
client.put_organization_conformance_pack(
|
||||||
|
DeliveryS3Bucket="awsconfigconforms-test-bucket",
|
||||||
|
OrganizationConformancePackName="test-pack",
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
ex = e.exception
|
||||||
|
ex.operation_name.should.equal("PutOrganizationConformancePack")
|
||||||
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||||
|
ex.response["Error"]["Code"].should.contain("ValidationException")
|
||||||
|
ex.response["Error"]["Message"].should.equal("Template body is invalid")
|
||||||
|
|
||||||
|
# when
|
||||||
|
with assert_raises(ClientError) as e:
|
||||||
|
client.put_organization_conformance_pack(
|
||||||
|
DeliveryS3Bucket="awsconfigconforms-test-bucket",
|
||||||
|
OrganizationConformancePackName="test-pack",
|
||||||
|
TemplateS3Uri="invalid-s3-uri",
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
ex = e.exception
|
||||||
|
ex.operation_name.should.equal("PutOrganizationConformancePack")
|
||||||
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||||
|
ex.response["Error"]["Code"].should.contain("ValidationException")
|
||||||
|
ex.response["Error"]["Message"].should.equal(
|
||||||
|
"1 validation error detected: "
|
||||||
|
"Value 'invalid-s3-uri' at 'templateS3Uri' failed to satisfy constraint: "
|
||||||
|
"Member must satisfy regular expression pattern: "
|
||||||
|
"s3://.*"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_config
|
||||||
|
def test_describe_organization_conformance_packs():
|
||||||
|
# given
|
||||||
|
client = boto3.client("config", region_name="us-east-1")
|
||||||
|
arn = client.put_organization_conformance_pack(
|
||||||
|
DeliveryS3Bucket="awsconfigconforms-test-bucket",
|
||||||
|
OrganizationConformancePackName="test-pack",
|
||||||
|
TemplateS3Uri="s3://test-bucket/test-pack.yaml",
|
||||||
|
)["OrganizationConformancePackArn"]
|
||||||
|
|
||||||
|
# when
|
||||||
|
response = client.describe_organization_conformance_packs(
|
||||||
|
OrganizationConformancePackNames=["test-pack"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
response["OrganizationConformancePacks"].should.have.length_of(1)
|
||||||
|
pack = response["OrganizationConformancePacks"][0]
|
||||||
|
pack["OrganizationConformancePackName"].should.equal("test-pack")
|
||||||
|
pack["OrganizationConformancePackArn"].should.equal(arn)
|
||||||
|
pack["DeliveryS3Bucket"].should.equal("awsconfigconforms-test-bucket")
|
||||||
|
pack["ConformancePackInputParameters"].should.have.length_of(0)
|
||||||
|
pack["ExcludedAccounts"].should.have.length_of(0)
|
||||||
|
pack["LastUpdateTime"].should.be.a("datetime.datetime")
|
||||||
|
|
||||||
|
|
||||||
|
@mock_config
|
||||||
|
def test_describe_organization_conformance_packs_errors():
|
||||||
|
# given
|
||||||
|
client = boto3.client("config", region_name="us-east-1")
|
||||||
|
|
||||||
|
# when
|
||||||
|
with assert_raises(ClientError) as e:
|
||||||
|
client.describe_organization_conformance_packs(
|
||||||
|
OrganizationConformancePackNames=["not-existing"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
ex = e.exception
|
||||||
|
ex.operation_name.should.equal("DescribeOrganizationConformancePacks")
|
||||||
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||||
|
ex.response["Error"]["Code"].should.contain(
|
||||||
|
"NoSuchOrganizationConformancePackException"
|
||||||
|
)
|
||||||
|
ex.response["Error"]["Message"].should.equal(
|
||||||
|
"One or more organization conformance packs with specified names are not present. "
|
||||||
|
"Ensure your names are correct and try your request again later."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_config
|
||||||
|
def test_describe_organization_conformance_pack_statuses():
|
||||||
|
# given
|
||||||
|
client = boto3.client("config", region_name="us-east-1")
|
||||||
|
arn = client.put_organization_conformance_pack(
|
||||||
|
DeliveryS3Bucket="awsconfigconforms-test-bucket",
|
||||||
|
OrganizationConformancePackName="test-pack",
|
||||||
|
TemplateS3Uri="s3://test-bucket/test-pack.yaml",
|
||||||
|
)["OrganizationConformancePackArn"]
|
||||||
|
|
||||||
|
# when
|
||||||
|
response = client.describe_organization_conformance_pack_statuses(
|
||||||
|
OrganizationConformancePackNames=["test-pack"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
response["OrganizationConformancePackStatuses"].should.have.length_of(1)
|
||||||
|
status = response["OrganizationConformancePackStatuses"][0]
|
||||||
|
status["OrganizationConformancePackName"].should.equal("test-pack")
|
||||||
|
status["Status"].should.equal("CREATE_SUCCESSFUL")
|
||||||
|
update_time = status["LastUpdateTime"]
|
||||||
|
update_time.should.be.a("datetime.datetime")
|
||||||
|
|
||||||
|
# when
|
||||||
|
response = client.describe_organization_conformance_pack_statuses()
|
||||||
|
|
||||||
|
# then
|
||||||
|
response["OrganizationConformancePackStatuses"].should.have.length_of(1)
|
||||||
|
status = response["OrganizationConformancePackStatuses"][0]
|
||||||
|
status["OrganizationConformancePackName"].should.equal("test-pack")
|
||||||
|
status["Status"].should.equal("CREATE_SUCCESSFUL")
|
||||||
|
status["LastUpdateTime"].should.equal(update_time)
|
||||||
|
|
||||||
|
# when
|
||||||
|
time.sleep(1)
|
||||||
|
client.put_organization_conformance_pack(
|
||||||
|
DeliveryS3Bucket="awsconfigconforms-test-bucket",
|
||||||
|
OrganizationConformancePackName="test-pack",
|
||||||
|
TemplateS3Uri="s3://test-bucket/test-pack-2.yaml",
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
response = client.describe_organization_conformance_pack_statuses(
|
||||||
|
OrganizationConformancePackNames=["test-pack"]
|
||||||
|
)
|
||||||
|
response["OrganizationConformancePackStatuses"].should.have.length_of(1)
|
||||||
|
status = response["OrganizationConformancePackStatuses"][0]
|
||||||
|
status["OrganizationConformancePackName"].should.equal("test-pack")
|
||||||
|
status["Status"].should.equal("UPDATE_SUCCESSFUL")
|
||||||
|
status["LastUpdateTime"].should.be.greater_than(update_time)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_config
|
||||||
|
def test_describe_organization_conformance_pack_statuses_errors():
|
||||||
|
# given
|
||||||
|
client = boto3.client("config", region_name="us-east-1")
|
||||||
|
|
||||||
|
# when
|
||||||
|
with assert_raises(ClientError) as e:
|
||||||
|
client.describe_organization_conformance_pack_statuses(
|
||||||
|
OrganizationConformancePackNames=["not-existing"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
ex = e.exception
|
||||||
|
ex.operation_name.should.equal("DescribeOrganizationConformancePackStatuses")
|
||||||
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||||
|
ex.response["Error"]["Code"].should.contain(
|
||||||
|
"NoSuchOrganizationConformancePackException"
|
||||||
|
)
|
||||||
|
ex.response["Error"]["Message"].should.equal(
|
||||||
|
"One or more organization conformance packs with specified names are not present. "
|
||||||
|
"Ensure your names are correct and try your request again later."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_config
|
||||||
|
def test_get_organization_conformance_pack_detailed_status():
|
||||||
|
# given
|
||||||
|
client = boto3.client("config", region_name="us-east-1")
|
||||||
|
arn = client.put_organization_conformance_pack(
|
||||||
|
DeliveryS3Bucket="awsconfigconforms-test-bucket",
|
||||||
|
OrganizationConformancePackName="test-pack",
|
||||||
|
TemplateS3Uri="s3://test-bucket/test-pack.yaml",
|
||||||
|
)["OrganizationConformancePackArn"]
|
||||||
|
|
||||||
|
# when
|
||||||
|
response = client.get_organization_conformance_pack_detailed_status(
|
||||||
|
OrganizationConformancePackName="test-pack"
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
response["OrganizationConformancePackDetailedStatuses"].should.have.length_of(1)
|
||||||
|
status = response["OrganizationConformancePackDetailedStatuses"][0]
|
||||||
|
status["AccountId"].should.equal(ACCOUNT_ID)
|
||||||
|
status["ConformancePackName"].should.equal(
|
||||||
|
"OrgConformsPack-{}".format(arn[arn.rfind("/") + 1 :])
|
||||||
|
)
|
||||||
|
status["Status"].should.equal("CREATE_SUCCESSFUL")
|
||||||
|
update_time = status["LastUpdateTime"]
|
||||||
|
update_time.should.be.a("datetime.datetime")
|
||||||
|
|
||||||
|
# when
|
||||||
|
time.sleep(1)
|
||||||
|
client.put_organization_conformance_pack(
|
||||||
|
DeliveryS3Bucket="awsconfigconforms-test-bucket",
|
||||||
|
OrganizationConformancePackName="test-pack",
|
||||||
|
TemplateS3Uri="s3://test-bucket/test-pack-2.yaml",
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
response = client.get_organization_conformance_pack_detailed_status(
|
||||||
|
OrganizationConformancePackName="test-pack"
|
||||||
|
)
|
||||||
|
response["OrganizationConformancePackDetailedStatuses"].should.have.length_of(1)
|
||||||
|
status = response["OrganizationConformancePackDetailedStatuses"][0]
|
||||||
|
status["AccountId"].should.equal(ACCOUNT_ID)
|
||||||
|
status["ConformancePackName"].should.equal(
|
||||||
|
"OrgConformsPack-{}".format(arn[arn.rfind("/") + 1 :])
|
||||||
|
)
|
||||||
|
status["Status"].should.equal("UPDATE_SUCCESSFUL")
|
||||||
|
status["LastUpdateTime"].should.be.greater_than(update_time)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_config
|
||||||
|
def test_get_organization_conformance_pack_detailed_status_errors():
|
||||||
|
# given
|
||||||
|
client = boto3.client("config", region_name="us-east-1")
|
||||||
|
|
||||||
|
# when
|
||||||
|
with assert_raises(ClientError) as e:
|
||||||
|
client.get_organization_conformance_pack_detailed_status(
|
||||||
|
OrganizationConformancePackName="not-existing"
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
ex = e.exception
|
||||||
|
ex.operation_name.should.equal("GetOrganizationConformancePackDetailedStatus")
|
||||||
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||||
|
ex.response["Error"]["Code"].should.contain(
|
||||||
|
"NoSuchOrganizationConformancePackException"
|
||||||
|
)
|
||||||
|
ex.response["Error"]["Message"].should.equal(
|
||||||
|
"One or more organization conformance packs with specified names are not present. "
|
||||||
|
"Ensure your names are correct and try your request again later."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_config
|
||||||
|
def test_delete_organization_conformance_pack():
|
||||||
|
# given
|
||||||
|
client = boto3.client("config", region_name="us-east-1")
|
||||||
|
arn = client.put_organization_conformance_pack(
|
||||||
|
DeliveryS3Bucket="awsconfigconforms-test-bucket",
|
||||||
|
OrganizationConformancePackName="test-pack",
|
||||||
|
TemplateS3Uri="s3://test-bucket/test-pack.yaml",
|
||||||
|
)["OrganizationConformancePackArn"]
|
||||||
|
|
||||||
|
# when
|
||||||
|
response = client.delete_organization_conformance_pack(
|
||||||
|
OrganizationConformancePackName="test-pack"
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
response = client.describe_organization_conformance_pack_statuses()
|
||||||
|
response["OrganizationConformancePackStatuses"].should.have.length_of(0)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_config
|
||||||
|
def test_delete_organization_conformance_pack_errors():
|
||||||
|
# given
|
||||||
|
client = boto3.client("config", region_name="us-east-1")
|
||||||
|
|
||||||
|
# when
|
||||||
|
with assert_raises(ClientError) as e:
|
||||||
|
client.delete_organization_conformance_pack(
|
||||||
|
OrganizationConformancePackName="not-existing"
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
ex = e.exception
|
||||||
|
ex.operation_name.should.equal("DeleteOrganizationConformancePack")
|
||||||
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||||
|
ex.response["Error"]["Code"].should.contain(
|
||||||
|
"NoSuchOrganizationConformancePackException"
|
||||||
|
)
|
||||||
|
ex.response["Error"]["Message"].should.equal(
|
||||||
|
"Could not find an OrganizationConformancePack for given request with resourceName not-existing"
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user