having errors with slsart deploy command
See original GitHub issueDiscussed in https://github.com/artilleryio/artillery/discussions/1397
<div type='discussions-op-text'>Originally posted by sirishaganti April 7, 2022 Hi,
I am trying to use this slsart deploy. I have my script.yml which looks something like below -
config:
target: "https://d8snwdhbfd.execute-api.us-east-1.amazonaws.com/default"
phases:
- duration: 60
arrivalRate: 5
name: Warm up
- duration: 120
arrivalRate: 5
rampTo: 50
name: Ramp up load
- duration: 60
arrivalRate: 5
name: Sustained load
payload:
path: "input.csv"
skipHeader: true
cast: true
fields:
- "EventName"
- "RequestId"
- "RequestedBy"
- "Timestamp"
scenarios:
- name: "Profile hit"
flow:
- post:
url: "/my_lambda"
json:
EventName: '{{ EventName }}'
RequestId: '{{ RequestId }}'
RequestedBy: '{{ RequestedBy }}'
Timestamp: '{{ Timestamp }}'
capture:
- json: "$.results[0].id"
as: "productId"
My input.csv is in the same folder as the script.yml. Below is handler.js -
/* eslint-disable no-underscore-dangle */
const fs = require('fs');
const { safeLoad } = require('js-yaml');
const merge = require('lodash.merge');
const omit = require('lodash.omit'); // eslint-disable-line import/no-unresolved
const task = require('./artillery-task.js');
const platform = require('./platform-settings.js');
const path = require('path');
const promisify = require('util-promisify');// eslint-disable-line import/no-unresolved
const mergeFileField = '>>'
const readFileAsync = promisify(fs.readFile)
const lambdaHandler = {
handleUnhandledRejection: (ex) => {
console.log('###############################################################')
console.log('## !! Unhandled promise rejection !! ##')
console.log('## This probably results from an unforseen circumstance in ##')
console.log('## a plugin. Please report the following stack trace at: ##')
console.log('## https://github.com/Nordstrom/serverless-artillery/issues ##')
console.log('###############################################################')
console.log(ex.stack)
console.log('###############################################################')
throw ex
},
getMergeFilePath: (
mergeFileInput,
resolve = path.resolve,
dirname = __dirname
) => {
const reject = message => Promise.reject(new Error(message))
if (!mergeFileInput || typeof mergeFileInput !== 'string') {
return reject(`'${typeof mergeFileInput}' is not a valid path.`)
}
const absolutePath = resolve(mergeFileInput)
if (!absolutePath.startsWith(dirname)) {
return reject(`Merge file ${absolutePath} is not a local file path.`)
}
return Promise.resolve(absolutePath)
},
readMergeFile: (
mergeFilePath,
readFile = readFileAsync,
error = console.error,
getMergeFilePath = lambdaHandler.getMergeFilePath
) =>
getMergeFilePath(mergeFilePath)
.then(readFile)
.then(safeLoad)
.catch((ex) => {
error('Failed to read merge file.', mergeFilePath, ex.stack)
throw ex
}),
mergeIf: (script, readMergeFile = lambdaHandler.readMergeFile) =>
(mergeFileField in script
? readMergeFile(script[mergeFileField])
.then(inputData => merge({}, inputData, omit(script, [mergeFileField])))
: Promise.resolve(script)),
createHandler: (taskToExecute, platformSettings) =>
(event, context, callback) => {
try {
const script = event
script._funcAws = {
functionName: context.functionName,
}
const settings = platformSettings.getSettings(script)
lambdaHandler.mergeIf(script)
.then(mergedScript => taskToExecute.executeTask(mergedScript, settings))
.then((result) => {
if (process.env.SA_DEBUG) console.log(`LambdaResult ${JSON.stringify(result)}`)
callback(null, result)
})
.catch((ex) => {
console.log(ex.stack)
if (process.env.SA_DEBUG) console.log(`LambdaResult ${JSON.stringify(ex)}`)
callback(null, `Error executing task: ${ex.message}`)
})
} catch (ex) {
console.log(ex.stack)
if (process.env.SA_DEBUG) console.log(`LambdaResult ${JSON.stringify(ex)}`)
callback(null, `Error validating event: ${ex.message}`)
}
},
}
process.on('unhandledRejection', lambdaHandler.handleUnhandledRejection)
module.exports.handler = lambdaHandler.createHandler(task, platform)
module.exports.lambdaHandler = lambdaHandler
and below is serverless.yml -
# We're excited that this project has provided you enough value that you are looking at its code!
#
# This is a standard [Serverless Framework](https://www.serverless.com) project and you should
# feel welcome to customize it to your needs and delight.
#
# If you do something super cool and would like to share the capability, please open a PR against
# https://www.github.com/Nordstrom/serverless-artillery
#
# Thanks!
# If the following value is changed, your service may be duplicated (this value is used to build the CloudFormation
# Template script's name)
service: serverless-artillery-yaAvA4n3DE
provider:
name: aws
runtime: nodejs10.x
iamRoleStatements:
# This policy allows the function to invoke itself which is important if the script is larger than a single
# function can produce
- Effect: 'Allow'
Action:
- 'lambda:InvokeFunction'
Resource:
'Fn::Join':
- ':'
-
- 'arn:aws:lambda'
- Ref: 'AWS::Region'
- Ref: 'AWS::AccountId'
- 'function'
- '${self:service}-${opt:stage, self:provider.stage}-loadGenerator*' # must match function name
# This policy allows the function to publish notifications to the SNS topic defined below with logical ID monitoringAlerts
- Effect: 'Allow'
Action:
- 'sns:Publish'
Resource:
Ref: monitoringAlerts # must match the SNS topic's logical ID
functions:
loadGenerator: # !!Do not edit this name!!
handler: handler.handler # the serverlessArtilleryLoadTester handler() method can be found in the handler.js source file
timeout: 300 # set timeout to be 5 minutes (max for Lambda)
environment:
TOPIC_ARN:
Ref: monitoringAlerts
TOPIC_NAME:
'Fn::GetAtt':
- monitoringAlerts
- TopicName
events:
- schedule:
name: '${self:service}-${opt:stage, self:provider.stage}-monitoring' # !!Do not edit this name!!
description: The scheduled event for running the function in monitoring mode
rate: rate(1 minute)
########################################################################################################################
### !! BEFORE ENABLING... !!!
### 0. Change `'>>': script.yml` below to reference the script you want to use for monitoring if that is not its name.
### The script must be in this directory or a subdirectory.
### 1. Modify your `script.yml` to provide the details of invoking every important surface of your service, as per
### https://artillery.io/docs
### 2. To receive alerts when errors exceed the budget:
### i. Add a `match` clause to your requests, specifying your expectations of a successful request. This relatively
### undocumented feature is implemented at: https://github.com/shoreditch-ops/artillery/blob/82bdcdfc32ce4407bb197deff2cee13b4ecbab3b/core/lib/engine_util.js#L318
### We would welcome the contribution of a plugin replacing this as discussed in https://github.com/Nordstrom/serverless-artillery/issues/116
### ii. Modify the `monitoringAlerts` SNS Topic below, uncommenting `Subscription` and providing subscriptions for any
### alerts that might be raised by the monitoring function. (To help you out, we've provided commented-out examples)
### (After all, what good is monitoring if noone is listening?)
### 3. Deploy your new assets/updated service using `slsart deploy`
### 4. [As appropriate] approve the subscription verifications for the SNS topic that will be sent following its creation
### 5. Re-deploy whenever you update your monitoring script
########################################################################################################################
enabled: false
input:
'>>': script.yml
mode: monitoring
resources:
Resources:
monitoringAlerts: # !!Do not edit this name!!
Type: 'AWS::SNS::Topic'
Properties:
DisplayName: '${self:service} Monitoring Alerts'
# Subscription: # docs at https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-subscription.html
# - Endpoint: http://<host>/<path> # the endpoint is an URL beginning with "http://"
# Protocol: http
# - Endpoint: https://<host>/<path> # the endpoint is a URL beginning with "https://"
# Protocol: https
# - Endpoint: <target>@<host> # the endpoint is an email address
# Protocol: email
# - Endpoint: <target>@<host> # the endpoint is an email address
# Protocol: email-json
# - Endpoint: <phone-number> # the endpoint is a phone number of an SMS-enabled device
# Protocol: sms
# - Endpoint: <sqs-queue-arn> # the endpoint is the ARN of an Amazon SQS queue
# Protocol: sqs
# - Endpoint: <endpoint-arn> # the endpoint is the EndpointArn of a mobile app and device.
# Protocol: application
# - Endpoint: <lambda-arn> # the endpoint is the ARN of an AWS Lambda function.
# Protocol: lambda
When I run slsart deploy , I get the following error -
/usr/local/lib/node_modules/serverless/node_modules/type/lib/resolve-exception.js:14
throw error;
^
TypeError: undefined is not an array
at module.exports (/usr/local/lib/node_modules/serverless/node_modules/type/lib/resolve-exception.js:12:14)
at module.exports (/usr/local/lib/node_modules/serverless/node_modules/type/array/ensure.js:15:25)
at new Serverless (/usr/local/lib/node_modules/serverless/lib/serverless.js:86:22)
at Object.serverlessLoader (/usr/local/lib/node_modules/serverless-artillery/lib/index.js:542:24)
at Object.deploy (/usr/local/lib/node_modules/serverless-artillery/lib/index.js:563:27)
at Object.<anonymous> (/usr/local/lib/node_modules/serverless-artillery/bin/serverless-artillery:205:16)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
at internal/main/run_main_module.js:17:47
I tried deploying the files handler.js, serverless.yml, script.yml and input.csv to AWS directly by zipping up the 4 files along with serverless and serverless-artillery library files in node_modules and when I ran the lambda function, I got the following error in the output -
Test Event Name
testevent
Response
"Error executing task: Cannot read property 'phases' of undefined"
Function Logs
START RequestId: 93642716-6e9e-4a8d-b705-db4c91a5fdd6 Version: $LATEST
2022-04-07T18:30:52.020Z 93642716-6e9e-4a8d-b705-db4c91a5fdd6 INFO SCRIPT OBJECT {"_funcAws":{"functionName":"loadtestlambda"},"_genesis":1649356252020}
2022-04-07T18:30:52.026Z 93642716-6e9e-4a8d-b705-db4c91a5fdd6 INFO TypeError: Cannot read property 'phases' of undefined
at Object.scriptDurationInSeconds (/opt/nodejs/node_modules/serverless-artillery/lib/lambda/planning.js:35:35)
at Object.planPerformance (/opt/nodejs/node_modules/serverless-artillery/lib/lambda/planning.js:554:46)
at Object.execute (/opt/nodejs/node_modules/serverless-artillery/lib/lambda/artillery-performance.js:6:28)
at Object.executeTask (/opt/nodejs/node_modules/serverless-artillery/lib/lambda/artillery-task.js:206:29)
at /var/task/handler.js:75:47
END RequestId: 93642716-6e9e-4a8d-b705-db4c91a5fdd6
REPORT RequestId: 93642716-6e9e-4a8d-b705-db4c91a5fdd6 Duration: 28.86 ms Billed Duration: 29 ms Memory Size: 128 MB Max Memory Used: 97 MB Init Duration: 1101.10 ms
Request ID
93642716-6e9e-4a8d-b705-db4c91a5fdd6
It seems to me like I am doing something wrong with the configuration because the script.yml is not getting picked by artillery. What am I doing wrong? I was able to run the script.yml from command line but not as a AWS lambda function. I need to generate cloudwatch logs on the script output. I am doing a load test on AWS lambda function which is not accessible to anyone. It has to be load tested using the AWS lambda function created by serverless artillery. That is my requirement.
Thank you</div>
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:6 (1 by maintainers)
Top GitHub Comments
It could be related to Artillery.io’s new pricing model. Pricing Details : https://www.artillery.io/pricing
This problem occurred due the node and serverless version compatibility. I just tried this with both windows and Ubuntu. Both shows the same error. (TypeError: undefined is not an array)
When trying along with older version of serverless and node which shows some another errors binds mutual.
At last found the compactable version of both serverless and node. with small edits in serverless config. 😉 💯
Platform using
Distributor ID : Ubuntu Description : Ubuntu 22.04 LTS Release : 22.04
Recommended versions
$ node -v v15.5.1 $ npm -v 7.3.0 $ serverless --version Framework Core: 1.83.0 Plugin: 3.8.4 SDK: 2.3.2 Components: 2.34.9
$ slsart --version 0.5.2
Steps to follow
npm uninstall -g serverless npm install -g serverless@1.83.0 npm install -g serverless-artillery
Create a custom service for your tests
$ mkdir customTestLambda $ cd customTestLambda $ cp …/script.yml . $ slsart configure $ ls handler.js package.json serverless.yml
$ vi serverless.yml
“Change the runtime like shows below”
provider: name: aws runtime: nodejs12.x ------------------->(important)
slsart deploy --stage dev --region ap-southeast-2 slsart invoke -p script.yml --stage dev --region ap-southeast-2
Enjoy the Fix! cheers
slsart
is not an @artilleryio project - as such we are unable to provide support for it. Nothing to do with Artillery Pro’s pricing.Recent versions of Artillery have built-in AWS Lambda support - https://www.artillery.io/docs/guides/guides/distributed-load-tests-on-aws-lambda