Slide 1

Slide 1 text

Everything-as-code. Eine vielsprachige Reise. // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 1

Slide 2

Slide 2 text

#whoami Mario-Leander Reimer Chief Technologist, QAware GmbH - Senior Developer && Architect - #CloudNativeNerd - Open Source Enthusiast [email protected] http://github.com/lreimer http://speakerdeck.com/lreimer // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 2

Slide 3

Slide 3 text

// JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 3

Slide 4

Slide 4 text

Welche Sprache verwenden echte Programmierer? // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 4

Slide 5

Slide 5 text

Meine #FirstSevenLanguages • Pascal • Basic • C / C++ • Assembler • PHP • Java • C# // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 5

Slide 6

Slide 6 text

Meine #LastSevenLanguages • Java • Groovy • TypeScript • Ruby • Kotlin • Scala • Go // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 6

Slide 7

Slide 7 text

// JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 7

Slide 8

Slide 8 text

// JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 8

Slide 9

Slide 9 text

Es gibt keine einstimmige Meinung ... • http://spectrum.ieee.org/computing/software/ the-2015-top-ten-programming-languages • http://spectrum.ieee.org/computing/software/ the-2016-top-programming-languages • http://redmonk.com/sogrady/2017/06/08/language- rankings-6-17/ • https://jaxenter.de/programmiersprachen-rankings- q1-2017-54308 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 9

Slide 10

Slide 10 text

Eine beste Programmiersprache gibt es nicht! Auf die Domäne kommt es an. // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 10

Slide 11

Slide 11 text

We are software craftsmen. The IDE is our workbench. // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 11

Slide 12

Slide 12 text

Unsere Definition von Software Industrialisierung • Hat nichts mit billiger Arbeitskraft zu tun! • 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 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 12

Slide 13

Slide 13 text

Software Industrialization ist eine Schlüsselanforderung für erfolgreiches DevOps und Continuous Delivery. // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 13

Slide 14

Slide 14 text

val softwareIndustrialization = everythingAsCode() open fun everythingAsCode() = everythingIsMadeFromCode() && everythingIsMadeByCode() private fun everythingIsMadeFromCode() = true private fun everythingIsMadeByCode() = true // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 14

Slide 15

Slide 15 text

The Quest for an ideal 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! // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 15

Slide 16

Slide 16 text

Eine vielsprachige Reise beginnt ... // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 16

Slide 17

Slide 17 text

SEU-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 17

Slide 18

Slide 18 text

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 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 18

Slide 19

Slide 19 text

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' } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 19

Slide 20

Slide 20 text

Build-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 20

Slide 21

Slide 21 text

Maven ist gut. Gradle ist besser. • Sehr flexibel und vielseitig einsetzbar. • Einfache Unterstützung für Polyglotte Projekte. • Build Skripte sind maximal kurz und prägnant. • Drastisch reduzierte Build-Zeiten (40x) durch Incremental Builds. • Zahlreiche neue Features: Composite Builds, Kotlin- basierte Build-Skripte, Performance Verbesserungen, ... • Regelmäßige Releases. Stabil und ausgereift. // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 21

Slide 22

Slide 22 text

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 @ JUG Darmstadt 2017.' } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 22

Slide 23

Slide 23 text

Main-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 23

Slide 24

Slide 24 text

Java ist nach wie vor die primäre Implementierungssprache! Und das ist gut so! // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 24

Slide 25

Slide 25 text

Aber: Kotlin als Alternative für Java ist einen Blick wert. // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 25

Slide 26

Slide 26 text

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. // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 26

Slide 27

Slide 27 text

@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) } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 27

Slide 28

Slide 28 text

Frontend-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 28

Slide 29

Slide 29 text

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 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 29

Slide 30

Slide 30 text

Test-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 30

Slide 31

Slide 31 text

Groovy und Spock für Unit & Integration 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" } } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 31

Slide 32

Slide 32 text

Scala und Gatling für 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) } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 32

Slide 33

Slide 33 text

Pipeline-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 33

Slide 34

Slide 34 text

Definition der Build-Pipeline per Jenkinsfile #!/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' } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 34

Slide 35

Slide 35 text

Infrastructure-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 35

Slide 36

Slide 36 text

Docker, Docker, Docker, ... FROM qaware-oss-docker-registry.bintray.io/base/alpine-k8s-openjdk8:8u121 MAINTAINER M.-Leander Reimer 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 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 36

Slide 37

Slide 37 text

Vagrant und Ruby zum Setup lokaler VMs require 'yaml' $setup = < { created with ❤ and ☕ by @LeanderReimer @qaware } 37

Slide 38

Slide 38 text

Provisionierung mit Ansible (und Python) --- # 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 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 38

Slide 39

Slide 39 text

Cluster Orchestration mit Kubernetes --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: everything-as-code spec: replicas: 3 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 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 39

Slide 40

Slide 40 text

Documentation-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 40

Slide 41

Slide 41 text

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 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 41

Slide 42

Slide 42 text

// 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 // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 42

Slide 43

Slide 43 text

AsciidoctorJ und Gradle to the Rescue 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' options doctype: 'article' attributes 'source-highlighter': 'coderay' } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 43

Slide 44

Slide 44 text

Architecture-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 44

Slide 45

Slide 45 text

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]") // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 45

Slide 46

Slide 46 text

Architektur-Validierung mit dem QAvalidator 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" } } } // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 46

Slide 47

Slide 47 text

Presentation-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 47

Slide 48

Slide 48 text

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. --- // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 48

Slide 49

Slide 49 text

Heutige Projekte sind polyglot. // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 49

Slide 50

Slide 50 text

// JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 50

Slide 51

Slide 51 text

Use the right tool for the job! // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 51

Slide 52

Slide 52 text

Alles mit Augenmaß! Der richtige Technologie-Stack hängt ab vom Team, dem Projekt-Kontext und unseren Kunden. // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 52

Slide 53

Slide 53 text

Fork me on GitHub. https://github.com/lreimer/everything-as-code // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 53

Slide 54

Slide 54 text

We are hiring. http://www.qaware.de/karriere/#jobs // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 54

Slide 55

Slide 55 text

Thanks! Questions? // JUG Darmastadt 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware } 55