SlideShare a Scribd company logo
Everything-as-code – Polyglotte Entwicklung in der Praxis
#whoami
Mario-Leander Reimer
Cheftechnologe, QAware GmbH
- Senior Developer && Architect
- 20+ Jahre Erfahrung
- #CloudNativeNerd
- Open Source Enthusiast
mario-leander.reimer@qaware.de
http://github.com/lreimer
http://speakerdeck.com/lreimer
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Software Industrialization
ist eine Schlüsselanforderung
für erfolgreiches DevOps und
Continuous Delivery.
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Ein Software-Fließband produziert
und liefert die fertige Software an.
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Software Industrialisierung bedeutet ...
• Hoher Automatisiersgrad von arbeitsintensiven
und wiederkehrenden Arbeitsschritten
• Bessere Software-Qualität durch eine
abgestimmte Tool-Chain
• Mehr Produktivität und Zufriedenheit der Teams
• Kosten-Effizienz und Wettbewerbsfähigkeit
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Everything-as-code – Polyglotte Entwicklung in der Praxis
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Everything-as-code – Polyglotte Entwicklung in der Praxis
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
val softwareIndustrialization = everythingAsCode()
open fun everythingAsCode() =
everythingIsMadeFromCode()
&& everythingIsMadeByCode()
private fun everythingIsMadeFromCode() = true
private fun everythingIsMadeByCode() = true
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Auf die Domäne kommt es an!
Eine beste Programmiersprache gibt es nicht.
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Die Queste nach dem idealen Polyglot Project Archetype
• Welche Sprachen werden in unseren Projekten in
welchen Domänen verwendet?
• Welche Tools verwenden wir für Setup, Build, Code,
Test, CI, Infrastructure, Documentation?
• Was davon hat sich bewährt und was eher nicht?
• Gibt es bereits Best Practices oder Anti-Patterns?
+ Wishful Greenfield Thinking!
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Eine vielsprachige
Reise beginnt ...
Everything-as-code – Polyglotte Entwicklung in der Praxis
Lightweight Developer Provisioning mit Gradle
• [ SEU ] -> Software Entwicklungs Umgebung
• Nutzung von Gradle als Build-Tool für das Setup und
die Aktualisierung unserer Entwicklungsumgebungen
• Software-Pakete werden als Dependencies definiert
• Gradle Tasks und Groovy Code statt Shell-Scripting
• Versionskontrolle der SEU Definition und Skripte
• Open Source. http://seu-as-code.io
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
plugins { id 'de.qaware.seu.as.code.base' version '2.4.0' }
import static de.qaware.seu.as.code.plugins.base.Platform.isMac
seuAsCode {
seuHome = { if (isMac()) '/Volumes/Everything-as-code' else 'Y:' }
projectName = 'Everything-as-code'
}
dependencies {
// list of software dependencies ...
software 'org.groovy-lang:groovy:2.4.7'
software 'org.scala-lang:scala:2.11.8'
software 'org.jruby:jruby:9.1.4.0'
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Everything-as-code – Polyglotte Entwicklung in der Praxis
# language: en
Functionality: Authentication and Authorization
Scenario Outline: Check proper login behaviour
Given the username "<USERNAME>"
And the password "<PASSWORD>"
When the user logs into the system
Then the login result is "<RESULT>"
Examples: Login data
| USERNAME | PASSWORD | RESULT |
| mario-leander.reimer | invalidpwd | failure |
| unknown | somepwd | failure |
| mario-leander.reimer | correctpwd | success |
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Everything-as-code – Polyglotte Entwicklung in der Praxis
Maven ist gut. Gradle ist 100x schneller.
• Sehr flexibel und vielseitig einsetzbar.
• Einfache Unterstützung für polyglotte Projekte.
• Build Skripte sind maximal kurz und prägnant.
• Deutlich reduzierte Build-Zeiten durch inkrementelle
Builds und Caching
• Zahlreiche neue Features: Composite Builds, Kotlin-
basierte Build-Skripte, Performance Verbesserungen, ...
• Regelmäßige Releases. Stabil und ausgereift.
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
apply plugin: 'application'
apply plugin: 'war'
apply plugin: 'kotlin'
apply plugin: 'groovy'
repositories { jcenter() }
dependencies {
providedCompile 'fish.payara.extras:payara-micro:4.1.1.164'
// and many more ...
}
task everythingAsCode() << {
println 'Everything-as-code using Gradle @ ContinuousLifecycle 2017.'
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Everything-as-code – Polyglotte Entwicklung in der Praxis
Java ist nach wie vor unsere
primäre Implementierungssprache!
Und das ist gut so!
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Aber:
Kotlin als Alternative zu
Java ist einen Blick wert!
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Warum Kotlin? Und nicht Scala, Clojure, ...
• Für Java Entwickler sehr schnell zu erlernen.
• Sehr ausgewogene Universalsprache.
• Null Safety + Synatctic Sugar + jede Menge
andere nützliche Features.
• JDK6 kompatibel. Kleine Library-Größe.
• Sehr guter IDE und Tool Support.
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
@JsonIgnoreProperties(ignoreUnknown = true)
data class Book(val title: String, val isbn: String, val author: String)
@ApplicationScoped
open class Bookshelf {
private val books = listOf(Book("The Hitchhiker's Guide to the Galaxy", "0345391802"))
open fun byIsbn(isbn: String): Book? = books.find { it.isbn == isbn }
}
@Path("books")
@Produces(MediaType.APPLICATION_JSON)
open class BookResource @Inject constructor(private val bookshelf: Bookshelf) {
@GET @Path("/{isbn}")
open fun byIsbn(@PathParam("isbn") isbn: String): Response {
val book = bookshelf.byIsbn(isbn)
return if (book != null) Response.ok(book).build() else Response.status(Status.NOT_FOUND).build()
}
}
@ApplicationPath("api")
class BookstoreAPI : Application() {
override fun getClasses() = hashSetOf(JacksonFeature::class.java, BookResource::class.java)
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Everything-as-code – Polyglotte Entwicklung in der Praxis
Willkommen in der JavaScript Wunderwelt.
• Ein Universum für sich!
• Klarer Trend: Single Page Webapplikationen.
• HTML5 + CSS3 + ?
• ? = TypeScript oder
• ? = ECMAScript2015 + Babel
• Rückgrat des Builds: node + npm + webpack
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Everything-as-code – Polyglotte Entwicklung in der Praxis
Grovy + Spock eignen sich für Unit,
Integration, Acceptance und UI-Tests
class BookshelfSpec extends Specification {
@Subject
def bookshelf = new Bookshelf()
@Unroll
def "Find book #title by ISBN #isbn"() {
when: 'we search a book by ISBN'
def book = bookshelf.byIsbn(isbn)
then: 'the title and author are correct'
book?.title == title
book?.author == author
where:
isbn || title | author
"0345391802" || "The Hitchhiker's Guide to the Galaxy" | "Douglas Adams"
"0345391829" || "Life, the Universe and Everything" | "Douglas Adams"
}
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Scala und Gatling für lesbare und
performante Last-Tests
class BooksPerformanceTest extends Simulation {
val conf = http.baseURL("http://localhost:18080").acceptHeader("application/json")
val feeder = csv("books.csv").random
val scn = scenario("Book Search")
.exec(http("Get all books").get("/api/books"))
.during(30 seconds) {
feed(feeder)
.exec(http("Get book by title ${Title}").get("/api/books?title=${Title}"))
.pause(1 second)
.exec(http("Get book with ISBN ${ISBN}").get("/api/books/${ISBN}"))
}
setUp(scn.inject(atOnceUsers(10), rampUsers(50) over (30 seconds)))
.assertions(global.responseTime.max.lessThan(5000))
.protocols(conf)
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Everything-as-code – Polyglotte Entwicklung in der Praxis
Definition einer Build-Pipeline per
Jenkinsfile und Groovy
#!/usr/bin/env groovy
node {
stage 'Checkout SCM'
checkout scm
stage 'Build/Analyse/Test'
sh './gradlew clean build'
archiveUnitTestResults()
archiveDistributions()
stage 'Dockerize'
sh './gradlew buildDockerImage'
stage 'Generate Documentation'
sh './gradlew asciidoctor'
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Everything-as-code – Polyglotte Entwicklung in der Praxis
Architektur-Definition und Prüfung
mit QAvalidator für wartbaren Code.
architecture(name: "Mail Example", prefix: "tview", reflexMLversion: "1.0") {
excludes "java.lang.*"
api "JavaMail" : "javax.mail.*"
component "Mail" {
api "IMail" : "de.qaware.mail.*"
impl ["de.qaware.mail.impl.*", "de.qaware.mail.impl2.*"]
uses "JavaMail"
component "MailSender" {
api ["de.qaware.mail.sender.*", "javax.mail.*"]
impl "de.qaware.mail.impl.javamail.JavaMailSender"
uses "JavaMail"
}
}
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Everything-as-code – Polyglotte Entwicklung in der Praxis
Docker, Docker, Docker, ...
FROM qaware-oss-docker-registry.bintray.io/base/alpine-k8s-openjdk8:8u121
MAINTAINER M.-Leander Reimer <mario-leander.reimer@qaware.de>
RUN mkdir -p /app
ADD build/distributions/everything-as-code-1.2.3.tar /app
WORKDIR /app/everything-as-code-1.2.3
RUN chmod 755 bin/everything-as-code
EXPOSE 18080
CMD ./bin/everything-as-code
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Cluster Orchestration mit K8s et.al.
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: everything-as-code
spec:
replicas: 2
template:
metadata:
labels:
tier: backend
spec:
containers:
- name: everything-as-code
image: "qaware-oss-docker-registry.bintray.io/lreimer/everything-as-code:1.2.3"
ports:
- containerPort: 18080
env:
- name: PORT
value: 18080
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Einfache Provisionierung mit Ansible.
---
# file: jenkinsci.yml
- hosts: jenkinsci
remote_user: root
tasks:
- debug: msg="Creating a Jenkins pipeline job on {{ inventory_hostname }}"
- jenkins_job:
name: Everything-as-code Pipeline
config: "{{ lookup('file', 'templates/pipeline-job.xml') }}"
url: "http://{{ inventory_hostname }}"
user: admin
password: admin
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Vagrant und Ruby zum Setup lokaler VMs.
require 'yaml'
$setup = <<SCRIPT
sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update
sudo apt-get install -y ansible sshpass
SCRIPT
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/trusty32"
settings = YAML.load_file 'src/vagrant/vagrant.yml'
config.vm.provider "virtualbox" do |vb|
vb.name = settings['vm']['name']
vb.gui = false
vb.memory = "512"
end
config.vm.provision "shell", inline: $setup
end
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Everything-as-code – Polyglotte Entwicklung in der Praxis
Ja, wir brauchen Dokumentation!
• Und nein. Der Quellcode ist nicht genug!
• Technische Dokumente mit Word sind ! " #
• Dokumentation sollte neben dem Quellcode
liegen: change code, change docs.
• Schnell und einfach zu schreiben.
• Unterstützung für Code, Bilder, Diagramme
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
// Beispiel Architektur-Dokumentation mit arc42 (https://arc42.github.io)
:imagesdir: ./images
= image:qaware-logo.png[QAware GmbH,2016] Everything-as-code
:toc-title: Table of Contents
:toc:
[[section-introduction-and-goals]]
== Introduction and Goals
The introduction to the architecture documentation should list the driving forces
that software architects must consider in their decisions.
=== Requirements Overview
=== Quality Goals
=== Stakeholders
<<<<
include::02_architecture_constraints.adoc[]
// further includes for the remaining sections
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Mit AsciidoctorJ und Gradle zum fertigen Dokument.
plugins { id "org.asciidoctor.convert" version "1.5.3" }
asciidoctorj { version = '1.5.4.1' }
asciidoctor {
sourceDir 'src/docs/architecture'
resources {
from('src/docs/architecture') {
include 'images/**/*.png'
include 'images/**/*.jpg'
}
}
backends ['html5', 'pdf']
options doctype: 'article'
attributes 'source-highlighter': 'coderay'
}
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Architectur-Dokumentation mit Structurizr
def workspace = new Workspace("Everything-as-code", "The system context of Everything-as-code.")
def model = workspace.model
// create a model and the software system we want to describe
def bookApp = model.addSoftwareSystem("Book Application", "The best source to get info on books.")
// create the various types of people (roles) that use the software system
def anonymousUser = model.addPerson("Anonymous User", "Anybody on the web.")
anonymousUser.uses(bookApp, "Searches for books and views details.")
def browser = bookApp.addContainer("Web Browser",
"Allows users to view information about books", "Edge, Chrome, Firefox")
anonymousUser.uses(browser, "Views information from and makes requests to")
def webApp = bookApp.addContainer("Web Application",
"Hosts the browser-based web application and services", "Payara Fish")
browser.uses(webApp, "uses [JSON/HTTPS]")
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Everything-as-code – Polyglotte Entwicklung in der Praxis
These slides were written in Markdown.
---
## [fit] These slides were written in Markdown.
- This is for real programmers! :smiley:
- Several open source projects available
- Use HTML and JavaScript alternatively.
---
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Everything-as-code – Polyglotte Entwicklung in der Praxis
Use the right tool
for the job!
Everything-as-code – Polyglotte Entwicklung in der Praxis
Alles mit Augenmaß!
Der richtige Technologie-Stack hängt vom Team,
dem Projekt-Kontext und unseren Kunden ab.
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Fork me on GitHub.
https://github.com/lreimer/everything-as-code
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
// IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
Everything-as-code – Polyglotte Entwicklung in der Praxis

More Related Content

Everything-as-code – Polyglotte Entwicklung in der Praxis

  • 2. #whoami Mario-Leander Reimer Cheftechnologe, QAware GmbH - Senior Developer && Architect - 20+ Jahre Erfahrung - #CloudNativeNerd - Open Source Enthusiast mario-leander.reimer@qaware.de http://github.com/lreimer http://speakerdeck.com/lreimer // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 3. Software Industrialization ist eine Schlüsselanforderung für erfolgreiches DevOps und Continuous Delivery. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 4. Ein Software-Fließband produziert und liefert die fertige Software an. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 5. Software Industrialisierung bedeutet ... • Hoher Automatisiersgrad von arbeitsintensiven und wiederkehrenden Arbeitsschritten • Bessere Software-Qualität durch eine abgestimmte Tool-Chain • Mehr Produktivität und Zufriedenheit der Teams • Kosten-Effizienz und Wettbewerbsfähigkeit // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 7. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 8. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 9. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 11. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 12. val softwareIndustrialization = everythingAsCode() open fun everythingAsCode() = everythingIsMadeFromCode() && everythingIsMadeByCode() private fun everythingIsMadeFromCode() = true private fun everythingIsMadeByCode() = true // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 13. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 14. Auf die Domäne kommt es an! Eine beste Programmiersprache gibt es nicht. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 15. Die Queste nach dem idealen Polyglot Project Archetype • Welche Sprachen werden in unseren Projekten in welchen Domänen verwendet? • Welche Tools verwenden wir für Setup, Build, Code, Test, CI, Infrastructure, Documentation? • Was davon hat sich bewährt und was eher nicht? • Gibt es bereits Best Practices oder Anti-Patterns? + Wishful Greenfield Thinking! // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 18. Lightweight Developer Provisioning mit Gradle • [ SEU ] -> Software Entwicklungs Umgebung • Nutzung von Gradle als Build-Tool für das Setup und die Aktualisierung unserer Entwicklungsumgebungen • Software-Pakete werden als Dependencies definiert • Gradle Tasks und Groovy Code statt Shell-Scripting • Versionskontrolle der SEU Definition und Skripte • Open Source. http://seu-as-code.io // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 19. plugins { id 'de.qaware.seu.as.code.base' version '2.4.0' } import static de.qaware.seu.as.code.plugins.base.Platform.isMac seuAsCode { seuHome = { if (isMac()) '/Volumes/Everything-as-code' else 'Y:' } projectName = 'Everything-as-code' } dependencies { // list of software dependencies ... software 'org.groovy-lang:groovy:2.4.7' software 'org.scala-lang:scala:2.11.8' software 'org.jruby:jruby:9.1.4.0' } // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 21. # language: en Functionality: Authentication and Authorization Scenario Outline: Check proper login behaviour Given the username "<USERNAME>" And the password "<PASSWORD>" When the user logs into the system Then the login result is "<RESULT>" Examples: Login data | USERNAME | PASSWORD | RESULT | | mario-leander.reimer | invalidpwd | failure | | unknown | somepwd | failure | | mario-leander.reimer | correctpwd | success | // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 22. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 24. Maven ist gut. Gradle ist 100x schneller. • Sehr flexibel und vielseitig einsetzbar. • Einfache Unterstützung für polyglotte Projekte. • Build Skripte sind maximal kurz und prägnant. • Deutlich reduzierte Build-Zeiten durch inkrementelle Builds und Caching • Zahlreiche neue Features: Composite Builds, Kotlin- basierte Build-Skripte, Performance Verbesserungen, ... • Regelmäßige Releases. Stabil und ausgereift. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 25. apply plugin: 'application' apply plugin: 'war' apply plugin: 'kotlin' apply plugin: 'groovy' repositories { jcenter() } dependencies { providedCompile 'fish.payara.extras:payara-micro:4.1.1.164' // and many more ... } task everythingAsCode() << { println 'Everything-as-code using Gradle @ ContinuousLifecycle 2017.' } // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 27. Java ist nach wie vor unsere primäre Implementierungssprache! Und das ist gut so! // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 28. Aber: Kotlin als Alternative zu Java ist einen Blick wert! // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 29. Warum Kotlin? Und nicht Scala, Clojure, ... • Für Java Entwickler sehr schnell zu erlernen. • Sehr ausgewogene Universalsprache. • Null Safety + Synatctic Sugar + jede Menge andere nützliche Features. • JDK6 kompatibel. Kleine Library-Größe. • Sehr guter IDE und Tool Support. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 30. @JsonIgnoreProperties(ignoreUnknown = true) data class Book(val title: String, val isbn: String, val author: String) @ApplicationScoped open class Bookshelf { private val books = listOf(Book("The Hitchhiker's Guide to the Galaxy", "0345391802")) open fun byIsbn(isbn: String): Book? = books.find { it.isbn == isbn } } @Path("books") @Produces(MediaType.APPLICATION_JSON) open class BookResource @Inject constructor(private val bookshelf: Bookshelf) { @GET @Path("/{isbn}") open fun byIsbn(@PathParam("isbn") isbn: String): Response { val book = bookshelf.byIsbn(isbn) return if (book != null) Response.ok(book).build() else Response.status(Status.NOT_FOUND).build() } } @ApplicationPath("api") class BookstoreAPI : Application() { override fun getClasses() = hashSetOf(JacksonFeature::class.java, BookResource::class.java) } // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 32. Willkommen in der JavaScript Wunderwelt. • Ein Universum für sich! • Klarer Trend: Single Page Webapplikationen. • HTML5 + CSS3 + ? • ? = TypeScript oder • ? = ECMAScript2015 + Babel • Rückgrat des Builds: node + npm + webpack // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 34. Grovy + Spock eignen sich für Unit, Integration, Acceptance und UI-Tests class BookshelfSpec extends Specification { @Subject def bookshelf = new Bookshelf() @Unroll def "Find book #title by ISBN #isbn"() { when: 'we search a book by ISBN' def book = bookshelf.byIsbn(isbn) then: 'the title and author are correct' book?.title == title book?.author == author where: isbn || title | author "0345391802" || "The Hitchhiker's Guide to the Galaxy" | "Douglas Adams" "0345391829" || "Life, the Universe and Everything" | "Douglas Adams" } } // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 35. Scala und Gatling für lesbare und performante Last-Tests class BooksPerformanceTest extends Simulation { val conf = http.baseURL("http://localhost:18080").acceptHeader("application/json") val feeder = csv("books.csv").random val scn = scenario("Book Search") .exec(http("Get all books").get("/api/books")) .during(30 seconds) { feed(feeder) .exec(http("Get book by title ${Title}").get("/api/books?title=${Title}")) .pause(1 second) .exec(http("Get book with ISBN ${ISBN}").get("/api/books/${ISBN}")) } setUp(scn.inject(atOnceUsers(10), rampUsers(50) over (30 seconds))) .assertions(global.responseTime.max.lessThan(5000)) .protocols(conf) } // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 37. Definition einer Build-Pipeline per Jenkinsfile und Groovy #!/usr/bin/env groovy node { stage 'Checkout SCM' checkout scm stage 'Build/Analyse/Test' sh './gradlew clean build' archiveUnitTestResults() archiveDistributions() stage 'Dockerize' sh './gradlew buildDockerImage' stage 'Generate Documentation' sh './gradlew asciidoctor' } // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 38. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 40. Architektur-Definition und Prüfung mit QAvalidator für wartbaren Code. architecture(name: "Mail Example", prefix: "tview", reflexMLversion: "1.0") { excludes "java.lang.*" api "JavaMail" : "javax.mail.*" component "Mail" { api "IMail" : "de.qaware.mail.*" impl ["de.qaware.mail.impl.*", "de.qaware.mail.impl2.*"] uses "JavaMail" component "MailSender" { api ["de.qaware.mail.sender.*", "javax.mail.*"] impl "de.qaware.mail.impl.javamail.JavaMailSender" uses "JavaMail" } } } // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 42. Docker, Docker, Docker, ... FROM qaware-oss-docker-registry.bintray.io/base/alpine-k8s-openjdk8:8u121 MAINTAINER M.-Leander Reimer <mario-leander.reimer@qaware.de> RUN mkdir -p /app ADD build/distributions/everything-as-code-1.2.3.tar /app WORKDIR /app/everything-as-code-1.2.3 RUN chmod 755 bin/everything-as-code EXPOSE 18080 CMD ./bin/everything-as-code // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 43. Cluster Orchestration mit K8s et.al. --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: everything-as-code spec: replicas: 2 template: metadata: labels: tier: backend spec: containers: - name: everything-as-code image: "qaware-oss-docker-registry.bintray.io/lreimer/everything-as-code:1.2.3" ports: - containerPort: 18080 env: - name: PORT value: 18080 // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 44. Einfache Provisionierung mit Ansible. --- # file: jenkinsci.yml - hosts: jenkinsci remote_user: root tasks: - debug: msg="Creating a Jenkins pipeline job on {{ inventory_hostname }}" - jenkins_job: name: Everything-as-code Pipeline config: "{{ lookup('file', 'templates/pipeline-job.xml') }}" url: "http://{{ inventory_hostname }}" user: admin password: admin // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 45. Vagrant und Ruby zum Setup lokaler VMs. require 'yaml' $setup = <<SCRIPT sudo apt-add-repository ppa:ansible/ansible sudo apt-get update sudo apt-get install -y ansible sshpass SCRIPT Vagrant.configure("2") do |config| config.vm.box = "ubuntu/trusty32" settings = YAML.load_file 'src/vagrant/vagrant.yml' config.vm.provider "virtualbox" do |vb| vb.name = settings['vm']['name'] vb.gui = false vb.memory = "512" end config.vm.provision "shell", inline: $setup end // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 47. Ja, wir brauchen Dokumentation! • Und nein. Der Quellcode ist nicht genug! • Technische Dokumente mit Word sind ! " # • Dokumentation sollte neben dem Quellcode liegen: change code, change docs. • Schnell und einfach zu schreiben. • Unterstützung für Code, Bilder, Diagramme // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 48. // Beispiel Architektur-Dokumentation mit arc42 (https://arc42.github.io) :imagesdir: ./images = image:qaware-logo.png[QAware GmbH,2016] Everything-as-code :toc-title: Table of Contents :toc: [[section-introduction-and-goals]] == Introduction and Goals The introduction to the architecture documentation should list the driving forces that software architects must consider in their decisions. === Requirements Overview === Quality Goals === Stakeholders <<<< include::02_architecture_constraints.adoc[] // further includes for the remaining sections // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 49. Mit AsciidoctorJ und Gradle zum fertigen Dokument. plugins { id "org.asciidoctor.convert" version "1.5.3" } asciidoctorj { version = '1.5.4.1' } asciidoctor { sourceDir 'src/docs/architecture' resources { from('src/docs/architecture') { include 'images/**/*.png' include 'images/**/*.jpg' } } backends ['html5', 'pdf'] options doctype: 'article' attributes 'source-highlighter': 'coderay' } // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 50. Architectur-Dokumentation mit Structurizr def workspace = new Workspace("Everything-as-code", "The system context of Everything-as-code.") def model = workspace.model // create a model and the software system we want to describe def bookApp = model.addSoftwareSystem("Book Application", "The best source to get info on books.") // create the various types of people (roles) that use the software system def anonymousUser = model.addPerson("Anonymous User", "Anybody on the web.") anonymousUser.uses(bookApp, "Searches for books and views details.") def browser = bookApp.addContainer("Web Browser", "Allows users to view information about books", "Edge, Chrome, Firefox") anonymousUser.uses(browser, "Views information from and makes requests to") def webApp = bookApp.addContainer("Web Application", "Hosts the browser-based web application and services", "Payara Fish") browser.uses(webApp, "uses [JSON/HTTPS]") // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 51. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 53. These slides were written in Markdown. --- ## [fit] These slides were written in Markdown. - This is for real programmers! :smiley: - Several open source projects available - Use HTML and JavaScript alternatively. --- // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 55. Use the right tool for the job!
  • 57. Alles mit Augenmaß! Der richtige Technologie-Stack hängt vom Team, dem Projekt-Kontext und unseren Kunden ab. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 58. Fork me on GitHub. https://github.com/lreimer/everything-as-code // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }
  • 59. // IT-Tage 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }