While controller is not working correctly - jmeter

On a http request, getting a task status as ongoing but want to run it in loop till it is sucessful. I am using while controller with a counter which is not working.
http response
{
"data": {
"uri": null,
"taskId": "f5b6aaf3-8b14-49ba-a495-788eef5c523b",
"taskStatus": "Ongoing"
},
"apiUrl": "http:\/\/imp-901v.pii.int:8081\/release01-nightly-api\/\/2192_IND_1_40",
"statusCode": "102"
}
setting for while controller :
setting for counter:
transaction setting
user defined variable:
What I missed here ?

There are at least following problems with your script:
You need to put statsCounter as the "Exported Variable Name" in the Counter (or just remove the counter and use __jm__While Controller__idx pre-defined variable instead)
You need to change props to vars
props - is a shorthand for JMeter Properties
vars - is a shorthand for JMeter Variables
More information: Top 8 JMeter Java Classes You Should Be Using with Groovy

Related

How to assert failure if string is in JSON response from http request JMeter

I am trying to write a test that ensures that the name property in a JSON response is not MYGROUP. I'm stuck here because I'm trying to use the code from a test that checks that the name property is MYGROUP. I know I need to fix something in the if condition of this test:
# Check AD group deletion
- url: ${ADSubscriptions}/${NetworkID}/clientsyncs/${syncId}/groups
label: 1360_CheckADGroupDeletion
method: GET
headers:
Authorization: Bearer ${access_token}
Content-Type: "application/json"
Accept: "application/json, text/plain, */*"
assert-httpcode:
- 200
- 202
jsr223:
- langauge: groovy
execute: after
script-text: |
import groovy.json.JsonSlurper
def slurperresponse = new JsonSlurper().parseText(prev.getResponseDataAsString())
for (entry in slurperresponse){
if(entry.name == "MYGROUP" || entry.name == "mygroup" ){
{RETURN FALSE HERE}
break;
}
}
- langauge: groovy
execute: after
script-file: jsr223/logger.groovy
parameters: check_adgroup_deletion
The expected json structure for the request used in the test looks like this:
[
{
"id": "id1",
"name": "MYGROUP",
"selected": true
}
]
The above response would equate to a failing test. The below would equate to a passing test.
[
{
"id": "id1",
"name": "MYGROUP",
"selected": false
}
]
The code snippet you're looking for is prev.setSuccessful(false) where prev stands for the parent SampleResult class instance.
See the above JavaDoc for all available functions and Top 8 JMeter Java Classes You Should Be Using with Groovy article to learn more about JMeter API shorthands available for JSR223 blocks.
In particular your case it would be easier to use assert-jsonpath Taurus assertion

How to use Validating String Parameter Plugin in the Jenkins declarative pipeline code?

I'm curious as to if it is possible to define the String Validator Plugin in a Jenkins declarative pipeline code? I already have a working setup defined via job UI, but my intention is to put everything in the pipeline defined as:
string(name='', ......).
Unfortunately, all examples on the web are explaining how to set up the validation in the UI, which I already have. Or is it one of those plugins that is not supported in a pipeline model?
This plugin can be used as a validatingString parameter in the declarative pipeline code.
pipeline {
agent any
parameters {
validatingString(name: "test", defaultValue: "", regex: /^abc-[0-9]+$/, failedValidationMessage: "Validation failed!", description: "ABC")
}
stages {
stage("Test") {
steps {
echo "${params.test}"
}
}
}
}
Keep in mind, that the first time you will run your pipeline after adding this code, the parameter won't show up - it will be added during the first run of the pipeline. After that you will see the parameter in the pipeline UI:
And when you run the parameterized pipeline, the validation will be applied:
I am not sure why, but when I wrapped each of my arguments into a named key, I was able to bypass this error I received:
So this will give you javaposse.jobdsl.dsl.helpers.BuildParametersContext.validatingString() is applicable for argument types Error:
validatingString (
"EMAIL_VALIDATED"
'defaultEmail'
'someregex',
'somevalidationfailuremessage',
'Use your email'
)
However, this worked:
validatingString {
name("EMAIL_VALIDATED")
defaultValue('defaultEmail')
regex('someregex')
failedValidationMessage('somevalidationfailuremessage')
description('Use your email')
}

CloudFoundry manifest.yml with objects as env variables

