Skip to content

Commit

Permalink
Separate S3Control methods from S3 (#4745)
Browse files Browse the repository at this point in the history
  • Loading branch information
bblommers authored Jan 18, 2022
1 parent 9c8744f commit 6610862
Show file tree
Hide file tree
Showing 20 changed files with 953 additions and 659 deletions.
64 changes: 63 additions & 1 deletion IMPLEMENTATION_COVERAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4318,6 +4318,69 @@
- [ ] write_get_object_response
</details>

## s3control
<details>
<summary>5% implemented</summary>

- [ ] create_access_point
- [ ] create_access_point_for_object_lambda
- [ ] create_bucket
- [ ] create_job
- [ ] create_multi_region_access_point
- [ ] delete_access_point
- [ ] delete_access_point_for_object_lambda
- [ ] delete_access_point_policy
- [ ] delete_access_point_policy_for_object_lambda
- [ ] delete_bucket
- [ ] delete_bucket_lifecycle_configuration
- [ ] delete_bucket_policy
- [ ] delete_bucket_tagging
- [ ] delete_job_tagging
- [ ] delete_multi_region_access_point
- [X] delete_public_access_block
- [ ] delete_storage_lens_configuration
- [ ] delete_storage_lens_configuration_tagging
- [ ] describe_job
- [ ] describe_multi_region_access_point_operation
- [ ] get_access_point
- [ ] get_access_point_configuration_for_object_lambda
- [ ] get_access_point_for_object_lambda
- [ ] get_access_point_policy
- [ ] get_access_point_policy_for_object_lambda
- [ ] get_access_point_policy_status
- [ ] get_access_point_policy_status_for_object_lambda
- [ ] get_bucket
- [ ] get_bucket_lifecycle_configuration
- [ ] get_bucket_policy
- [ ] get_bucket_tagging
- [ ] get_job_tagging
- [ ] get_multi_region_access_point
- [ ] get_multi_region_access_point_policy
- [ ] get_multi_region_access_point_policy_status
- [X] get_public_access_block
- [ ] get_storage_lens_configuration
- [ ] get_storage_lens_configuration_tagging
- [ ] list_access_points
- [ ] list_access_points_for_object_lambda
- [ ] list_jobs
- [ ] list_multi_region_access_points
- [ ] list_regional_buckets
- [ ] list_storage_lens_configurations
- [ ] put_access_point_configuration_for_object_lambda
- [ ] put_access_point_policy
- [ ] put_access_point_policy_for_object_lambda
- [ ] put_bucket_lifecycle_configuration
- [ ] put_bucket_policy
- [ ] put_bucket_tagging
- [ ] put_job_tagging
- [ ] put_multi_region_access_point_policy
- [X] put_public_access_block
- [ ] put_storage_lens_configuration
- [ ] put_storage_lens_configuration_tagging
- [ ] update_job_priority
- [ ] update_job_status
</details>

## sagemaker
<details>
<summary>15% implemented</summary>
Expand Down Expand Up @@ -5343,7 +5406,6 @@
- route53-recovery-readiness
- route53domains
- rum
- s3control
- s3outposts
- sagemaker-a2i-runtime
- sagemaker-edge
Expand Down
87 changes: 87 additions & 0 deletions docs/docs/services/s3control.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
.. _implementedservice_s3control:

.. |start-h3| raw:: html

<h3>

.. |end-h3| raw:: html

</h3>

=========
s3control
=========

.. autoclass:: moto.s3control.models.S3ControlBackend

|start-h3| Example usage |end-h3|

.. sourcecode:: python

@mock_s3control
def test_s3control_behaviour:
boto3.client("s3control")
...



|start-h3| Implemented features for this service |end-h3|

- [ ] create_access_point
- [ ] create_access_point_for_object_lambda
- [ ] create_bucket
- [ ] create_job
- [ ] create_multi_region_access_point
- [ ] delete_access_point
- [ ] delete_access_point_for_object_lambda
- [ ] delete_access_point_policy
- [ ] delete_access_point_policy_for_object_lambda
- [ ] delete_bucket
- [ ] delete_bucket_lifecycle_configuration
- [ ] delete_bucket_policy
- [ ] delete_bucket_tagging
- [ ] delete_job_tagging
- [ ] delete_multi_region_access_point
- [X] delete_public_access_block
- [ ] delete_storage_lens_configuration
- [ ] delete_storage_lens_configuration_tagging
- [ ] describe_job
- [ ] describe_multi_region_access_point_operation
- [ ] get_access_point
- [ ] get_access_point_configuration_for_object_lambda
- [ ] get_access_point_for_object_lambda
- [ ] get_access_point_policy
- [ ] get_access_point_policy_for_object_lambda
- [ ] get_access_point_policy_status
- [ ] get_access_point_policy_status_for_object_lambda
- [ ] get_bucket
- [ ] get_bucket_lifecycle_configuration
- [ ] get_bucket_policy
- [ ] get_bucket_tagging
- [ ] get_job_tagging
- [ ] get_multi_region_access_point
- [ ] get_multi_region_access_point_policy
- [ ] get_multi_region_access_point_policy_status
- [X] get_public_access_block
- [ ] get_storage_lens_configuration
- [ ] get_storage_lens_configuration_tagging
- [ ] list_access_points
- [ ] list_access_points_for_object_lambda
- [ ] list_jobs
- [ ] list_multi_region_access_points
- [ ] list_regional_buckets
- [ ] list_storage_lens_configurations
- [ ] put_access_point_configuration_for_object_lambda
- [ ] put_access_point_policy
- [ ] put_access_point_policy_for_object_lambda
- [ ] put_bucket_lifecycle_configuration
- [ ] put_bucket_policy
- [ ] put_bucket_tagging
- [ ] put_job_tagging
- [ ] put_multi_region_access_point_policy
- [X] put_public_access_block
- [ ] put_storage_lens_configuration
- [ ] put_storage_lens_configuration_tagging
- [ ] update_job_priority
- [ ] update_job_status

1 change: 1 addition & 0 deletions moto/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ def f(*args, **kwargs):
".route53resolver", "mock_route53resolver", boto3_name="route53resolver"
)
mock_s3 = lazy_load(".s3", "mock_s3")
mock_s3control = lazy_load(".s3control", "mock_s3control")
mock_sagemaker = lazy_load(".sagemaker", "mock_sagemaker")
mock_secretsmanager = lazy_load(".secretsmanager", "mock_secretsmanager")
mock_ses = lazy_load(".ses", "mock_ses")
Expand Down
8 changes: 6 additions & 2 deletions moto/backend_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,17 @@
"route53resolver",
re.compile("https?://route53resolver\\.(.+)\\.amazonaws\\.com"),
),
("s3", re.compile("https?://s3(.*)\\.amazonaws.com")),
("s3", re.compile("https?://s3(?!-control)(.*)\\.amazonaws.com")),
(
"s3",
re.compile(
"https?://(?P<bucket_name>[a-zA-Z0-9\\-_.]*)\\.?s3(.*)\\.amazonaws.com"
"https?://(?P<bucket_name>[a-zA-Z0-9\\-_.]*)\\.?s3(?!-control)(.*)\\.amazonaws.com"
),
),
(
"s3control",
re.compile("https?://([0-9]+)\\.s3-control\\.(.+)\\.amazonaws\\.com"),
),
("sagemaker", re.compile("https?://api.sagemaker\\.(.+)\\.amazonaws.com")),
("sdb", re.compile("https?://sdb\\.(.+)\\.amazonaws\\.com")),
("secretsmanager", re.compile("https?://secretsmanager\\.(.+)\\.amazonaws\\.com")),
Expand Down
3 changes: 2 additions & 1 deletion moto/config/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@
from moto.core.responses import AWSServiceSpec
from moto.core.utils import BackendDict
from moto.iam.config import role_config_query, policy_config_query
from moto.s3.config import s3_account_public_access_block_query, s3_config_query
from moto.s3.config import s3_config_query
from moto.s3control.config import s3_account_public_access_block_query
from moto.utilities.utils import load_resource


