@artilleryio/platform-fargate
Version:
Fargate support for Artillery
10 lines • 9.36 kB
JavaScript
;const os=require("os"),path=require("path"),fs=require("fs"),debug=require("debug")("artillery:pro"),jwt=require("jsonwebtoken"),AWS=require("aws-sdk"),chalk=require("chalk"),_=require("lodash"),A=require("async"),createS3Client=require("./utils/create-s3-client"),supportedRegions=["us-east-1","us-west-1","eu-west-1","eu-central-1","ap-south-1","ap-northeast-1"],partiallySupportedRegions=["cn-northwest-1","eu-west-3","eu-north-1","sa-east-1"],S3_BUCKET_NAME_PREFIX=require("./constants")["S3_BUCKET_NAME_PREFIX"],putParameter=require("./aws-util")["putParameter"];function vlk(token,callback){verify(token,(err,decoded)=>{if(err)return(err=new Error("Could not verify license key")).name="LicenseKeyValidationError",callback(err,null);if(decoded.it){if(decoded.sed>Date.now())return callback(null,decoded);{const e=new Error(`Artillery Pro trial license for ${decoded.email} has expired`);return e.name="LicenseKeyExpiredError",callback(e,null)}}return callback(null,decoded)})}function ensureDotDir(callback){fs.mkdir(path.join(os.homedir(),".artillery"),function(){callback()})}const PUBLIC_KEY=`-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+W5jx0a+iKORj7ikIlpm
MvHoL+9icjiQuyHfGYPNh4UsOnhAQhrnNGcK981I7UmI+wzKryLZu+R1rJiq8r51
Ya2f1CDwHZCXIN17+0dQEflyXl/NfAqxNaenP0GBnQ6bSFVbEflANpO9Jtn+GAz2
GutTv8taLHrPCxa1S0dbv/FestbYTDZkH4iIX7o5Z+hNtLkNKnzJesn0ZyUBpezg
YauGiPKQo6ESyzZIm7kBprH66Jiz0UcnI+w62i4aNj+wy9aegoIp0PvuAD2Q3M4y
U/k6XjxJcBj9QpxUNCqNCyaDUeagiL5Sbrk+1WkUwm54EXj8JkmixFz2elRWTNie
MwIDAQAB
-----END PUBLIC KEY-----
`;function verify(token,callback){jwt.verify(token,PUBLIC_KEY,{algorithms:["RS256"]},callback)}function verifySync(token){let payload=null;try{payload=jwt.verify(token,PUBLIC_KEY,{algorithms:["RS256"]})}catch(err){debug(err)}return payload||!1}let awsAccountId=null;async function getAccountId(cb){let err=null;if(!awsAccountId){let stsOpts={};process.env.ARTILLERY_STS_OPTS&&(stsOpts=Object.assign(stsOpts,JSON.parse(process.env.ARTILLERY_STS_OPTS)));var sts=new AWS.STS(stsOpts);try{awsAccountId=(await sts.getCallerIdentity({}).promise()).Account}catch(stsErr){err=stsErr}}if("function"==typeof cb)return cb(err,awsAccountId);if(err)throw err;return awsAccountId}function atob(data){return Buffer.from(data,"base64").toString("ascii")}function btoa(data){return Buffer.from(data).toString("base64")}async function getBackendConfig(){var bucketName=await getBucketName();try{var s3Resp=await createS3Client().getObject({Bucket:bucketName,Key:"artillerypro.rc"}).promise();return JSON.parse(Buffer.from(s3Resp.Body.toString(),"hex").toString())}catch(err){throw err}}function getRC(context,callback){let cb;cb="function"==typeof context&&void 0===callback?context:callback,getBucketName().then(bucketName=>{createS3Client().getObject({Bucket:bucketName,Key:"artillerypro.rc"},(s3Err,s3Data)=>{if(s3Err)return cb(s3Err,null);{let metadataDoc;try{metadataDoc=JSON.parse(Buffer.from(s3Data.Body.toString(),"hex").toString())}catch(parseErr){debug(parseErr),debug(s3Data.Body),debug(Buffer.from(s3Data.Body,"hex"))}return metadataDoc?cb(null,metadataDoc):cb(new Error("Could not fetch RC object"),null)}})}).catch(err=>cb(err,null))}function putRC(doc,cb){getBucketName().then(bucketName=>{var body=Buffer.from(JSON.stringify(doc)).toString("hex");createS3Client().putObject({Body:body,Bucket:bucketName,Key:"artillerypro.rc"},(s3Err,data)=>cb(s3Err||null))}).catch(err=>cb(err))}function updateRC(key,value,cb){getRC((getErr,doc)=>{if(getErr)return cb(getErr,null);doc[key]=value,putRC(doc,putErr=>putErr?cb(putErr,null):cb(null,doc))})}function getBucketName(){return new Promise((resolve,reject)=>{if(process.env.ARTILLERY_S3_BUCKET)return resolve(process.env.ARTILLERY_S3_BUCKET);getAccountId((err,accountId)=>{err?reject(err):(err=S3_BUCKET_NAME_PREFIX+"-"+accountId,resolve(err,"arn:aws:s3:::"+err))})})}function formatError(err){return chalk.red("Error")+": "+err.message+(err.code?` (${err.code})`:"")}function listAllObjectsWithPrefix(bucket,prefix,cb){const s3=createS3Client();let result=[];let params={Bucket:bucket,MaxKeys:100,Prefix:prefix};A.doWhilst(function(next){s3.listObjectsV2(params,(s3Err,s3Data)=>s3Err?next(s3Err):(debug("listObjectsV2: IsTruncated: "+s3Data.IsTruncated),debug(`listObjectsV2: KeyCount: ${s3Data.KeyCount} keys in the response`),result=result.concat(s3Data.Contents),s3Data.IsTruncated?(params.ContinuationToken=s3Data.NextContinuationToken,next(null,!0)):next(null,!1)))},function(shouldContinue){return shouldContinue},function(err){return err?cb(err):(debug(`listAllObjectsWithPrefix: returning ${result.length} results`),cb(null,result))})}function credentialsProvided(cb){var credsProvided=null!==(new AWS.Config).credentials;return cb?cb(credsProvided):credsProvided}function defaultQueryParams(options){var{tableName:options,indexName,limit,offset,created={}}=options,{start:created,end:createdTimeEnd}=created,options={TableName:options,IndexName:indexName,KeyConditions:{kind:{ComparisonOperator:"EQ",AttributeValueList:["createdTime"]}},QueryFilter:{testRunId:{ComparisonOperator:"NE",AttributeValueList:["__artilleryio:virtual:key"]}},ScanIndexForward:!1,Limit:limit};return options.KeyConditions.createdTime=created&&!createdTimeEnd?{ComparisonOperator:"GE",AttributeValueList:[created]}:!created&&createdTimeEnd?{ComparisonOperator:"LE",AttributeValueList:[createdTimeEnd]}:created&&createdTimeEnd?{ComparisonOperator:"BETWEEN",AttributeValueList:[created,createdTimeEnd]}:{ComparisonOperator:"BEGINS_WITH",AttributeValueList:["202"]},"object"==typeof offset&&(options.ExclusiveStartKey={...offset,kind:"createdTime"}),options}function statusFilterQueryParams(options){var{tableName:options,indexName,status,offset}=options,options={TableName:options,IndexName:indexName,KeyConditions:{statusName:{ComparisonOperator:"EQ",AttributeValueList:[status]}},ScanIndexForward:!1,Limit:100};return"object"==typeof offset&&(options.ExclusiveStartKey={...offset,statusName:status}),options}function tagsFilterQueryParams(options){var{tags:options=[],offset,tableName,indexName}=options,options="tags#"+[...new Set(options.map(x=>x.name+":"+x.value))].sort().join(","),tableName={TableName:tableName,IndexName:indexName,KeyConditions:{kind:{ComparisonOperator:"EQ",AttributeValueList:[options]}},ScanIndexForward:!1,Limit:100};return"object"==typeof offset&&(tableName.ExclusiveStartKey={...offset,kind:options}),tableName}function filterRecordsByDate(items,createdTimeStart,createdTimeEnd){if(createdTimeStart&&!createdTimeEnd){const start=new Date(createdTimeStart).getTime();return items.filter(i=>new Date(i.createdTime).getTime()>=start)}if(!createdTimeStart&&createdTimeEnd){const end=new Date(createdTimeEnd).getTime();return items.filter(i=>new Date(i.createdTime).getTime()<=end)}if(createdTimeStart&&createdTimeEnd){const start=new Date(createdTimeStart).getTime(),end=new Date(createdTimeEnd).getTime();return items.filter(i=>{i=new Date(i.createdTime).getTime();return i>=start&&i<=end})}return items}async function queryByTags(params){return queryBy(params,[(data,params)=>params.status?data.filter(x=>x.tagStatus===params.status):data,(data,params)=>{var{created:params={}}=params;return filterRecordsByDate(data,params.start,params.end)}])}async function queryByStatus(params){return queryBy(params,[(data,params)=>{var{created:params={}}=params;return filterRecordsByDate(data,params.start,params.end)}])}async function queryBy(params,filters=[]){var{ddb,limit,queryParams:qParams}=params;const queryParams=_.cloneDeep(qParams);let data,result=[];for(;;){if(0===(data=await ddb.query(queryParams).promise()).Items.length)break;if(result.push(...data.Items),0<filters.length&&filters.forEach(filterFn=>{result=filterFn(result,{...params,queryParams:queryParams})}),result.length<=limit&&!data.LastEvaluatedKey){data={Items:result,LastEvaluatedKey:void 0};break}if(result.length>=limit){result=result.slice(0,limit);let nextOffset;data.Items.length>limit&&(nextOffset={testRunId:result[result.length-1].testRunId,kind:result[result.length-1].kind}),data={Items:result,LastEvaluatedKey:nextOffset};break}data.LastEvaluatedKey&&(queryParams.ExclusiveStartKey=data.LastEvaluatedKey)}return data}async function getTestRunsTableName(region){region&&AWS.config.update({region:region});region=new AWS.SSM({apiVersion:"2014-11-06"});try{var ssmResponse=await region.getParameter({Name:"/artilleryio/TEST_RUNS_TABLE_NAME",WithDecryption:!0}).promise();return ssmResponse.Parameter&&ssmResponse.Parameter.Value}catch(ssmErr){if("ParameterNotFound"===ssmErr.code)return!1;throw ssmErr}}async function setTestRunsTableName(tableName,region){return putParameter("/artilleryio/TEST_RUNS_TABLE_NAME",tableName,"String",region)}module.exports={ensureDotDir:ensureDotDir,verify:verify,supportedRegions:supportedRegions,getAccountId:getAccountId,getTestRunsTableName:getTestRunsTableName,setTestRunsTableName:setTestRunsTableName,atob:atob,btoa:btoa,getRC:getRC,putRC:putRC,updateRC:updateRC,formatError:formatError,vlk:vlk,listAllObjectsWithPrefix:listAllObjectsWithPrefix,credentialsProvided:credentialsProvided,getBucketName:getBucketName,tagsFilterQueryParams:tagsFilterQueryParams,statusFilterQueryParams:statusFilterQueryParams,defaultQueryParams:defaultQueryParams,queryByTags:queryByTags,queryByStatus:queryByStatus,getBackendConfig:getBackendConfig};