Gatling Sequential scenarios - scala

I'm trying to use gatling and I have a problem.
1- I have one scenario that exec POST request for getting a list of tokens and save all tokens in csv
2- I create another scenario that exec GET request but I need a token for auth each request
My problem is before executing my first scenario my file doesn't exist and I have this following error:
Could not locate feeder file: Resource user-files/resources/token.csv not found
My code :
Scenario 1 :
val auth_app = scenario("App authentication")
.exec(http("App Authentication")
.post("/token")
.header("Content-Type", "application/x-www-form-urlencoded")
.formParamSeq(Seq(("grant_type", "password"), ("client_id", clientID), ("client_secret", clientSecret)))
.check(jsonPath("$.token").saveAs("token")))
.exec(session => {
val token_data = new File(token_file_path)
if(token_data.exists()){
val writer = new PrintWriter(new FileOutputStream(new File(token_file_path), true))
writer.write(session("access_token").as[String].trim)
writer.write("\n")
writer.close()
}
else {
val writer = new PrintWriter(new FileOutputStream(new File(token_file_path), true))
writer.println("AccessToken")
writer.write(session("access_token").as[String].trim)
writer.write("\n")
writer.close()
}
session
})
Scenario 2 :
val load_catalog = scenario("Load catalog")
.exec(http("Load catalog")
.get("/list")
.headers(Map("Content-Type" -> "application/json", "Authorization Bearer" -> "${AccessToken}")))
.feed(csv(token_file_path).random)
My setup :
setUp(
auth_app.inject(atOnceUsers(10)).protocols(httpProtocol),
load_catalog.inject(nothingFor(120 seconds), atOnceUsers(10)).protocols(httpProtocol)
)
Is it possible to have a dynamic feeder with gatling ?

Related

How can I parameterise information in Gatling scenarios