Expand Down
148 changes: 0 additions & 148 deletions moto/s3/config.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import datetime
import json
import time

from boto3 import Session

from moto.core.exceptions import InvalidNextTokenException
from moto.core.models import ConfigQueryModel
from moto.s3 import s3_backends
from moto.s3.models import get_moto_s3_account_id


class S3ConfigQuery(ConfigQueryModel):
Expand Down Expand Up @@ -124,147 +119,4 @@ def get_config_resource(
return config_data


class S3AccountPublicAccessBlockConfigQuery(ConfigQueryModel):
def list_config_service_resources(
self,
resource_ids,
resource_name,
limit,
next_token,
backend_region=None,
resource_region=None,
aggregator=None,
):
# For the Account Public Access Block, they are the same for all regions. The resource ID is the AWS account ID
# There is no resource name -- it should be a blank string "" if provided.

# The resource name can only ever be None or an empty string:
if resource_name is not None and resource_name != "":
return [], None

pab = None
account_id = get_moto_s3_account_id()
regions = [region for region in Session().get_available_regions("config")]

# If a resource ID was passed in, then filter accordingly:
if resource_ids:
for resource_id in resource_ids:
if account_id == resource_id:
pab = self.backends["global"].account_public_access_block
break

# Otherwise, just grab the one from the backend:
if not resource_ids:
pab = self.backends["global"].account_public_access_block

# If it's not present, then return nothing
if not pab:
return [], None

# Filter on regions (and paginate on them as well):
if backend_region:
pab_list = [backend_region]
elif resource_region:
# Invalid region?
if resource_region not in regions:
return [], None

pab_list = [resource_region]

# Aggregated query where no regions were supplied so return them all:
else:
pab_list = regions

# Pagination logic:
sorted_regions = sorted(pab_list)
new_token = None

# Get the start:
if not next_token:
start = 0
else:
# Tokens for this moto feature is just the region-name:
# For OTHER non-global resource types, it's the region concatenated with the resource ID.
if next_token not in sorted_regions:
raise InvalidNextTokenException()

start = sorted_regions.index(next_token)

# Get the list of items to collect:
pab_list = sorted_regions[start : (start + limit)]

if len(sorted_regions) > (start + limit):
new_token = sorted_regions[start + limit]

return (
[
{
"type": "AWS::S3::AccountPublicAccessBlock",
"id": account_id,
"region": region,
}
for region in pab_list
],
new_token,
)

def get_config_resource(
self, resource_id, resource_name=None, backend_region=None, resource_region=None
):
# Do we even have this defined?
if not self.backends["global"].account_public_access_block:
return None

# Resource name can only ever be "" if it's supplied:
if resource_name is not None and resource_name != "":
return None

# Are we filtering based on region?
account_id = get_moto_s3_account_id()
regions = [region for region in Session().get_available_regions("config")]

# Is the resource ID correct?:
if account_id == resource_id:
if backend_region:
pab_region = backend_region

# Invalid region?
elif resource_region not in regions:
return None

else:
pab_region = resource_region

else:
return None

# Format the PAB to the AWS Config format:
creation_time = datetime.datetime.utcnow()
config_data = {
"version": "1.3",
"accountId": account_id,
"configurationItemCaptureTime": str(creation_time),
"configurationItemStatus": "OK",
"configurationStateId": str(
int(time.mktime(creation_time.timetuple()))
), # PY2 and 3 compatible
"resourceType": "AWS::S3::AccountPublicAccessBlock",
"resourceId": account_id,
"awsRegion": pab_region,
"availabilityZone": "Not Applicable",
"configuration": self.backends[
"global"
].account_public_access_block.to_config_dict(),
"supplementaryConfiguration": {},
}

# The 'configuration' field is also a JSON string:
config_data["configuration"] = json.dumps(config_data["configuration"])

return config_data


s3_config_query = S3ConfigQuery(s3_backends)
s3_account_public_access_block_query = S3AccountPublicAccessBlockConfigQuery(
s3_backends
)
Loading

0 comments on commit 6610862

Please sign in to comment.