Skip to content

Commit

Permalink
Add Spring REST docs capability (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
nickebbitt authored Mar 17, 2020
1 parent 402045d commit 572c60e
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 42 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Chaos Kraken

Application to simulate JVM based failure scenarios when running on a delivery platform.
An application that can be used to simulate JVM based failure scenarios when running on a delivery platform.

> Terrorise the Shipp'ng lanes with the Chaos Kraken, an incomplete FAAS (Failures as a Service).
Expand Down
32 changes: 27 additions & 5 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.2.5.RELEASE"
id("io.spring.dependency-management") version "1.0.9.RELEASE"
id("org.asciidoctor.convert") version "1.5.9.2"
id("maven-publish")
kotlin("jvm") version "1.3.61"
kotlin("plugin.spring") version "1.3.61"
id("maven-publish")
}

java {
Expand All @@ -24,17 +25,16 @@ dependencies {
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.apache.commons:commons-lang3:3.4")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")

runtimeOnly("org.springframework.boot:spring-boot-devtools")
asciidoctor("org.springframework.restdocs:spring-restdocs-asciidoctor")

testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("com.natpryce:hamkrest:1.7.0.0")
testImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0")
testImplementation("org.springframework.restdocs:spring-restdocs-webtestclient")
}

tasks.withType<Test> {
useJUnitPlatform()
}
val snippetsDir by extra { file("build/generated-snippets") }

tasks.withType<KotlinCompile>() {
kotlinOptions {
Expand All @@ -43,6 +43,28 @@ tasks.withType<KotlinCompile>() {
}
}

tasks {
test {
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
}
outputs.dir(snippetsDir)
}

asciidoctor {
inputs.dir(snippetsDir)
dependsOn(test)
}

bootJar {
dependsOn(asciidoctor)
into("static/docs") {
from("build/asciidoc/html5")
}
}
}

publishing {
publications {
create<MavenPublication>("bootJava") {
Expand Down
70 changes: 70 additions & 0 deletions src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
= Chaos Kraken
:doctype: book
:icons: font
:source-highlighter: highlightjs
:toc: left

An application that can be used to simulate JVM based failure scenarios when running on a delivery platform.

Terrorise the Shipp'ng lanes with the Chaos Kraken, an incomplete FAAS (Failures as a Service).

The first version of Chaos Kraken was created at https://careers.autotrader.co.uk/[Auto Trader UK] back in 2017. It was
originally built to test various application failure conditions on their private cloud infrastructure.

As Auto Trader started their migration to public cloud and Kubernetes, the Chaos Kraken evolved to cater for more
failure modes.

Chaos Kraken is actively used within Auto Trader to verify various behaviours of their
https://cloud.google.com/kubernetes-engine[GKE] based delivery platform.

== Getting Started

A https://github.com/autotraderuk/chaos-kraken/packages/143034[GitHub package] containing the executable JAR for Chaos
Kraken is created every time a version is released using a
https://github.com/autotraderuk/chaos-kraken/actions?query=workflow%3A%22Publish+release%22[GitHub Actions workflow].

The application JAR can be downloaded from here, or you can clone the repo and build it yourself.

=== Building

Chaos Kraken uses https://gradle.org/[Gradle] for dependency management and other build time concerns. It also uses the
https://docs.gradle.org/current/userguide/gradle_wrapper.html[Gradle Wrapper] allowing you to simply clone the repo and
build the project with minimal effort.

....
./gradlew build
....

This will create an executable Spring Boot JAR providing all the features of the Chaos Kraken, as well as these docs
hosted at `/docs/index.html`.

=== Running

Once you've downloaded or built the application JAR simply run it, for example:

....
java -jar chaos-kraken-0.1.2.jar
....

By default, the application will then be available on port `8080`.

You can verify this from your terminal:

include::{snippets}/welcome/curl-request.adoc[]

Which will give you the following response:

include::{snippets}/welcome/http-response.adoc[]

== Simulating behaviours

Chaos Kraken provides a variety of behaviours that simulate ways in which an application may behave badly, or even fail,
whilst running on a delivery platform.

=== killapp

The `killapp` behaviour simulates the JVM process dying by exiting the process.

include::{snippets}/killapp/curl-request.adoc[]


2 changes: 2 additions & 0 deletions src/main/kotlin/uk/co/autotrader/application/Application.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package uk.co.autotrader.application
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean
import javax.annotation.PostConstruct

@SpringBootApplication
Expand All @@ -20,3 +21,4 @@ constructor(private val failureSimulator: FailureSimulator) {
fun main(args: Array<String>) {
runApplication<Application>(*args)
}

5 changes: 2 additions & 3 deletions src/main/kotlin/uk/co/autotrader/application/Failures.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import java.util.stream.Collectors
import java.util.stream.IntStream
import java.util.stream.Stream
import kotlin.concurrent.timer
import kotlin.system.exitProcess

interface Failure {
fun fail(params: Map<String, String> = emptyMap())
Expand Down Expand Up @@ -223,11 +222,11 @@ class FileWriter : Failure {
}

@Component("killapp")
class KillApp : Failure {
class KillApp(val systemExit: SystemExit) : Failure {

override fun fail(params: Map<String, String>) {
LOG.error("Application was killed by calling the 'killapp' failure")
exitProcess(1)
systemExit.exitProcess(1)
}
}

Expand Down
10 changes: 8 additions & 2 deletions src/main/kotlin/uk/co/autotrader/application/Routes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ import org.slf4j.LoggerFactory
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType.TEXT_HTML
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.server.ServerRequest
import org.springframework.web.reactive.function.server.ServerResponse
import org.springframework.web.reactive.function.server.router
import reactor.core.publisher.Mono


@Configuration
class Routes(private val echoStatusHandler: EchoStatusHandler, private val failureHandler: FailureHandler) {

@Bean
fun root() = router {
GET("/") { _ -> ServerResponse.ok().bodyValue("This kraken is running and ready to cause some chaos.") }
GET("/") { _ -> ServerResponse.ok().contentType(TEXT_HTML).bodyValue(WELCOME_MESSAGE) }
}

@Bean
Expand All @@ -31,6 +31,12 @@ class Routes(private val echoStatusHandler: EchoStatusHandler, private val failu

}

val WELCOME_MESSAGE = """
This kraken is running and ready to cause some chaos.
<p>
Read the <a href="docs/index.html">docs</a>.
""".trimIndent()

@Component
class FailureHandler(private val failureSimulator: FailureSimulator) {

Expand Down
14 changes: 14 additions & 0 deletions src/main/kotlin/uk/co/autotrader/application/SystemExit.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package uk.co.autotrader.application

import org.springframework.stereotype.Component

interface SystemExit {
fun exitProcess(status: Int)
}

@Component
class SystemExitImpl : SystemExit {
override fun exitProcess(status: Int) {
exitProcess(status)
}
}
Loading

0 comments on commit 572c60e

Please sign in to comment.