I need to send specific parameters to a scenario that is being reused multiple times with different payloads depending on the workflows. The following is the code that is to be reused:
var reqName = ""
var payloadName = ""
lazy val sendInfo: ScenarioBuilder = scenario("Send info")
.exec(session => {
reqName = session("localReqName").as[String]
payloadName = session("localPayloadName").as[String]
session}
)
.exec(jms(s"$reqName")
.send
.queue(simQueue)
.textMessage(ElFileBody(s"$payloadName.json"))
)
.exec(session => {
val filePath = s"$payloadName"
val body = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource(filePath).toURI)))
logger.info("timestamp value: " + session("timestamp").as[String])
logger.debug("Template body:\n " + body)
session
})
I know that you can chain scenarios in Scala/Gatling but how can I pass in information like reqName and payloadName down the chain, where reqName is a parameter to indicate the name of the request where the info is being sent and payloadName is the name of the actual JSON payload for the related request:
lazy val randomInfoSend: ScenarioBuilder = scenario("Send random info payloads")
.feed(csv("IDfile.csv").circular)
.randomSwitch(
(randomInfoType1prob) -> exec(
feed(timeFeeder)
.exec(session => {
payloadName = "Info1payload.json"
reqName ="Info1Send"
session.set("localReqName", "Info1Send")
session.set("localPayloadName", "Info1payload.json")
session
})
.exec(sendInfo)
),
(100.0 - randomInfoType1prob) -> exec(
feed(timeFeeder)
.exec(session => {
payloadName = "Info2Payload.json"
reqName ="Info2Send"
session.set("localReqName", "Info2Send")
session.set("localPayloadName", "Info2Payload.json")
session
})
.exec(sendInfo)
)
I attempted the above but the values of that 2 specific parameters were not passed through correctly. (The IDs and timestamps were fed through correctly though) Any suggestions?
Please properly read the Session API documentation. Session is immutable so Session#set returns a new instance.

Gatling Error when running multiple users - 'httpRequest-2' failed to execute: No attribute named 'access_token' is defined

im new to Gatling and have been trying to setup a test where my users login, get an access token, then perform some simple get requests using that token. Having 1-2 users works fine, however once i start ramping up the users i start getting spammed with this error:
[ERROR] i.g.h.a.HttpRequestAction - 'httpRequest-2' failed to execute: No attribute named 'access_token' is defined
Im thinking it could have something to do with the way I am saving and using the access token ?
class GatlingTest extends Simulation {
val httpProtocol = http
.baseUrl("https://myurl.com/api/v1")
.inferHtmlResources(BlackList(""".*\.js""", """.*\.css""", """.*\.gif""", """.*\.jpeg""", """.*\.jpg""", """.*\.ico""", """.*\.woff""", """.*\.woff2""", """.*\.(t|o)tf""", """.*\.png""", """.*detectportal\.firefox\.com.*"""), WhiteList())
.acceptLanguageHeader("en-GB,en;q=0.5")
.upgradeInsecureRequestsHeader("1")
object GetUserData {
val userData = exec(http("Get_User_Data")
.get("/user")
.header("Authorization", "Bearer ${access_token}"))
.pause(1)
}
object GetUserInfo {
val userInfo = exec(http("Get_User_Info")
.get("/userInfo")
.header("Authorization", "Bearer ${access_token}")
.header("Accept", "application/json"))
.pause(1)
}
object Login {
val sentHeaders = Map("api_key" -> "nnxzv336wt2374h6zw5x24qd", "Content-Type" -> "application/x-www-form-urlencoded", "Accept" -> "application/json")
val login = exec(http("Login_User")
.post("/login")
.basicAuth("username", "password")
.headers(sentHeaders)
.body(StringBody("grant_type=password&username=username#username.local&password=12345"))
.check(jsonPath("$.access_token").saveAs("access_token"))
)
}
val user = scenario("User").exec(Login.login).exec(GetUserData.userData, GetUserInfo.userInfo)
setUp(
user.inject(
rampUsers(5).during(2.seconds),
).protocols(httpProtocol)
)
}
I have added Authorization Bearer to the get requests, like i mentioned it does work, but as soon as 3+ users are involved i get the error.
It means the login request failed and hence, the user wasn't able to capture the access_token there.

How can I start a UiPath Robot from Groovy scripting language?

How can I start a UiPath Robot from Groovy scripting language?
I have my process on UiPath Orchestrator and I want to send a set of REST API commands to the UiPath Orchestrator from Groovy to start the process.
I have read the Orchestrator documentation, but I was not able to create a working script.
The main idea for this is that after more study different software like for example Jira or Jenkins uses this Groovy language for scripting.
Here you can find a Groovy script code that starts UiPath Process on the UiPath Orchestrator:
def builder = new groovy.json.JsonBuilder();
def root = builder{
grant_type 'refresh_token'
client_id 'YOUR CLIENT ID'
refresh_token 'YOUR REFRESH TOKEN'
}
assert root instanceof Map
def link = new URL("https://account.uipath.com/oauth/token");
def connection = link.openConnection() as HttpURLConnection;
connection.setRequestProperty("Content-Type","application/json");
connection.setRequestProperty("X-UIPATH-TenantName","YOUR TENANTNAME");
connection.setDoOutput(true);
def httpRequestBodyWriter = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()))
httpRequestBodyWriter.write(builder)
httpRequestBodyWriter.close()
def auth = "0"
if(connection.responseCode == 200)
{
def resp = connection.inputStream.text
auth = resp.substring(resp.indexOf("access_token")+15,resp.indexOf("id_token")-3)
println resp
}
def builder2 = new groovy.json.JsonBuilder();
//process without parameters
/*def root2 = builder2.startInfo {
ReleaseKey 'YOUR PROCESS ReleaseKey'
Strategy 'All'
}*/
//process with parameters
def root2 = builder2.startInfo {
ReleaseKey 'YOUR PROCESS ReleaseKey'
Strategy 'All'
InputArguments '{"param1":"Test Youtube","param2":"GroovyConsole"}'
}
assert root2 instanceof Map
def link2 = new URL("https://platform.uipath.com/[Account Logical Name]/[Tenant Logical Name]/odata/Jobs/UiPath.Server.Configuration.OData.StartJobs");
def connection2 = link2.openConnection() as HttpURLConnection;
connection2.setRequestProperty("Authorization",'Bearer '+auth);
connection2.setRequestProperty("Content-Type","application/json");
connection2.setRequestProperty("X-UIPATH-TenantName","YOUR TENANTNAME");
connection2.setRequestProperty("User-Agent","telnet");
connection2.setDoOutput(true);
def httpRequestBodyWriter2 = new BufferedWriter(new OutputStreamWriter(connection2.getOutputStream()))
httpRequestBodyWriter2.write(builder2)
httpRequestBodyWriter2.close()
println connection2.responseCode
println connection2.responseMessage

