Skip to content

Commit

Permalink
feat(dsl): Kotlin scenario tags + dataset + campaign (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
boddissattva authored Apr 10, 2024
1 parent 63b4fc6 commit a7b0bf6
Show file tree
Hide file tree
Showing 26 changed files with 1,110 additions and 420 deletions.
3 changes: 3 additions & 0 deletions chutney/packaging/local-api-unsecure/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<jmxPort>54320</jmxPort>
</configuration>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
Expand Down
3 changes: 3 additions & 0 deletions chutney/packaging/local-dev/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<jmxPort>54321</jmxPort>
</configuration>
</plugin>
<plugin>
<groupId>com.github.ulisesbocchio</groupId>
Expand Down
2 changes: 1 addition & 1 deletion chutney/packaging/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
<layout>ZIP</layout>
<mainClass>${mainClass}</mainClass>
<finalName>${chutney.package.file}</finalName>
<wait>1000</wait>
<wait>2000</wait>
<jmxPort>54321</jmxPort>
</configuration>
<executions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1195,7 +1195,7 @@ fun ChutneyStepBuilder.SeleniumFirefoxDriverInitAction(
driverPath: String? = null,
browserPath: String? = null,
firefoxProfile: String? = null,
firefoxPreferences: Map<String, Object>? = null,
firefoxPreferences: Map<String, Any>? = null,
outputs: Map<String, Any> = mapOf(),
validations: Map<String, Any> = mapOf(),
strategy: Strategy? = null
Expand Down Expand Up @@ -2156,14 +2156,15 @@ fun ChutneyStepBuilder.RadiusAccountingAction(

// Helpers
private fun <T> List<Pair<String, T?>?>.notEmptyToMap(): Map<String, T> {
return (this
return this
.filterNotNull()
.filter { it.second != null }
.filterIsInstance<Pair<String, T>>()
.filter {
when (it.second) {
is Collection<*> -> (it.second as Collection<*>).isNotEmpty()
is Map<*, *> -> (it.second as Map<*, *>).isNotEmpty()
else -> true
}
} as List<Pair<String, T>>).toMap()
}.toMap()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2017-2023 Enedis
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.chutneytesting.kotlin.dsl

data class Campaign(
val id: Int? = null,
val title: String,
val description: String? = null,
val environment: String,
val parallelRun: Boolean = false,
val retryAuto: Boolean = false,
val datasetId: String? = null,
val scenarioIds: List<Int> = emptyList(),
val tags: List<String> = emptyList()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2017-2023 Enedis
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.chutneytesting.kotlin.dsl

data class Dataset(
val name: String,
val description: String = "",
val uniqueValues: Set<KeyValue> = emptySet(),
val multipleValues: List<List<KeyValue>> = emptyList(),
val tags: List<String> = emptyList()
) {
val id: String = name.replace(" ", "_")

data class KeyValue(val key: String, val value: String)
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,23 @@ import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
@DslMarker
annotation class ChutneyScenarioDsl

fun Scenario(id: Int? = null, title: String, defaultDataset: String? = null, block: ChutneyScenarioBuilder.() -> Unit): ChutneyScenario {
return ChutneyScenarioBuilder(id, title, defaultDataset).apply(block).build()
fun Scenario(
id: Int? = null,
title: String,
defaultDataset: String? = null,
tags: List<String> = emptyList(),
block: ChutneyScenarioBuilder.() -> Unit
): ChutneyScenario {
return ChutneyScenarioBuilder(id, title, defaultDataset, tags).apply(block).build()
}

@ChutneyScenarioDsl
class ChutneyScenarioBuilder(val id: Int? = null, val title: String = "", val defaultDataset: String? = null) {
class ChutneyScenarioBuilder(
val id: Int? = null,
val title: String = "",
val defaultDataset: String? = null,
val tags: List<String> = emptyList(),
) {
var description = title
private val givens = mutableListOf<ChutneyStep>()
private var `when`: ChutneyStep? = null
Expand Down Expand Up @@ -64,7 +75,7 @@ class ChutneyScenarioBuilder(val id: Int? = null, val title: String = "", val de
}
}

fun build(): ChutneyScenario = ChutneyScenario(id, title, description, defaultDataset, givens, `when`, thens)
fun build(): ChutneyScenario = ChutneyScenario(id, title, description, defaultDataset, tags, givens, `when`, thens)
}

@JsonInclude(NON_EMPTY)
Expand Down Expand Up @@ -153,7 +164,7 @@ object Mapper {
var json = mapper.writeValueAsString(value)
json = json.replace(": [ ]", ": []")
json = json.replace(": { }", ": {}")
json += System.getProperty("line.separator")
json += System.lineSeparator()
return json
}
}
Expand All @@ -178,6 +189,7 @@ class ChutneyScenario(
val title: String = "",
val description: String = "",
@JsonIgnore val defaultDataset: String? = null,
@JsonIgnore val tags: List<String> = emptyList(),
@JsonInclude(NON_EMPTY) val givens: List<ChutneyStep> = mutableListOf(),
@JsonInclude(NON_NULL) val `when`: ChutneyStep? = null,
@JsonInclude(NON_EMPTY) val thens: List<ChutneyStep> = mutableListOf()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1198,7 +1198,7 @@ fun ChutneyStepBuilder.SeleniumFirefoxDriverInitTask(
driverPath: String,
browserPath: String,
firefoxProfile: String,
firefoxPreferences: Map<String, Object>,
firefoxPreferences: Map<String, Any>,
outputs: Map<String, Any> = mapOf(),
validations: Map<String, Any> = mapOf(),
strategy: Strategy? = null
Expand Down Expand Up @@ -2175,14 +2175,15 @@ fun ChutneyStepBuilder.RadiusAccountingTask(

// Helpers
private fun <T> List<Pair<String, T?>?>.notEmptyToMap(): Map<String, T> {
return (this
return this
.filterNotNull()
.filter { it.second != null }
.filterIsInstance<Pair<String, T>>()
.filter {
when (it.second) {
is Collection<*> -> (it.second as Collection<*>).isNotEmpty()
is Map<*, *> -> (it.second as Map<*, *>).isNotEmpty()
else -> true
}
} as List<Pair<String, T>>).toMap()
}.toMap()
}
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ class ChutneyScenarioExecutionContext(
} else {
ChutneyStepImpl(step.definition().type)
},
step.definition().strategy.map { Strategy(it.type, it.strategyProperties as Map<String, String>) }.orElse(null)
step.definition().strategy.map { Strategy(it.type, it.strategyProperties.mapValues { v -> v.toString() }) }.orElse(null)
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package com.chutneytesting.kotlin.synchronize

import com.chutneytesting.environment.api.environment.dto.EnvironmentDto
import com.chutneytesting.kotlin.dsl.Campaign
import com.chutneytesting.kotlin.dsl.ChutneyScenario
import com.chutneytesting.kotlin.dsl.Dataset
import com.chutneytesting.kotlin.dsl.Mapper
import com.chutneytesting.kotlin.util.ChutneyServerInfo
import com.chutneytesting.kotlin.util.HttpClient
import com.chutneytesting.kotlin.util.HttpClientException
import com.fasterxml.jackson.databind.ObjectMapper
import org.apache.commons.text.StringEscapeUtils.escapeJson
import java.util.*

interface ChutneyServerService {
fun getAllScenarios(serverInfo: ChutneyServerInfo): List<LinkedHashMap<String, Any>>
fun createOrUpdateJsonScenario(serverInfo: ChutneyServerInfo, scenario: ChutneyScenario): Int
fun getEnvironments(serverInfo: ChutneyServerInfo): Set<EnvironmentDto>
fun createOrUpdateDataset(serverInfo: ChutneyServerInfo, dataset: Dataset): String
fun createOrUpdateCampaign(serverInfo: ChutneyServerInfo, campaign: Campaign): Int
}

object ChutneyServerServiceImpl : ChutneyServerService {
Expand Down Expand Up @@ -44,15 +50,15 @@ object ChutneyServerServiceImpl : ChutneyServerService {
}
}

fun updateJsonScenario(
private fun updateJsonScenario(
serverInfo: ChutneyServerInfo,
scenario: ChutneyScenario,
remoteScenario: LinkedHashMap<String, Any>
): Int {
val generatedTag = "KOTLIN"
var tags = remoteScenario["tags"] as List<String>
if (!tags.contains(generatedTag)) {
tags = tags.plus(generatedTag)
var tags = emptyList<String>()
val remoteTags = remoteScenario["tags"]
if (remoteTags is List<*>) {
tags = (scenario.tags + remoteTags.filterIsInstance<String>()).distinct()
}
val body = """
{
Expand Down Expand Up @@ -83,14 +89,13 @@ object ChutneyServerServiceImpl : ChutneyServerService {
}

private fun createJsonScenario(serverInfo: ChutneyServerInfo, scenario: ChutneyScenario): Int {
val generatedTag = "KOTLIN"
val body = """
{
${buildIdJson(scenario)}
"content": "${escapeJson(scenario.toString())}",
"title": "${scenario.title}",
"description": "${scenario.description}",
"tags": ["$generatedTag"],
"tags": ${Mapper.toJson(scenario.tags)},
${buildDefaultDatasetJson(scenario)}
}
""".trimIndent()
Expand Down Expand Up @@ -125,4 +130,61 @@ object ChutneyServerServiceImpl : ChutneyServerService {
override fun getEnvironments(serverInfo: ChutneyServerInfo): Set<EnvironmentDto> {
return HttpClient.get(serverInfo, "/api/v2/environment")
}

private const val chutneyDatasetEndpoint = "/api/v1/datasets"
private fun Dataset.payload(): String {
val om = ObjectMapper()
return """
{
"id": "$id",
"name": "$name",
"description": "$description",
"uniqueValues": ${om.writeValueAsString(uniqueValues)},
"multipleValues": ${om.writeValueAsString(multipleValues)},
"tags": ${om.writeValueAsString(tags)}
}
""".trimIndent()
}

override fun createOrUpdateDataset(serverInfo: ChutneyServerInfo, dataset: Dataset): String {
val result = if (datasetIdExists(serverInfo, dataset.id)) {
HttpClient.put<HashMap<String, Any>>(serverInfo, chutneyDatasetEndpoint, dataset.payload())
} else {
HttpClient.post<HashMap<String, Any>>(serverInfo, chutneyDatasetEndpoint, dataset.payload())
}
return result["id"] as String
}

private fun datasetIdExists(serverInfo: ChutneyServerInfo, id: String): Boolean {
return try {
Optional.ofNullable(
HttpClient.get<HashMap<String, Any>>(serverInfo, "${chutneyDatasetEndpoint}/${id}")["id"]
).map { true }.orElseGet { false }
} catch (e: Exception) {
false
}
}

private const val chutneyCampaignEndpoint = "/api/ui/campaign/v1"
private fun Campaign.payload(): String {
val om = ObjectMapper()
return """
{
${Optional.ofNullable(id).map { l -> "\"id\": $l," }.orElseGet { "" }}
"title": "$title",
"description": "$description",
"scenarioIds": ${om.writeValueAsString(scenarioIds.map(Int::toString))},
"environment": "$environment",
"parallelRun": $parallelRun,
"retryAuto": $retryAuto,
${Optional.ofNullable(datasetId).map { d -> "\"datasetId\": \"$d\"," }.orElseGet { "" }}
"tags": ${om.writeValueAsString(tags)}
}
""".trimIndent()
}

override fun createOrUpdateCampaign(serverInfo: ChutneyServerInfo, campaign: Campaign): Int {
val result = HttpClient.post<HashMap<String, Any>>(serverInfo, chutneyCampaignEndpoint, campaign.payload())
return result["id"] as Int
}
}
Loading

0 comments on commit a7b0bf6

Please sign in to comment.