Skip to content

Commit

Permalink
adding example 3
Browse files Browse the repository at this point in the history
  • Loading branch information
cdsap committed Sep 3, 2019
1 parent 9fd26d8 commit d43a53f
Show file tree
Hide file tree
Showing 15 changed files with 119 additions and 37 deletions.
84 changes: 79 additions & 5 deletions README.md
Expand Up @@ -5,6 +5,8 @@

Bagan is a framework that helps to automate the execution, reporting and collection of data with different types of experiments in Gradle projects using Kubernetes.

![alt text](resources/experiment2.png "Bagan image")

# Table of Contents
1. [How to use Bagan](#how-to-use-bagan)
2. [bagan_conf.json](#bagan_conf.json)
Expand All @@ -21,14 +23,14 @@ Bagan is a framework that helps to automate the execution, reporting and collect


## How to use Bagan <a name="how-to-use-bagan"></a>
Once you have downloaded this repository you need to set up the `bagan_conf.json`. There you can setup different properties
Once you have downloaded this repository you need to set up the `bagan_conf.json`. You can setup different properties
like the type of experiments you want to apply, the target repository or the resources you want to use in the Kubernetes environments.

Bagan will be executed with the `./bagan` command following the next format:

` ./bagan MODE COMMAND`

Bagan will execute the experiments in a Kubernetes environment. For each experiment, Bagan will create a Helm Release where it will run the target repository applying the experimentation.
The execution framework and reporting happens in Kubernetes environment. For each experiment, Bagan will create a Helm Release where it will run the target repository applying the experimentation.
To report the information of the build Bagan will inject Talaiot in the Gradle configuration of the project using InfluxDb as time-series database and Grafana as dashboard visualization tool.

Bagan can deploy a new cluster or will use an existing cluster to execute the experimentation defined
Expand Down Expand Up @@ -58,8 +60,8 @@ Example:
"clusterName": "",
"machine": "n1-standard-4",
"private": true,
"ssh": "/Users/inaki/.ssh/id_rsa",
"known_hosts": "/Users/inaki/.ssh/known_hosts",
"ssh": "/user/.ssh/id_rsa",
"known_hosts": "/user/.ssh/known_hosts",
"iterations": 20,
"experiments": {
"properties": [
Expand Down Expand Up @@ -319,16 +321,88 @@ Simple example of private repository generated by Android Studio
| zone |asia-southeast1-b |
| repository |git@github.com:cdsap/TestPrivateRepository.git |
| private |true |
| experiments |gradle properties :{ "org.gradle.jvmargs": ["-Xmx3g","-Xmx4g"]|
| experiments |gradle properties :{ "org.gradle.jvmargs": ["-Xmx3g","-Xmx4g"]}|
| command | ./gradlew clean assembleDebug |
| iterations |20 |

2 experiments of Type Gradle Properties will be generated:
* -Xmx3g
* -Xmx4g

Result:

![alt text](resources/experiment1.png "experiment1")


### Example 2

Experimentation on Google project Plaid, with kapt properties

| bagan_conf | |
|-----------------|--------------------------------------------------------------|
| machine |n2-standard-8 |
| zone |asia-southeast1-b |
| repository |https://github.com/android/plaid.git |
| private |false |
| experiments |gradle properties:<br>{ "org.gradle.jvmargs": ["-Xmx2g","-Xmx4g"] }<br>{ "org.gradle.caching": ["true","false"] }<br>{ "kapt.incremental.apt": ["true","false"] }<br>{ "kapt.use.worker.api": ["true","false"] }<br>|
| command | ./gradlew clean assembleDebug |
| iterations |20 |

"properties": [
{
"name": "org.gradle.jvmargs",
"options": ["-Xmx2g","-Xmx4g"]
},
{
"name": "org.gradle.caching",
"options": ["true","false"]
},
{
"name": "kapt.incremental.apt",
"options": ["true","false"]
},
{
"name": "kapt.use.worker.api",
"options": ["true","false"]
}

16 experiments of Type Gradle Properties will be generated:

|Experiments | | ||
|----------------------|-------------------------------------------|----|--------------------------------|
| org.gradle.jvmargs="-Xmx2g"<br>org.gradle.caching="true"<br> kapt.incremental.apt="true" <br>kapt.use.worker.api="true" | org.gradle.jvmargs="-Xmx2g"<br> org.gradle.caching="true"<br> kapt.incremental.apt="true" <br>kapt.use.worker.api="false" | org.gradle.jvmargs="-Xmx2g"<br> org.gradle.caching="true"<br> kapt.incremental.apt="false" <br>kapt.use.worker.api="false" | org.gradle.jvmargs="-Xmx2g"<br> org.gradle.caching="true"<br> kapt.incremental.apt="false" <br>kapt.use.worker.api="true" |
| org.gradle.jvmargs="-Xmx2g"<br>org.gradle.caching="false"<br> kapt.incremental.apt="true" <br>kapt.use.worker.api="true" | org.gradle.jvmargs="-Xmx2g"<br> org.gradle.caching="false"<br> kapt.incremental.apt="true" <br>kapt.use.worker.api="false" | org.gradle.jvmargs="-Xmx2g"<br> org.gradle.caching="false"<br> kapt.incremental.apt="false" <br>kapt.use.worker.api="true" | org.gradle.jvmargs="-Xmx2g"<br> org.gradle.caching="false"<br> kapt.incremental.apt="false" <br>kapt.use.worker.api="false" |
| org.gradle.jvmargs="-Xmx4g"<br>org.gradle.caching="true"<br> kapt.incremental.apt="true" <br>kapt.use.worker.api="true" | org.gradle.jvmargs="-Xmx4g"<br> org.gradle.caching="true"<br> kapt.incremental.apt="true" <br>kapt.use.worker.api="false" | org.gradle.jvmargs="-Xmx4g"<br> org.gradle.caching="true"<br> kapt.incremental.apt="false" <br>kapt.use.worker.api="false" | org.gradle.jvmargs="-Xmx4g"<br> org.gradle.caching="true"<br> kapt.incremental.apt="false" <br>kapt.use.worker.api="true" |
| org.gradle.jvmargs="-Xmx4g"<br>org.gradle.caching="false"<br> kapt.incremental.apt="true" <br>kapt.use.worker.api="true" | org.gradle.jvmargs="-Xmx4g"<br> org.gradle.caching="false"<br> kapt.incremental.apt="true" <br>kapt.use.worker.api="false" | org.gradle.jvmargs="-Xmx4g"<br> org.gradle.caching="false"<br> kapt.incremental.apt="false" <br>kapt.use.worker.api="true" | org.gradle.jvmargs="-Xmx4g"<br> org.gradle.caching="false"<br> kapt.incremental.apt="false" <br>kapt.use.worker.api="false" |


Result:

![alt text](resources/experiment2.png "experiment1")

We don't appreciate on Plaid project significant different using properties like `kapt.incremental.apt` and `kapt.use.worker.api`. However, you can notice the benefits of using caching on the Gradle Builds.

### Example 3

Experimentation on Android Showcase project, with Gradle properties and different Gradle Wrapper versions

| bagan_conf | |
|-----------------|--------------------------------------------------------------|
| machine |n2-standard-8 |
| zone |asia-southeast1-b |
| repository |https://github.com/igorwojda/android-showcase |
| private |false |
| experiments |gradle properties:<br>{ "org.gradle.jvmargs": ["-Xmx2g","-Xmx4g"] }<br>{ "org.gradle.caching": ["true","false"] }<br>{ "kapt.incremental.apt": ["true","false"] }<br>{ "kapt.use.worker.api": ["true","false"] }<br>Gradle Wrapper versions: ["5.6.1","5.5"]|
| command | ./gradlew clean :app:bundleDebug |
| iterations |20 |

Result:

![alt text](resources/experiment3.png "experiment3")


Best times are using Gradle `5.6.1`.

## Deploy <a name="deploy"></a>
Bagan is open source and you can update create your requirements.
This is the structure of the project:
Expand Down
4 changes: 2 additions & 2 deletions bagan
Expand Up @@ -66,8 +66,8 @@ fi
if [ "$branch" != "null" ]; then
log " -branch: $branch"
fi
if [ "$gradleWrapper" != "null" ]; then
log " -gradleWrapper: $gradleWrapper"
if [ "$gradleWrapperVersion" != "null" ]; then
log " -gradleWrapperVersion: $gradleWrapperVersion"
fi
log ""

Expand Down
Expand Up @@ -18,15 +18,15 @@ class GradleWrapperVersion(
logger.log(TAG, "Error, not value found for the env variable gradleWrapperVersion")
} else {
logger.log(TAG, "gradleWrapperVersion version value $value")
val url = "https://services.gradle.org/distributions/gradle-$value-bin.zip"
val url = "https://services.gradle.org/distributions/gradle-${value.replace("'", "")}-bin.zip"
try {
val inProperties = FileInputStream("$path/gradle/wrapper/gradle-wrapper.properties")
val props = Properties()
props.load(inProperties)
inProperties.close()

val outProperties = FileOutputStream("$path/gradle/wrapper/gradle-wrapper.properties")
logger.log(TAG, "Writing property distributionUrl-$url")
logger.log(TAG, "Writing property distributionUrl-${url.replace("'", "")}")
props.setProperty("distributionUrl", url)
props.store(outProperties, null)
outProperties.close()
Expand Down
Expand Up @@ -189,7 +189,7 @@ fun getContentLegend(experiments: List<Experiment>): String {
}
if (it.gradleWrapperVersion.isNotBlank()) {
contentExperiment += "#### Gradle Wrapper:\n"
contentExperiment += "${it.gradleWrapperVersion}\n"
contentExperiment += "${it.gradleWrapperVersion.replace("'", "")}\n"
}
content += contentExperiment
}
Expand Down
Expand Up @@ -195,7 +195,7 @@ for i in `seq 1 {{ .Values.iterations }}`; do {{ .Values.command }}; done;

object ConfigMapExperiments {
fun branch(branch: String) = """branch: $branch"""
fun gradleWrapperVersion(version: String) = """gradleWrapperVersion: $version"""
fun gradleWrapperVersion(version: String) = """gradleWrapperVersion: '$version'"""
fun properties(properties: String) =
"""properties: |
$properties""".trimIndent()
Expand Down
Expand Up @@ -27,7 +27,7 @@ class WrapperVersionTest : BehaviorSpec({
`when`("Environment variable is found but not the file gradle-wrapper.properties") {
val testLogger = TestPodLogger()
val exception = shouldThrow<FileNotFoundException> {
withEnvironment("gradleWrapperVersion" to "5.1") {
withEnvironment("gradleWrapperVersion" to "'5.1'") {
val wrapperVersion = GradleWrapperVersion("tmp", testLogger)
wrapperVersion.applyExperiments()

Expand All @@ -47,7 +47,7 @@ class WrapperVersionTest : BehaviorSpec({
val contentFile = File("tmp/gradle/wrapper/gradle-wrapper.properties")
contentFile.writeText("distributionUrl=https://services.gradle.org/distributions/gradle-5.4.1-bin.zip")

withEnvironment("gradleWrapperVersion" to "5.5") {
withEnvironment("gradleWrapperVersion" to "'5.5'") {
val wrapperVersion = GradleWrapperVersion("tmp", testLogger)
wrapperVersion.applyExperiments()
}
Expand Down
Expand Up @@ -41,7 +41,7 @@ class BaganFileGeneratorTest : BehaviorSpec({
contentValuesFile should haveSubstring("branch: master")
contentValuesFile should haveSubstring("properties: |")
contentValuesFile should haveSubstring("property1")
contentValuesFile should haveSubstring("gradleWrapperVersion: 4.5")
contentValuesFile should haveSubstring("gradleWrapperVersion: '4.5'")

}
then("pod is generated with ssh options") {
Expand Down
Expand Up @@ -44,7 +44,7 @@ metadata:
session: {{ .Values.session }}
data:
id: {{ .Values.name }}
gradleWrapperVersion: 4.3
gradleWrapperVersion: '4.3'
""".trimIndent()
)
}
Expand Down Expand Up @@ -98,7 +98,7 @@ data:
properties: |
property1=a
branch: develop
gradleWrapperVersion: 4.5""".trimIndent()
gradleWrapperVersion: '4.5'""".trimIndent()

)
}
Expand Down
26 changes: 17 additions & 9 deletions bagan_conf.json
@@ -1,22 +1,30 @@
{
"bagan": {
"repository": "git@github.com:cdsap/TestPrivateRepository.git",
"gradleCommand": "./gradlew clean assembleDebug",
"repository": "https://github.com/igorwojda/android-showcase.git",
"gradleCommand": "./gradlew clean :app:bundleDebug",
"clusterName": "",
"machine": "n1-standard-4",
"zone": null,
"private": true,
"ssh": "/Users/inaki/.ssh/id_rsa",
"known_hosts": "/Users/inaki/.ssh/known_hosts",
"machine": "n2-standard-8",
"zone": "asia-southeast1-b",
"private": false,
"ssh": "",
"known_hosts": "",
"iterations": 20,
"experiments": {
"properties": [
{
"name": "org.gradle.jvmargs",
"options": ["-Xmx3g","-Xmx4g"]
"options": ["-Xmx2g","-Xmx4g"]
},
{
"name": "kapt.incremental.apt",
"options": ["true","false"]
},
{
"name": "kapt.use.worker.api",
"options": ["true","false"]
}
],
"branch": [ "develop3","master"]
"gradleWrapperVersion": ["5.6.1","5.5"]
}
}
}
2 changes: 1 addition & 1 deletion docker/installer/bin/generator/K8Template.kt
Expand Up @@ -195,7 +195,7 @@ for i in `seq 1 {{ .Values.iterations }}`; do {{ .Values.command }}; done;

object ConfigMapExperiments {
fun branch(branch: String) = """branch: $branch"""
fun gradleWrapperVersion(version: String) = """gradleWrapperVersion: $version"""
fun gradleWrapperVersion(version: String) = """gradleWrapperVersion: '$version'"""
fun properties(properties: String) =
"""properties: |
$properties""".trimIndent()
Expand Down
4 changes: 2 additions & 2 deletions docker/pod/bin/experiments/GradleWrapperVersion.kt
Expand Up @@ -22,15 +22,15 @@ class GradleWrapperVersion(
logger.log(TAG, "Error, not value found for the env variable gradleWrapperVersion")
} else {
logger.log(TAG, "gradleWrapperVersion version value $value")
val url = "https://services.gradle.org/distributions/gradle-$value-bin.zip"
val url = "https://services.gradle.org/distributions/gradle-${value.replace("'", "")}-bin.zip"
try {
val inProperties = FileInputStream("$path/gradle/wrapper/gradle-wrapper.properties")
val props = Properties()
props.load(inProperties)
inProperties.close()

val outProperties = FileOutputStream("$path/gradle/wrapper/gradle-wrapper.properties")
logger.log(TAG, "Writing property distributionUrl-$url")
logger.log(TAG, "Writing property distributionUrl-${url.replace("'", "")}")
props.setProperty("distributionUrl", url)
props.store(outProperties, null)
outProperties.close()
Expand Down
Binary file added resources/experiment2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/experiment3.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions scripts/mode_gcloud_docker.sh
Expand Up @@ -4,10 +4,10 @@ function gcloudDockerExecutor(){
log "Command $command"
if [ $command == "cluster" ]; then
printf '%s\n' "Mode cluster"
execution="$(gcloudInit) $(gcloudCreateCluster) $(gcloudClusterCredentials) $(helm1) $(infraPods) $(createSecretDockerContainer) $(dockerBagan)"
execution="$(gcloudInit) $(gcloudCreateCluster) $(gcloudClusterCredentials) $(helmInstaller) $(infraPods) $(createSecretDockerContainer) $(dockerBagan)"
elif [ $command == "infrastructure" ]; then
printf '%s\n' "Mode infrastrucure"
execution="$(gcloudClusterCredentials) $(helm1) $(infraPods) $(createSecretDockerContainer) $(dockerBagan) "
execution="$(gcloudClusterCredentials) $(helmInstaller) $(infraPods) $(createSecretDockerContainer) $(dockerBagan) "
elif [ $command == "experiment" ]; then
printf '%s\n' "Mode experiment"
execution="$(gcloudClusterCredentials) $(dockerBagan)"
Expand All @@ -18,7 +18,7 @@ function gcloudDockerExecutor(){
elif [[ $command == "secret" ]]; then
execution="$(gcloudClusterCredentials) $(createSecretDockerContainer)"
elif [[ $command == "helm" ]]; then
execution="$(gcloudClusterCredentials) $(helm1)"
execution="$(gcloudClusterCredentials) $(helmInstaller)"
elif [[ $command == "helm_init" ]]; then
execution="$(gcloudClusterCredentials) $(helmInit)"
elif [[ $command == "helm_clusterrolebinding" ]]; then
Expand Down
12 changes: 6 additions & 6 deletions scripts/validate_json.sh
Expand Up @@ -8,8 +8,8 @@ propertiesJson=$(cat $FILE | jq -c -r '.bagan.experiments.properties' | tr -d '\
propertiesCountJson=$(cat $FILE | jq -c -r '.bagan.experiments.properties | length' | tr -d '\r')
branchJson=$(cat $FILE | jq -c -r '.bagan.experiments.branch' | tr -d '\r')
branchCountJson=$(cat $FILE | jq -c -r '.bagan.experiments.branch | length' | tr -d '\r')
gradleWrapperJson=$(cat $FILE | jq -c -r '.bagan.experiments.gradleWrapper' | tr -d '\r')
gradleWrapperCountJson=$(cat $FILE | jq -c -r '.bagan.experiments.gradleWrapper | length' | tr -d '\r')
gradleWrapperVersionJson=$(cat $FILE | jq -c -r '.bagan.experiments.gradleWrapperVersion' | tr -d '\r')
gradleWrapperVersionCountJson=$(cat $FILE | jq -c -r '.bagan.experiments.gradleWrapperVersion | length' | tr -d '\r')
clusterJson=$(cat $FILE | jq -c -r '.bagan.clusterName' | tr -d '\r')
zoneJson=$(cat $FILE | jq -c -r '.bagan.zone' | tr -d '\r')
machineJson=$(cat $FILE | jq -c -r '.bagan.machine' | tr -d '\r')
Expand All @@ -34,7 +34,7 @@ then
exit 1
fi

if [ "$propertiesJson" == "null" ] && [ "$branchJson" == "null" ] && [ "$gradleWrapperJson" == "null" ]; then
if [ "$propertiesJson" == "null" ] && [ "$branchJson" == "null" ] && [ "$gradleWrapperVersionJson" == "null" ]; then
color '31;1' "Error: you have to include at least one type experiment in the configuration file."
log "Example:"
log "\"experiments\": {
Expand All @@ -45,7 +45,7 @@ if [ "$propertiesJson" == "null" ] && [ "$branchJson" == "null" ] && [ "$gradleW
}
],
\"branch\": [ \"develop\",\"master\"],
\"gradleWrapper\": [ \"5.6\",\"5.5\",\"5.4\"]
\"gradleWrapperVersion\": [ \"5.6\",\"5.5\",\"5.4\"]
}"
exit 1
fi
Expand Down Expand Up @@ -103,8 +103,8 @@ properties=$propertiesJson
propertiesCount=$propertiesCountJson
branch=$branchJson
branchCount=$branchCountJson
gradleWrapper=$gradleWrapperJson
gradleWrapperCountJson=$gradleWrapperCountJson
gradleWrapperVersion=$gradleWrapperVersionJson
gradleWrapperVersionCountJson=$gradleWrapperVersionCountJson
private=$privateJson
ssh=$sshJson
known_hosts=$known_hostsJson

0 comments on commit d43a53f

Please sign in to comment.