Skip to content

Commit

Permalink
Custom id tag support (#8230)
Browse files Browse the repository at this point in the history
  • Loading branch information
cloutierMat authored Oct 16, 2024
1 parent 947004f commit 6d51cae
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 25 deletions.
2 changes: 1 addition & 1 deletion moto/apigateway/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1658,7 +1658,7 @@ def create_rest_api(
) -> RestAPI:
api_id = ApigwRestApiIdentifier(
self.account_id, self.region_name, name
).generate()
).generate(tags=tags)
rest_api = RestAPI(
api_id,
self.account_id,
Expand Down
2 changes: 1 addition & 1 deletion moto/secretsmanager/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def __init__(
self.name = secret_id
self.arn = SecretsManagerSecretIdentifier(
account_id, region_name, secret_id
).generate()
).generate(tags=tags)
self.account_id = account_id
self.region = region_name
self.secret_string = secret_string
Expand Down
20 changes: 16 additions & 4 deletions moto/utilities/id_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
log = logging.getLogger(__name__)

ExistingIds = Union[List[str], None]
Tags = Union[Dict[str, str], None]
Tags = Union[Dict[str, str], List[Dict[str, str]], None]

# Custom resource tag to override the generated resource ID.
TAG_KEY_CUSTOM_ID = "_custom_id_"
Expand Down Expand Up @@ -71,7 +71,8 @@ def __init__(self) -> None:
def get_custom_id(
self, resource_identifier: ResourceIdentifier
) -> Union[str, None]:
# retrieves a custom_id for a resource. Returns None
# retrieves a custom_id for a resource. Returns None if no id were registered
# that matches the `resource_identifier`
return self._custom_ids.get(resource_identifier.unique_identifier)

def set_custom_id(
Expand All @@ -95,10 +96,21 @@ def add_id_source(

@staticmethod
def get_id_from_tags(id_source_context: IdSourceContext) -> Union[str, None]:
if tags := id_source_context.get("tags"):
if not (tags := id_source_context.get("tags")):
return None

if isinstance(tags, dict):
return tags.get(TAG_KEY_CUSTOM_ID)

return None
if isinstance(tags, list):
return next(
(
tag.get("Value")
for tag in tags
if tag.get("Key") == TAG_KEY_CUSTOM_ID
),
None,
)

def get_custom_id_from_context(
self, id_source_context: IdSourceContext
Expand Down
44 changes: 33 additions & 11 deletions tests/test_apigateway/test_apigateway_custom_ids.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
ApigwRestApiIdentifier,
ApigwUsagePlanIdentifier,
)
from moto.utilities.id_generator import TAG_KEY_CUSTOM_ID
from tests import DEFAULT_ACCOUNT_ID

API_ID = "ApiId"
API_KEY_ID = "ApiKeyId"
Expand All @@ -27,7 +29,7 @@
@pytest.mark.skipif(
not settings.TEST_DECORATOR_MODE, reason="Can't access the id manager in proxy mode"
)
def test_custom_id_rest_api(set_custom_id, account_id):
def test_custom_id_rest_api(set_custom_id):
region_name = "us-west-2"
rest_api_name = "my-api"
model_name = "modelName"
Expand All @@ -37,33 +39,40 @@ def test_custom_id_rest_api(set_custom_id, account_id):
client = boto3.client("apigateway", region_name=region_name)

set_custom_id(
ApigwRestApiIdentifier(account_id, region_name, rest_api_name), API_ID
ApigwRestApiIdentifier(DEFAULT_ACCOUNT_ID, region_name, rest_api_name), API_ID
)
set_custom_id(
ApigwResourceIdentifier(account_id, region_name, path_name="/"),
ApigwResourceIdentifier(DEFAULT_ACCOUNT_ID, region_name, path_name="/"),
ROOT_RESOURCE_ID,
)
set_custom_id(
ApigwResourceIdentifier(
account_id, region_name, parent_id=ROOT_RESOURCE_ID, path_name="pet"
DEFAULT_ACCOUNT_ID, region_name, parent_id=ROOT_RESOURCE_ID, path_name="pet"
),
PET_1_RESOURCE_ID,
)
set_custom_id(
ApigwResourceIdentifier(
account_id, region_name, parent_id=PET_1_RESOURCE_ID, path_name="pet"
DEFAULT_ACCOUNT_ID,
region_name,
parent_id=PET_1_RESOURCE_ID,
path_name="pet",
),
PET_2_RESOURCE_ID,
)
set_custom_id(ApigwModelIdentifier(account_id, region_name, model_name), MODEL_ID)
set_custom_id(
ApigwModelIdentifier(DEFAULT_ACCOUNT_ID, region_name, model_name), MODEL_ID
)
set_custom_id(
ApigwRequestValidatorIdentifier(
account_id, region_name, request_validator_name
DEFAULT_ACCOUNT_ID, region_name, request_validator_name
),
REQUEST_VALIDATOR_ID,
)
set_custom_id(
ApigwDeploymentIdentifier(account_id, region_name, stage_name=stage_name),
ApigwDeploymentIdentifier(
DEFAULT_ACCOUNT_ID, region_name, stage_name=stage_name
),
DEPLOYMENT_ID,
)

Expand Down Expand Up @@ -113,18 +122,19 @@ def test_custom_id_rest_api(set_custom_id, account_id):
@pytest.mark.skipif(
not settings.TEST_DECORATOR_MODE, reason="Can't access the id manager in proxy mode"
)
def test_custom_id_api_key(account_id, set_custom_id):
def test_custom_id_api_key(set_custom_id):
region_name = "us-west-2"
api_key_value = "01234567890123456789"
usage_plan_name = "usage-plan"

client = boto3.client("apigateway", region_name=region_name)

set_custom_id(
ApigwApiKeyIdentifier(account_id, region_name, value=api_key_value), API_KEY_ID
ApigwApiKeyIdentifier(DEFAULT_ACCOUNT_ID, region_name, value=api_key_value),
API_KEY_ID,
)
set_custom_id(
ApigwUsagePlanIdentifier(account_id, region_name, usage_plan_name),
ApigwUsagePlanIdentifier(DEFAULT_ACCOUNT_ID, region_name, usage_plan_name),
USAGE_PLAN_ID,
)

Expand All @@ -138,3 +148,15 @@ def test_custom_id_api_key(account_id, set_custom_id):

assert api_key["id"] == API_KEY_ID
assert usage_plan["id"] == USAGE_PLAN_ID


@mock_aws
def test_create_rest_api_with_custom_id_tag():
rest_api_name = "rest_api"
api_id = "testTagId"
client = boto3.client("apigateway", region_name="us-west-2")
rest_api = client.create_rest_api(
name=rest_api_name, tags={TAG_KEY_CUSTOM_ID: api_id}
)

assert rest_api["id"] == api_id
22 changes: 20 additions & 2 deletions tests/test_secretsmanager/test_secretsmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
from moto import mock_aws, settings
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
from moto.secretsmanager.utils import SecretsManagerSecretIdentifier
from moto.utilities.id_generator import TAG_KEY_CUSTOM_ID

from .. import DEFAULT_ACCOUNT_ID
from . import secretsmanager_aws_verified

DEFAULT_SECRET_NAME = "test-secret7"
Expand Down Expand Up @@ -1968,17 +1970,33 @@ def test_update_secret_version_stage_dont_specify_current_stage(secret_arn=None)
@pytest.mark.skipif(
not settings.TEST_DECORATOR_MODE, reason="Can't access the id manager in proxy mode"
)
def test_create_secret_custom_id(account_id, set_custom_id):
def test_create_secret_custom_id(set_custom_id):
secret_suffix = "randomSuffix"
secret_name = "secret-name"
region_name = "us-east-1"

client = boto3.client("secretsmanager", region_name=region_name)

set_custom_id(
SecretsManagerSecretIdentifier(account_id, region_name, secret_name),
SecretsManagerSecretIdentifier(DEFAULT_ACCOUNT_ID, region_name, secret_name),
secret_suffix,
)
secret = client.create_secret(Name=secret_name, SecretString="my secret")

assert secret["ARN"].split(":")[-1] == f"{secret_name}-{secret_suffix}"


@mock_aws
def test_create_secret_with_tag_custom_id(set_custom_id):
secret_suffix = "randomSuffix"
secret_name = "secret-name"

client = boto3.client("secretsmanager")

secret = client.create_secret(
Name=secret_name,
SecretString="my secret",
Tags=[{"Key": TAG_KEY_CUSTOM_ID, "Value": secret_suffix}],
)

assert secret["ARN"].split(":")[-1] == f"{secret_name}-{secret_suffix}"
12 changes: 6 additions & 6 deletions tests/test_utilities/test_id_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
RESOURCE_NAME = "my-resource"

CUSTOM_ID = "custom"
GENERATED_ID = "generated"
GENERIC_ID = "generated"
TAG_ID = "fromTag"
SERVICE = "test-service"
RESOURCE = "test-resource"
Expand All @@ -24,7 +24,7 @@ def generate_test_id(
existing_ids: ExistingIds = None,
tags: Tags = None,
):
return GENERATED_ID
return GENERIC_ID


class TestResourceIdentifier(ResourceIdentifier):
Expand All @@ -39,7 +39,7 @@ def generate(self, existing_ids: ExistingIds = None, tags: Tags = None) -> str:

def test_generate_with_no_resource_identifier():
generated_id = generate_test_id(None)
assert generated_id == GENERATED_ID
assert generated_id == GENERIC_ID


def test_generate_with_matching_resource_identifier(set_custom_id):
Expand All @@ -58,7 +58,7 @@ def test_generate_with_non_matching_resource_identifier(set_custom_id):
set_custom_id(resource_identifier, CUSTOM_ID)

generated_id = generate_test_id(resource_identifier=resource_identifier_2)
assert generated_id == GENERATED_ID
assert generated_id == GENERIC_ID


def test_generate_with_custom_id_tag():
Expand Down Expand Up @@ -87,7 +87,7 @@ def test_generate_with_existing_id(set_custom_id):
generated_id = generate_test_id(
resource_identifier=resource_identifier, existing_ids=[CUSTOM_ID]
)
assert generated_id == GENERATED_ID
assert generated_id == GENERIC_ID


def test_generate_with_tags_and_existing_id(set_custom_id):
Expand All @@ -98,7 +98,7 @@ def test_generate_with_tags_and_existing_id(set_custom_id):
existing_ids=[TAG_ID],
tags={TAG_KEY_CUSTOM_ID: TAG_ID},
)
assert generated_id == GENERATED_ID
assert generated_id == GENERIC_ID


def test_generate_with_tags_fallback(set_custom_id):
Expand Down

0 comments on commit 6d51cae

Please sign in to comment.