Skip to content

Commit

Permalink
Merge from aws/aws-sam-cli/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
aws-sam-cli-bot authored Aug 17, 2022
2 parents 1e14386 + 7982e4f commit 66ca249
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 11 deletions.
2 changes: 1 addition & 1 deletion requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ boto3>=1.19.5,==1.*
jmespath~=0.10.0
PyYAML~=5.3
cookiecutter~=2.1.1
aws-sam-translator==1.49.0
aws-sam-translator==1.50.0
#docker minor version updates can include breaking changes. Auto update micro version only.
docker~=4.2.0
dateparser~=1.0
Expand Down
8 changes: 4 additions & 4 deletions requirements/reproducible-linux.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ aws-lambda-builders==1.18.0 \
--hash=sha256:c0bd4b4288f0aa9cba27493065f5fb986425b5b49620b93a391620403eeb97e0 \
--hash=sha256:c5235699d36b8edda7e649fbc3a23ed868eda1e15c4a83528df33939bdb75754
# via aws-sam-cli (setup.py)
aws-sam-translator==1.49.0 \
--hash=sha256:71ffd82a72de769b5f35be30af1f7ca7800b7c6abaf146bdff6ae52c85734ef1 \
--hash=sha256:a0d3bba2fb16d72e1e4fc5ef50e227e8e6a869f4c417dd760191d26470dca91f \
--hash=sha256:ab7b6ae0ecdf76ef14fb89f9503bc2c7719ed0e1be1dbbf3d3b3dfb0fe8d5c5b
aws-sam-translator==1.50.0 \
--hash=sha256:09668d12b5d330412421d30d4a8e826da6fe06f5a451f771c3b37f48f1b25889 \
--hash=sha256:85bea2739e1b4a61b3e4add8a12f727d7a8e459e3da195dfd0cd2e756be054ec \
--hash=sha256:d375e9333c0262ed74b6d7ae90938060713ab17341f4e06c5cdbfd755902d9b4
# via aws-sam-cli (setup.py)
backports-zoneinfo==0.2.1 \
--hash=sha256:17746bd546106fa389c51dbea67c8b7c8f0d14b5526a579ca6ccf5ed72c526cf \
Expand Down
2 changes: 1 addition & 1 deletion samcli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
SAM CLI version
"""

__version__ = "1.54.0"
__version__ = "1.55.0"
6 changes: 6 additions & 0 deletions samcli/cli/cli_config_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,13 @@ def configuration_callback(cmd_name, option_name, saved_callback, provider, ctx,
cmd_name = cmd_name or ctx.info_name
param.default = None
config_env_name = ctx.params.get("config_env") or DEFAULT_ENV

config_file = ctx.params.get("config_file") or DEFAULT_CONFIG_FILE_NAME
if config_file and config_file != DEFAULT_CONFIG_FILE_NAME and not Path(config_file).is_file():
error_msg = f"Config file {config_file} does not exist or could not be read"
LOG.debug(error_msg)
raise ConfigException(error_msg)

config_dir = getattr(ctx, "samconfig_dir", None) or os.getcwd()
# If --config-file is an absolute path, use it, if not, start from config_dir
config_file_name = config_file if os.path.isabs(config_file) else os.path.join(config_dir, config_file)
Expand Down
24 changes: 21 additions & 3 deletions samcli/cli/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,16 @@ class CfnTags(click.ParamType):
"""
Custom Click options type to accept values for tag parameters.
tag parameters can be of the type KeyName1=string KeyName2=string
If multiple_values_per_key is set to True, the returned dictionary will map
each key to a list of corresponding values.
E.g. Input: KeyName1=Value1 KeyName1=Value2 Output: {KeyName1 : [Value1, Value2]}
"""

def __init__(self, multiple_values_per_key=False):
self.multiple_values_per_key = multiple_values_per_key

_EXAMPLE = "KeyName1=string KeyName2=string"
# Tags have additional constraints and they allow "+ - = . _ : / @" apart from alpha-numerics.
TAG_REGEX = '[A-Za-z0-9\\"_:\\.\\/\\+-\\@=]'
Expand Down Expand Up @@ -212,16 +220,15 @@ def convert(self, value, param, ctx):
parsed, tags = self._space_separated_key_value_parser(val)
if parsed:
for k in tags:
result[_unquote_wrapped_quotes(k)] = _unquote_wrapped_quotes(tags[k])
self._add_value(result, _unquote_wrapped_quotes(k), _unquote_wrapped_quotes(tags[k]))
else:
groups = re.findall(self._pattern, val)

if not groups:
fail = True
for group in groups:
key, v = group
# assign to result['KeyName1'] = string and so on.
result[_unquote_wrapped_quotes(key)] = _unquote_wrapped_quotes(v)
self._add_value(result, _unquote_wrapped_quotes(key), _unquote_wrapped_quotes(v))

if fail:
return self.fail(
Expand All @@ -232,6 +239,17 @@ def convert(self, value, param, ctx):

return result

def _add_value(self, result: dict, key: str, new_value: str):
"""
Add a given value to a given key in the result map.
"""
if self.multiple_values_per_key:
if not result.get(key):
result[key] = []
result[key].append(new_value)
return
result[key] = new_value

@staticmethod
def _standard_key_value_parser(tag_value):
"""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
AWSTemplateFormatVersion: '2010-09-09'
Parameters: {}