Gatling Login scenario with CSV feeder

I have to write some tests with Gatling / Scala. In my concrete case I have to login to a website with username and password (additionally there is also keycloak security). There is a CSV file with a lot of user/password lines and my goal is to login with every single user/password out of this CSV file.
The problem is I do not know how to do that. I am able to login with username/password and the security token of the keycloak with just one user. That's fine so far, but not enough. Here is what I have done so far.
The first class:
class LasttestBestand extends Simulation {
val context = Context.ladeContext("de", "integ")
val userCredentials = TestdatenImport.ladeTestDaten("de")
val httpProtocol = http
.baseUrl(s"${context.protocol}://${context.host}")
.inferHtmlResources(
BlackList(""".*\.css""", """.*\.js""", """.*\.ico""", """.*\.woff"""),
WhiteList()
)
.acceptHeader("application/json, text/plain, */*")
.acceptEncodingHeader("gzip, deflate")
.acceptLanguageHeader("de,en-US;q=0.7,en;q=0.3")
.disableFollowRedirect
.userAgentHeader(
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:63.0) Gecko/20100101 Firefox/63.0"
)
val scn = scenario("Lasttest Bestand")
.feed(userCredentials.csvFeeder)
.exec(Login.holeAccessToken("${Benutzername}", "${Passwort}", context))
.exec(Suche.ladeKundensucheResourcen(context))
setUp(
scn.inject(
atOnceUsers(1)
)
).protocols(httpProtocol)
}
The feeder class:
class TestdatenImport(val csvFeeder: BatchableFeederBuilder[String]) {}
object TestdatenImport {
def ladeTestDaten(land: String) = {
val csvFeeder = csv(s"data/eca-bb3-${land}-testdaten.csv").circular
new TestdatenImport(
csvFeeder
)
}
}
The Login:
object Login {
def holeAccessToken(
benutzer: String,
passwort: String,
context: Context
): ChainBuilder = {
val keycloakUri = s"${context.protocol}://${context.keycloakHost}"
val redirectUri =
s"${context.protocol}%3A%2F%2F${context.host}%2Fapp%2F%3Fredirect_fragment%3D%252Fsuche"
exec(
http("Login Page")
.get(
s"$keycloakUri/auth/realms/${context.realm}/protocol/openid-connect/auth"
)
.queryParam("client_id", "bestand-js")
.queryParam("redirect_uri", redirectUri)
.queryParam("state", UUID.randomUUID().toString())
.queryParam("nonce", UUID.randomUUID().toString())
.queryParam("response_mode", "fragment")
.queryParam("response_type", "code")
.queryParam("scope", "openid")
.header(
"Accept",
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
)
.header("Upgrade-Insecure-Requests", "1")
.check(status.is(200))
.check(
css("#kc-form-login")
.ofType[Node]
.transform(variable => {
variable.getAttribute("action")
})
.saveAs("loginUrl")
)
).exec(
http("Login")
.post("${loginUrl}")
.formParam("username", benutzer)
.formParam("password", passwort)
.header(
"Accept",
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
)
.header("Upgrade-Insecure-Requests", "1")
.check(status.is(302))
.check(
header("Location")
.transform(url => {
url.substring(url.indexOf("code=") + 5, url.length())
})
.saveAs("code")
)
.check(header("Location").saveAs("nextPage"))
)
.exec(
http("Fetch Token")
.post(
s"$keycloakUri/auth/realms/${context.realm}/protocol/openid-connect/token"
)
.header("Accept", "*/*")
.header("Origin", s"${context.protocol}://${context.host}")
.formParam("code", "${code}")
.formParam("grant_type", "authorization_code")
.formParam("client_id", "bestand-js")
.formParam("redirect_uri", redirectUri)
.check(status.is(200))
.check(
jsonPath("$..access_token")
.saveAs("accessToken")
)
)
}
}
As you can see I added a feeder to the scenario, but I do not know how to "repeat" the login the number of times there are user/password lines in the CSV file. What do I do wrong?
Inject as many users as you have entries in your CSV file, eg:
scn.inject(
rampUsers(numberOfEntries) during(10 minutes)
)