so I am building a SpringBootApplication and I currently have the following settings in the yml:
my:
caller:
- id: someId
url: someUrl
context: someContext
- id: someId2
url: someUrl2
context: someContext2
So basically it's a list of objects (I've created a POJO which has the 3 fields). Those objects are represented as a List in another class which is a #Component and has a #ConfigurationProperties(prefix = "my") and the List of POJOs is with #NestedConfigurationproperty.
So far everything works perfectly, Spring constructs the objects from the application.yml and fills the List just fine, however I can't simulate this configuration in CloudFoundry. I'm using a different manifest.yml for cloudfoundry, and I'm trying to place this structure in the env part of the manifest but it's not working (Cloudfoundry ignores it).
It looks something like this:
env:
my:
caller:
- id: someId
url: someUrl
context: someContext
- id: someId2
url: someUrl2
context: someContext2
I know with simple lines it works (for example ev_my_caller_id) but that way I can construct only 1 object, not a whole list and I haven't found anything in the CloudFoundry doc on how to construct multiple objects from the manifest.
If anyone has any ideas I would be really grateful!
The env block of the Cloud Foundry cli's manifest.yml file has a specific format. You cannot use an arbitrary structure and expect it to work.
The format is:
env:
var_name_1: val_1
var_name_2: val_2
See docs for more details -> https://docs.cloudfoundry.org/devguide/deploy-apps/manifest.html#env-block
If you set the env variable with the correct name, you can use that to override certain values in Spring. Thanks to Spring Boot's external configuration support. Maybe that would be an option for you here.
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
Ex: MY_PROPERTY=1234 would override my.property in application.properties.
You could use the SPRING_APPLICATION_JSON environment variable mentioned in the Spring Boot external config link that Daniel provided.
In your case, that would like something like this:
env:
SPRING_APPLICATION_JSON: '{ "my": { "caller": [{ "id": "someId", "url": "someUrl", "context": "someContext" }, { "id": "someId2", "url": "someUrl2", "context": "someContext2" }]}}'
Not sure what you are trying to do, but you can try something like this:
env:
test: '{ whatever complex object/variables }'
e.g.
env:
test: '{ variable = value, variable2 = value2 }'

Grails 3 - Spring Rest Docs using Rest assured giving SnippetException when using JSON views

I am trying to integrate Spring REST docs with rest assured with Grails 3.1.4 application. I am using JSON Views.
Complete code is at https://github.com/rohitpal99/rest-docs
In NoteController when I use
List<Note> noteList = Note.findAll()
Map response = [totalCount: noteList.size(), type: "note"]
render response as grails.converters.JSON
Document generation works well.
But I want to use JSON views like
respond Note.findAll()
where I have _notes.gson and index.gson files in /views directory. I get a SnippetException. A usual /notes GET request response is correct.
rest.docs.ApiDocumentationSpec > test and document get request for /index FAILED
org.springframework.restdocs.snippet.SnippetException at ApiDocumentationSpec.groovy:54
with no message. Unable to track why it occurs.
Please suggest.
Full stacktrace
org.springframework.restdocs.snippet.SnippetException: The following parts of the payload were not documented:
{
"instanceList" : [ {
"title" : "Hello, World!",
"body" : "Integration Test from Hello"
}, {
"title" : "Hello, Grails",
"body" : "Integration Test from Grails"
} ]
}
at org.springframework.restdocs.payload.AbstractFieldsSnippet.validateFieldDocumentation(AbstractFieldsSnippet.java:134)
at org.springframework.restdocs.payload.AbstractFieldsSnippet.createModel(AbstractFieldsSnippet.java:74)
at org.springframework.restdocs.snippet.TemplatedSnippet.document(TemplatedSnippet.java:64)
at org.springframework.restdocs.generate.RestDocumentationGenerator.handle(RestDocumentationGenerator.java:192)
at org.springframework.restdocs.restassured.RestDocumentationFilter.filter(RestDocumentationFilter.java:63)
at com.jayway.restassured.internal.filter.FilterContextImpl.next(FilterContextImpl.groovy:73)
at org.springframework.restdocs.restassured.RestAssuredRestDocumentationConfigurer.filter(RestAssuredRestDocumentationConfigurer.java:65)
at com.jayway.restassured.internal.filter.FilterContextImpl.next(FilterContextImpl.groovy:73)
at com.jayway.restassured.internal.RequestSpecificationImpl.applyPathParamsAndSendRequest(RequestSpecificationImpl.groovy:1574)
at com.jayway.restassured.internal.RequestSpecificationImpl.get(RequestSpecificationImpl.groovy:159)
at rest.docs.ApiDocumentationSpec.$tt__$spock_feature_0_0(ApiDocumentationSpec.groovy:54)
at rest.docs.ApiDocumentationSpec.test and document get request for /index_closure2(ApiDocumentationSpec.groovy)
at groovy.lang.Closure.call(Closure.java:426)
at groovy.lang.Closure.call(Closure.java:442)
at grails.transaction.GrailsTransactionTemplate$1.doInTransaction(GrailsTransactionTemplate.groovy:70)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
at grails.transaction.GrailsTransactionTemplate.executeAndRollback(GrailsTransactionTemplate.groovy:67)
at rest.docs.ApiDocumentationSpec.test and document get request for /index(ApiDocumentationSpec.groovy)
REST Docs will fail a test if you try to document something that isn't there or fail to document something that is there. You've documented two fields in your test:
responseFields(
fieldWithPath('totalCount').description('Total count'),
fieldWithPath('type').description("Type of result")
)))
REST Docs has failed the test as some parts of the response haven't been documented. Specifically an instanceList array that contains maps with two keys: title and body. You can document those and the other two fields with something like this:
responseFields(
fieldWithPath('totalCount').description('Total count'),
fieldWithPath('type').description("Type of result"),
fieldWithPath('instanceList[].title').description('Foo'),
fieldWithPath('instanceList[].body').description('Bar')
)))
If you don't care about potentially missing fields, you can use relaxedResponseFields instead of responseFields:
relaxedResponseFields(
fieldWithPath('totalCount').description('Total count'),
fieldWithPath('type').description("Type of result")
))
This won't fail the test if some fields are not mentioned.