Resources:
MyMskStreamProcessor:
Type: AWS::Serverless::Function
Properties:
Runtime: nodejs12.x
Handler: index.handler
CodeUri: s3://sam-demo-bucket/kafka.zip
Events:
MyMskEvent:
Type: MSK
Properties:
StartingPosition: LATEST
Stream: !Sub arn:aws:kafka:${AWS::Region}:012345678901:cluster/mycluster/6cc0432b-8618-4f44-bccc-e1fbd8fb7c4d-2
Topics:
- "MyDummyTestTopic"
ConsumerGroupId: consumergroup1

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
StartingPositionValue:
Type: String
Default: LATEST

StreamValue:
Type: String
Default: arn:aws:kafka:us-east-1:012345678901:cluster/mycluster/6cc0432b-8618-4f44-bccc-e1fbd8fb7c4d-2

TopicsValue:
Type: CommaDelimitedList
Default: Topic

ConsumerGroupValue:
Type: String
Default: consumergroup1


Resources:
MyMskStreamProcessor:
Type: AWS::Serverless::Function
Properties:
Runtime: nodejs12.x
Handler: index.handler
CodeUri: s3://sam-demo-bucket/kafka.zip
Events:
MyMskEvent:
Type: MSK
Properties:
StartingPosition: !Ref StartingPositionValue
Stream: !Ref StreamValue
Topics: !Ref TopicsValue
ConsumerGroupId: !Ref ConsumerGroupValue

Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ Resources:
URI: subnet:subnet-12345
- Type: VPC_SECURITY_GROUP
URI: security_group:sg-67890
ConsumerGroupId: consumergroup1

Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ Parameters:
KafkaBootstrapServersValue:
Type: CommaDelimitedList
Default: abc.xyz.com:9092,123.45.67.89:9096



ConsumerGroupValue:
Type: String
Default: consumergroup1


Resources:
KafkaFunction:
Type: 'AWS::Serverless::Function'
Expand Down Expand Up @@ -43,6 +47,8 @@ Resources:
- Type: BASIC_AUTH
URI:
Ref: KafkaUserSecret
ConsumerGroupId:
Ref: ConsumerGroupValue

KafkaUserSecret:
Type: AWS::SecretsManager::Secret
Expand Down
19 changes: 19 additions & 0 deletions tests/unit/cli/test_cli_config_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,25 @@ def test_callback_with_valid_config_env(self):
self.assertIn(arg, self.saved_callback.call_args[0])
self.assertNotIn(self.value, self.saved_callback.call_args[0])

def test_callback_with_invalid_config_file(self):
mock_context1 = MockContext(info_name="sam", parent=None)
mock_context2 = MockContext(info_name="local", parent=mock_context1)
mock_context3 = MockContext(info_name="start-api", parent=mock_context2)
self.ctx.parent = mock_context3
self.ctx.info_name = "test_info"
self.ctx.params = {"config_file": "invalid_config_file"}
setattr(self.ctx, "samconfig_dir", None)
with self.assertRaises(ConfigException):
configuration_callback(
cmd_name=self.cmd_name,
option_name=self.option_name,
saved_callback=self.saved_callback,
provider=self.provider,
ctx=self.ctx,
param=self.param,
value=self.value,
)

def test_configuration_option(self):
toml_provider = TomlProvider()
click_option = configuration_option(provider=toml_provider)
Expand Down
58 changes: 58 additions & 0 deletions tests/unit/cli/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,64 @@ def test_successful_parsing(self, input, expected):
self.assertEqual(result, expected, msg="Failed with Input = " + str(input))


class TestCfnTagsMultipleValues(TestCase):
"""
Tests for the CfnTags parameter allowing multiple values per key.
"""

def setUp(self):
self.param_type = CfnTags(multiple_values_per_key=True)

@parameterized.expand(
[
# Just a string
("some string"),
# Wrong notation
# ("a==b"),
# Wrong multi-key notation
# ("a==b,c==d"),
]
)
def test_must_fail_on_invalid_format(self, input):
self.param_type.fail = Mock()
self.param_type.convert(input, "param", "ctx")

self.param_type.fail.assert_called_with(ANY, "param", "ctx")

@parameterized.expand(
[
(("a=b",), {"a": ["b"]}),
(("a=b", "c=d"), {"a": ["b"], "c": ["d"]}),
(('"a+-=._:/@"="b+-=._:/@" "--c="="=d/"',), {"a+-=._:/@": ["b+-=._:/@"], "--c=": ["=d/"]}),
(('owner:name="son of anton"',), {"owner:name": ["son of anton"]}),
(("a=012345678901234567890123456789",), {"a": ["012345678901234567890123456789"]}),
(
("a=012345678901234567890123456789 name=this-is-a-very-long-tag-value-now-it-should-not-fail"),
{
"a": ["012345678901234567890123456789"],
"name": ["this-is-a-very-long-tag-value-now-it-should-not-fail"],
},
),
(
("a=012345678901234567890123456789", "c=012345678901234567890123456789"),
{"a": ["012345678901234567890123456789"], "c": ["012345678901234567890123456789"]},
),
(("",), {}),
# list as input
([], {}),
(
["stage=int", "company:application=awesome-service", "company:department=engineering"],
{"stage": ["int"], "company:application": ["awesome-service"], "company:department": ["engineering"]},
),
(("a=b", "a=d"), {"a": ["b", "d"]}),
(("stage=alpha", "stage=beta", "stage=gamma", "stage=prod"), {"stage": ["alpha", "beta", "gamma", "prod"]}),
]
)
def test_successful_parsing(self, input, expected):
result = self.param_type.convert(input, None, None)
self.assertEqual(result, expected, msg="Failed with Input = " + str(input))


class TestCodeSignOptionType(TestCase):
def setUp(self):
self.param_type = SigningProfilesOptionType()
Expand Down

0 comments on commit 66ca249

Please sign in to comment.