Scala - Flink Monitoring API (Upload Jobs)

Good Day, I have an Issue uploading Jobs to Flink API using Scala
All Get request seem to work
import scalaj.http._
val url: String = "http://127.0.0.1:8081"
val response: HttpResponse[String] = Http(url+"/config").asString
return response
When I try Uploading a JAR file through CURL (works)
curl -vvv -X POST -H "Expect:" -F "jarfile=#/home/Downloads/myJob.jar" http://127.0.0.1:8081/jars/upload
Now I would Like to upload using SCALA
The documentation does not provide a working example and I am fairly new to this type of post: https://ci.apache.org/projects/flink/flink-docs-release-1.3/monitoring/rest_api.html#submitting-programs
Currently my code is (Does not Work):
Taken from : https://github.com/Guru107/flinkjobuploadplugin/tree/master/src/main/java/com/github/guru107 - Edited to my needs
// Ideal Case is to upload a Jar File as a multipart in Scala
import java.io.IOException
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.mime.MultipartEntityBuilder
import org.apache.http.impl.client.{HttpClients, LaxRedirectStrategy}
import org.apache.http.message.BasicHeader
import org.apache.http.util.EntityUtils
val requestUrl = "http://localhost:8081/jars/upload"
val jarPath = "#/home/Downloads/myJob.jar"
val httpClient: CloseableHttpClient = HttpClients.custom.setRedirectStrategy(new LaxRedirectStrategy).build
val fileToUpload: File = new File(jarPath)
val uploadFileUrl: HttpPost = new HttpPost(requestUrl)
val builder: MultipartEntityBuilder = MultipartEntityBuilder.create
builder.addBinaryBody("jarfile", fileToUpload)
val multipart: HttpEntity = builder.build
var jobUploadResponse: JSONObject = null
uploadFileUrl.setEntity(multipart)
var response: CloseableHttpResponse = null
try {
response = httpClient.execute(uploadFileUrl)
println("response: " + response)
response.setHeader(new BasicHeader("Expect", ""))
response.setHeader(new BasicHeader("content-type", "application/x-java-archive"))
val bodyAsString = EntityUtils.toString(response.getEntity, "UTF-8")
println("bodyAsString: " + bodyAsString)
jobUploadResponse = new JSONObject(bodyAsString)
println("jobUploadResponse: " + jobUploadResponse)
}
It fails to upload file.
Please provide a working example or link of scala example to upload a job/jar file to flink in scala
Thanks in Advance
You can use the client code from com.github.mjreid.flinkwrapper
And upload jar file with scala code:
val apiEndpoint: String = as.settings.config.getString("flink.url") //http://<flink_web_host>:<flink_web_port>
val client = FlinkRestClient(apiEndpoint, as)
client.runProgram(<jarId>)