Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smoke test using several templates from SAR #1357

Merged
merged 7 commits into from
Aug 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ func-test:
@echo Telemetry Status: $(SAM_CLI_TELEMETRY)
pytest --cov samcli.local --cov samcli.commands.local --cov-report term-missing tests/functional

smoke-test:
# Smoke tests run in parallel
pytest -n 4 tests/functional

flake:
# Make sure code conforms to PEP8 standards
flake8 samcli
Expand Down
13 changes: 13 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ environment:
PYTHON_VERSION: '3.7.4'
PYTHON_ARCH: '64'

- ONLY_SMOKE: 1
PYTHON_HOME: "C:\\Python37-x64"
PYTHON_VERSION: '3.7.4'
PYTHON_ARCH: '64'

for:
-
matrix:
Expand Down Expand Up @@ -52,6 +57,14 @@ for:
- sh: "sudo unzip -d /opt/gradle /tmp/gradle-*.zip"
- sh: "PATH=/opt/gradle/gradle-5.5/bin:$PATH"

-
matrix:
only:
- ONLY_SMOKE: 1
test_script:
# Smoke tests run in parallel
- "pytest -n 4 -vv tests/smoke"

build_script:
- "python -c \"import sys; print(sys.executable)\""

Expand Down
3 changes: 2 additions & 1 deletion requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ astroid>=1.5.8,<2.1.0
pylint==1.7.2