How do I use CloudFormation resources in a Lambda function?

I have added a Redis ElastiCache section to my s-resource-cf.json (a CloudFormation template), and selected its hostname as an output.
"Resources": {
...snip...
"Redis": {
"Type": "AWS::ElastiCache::CacheCluster",
"Properties": {
"AutoMinorVersionUpgrade": "true",
"AZMode": "single-az",
"CacheNodeType": "cache.t2.micro",
"Engine": "redis",
"EngineVersion": "2.8.24",
"NumCacheNodes": "1",
"PreferredAvailabilityZone": "eu-west-1a",
"PreferredMaintenanceWindow": "tue:00:30-tue:01:30",
"CacheSubnetGroupName": {
"Ref": "cachesubnetdefault"
},
"VpcSecurityGroupIds": [
{
"Fn::GetAtt": [
"sgdefault",
"GroupId"
]
}
]
}
}
},
"Outputs": {
"IamRoleArnLambda": {
"Description": "ARN of the lambda IAM role",
"Value": {
"Fn::GetAtt": [
"IamRoleLambda",
"Arn"
]
}
},
"RedisEndpointAddress": {
"Description": "Redis server host",
"Value": {
"Fn::GetAtt": [
"Redis",
"Address"
]
}
}
}
I can get CloudFormation to output the Redis server host when running sls resources deploy, but how can I access that output from within a Lambda function?
There is nothing in this starter project template that refers to that IamRoleArnLambda, which came with the example project. According to the docs, templates are only usable for project configuration, they are not accessible from Lambda functions:
Templates & Variables are for Configuration Only
Templates and variables are used for configuration of the project only. This information is not usable in your lambda functions. To set variables which can be used by your lambda functions, use environment variables.
So, then how do I set an environment variable to the hostname of the ElastiCache server after it has been created?
You can set environment variables in the environment section of a function's s-function.json file. Furthermore, if you want to prevent those variables from being put into version control (for example, if your code will be posted to a public GitHub repo), you can put them in the appropriate files in your _meta/variables directory and then reference those from your s-function.json files. Just make sure you add a _meta line to your .gitignore file.
For example, in my latest project I needed to connect to a Redis Cloud server, but didn't want to commit the connection details to version control. I put variables into my _meta/variables/s-variables-[stage]-[region].json file, like so:
{
"redisUrl": "...",
"redisPort": "...",
"redisPass": "..."
}
…and referenced the connection settings variables in that function's s-function.json file:
"environment": {
"REDIS_URL": "${redisUrl}",
"REDIS_PORT": "${redisPort}",
"REDIS_PASS": "${redisPass}"
}
I then put this redis.js file in my functions/lib directory:
module.exports = () => {
const redis = require('redis')
const jsonify = require('redis-jsonify')
const redisOptions = {
host: process.env.REDIS_URL,
port: process.env.REDIS_PORT,
password: process.env.REDIS_PASS
}
return jsonify(redis.createClient(redisOptions))
}
Then, in any function that needed to connect to that Redis database, I imported redis.js:
redis = require('../lib/redis')()
(For more details on my Serverless/Redis setup and some of the challenges I faced in getting it to work, see this question I posted yesterday.)
update
CloudFormation usage has been streamlined somewhat since that comment was posted in the issue tracker. I have submitted a documentation update to http://docs.serverless.com/docs/templates-variables, and posted a shortened version of my configuration in a gist.
It is possible to refer to a CloudFormation output in a s-function.json Lambda configuration file, in order to make those outputs available as environment variables.
s-resource-cf.json output section:
"Outputs": {
"redisHost": {
"Description": "Redis host URI",
"Value": {
"Fn::GetAtt": [
"RedisCluster",
"RedisEndpoint.Address"
]
}
}
}
s-function.json environment section:
"environment": {
"REDIS_HOST": "${redisHost}"
},
Usage in a Lambda function:
exports.handler = function(event, context) {
console.log("Redis host: ", process.env.REDIS_HOST);
};
old answer
Looks like a solution was found / implemented in the Serverless issue tracker (link). To quote HyperBrain:
CF Output variables
To have your lambda access the CF output variables you have to give it the cloudformation:describeStacks access rights in the lambda IAM role.
The CF.loadVars() promise will add all CF output variables to the process'
environment as SERVERLESS_CF_OutVar name. It will add a few ms to the
startup time of your lambda.
Change your lambda handler as follows:
// Require Serverless ENV vars
var ServerlessHelpers = require('serverless-helpers-js');
ServerlessHelpers.loadEnv();
// Require Logic
var lib = require('../lib');
// Lambda Handler
module.exports.handler = function(event, context) {
ServerlessHelpers.CF.loadVars()
.then(function() {
lib.respond(event, function(error, response) {
return context.done(error, response);
});
})
};

Resources