ninja tricks for groovy system scripting for javaland 2016

Post on 07-Apr-2017

1.910 Views

Category:

Technology

3 Downloads

Preview:

Click to see full reader

TRANSCRIPT

01

About me02

Andrey AdamovichBio: Developer, coach, speaker, author

Company: Aestas/IT (http://aestasit.com)

E­mail: andrey@aestasit.com

Linkedin: http://www.linkedin.com/in/andreyadamovich

Lanyrd: http://lanyrd.com/profile/andrey­adamovich

GitHub: https://github.com/aadamovich

SO: http://stackoverflow.com/users/162792/andrey­adamovich

Twitter: @codingandrey, @aestasit

••••••••

03

Exposed to operationsMaintenance scripts (backup, cleaning, monitoring)

Scheduled/CRON jobs (transfers, conversions, notifications)

Automation tasks (deployment, packaging, testing)

Web applications (status pages, back doors, dashboards)

••••

04

Why Groovy?05

Native system scriptingBash, Dash, Zsh, Fish, Csh etc.

Bat, Cmd and, eventually, PowerShell (PoSH)••

06

Arrays in BAT?

07

BASH vs. PoSH

08

Scripting languagesPerl

Python

Ruby

Lua

Javascript

...

••••••

09

Multi­platformsupport

10

Does it workon Windows?

11

Operationalsimplicity

12

Maintainablecode

13

Stableecosystem14

Richextensionlibrary

15

Groovy is just a JAR

16

Reuse JVMknowledge17

sdkman.io

18

sdkman.iocurl ‐s http://get.sdkman.io | bash

sdk install groovy 2.4.6

sdk default groovy 2.4.6

sdk list groovy

01.

02.

03.

04.

19

PoSH GVM> posh‐gvm.psm1 cannot be loaded 

> because the execution of scripts 

> is disabled on this system.

01.

02.

03.

20

Speed up!21

GroovyServ

22

Files,directories,and otheranimals23

Readingf = new File('test.txt')

String textContent = f.text

byte[] binaryContent = file.bytes

01.

02.

03.

24

Writing If << 'hello, this is a test file'

f.text = new URL('http://server/my_data.json').text

file.bytes = [ 65, 66, 67, 68 ] as byte[]

01.

02.

03.

25

Writing IIfile.text = '''What's in a name? That which we call a rose

By any other name would smell as sweet.'''

file << 'What\'s in a name? That which we call a rose\n'

file << 'By any other name would smell as sweet.'

01.

02.

03.04.

05.

26

Writing IIIfile.withWriter { Writer writer ‐>

  writer << 'What\'s in a name? That which we call a rose\n'

  writer << 'By any other name would smell as sweet.'

}

file.withOutputStream { OutputStream stream ‐>

  stream << 'What\'s in a name? That which we call a rose\n'

  stream << 'By any other name would smell as sweet.'

}

01.

02.

03.

04.

05.06.

07.

08.

09.

27

Line­by­linedef lines = f.readLines()

lines.each { String line ‐>

  println line

}

01.

02.

03.

04.

28

eachLine and eachBytef.eachLine { String line ‐>

  println line

}

file.eachByte { int b ‐>

  ...

}

01.

02.

03.

04.

05.

06.

29

Filtering IoutputFile.withPrintWriter { writer ‐>

  inputFile.eachLine { line ‐>

    if (!line.startsWith('#')) {

      writer.println(line)

    }

  }

}

01.

02.

03.

04.

05.

06.

07.

30

Filtering IIinputFile.filterLine(outputFile.newWriter()) { line ‐>

  !line.startsWith('#')

}

01.

02.

03.

31

Filtering IIIoutputFile.withWriter { Writer writer ‐>

  inputFile.withReader { Reader reader ‐>

    reader.transformLine(writer) { String line ‐>

      line.replaceAll('\t', '  ')

    }

  }

}

01.

02.

03.

04.

05.

06.

07.

32

Filtering IVinputFile.withReader { reader ‐>

  reader.transformLine(outputFile.newWriter()) { line ‐>

    line.replaceAll('\t', '  ')

  }

}

01.

02.

03.

04.

05.

33

Filtering VoutputFile.text = inputFile.text.replaceAll('\t', '  ')01.

34

Walking thepath

35

eachFile and eachDirf.eachFile { File file ‐>

  ...

}

f.eachDir { File dir ‐>

  ...

}

01.

02.

03.

04.

05.

06.

36

Recursive walking IcurrentDir.eachFileRecurse { File file ‐>

  println file.name

}

currentDir.eachDirRecurse { File dir ‐>

  println dir.name

}

01.

02.

03.

04.

05.

06.

37

Recursive walking IIcurrentDir.traverse { File file ‐>

  if (file.name.endsWith('.groovy')) {

    println file.name

  }

}

01.

02.

03.

04.

05.

38

Recursive walking IIIcurrentDir.traverse(nameFilter: ~/.*\.groovy/) { File file ‐>

  println file.name

}

01.

02.

03.

39

Recursive walking IVimport static groovy.io.FileType.*

...

currentDir.traverse(

  type: FILES,

  nameFilter: ~/.*\.groovy/,

  excludeNameFilter: ~/^C.*$/) { File file ‐>

    println file.name

}

01.

02.

03.

04.

05.

06.

07.

08.

40

Extending File IFile.metaClass.safeDelete = {

  if (exists()) {

    if (isDirectory()) {

      if (!deleteDir()) {

        def msg = "Unable to delete a directory: ${name}"

        throw new IOException(msg)

      }

    ...

01.

02.

03.

04.

05.

06.

07.

08.

41

Extending File II    ...

    } else {

      if (!delete()) {

        def msg = "Unable to delete a file: ${name}"

        throw new IOException(msg)

      }

    }

  }

}

01.

02.

03.

04.

05.

06.

07.

08.

09. 42

Extending File IIIFile f = new File('test.txt')

f.safeDelete()

File d = new File('test_dir')

d.safeDelete()

01.

02.

03.

04.

43

Base script44

Base script IBaseScript.groovy :

abstract class BaseScript extends Script {

  static {

    File.metaClass.safeDelete = {

      if (exists()) {

        ...

  }

}

01.

02.

03.

04.

05.

06.

07.

45

Base script IIdelete.groovy :

new File('idonotexist.txt').safeDelete()01.

46

Base script IIIgroovy ‐b BaseScript delete.groovy01.

47

Externalcommands48

External commands Idef exitValue = "ls ‐l".execute().exitValue()

if (!exitValue) {

  println "Command failed with exit code: ${exitValue}"

}

01.

02.

03.

04.

49

External commands IIprintln "ls".execute().text()

println "ls".execute().inputStream.eachLine { println it }

"grep abc".execute().waitForOrKill(1000)

01.

02.

03.

50

External commands IIIProcess process = "command".execute()   

def out = new StringBuffer()

def err = new StringBuffer()

process.waitForProcessOutput(out, err)

01.

02.

03.

04.

51

External commands IV"less temp.txt".execute().pipeTo("grep error".execute()).text

def proc1 = "less temp.txt".execute()

def proc2 = "grep error".execute()

proc1 | proc2

println proc2.text

01.

02.

03.

04.

05.

52

Arguments53

CliBuilderdef cli = new CliBuilder(usage:'ls')

cli.a('display all files')

cli.l('use a long listing format')

cli.t('sort by modification time')

def options = cli.parse(args)

01.

02.

03.

04.

05.

54

Defensivescripting

55

Do you likeNPEs?

56

Even simple things can cause NPEJava:

System.out.println(user.

                     getAddress().

                     getCity())

Groovy:

println user.

          address.

            city

01.

02.

03.

01.

02.

03. 57

Safe navigation operator (?.)println user?.

          address?.

            city 

01.

02.

03.

58

Elvis operator (?:)println user?.

         address?.

           city ?: "No idea"

01.

02.

03.

59

Closures forDSLs

60

Imaginary DSLtransaction {

  request {

    id     = '2L'

    name   = 'PUT'

    amount = 25

  }

  request {

    ...

  }

}

01.

02.

03.

04.

05.

06.

07.

08.

09.

10.61

DSL: transaction() methoddef transaction(Closure cl) {

  def processor = new RequestProcessor()

  try {

    processor.init()

    cl.delegate = processor

    cl()

    sendRequests()

  } finally {

    processor.cleanup()

}}

01.

02.

03.

04.

05.

06.

07.

08.

09.

10.62

DSL: request() methodclass RequestProcessor {

  def requests = []

  def request(Closure cl) {

    def request = new Request()

    requests << request

    cl.delegate = request

    cl()

  }

  ...

01.

02.

03.

04.

05.

06.

07.

08.

09. 63

DSL: Request structureclass Request {

  String id

  String name

  String amount 

}

01.

02.

03.

04.

05.

64

Datamanipulation

65

XMLimport groovy.util.XmlSlurper

def xmlSource = new File('shakespeare.xml')

def bibliography = new XmlSlurper().parse(xmlSource)

println bibliography.author

bibliography.play

              .findAll { it.year.toInteger() > 1592 }

              .each { println it.title }

01.

02.

03.

04.

05.

06.

07.

66

JSONimport groovy.json.JsonSlurper

def reader = new FileReader('ui.json')

def ui = new JsonSlurper().parse(reader)

ui.items.each { println it.type }

println ui.items[0]

          .axes

          .find {

            it.fields.contains('y')

          }.title

01.

02.

03.

04.

05.

06.

07.

08.

09. 67

Grab yourstuff!

68

@Grab: import@Grab('org.apache.httpcomponents:httpclient:4.2.1')

import org.apache.http.impl.client.DefaultHttpClient

import org.apache.http.client.methods.HttpGet

01.

02.

03.

69

@Grab: variable@Grab('org.apache.httpcomponents:httpclient:4.2.1')

def httpClient =

  new org.apache.http.impl.client.DefaultHttpClient()

01.

02.

03.

70

@Grab: method@Grab('org.apache.httpcomponents:httpclient:4.2.1')

def getHttpClient() {

  new org.apache.http.impl.client.DefaultHttpClient()

}

01.

02.

03.

04.

71

@Grab: class@Grab('org.apache.httpcomponents:httpclient:4.2.1')

class Searcher {

  def httpClient

  Searcher() {

    httpClient =

      new org.apache.http.impl.client.DefaultHttpClient()

  }

}

01.

02.

03.

04.

05.

06.

07.

08.

72

@Grab: multiple@Grapes([

   @Grab('org.apache.httpcomponents:httpclient:4.2.1'),

   @Grab('org.ccil.cowan.tagsoup:tagsoup:1.2')])

class Searcher { ... }

01.

02.

03.

04.

73

@Grab: repository@GrabResolver(name='codehaus',

              root='http://repository.codehaus.org/')

class Searcher { ... }

01.

02.

03.

74

@Grab: exclude@GrabExclude(group='commons‐codec',

             module='commons‐codec')

class Searcher { ... }

01.

02.

03.

75

HTTP76

HTTPBuilder: import@Grab(

  group='org.codehaus.groovy.modules.http‐builder',

  module='http‐builder',

  version='0.6'

)

import groovyx.net.http.*

01.

02.

03.

04.

05.

06.

77

HTTPBuilder: instantiationdef baseUrl = 'http://api.duckduckgo.com'

def queryString = 'q=groovy&format=json&pretty=1'

def http = new HTTPBuilder(baseUrl)

01.

02.

03.

78

HTTPBuilder: requesthttp.request(Method.POST) {

  send ContentType.URLENC, queryString

  response.success = { response, reader ‐>

    println response.statusLine

    println reader.text

  }

  response.failure = { response ‐>

    println response.statusLine

  }

}

01.

02.

03.

04.

05.

06.

07.

08.

09.

10.79

SQL80

SQL: settingsimport groovy.sql.Sql

def dbSettings = [

  url: 'jdbc:hsqldb:hsql://localhost/cookingdb',

  driver: 'org.hsqldb.jdbcDriver',

  user: 'sa',

  password: ''

]

01.

02.03.

04.

05.

06.

07.

08.

81

SQL: querydef sql = Sql.newInstance(dbSettings)

sql.eachRow('SELECT * FROM COOKBOOK') { cookbook ‐>

  printf '%‐20s%s\n',

         cookbook.id,

         cookbook[1]

}

01.

02.03.

04.

05.

06.

07.

82

Groovy as a server (GaaS?)> groovy ‐l 4444 ‐e "println new Date()" &

> telnet localhost 4444

hey groovy give me the date

Wed Feb 04 10:03:23 EET 2015

01.

02.

03.

04.

83

Ratpack84

Ratpack: import@Grab("io.ratpack:ratpack‐groovy:1.1.1")

import static ratpack.groovy.Groovy.ratpack

01.

02.

85

Ratback: script bodyratpack {

  handlers {

    get {

      response.send "This is the app root (try: /date)"

    }

    get("date") {

      response.send new Date().toString()

    }

  }

}

01.

02.

03.

04.

05.

06.

07.

08.

09.

10.86

Sshoogr87

Sshoogr: import@Grab(

  group='com.aestasit.infrastructure.sshoogr',

  module='sshoogr',

  version='0.9.16')

import static com.aestasit.ssh.DefaultSsh.*

01.

02.

03.

04.

05.

88

Sshoogr: defaultsdefaultUser    = 'root'

defaultKeyFile = new File('secret.pem')

execOptions {

  verbose      = true

  showCommand  = true

}

01.

02.

03.

04.

05.

06.

89

Sshoogr: connectionremoteSession {

  url = 'user2:654321@localhost:2222'

  exec 'rm ‐rf /tmp/*'

  exec 'touch /var/lock/my.pid'

  remoteFile('/var/my.conf').text = "enabled=true"

}

01.

02.

03.

04.

05.

06.

90

Sshoogr: multi­line contentremoteFile('/etc/yum.repos.d/puppet.repo').text = '''

  [puppet]

  name=Puppet Labs Packages

  baseurl=http://yum.puppetlabs.com/el/

  enabled=0

  gpgcheck=0

'''

01.

02.

03.

04.

05.

06.

07.

91

Sshoogr: file copyingremoteSession {

  scp {

    from { localDir "$buildDir/application" }

    into { remoteDir '/var/bea/domain/application' }

  }

}

01.

02.

03.

04.

05.

06.

92

Sshoogr: command resultdef result = exec(command: '/usr/bin/mycmd',

  failOnError: false, showOutput: false)

if (result.exitStatus == 1) {

  result.output.eachLine { line ‐>

    if (line.contains('WARNING')) {

      throw new RuntimeException("First warning: ${line}")

    }

  }

}

01.

02.

03.

04.

05.

06.

07.

08.

09. 93

Sshoogr: shortcutsif (ok('/usr/bin/mycmd')) {

  ...

}

if (fail('/usr/bin/othercmd')) {

  ...

}

01.

02.

03.

04.

05.

06.

94

Sshoogr: tunnelstunnel('1.2.3.4', 8080) { int localPort ‐>

  def url = "http://localhost:${localPort}/flushCache"

  def result = new URL(url).text

  if (result == 'OK') {

    println "Cache is flushed!"

  } else {

    throw new RuntimeException(result)

  }

}

01.

02.

03.

04.

05.

06.

07.

08.

09. 95

Sshoogr: prefix/suffixprefix('sudo ') {

  exec 'rm ‐rf /var/log/abc.log'

  exec 'service abc restart'

}

suffix(' >> output.log') {

  exec 'yum ‐y install nginx'

  exec 'yum ‐y install mc'

  exec 'yum ‐y install links'

}

01.

02.

03.

04.

05.

06.

07.

08.

09. 96

Summary97

Take­awaysGroovy scripts are portable.

Groovy scripts are concise.

Groovy scripts are powerful.

Well, the name is groovy as well!

••••

98

Danke schön!99

Questions?100

Happyscripting!

101

top related