# Test requirements
pytest==3.0.7
pytest==3.1.0
py==1.4.33
mock==2.0.0
parameterized==0.6.1
pathlib2==2.3.2; python_version<"3.4"
futures==3.2.0; python_version<"3.2.3"
# Py3.2 backport
backports.tempfile==1.0
pytest-xdist==1.20.0
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,12 @@ def intrinsic_property_resolver(self, intrinsic, parent_function="template"):
"""
if intrinsic is None:
raise InvalidIntrinsicException("Missing Intrinsic property in {}".format(parent_function))
if any(isinstance(intrinsic, object_type) for object_type in [string_types, bool, int]) or intrinsic == {}:
return intrinsic
if isinstance(intrinsic, list):
return [self.intrinsic_property_resolver(item) for item in intrinsic]
if not isinstance(intrinsic, dict) or intrinsic == {}:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice change.

return intrinsic

# `intrinsic` is a dict at this point.

keys = list(intrinsic.keys())
key = keys[0]
Expand Down Expand Up @@ -720,7 +722,7 @@ def resolve_sub_attribute(intrinsic_item, symbol_resolver):
)
result = resolve_sub_attribute(sanitized_item, self._symbol_resolver)
sub_str = re.sub(
pattern=r"\$\{" + sub_item + r"\}", string=sub_str, repl=result
pattern=r"\$\{" + sub_item + r"\}", string=sub_str, repl=str(result)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the str? is the resolved result not a string?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because Python expects the replacement to be a string. In some cases customers provide an integer value via say a CFN parameter like az number or something.

)
return sub_str

Expand Down
Empty file added tests/smoke/__init__.py
Empty file.
61 changes: 61 additions & 0 deletions tests/smoke/download_sar_templates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import requests
import os
import logging
import time
import boto3


logging.basicConfig(level=logging.INFO)
LOG = logging.getLogger()
TEMPLATE_FOLDER = os.path.join("templates", "sar")


def download(count=100):

sar_browse_url = "https://shr32taah3.execute-api.us-east-1.amazonaws.com/Prod/applications/browse"
current_page = 1
retry_count = 0
apps = []

while len(apps) < count and retry_count < 10:
try:
response = requests.get(sar_browse_url, {
"pageSize": count if count < 10 else 10,
"pageNumber": current_page,
"includeAppsWithCapabilities": "CAPABILITY_IAM,CAPABILITY_NAMED_IAM,CAPABILITY_RESOURCE_POLICY,CAPABILITY_AUTO_EXPAND"
})

response.raise_for_status()
result = response.json()

# Successful request
apps = apps + result["applications"]
current_page += 1
retry_count = 0
except requests.exceptions.RequestException as ex:
LOG.warning("Got throttled by SAR", exc_info=ex)
retry_count += 1

for index, app in enumerate(apps):
app_id = app["id"]
name = app["name"]
template_file_name = os.path.join(TEMPLATE_FOLDER, name+"-template.yaml")
LOG.info("[%s/%s] %s", index, count, name)
_download_templates(app_id, template_file_name)
time.sleep(0.1) # 100ms aka 10 TPS

def _download_templates(app_id, template_file_path):
sar = boto3.client('serverlessrepo')
response = sar.get_application(ApplicationId=app_id)

template_url = response["Version"]["TemplateUrl"]

with open(template_file_path, "wb") as fp:
r = requests.get(template_url, stream=True)
for chunk in r.iter_content(chunk_size=128):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could probably do bigger chunks, since I'm assuming the templates are not megabytes in size.

fp.write(chunk)

if __name__ == "__main__":
count = 100
LOG.info("Downloading %s templates", count)
download(count=count)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
AWSTemplateFormatVersion: '2010-09-09'
Outputs:
HelloWorldFunctionARN:
Description: ARN of the HelloWorld Lambda function
Value:
Fn::GetAtt:
- HelloWorldFunction
- Arn
Description: HelloWorld Lambda function template for Application Load Balancer Lambda as target
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri:
Bucket: <%REPO_BUCKET%>
Key: 157edf07-69a8-4e05-ae78-656398b775c2
Runtime: python2.7
Handler: helloworld_27.lambda_handler
Description: An Application Load Balancer Lambda Target that returns "HelloWorld"
Timeout: 300
Transform: AWS::Serverless-2016-10-31
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Amazon Connect SalesForce Lambda integration
Parameters:
SalesforceProduction:
Default: true
Description: True for Production Environment, False for Sandbox
Type: String
AllowedPattern: ^([Tt]rue|[Ff]alse)$
AllowedValues:
- true
- true
- false
- false
ConstraintDescription: True or False
SalesforceHost:
Default: ''
Description: Your Salesforce Host
Type: String
SalesforceConsumerKey:
Default: ''
Description: Your Salesforce consumer key
Type: String
SalesforceConsumerSecret:
Default: ''
Description: Your Salesforce consumer secret is available in Salesforce immediately to the right of your Salesforce Consumer Key
Type: String
SalesforceUsername:
Default: Salesforce API Username
Description: The username of a valid Salesforce API account for your environment. For example, [email protected]
Type: String
SalesforcePassword:
Default: ''
Description: The password of a valid Salesforce API account for your environment. This account must be the same one as entered in the “Salesforce API Configuration Username” parameter above.
Type: String
NoEcho: true
SalesforceAccessToken:
Default: ''
Description: The security token of the Salesforce API user account used above.
Type: String
SalesforceVersion:
Default: v42.0
Description: To find the Salesforce Edition and API Version please visit https://help.salesforce.com/articleView?id=000199268&type=1
Type: String
ConnectReportingS3BucketName:
Default: '*'
Description: This is the S3 bucket where Amazon Connect stores scheduled reports. Please refer to http://docs.aws.amazon.com/connect/latest/adminguide/amazon-connect-instance.html#datastorage for details on how retrieve the S3 bucket associated with your Amazon Connect instance.
Type: String
SalesforceAdapterNamespace:
Default: amazonconnect
Description: This is the namespace for CTI Adapter managed package. The default value is [amazonconnect]. If a non-managed package is used, leave this field blank.
Type: String
Resources:
LambdaBasicExecWithS3Read:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: connect-bucket-read
PolicyDocument:
Version: '2012-10-17'
Statement:
Effect: Allow
Action:
- s3:GetObject
Resource:
Fn::Sub: arn:aws:s3:::${ConnectReportingS3BucketName}
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
sfInvokeAPI:
Type: AWS::Serverless::Function
Properties:
Timeout: 6
Runtime: python3.6
CodeUri:
Bucket: <%REPO_BUCKET%>
Key: 6503224b-2627-4c1c-90cd-e11062db858b
Environment:
Variables:
SF_HOST:
Ref: SalesforceHost
SF_PRODUCTION:
Ref: SalesforceProduction
SF_CONSUMER_KEY:
Ref: SalesforceConsumerKey
SF_CONSUMER_SECRET:
Ref: SalesforceConsumerSecret
SF_USERNAME:
Ref: SalesforceUsername
SF_PASSWORD:
Ref: SalesforcePassword
SF_ACCESS_TOKEN:
Ref: SalesforceAccessToken
SF_VERSION:
Ref: SalesforceVersion
SF_ADAPTER_NAMESPACE:
Ref: SalesforceAdapterNamespace
Handler: sfInvokeAPI.lambda_handler
sfIntervalAgent:
Type: AWS::Serverless::Function
Properties:
Timeout: 60
Runtime: python3.6
CodeUri:
Bucket: <%REPO_BUCKET%>
Key: 6503224b-2627-4c1c-90cd-e11062db858b
Environment:
Variables:
SF_HOST:
Ref: SalesforceHost
SF_PRODUCTION:
Ref: SalesforceProduction
SF_CONSUMER_KEY:
Ref: SalesforceConsumerKey
SF_CONSUMER_SECRET:
Ref: SalesforceConsumerSecret
SF_USERNAME:
Ref: SalesforceUsername
SF_PASSWORD:
Ref: SalesforcePassword
SF_ACCESS_TOKEN:
Ref: SalesforceAccessToken
SF_VERSION:
Ref: SalesforceVersion
SF_ADAPTER_NAMESPACE:
Ref: SalesforceAdapterNamespace
Handler: sfIntervalAgent.lambda_handler
Role:
Fn::GetAtt: LambdaBasicExecWithS3Read.Arn
sfIntervalQueue:
Type: AWS::Serverless::Function
Properties:
Timeout: 60
Runtime: python3.6
CodeUri:
Bucket: <%REPO_BUCKET%>
Key: 6503224b-2627-4c1c-90cd-e11062db858b
Environment:
Variables:
SF_HOST:
Ref: SalesforceHost
SF_PRODUCTION:
Ref: SalesforceProduction
SF_CONSUMER_KEY:
Ref: SalesforceConsumerKey
SF_CONSUMER_SECRET:
Ref: SalesforceConsumerSecret
SF_USERNAME:
Ref: SalesforceUsername
SF_PASSWORD:
Ref: SalesforcePassword
SF_ACCESS_TOKEN:
Ref: SalesforceAccessToken
SF_VERSION:
Ref: SalesforceVersion
SF_ADAPTER_NAMESPACE:
Ref: SalesforceAdapterNamespace
Handler: sfIntervalQueue.lambda_handler
Role:
Fn::GetAtt: LambdaBasicExecWithS3Read.Arn
Outputs:
LambdaBasicExecWithS3Read:
Description: Lambda Function Execution and S3 Read Role ARN
Value:
Fn::GetAtt: LambdaBasicExecWithS3Read.Arn
Loading