Successfully reported this slideshow.
Your SlideShare is downloading. ×

Sshoogr for your infrastructure

Ad

01

Ad

About me
02

Ad

Andrey Adamovich
Java/Groovy developer
DevOps guy, automation junkie
Co­author of Groovy 2 Cookbook
Co­organizer of @latcr...

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Loading in …3
×

Check these out next

1 of 71 Ad
1 of 71 Ad

Sshoogr for your infrastructure

Download to read offline

Infrastructure automation is not what most developers prefer to do, but when they do, they seek for simplicity. Sshoogr started as a simple SSH wrapper, but currently it is growing to become Ansible of Groovy. That allows to combine configuration, connectivity and state management of your servers and containers within a simple and readable DSL.

Infrastructure automation is not what most developers prefer to do, but when they do, they seek for simplicity. Sshoogr started as a simple SSH wrapper, but currently it is growing to become Ansible of Groovy. That allows to combine configuration, connectivity and state management of your servers and containers within a simple and readable DSL.

Advertisement
Advertisement

More Related Content

Advertisement

Sshoogr for your infrastructure

  1. 1. 01
  2. 2. About me 02
  3. 3. Andrey Adamovich Java/Groovy developer DevOps guy, automation junkie Co­author of Groovy 2 Cookbook Co­organizer of @latcraft and @devternity Coach at @devchampions Twitter: @codingandrey • • • • • • 03
  4. 4. Background 04
  5. 5. Background Big projects built by Ant, Maven, and eventually Gradle Teams composed mostly of Java developers Complex (sometimes, over­engineered) architectures Many environments (DEV, TEST, QA, SIT, UAT, PRE­PROD, PROD) to support • • • • 05
  6. 6. Problems I Infrastructure is influenced by (relatively) frequent architecture changes (components, versions, layers) We want our environments to be the same (or at least quite similar) to avoid any side effects during development, testing and production We don't want to spend hours/days/weeks on configuring each and every new server and keeping them in­sync • • • 06
  7. 7. Problems II Operations guys are not always available (e.g. busy supporting production systems or just not skilled enough) Development infrastructure (Jenkins, Sonar, Version Control, Load Testing etc.) also needs maintenance We want to reuse experience available in our team and avoid throwing in too many various trendy technologies that will fail our expectations • • • 07
  8. 8. First Blood 08
  9. 9. Ant + Gradle ant.taskdef(   name: 'scp',    classname: 'o.a.t.a.t.o.ssh.Scp',    classpath: configurations.secureShell.asPath)  ant.taskdef(   name: 'sshexec',    classname: 'o.a.t.a.t.o.ssh.SSHExec',    classpath: configurations.secureShell.asPath)  01. 02. 03. 04. 05.06. 07. 08. 09. 09
  10. 10. Simple call ant.sshexec(   host: host,    username: user,    password: password,    command: command,    trust: 'true',    failonerror: failOnError) 01. 02. 03. 04. 05. 06. 07. 10
  11. 11. Sshoogr 11
  12. 12. Sshoogr features Groovy­based SSH DSL for: Remote command execution File uploading/downloading Tunneling • • • 12
  13. 13. Sshoogr 0.9.23! 13
  14. 14. Sshoogr usage (import) @Grab(   group='com.aestasit.infrastructure.sshoogr',   module='sshoogr',   version='0.9.23') import static com.aestasit.ssh.DefaultSsh.* 01. 02. 03. 04. 05. 14
  15. 15. Sshoogr usage (defaults) defaultUser    = 'root' defaultKeyFile = new File('secret.pem') execOptions {   verbose      = true   showCommand  = true } 01. 02. 03. 04. 05. 06. 15
  16. 16. Sshoogr usage (connection) remoteSession {   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. 16
  17. 17. Sshoogr usage (multi­line content) remoteFile('/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. 17
  18. 18. Sshoogr usage (appendable) remoteFile('/etc/motd') << 'Additional message' new File('localFile') << remoteFile('/etc/motd') localFile << remoteFile('/etc/motd') << 'msg' 01. 02. 03. 18
  19. 19. Sshoogr usage (file copying) remoteSession {   scp {     from { localDir "$buildDir/application" }     into { remoteDir '/var/bea/domain/application' }   } } 01. 02. 03. 04. 05. 06. 19
  20. 20. Sshoogr usage (file copying) remoteSession {   scp {     from { remoteDir '/var/bea/domain/application' }     into { localDir "$buildDir/application" }   } } 01. 02. 03. 04. 05. 06. 20
  21. 21. Sshoogr usage (file copying) remoteSession {   scp {     from {        remoteFile '/etc/init.d/service1'        remoteFile '/etc/init.d/service2'      }     into { localDir "$buildDir/application" }   } } 01. 02. 03. 04. 05. 06. 07. 08. 09. 21
  22. 22. Sshoogr usage (command result) def 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("Warning!!!")     }   } } 01. 02. 03. 04. 05. 06. 07. 08. 09. 22
  23. 23. Sshoogr usage (shortcuts) if (ok('/usr/bin/mycmd')) {   ... } if (fail('/usr/bin/othercmd')) {   ... } 01. 02. 03. 04. 05. 06. 23
  24. 24. Sshoogr usage (tunnels) tunnel('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. 24
  25. 25. Sshoogr usage (prefix/suffix) prefix('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. 25
  26. 26. Sshoogr: more features ANSI coloured output Download/upload progress HTTP proxy • • • 26
  27. 27. Sshoogr: executable sshoogr ‐h 192.168.43.122          ‐u ubuntu          ‐l color          default.sshoogr 01. 02. 03. 04. 27
  28. 28. Sshoogr: *.sshoogr No need to install Groovy Can ommit  @Grab Can ommit connection details Scripts are more portable Ansible for Groovy! • • • • • 28
  29. 29. Sshoogr: *.sshoogr remoteSession {   exec('uname ‐a')   exec('date')   ... } 01. 02. 03. 04. 05. 29
  30. 30. sdkman.io 30
  31. 31. sdkman.io curl ‐s http://get.sdkman.io | bash sdk install sshoogr 0.9.23 sdk default sshoogr 0.9.23 sdk list sshoogr 01. 02. 03. 04. 31
  32. 32. More goodies 32
  33. 33. Intellij IDEA DSL 33
  34. 34. Intellij IDEA DSL 34
  35. 35. Intellij IDEA DSL 35
  36. 36. SSHD Mock 36
  37. 37. SSHD Mock MockSshServer.with {   command('^ls.*$') { inp, out, err, callback, env ‐>     out << '''total 20       drwxr‐xr‐x 3 1100 1100 4096 Aug  7 16:52 .       drwxr‐xr‐x 8 1100 1100 4096 Aug  1 17:53 ..       drwxr‐xr‐x 3 1100 1100 4096 Aug  7 16:49 examples       callback.onExit(0)     }     ... 01. 02. 03. 04. 05. 06. 07. 08. 09. 37
  38. 38. SSHD Mock   ...    command('^whoami.*$') { inp, out, err, callback, env ‐>     out << "rootn"     callback.onExit(0)   }   command('^du.*$') { inp, out, err, callback, env ‐>     out << "100n"     callback.onExit(0)   }   ... 01. 02. 03. 04. 05. 06. 07. 08. 09. 10. 38
  39. 39. SSHD Mock   ...   // Create file expectations.   dir('.')   dir('/tmp')   ... 01. 02. 03. 04. 05. 39
  40. 40. SSHD Mock   ...   // Start server   startSshd(2233) } 01. 02. 03. 04. 40
  41. 41. Gradle integration 41
  42. 42. Gradle integration buildscript {   repositories { mavenCentral() }   dependencies {     classpath 'com.a....sshoogr:sshoogr‐gradle:0.9.18'   } } apply plugin: 'secureShell' 01. 02. 03. 04. 05. 06. 07. 42
  43. 43. Gradle integration task remoteTask << {   remoteSession("user:password@localhost:22") {     exec 'rm ‐rf /tmp/cache/'     scp "$buildDir/cache.content",          '/tmp/cache/cache.content'           } } 01. 02. 03. 04. 05. 06. 07. 43
  44. 44. Little brother 44
  45. 45. Groowin @Grab('com.aestasit.infrastructure.groowin:groowin:0.1.8') import static com.aestasit.winrm.DefaultWinRM.* 01. 02. 45
  46. 46. Groowin remoteManagement {   host     = '127.0.0.1'   user     = 'Administrator'   password = 'secret'   exec 'del', 'C:temp.txt'   remoteFile('C:my.conf').text = "enabled=true" } 01. 02. 03. 04. 05. 06. 07. 46
  47. 47. PUnit 47
  48. 48. PUnit Simple testing tool for verifying remote server state Uses Sshoogr and JUnit Reuse reporting features of JUnit As simple as ... • • • • 48
  49. 49. PUnit: example (derby) class DerbyInstallTest      extends BasePuppetIntegrationTest {   @Before   void installDerby() {     apply("include derby")   }   ... } 01. 02. 03. 04. 05. 06. 07. 08. 49
  50. 50. PUnit: example (derby) @Test void ensureDerbyRunning() {   command('service derby status > derbystatus.log')   assertTrue fileText("/root/derbystatus.log")                .contains('Derby')   assertTrue fileText("/root/derbystatus.log")                .contains('is running.') } 01. 02. 03. 04. 05. 06. 07. 08. 50
  51. 51. PUnit: example (derby) @Test void ensureCanConnect() {   Thread.sleep(10000)   uploadScript()   command('/opt/derby/db‐derby‐10.9.1.0‐bin/bin/ij ' +            'testDataScript.sql > derbytest.log')   ... 01. 02. 03. 04. 05. 06. 07. 51
  52. 52. PUnit: example (derby)   ...   // Check if the log of the insert    // operation contains the word ERROR.   assertFalse(     "The script should return at least one error",     fileText("/root/derbytest.log")       .contains('ERROR')   )   ... 01. 02. 03. 04. 05. 06. 07. 08. 09. 52
  53. 53. PUnit: example (derby)   ...   // Check on data that was inserted into a table.   assertTrue(     "The log should contain a SELECT result",     fileText("/root/derbytest.log")      .contains('Grand Ave.')   ) } 01. 02. 03. 04. 05. 06. 07. 08. 53
  54. 54. PUnit: example (jenkins) session {   tunnel ('127.0.0.1', 8080) { int localPort ‐>     def driver = new HtmlUnitDriver(false)     driver.manage()           .timeouts()           .pageLoadTimeout(300, TimeUnit.SECONDS)           .implicitlyWait(30, TimeUnit.SECONDS)     driver.get("http://127.0.0.1:${localPort}/login")     ... 01. 02. 03. 04. 05. 06. 07. 08. 09. 10. 54
  55. 55. PUnit: example (jenkins)     ...     def input = driver.findElement(By.name('j_username'))     input.sendKeys('john')     input = driver.findElement(By.name('j_password'))     input.sendKeys('123456')     input.submit()     ... 01. 02. 03. 04. 05. 06. 07. 55
  56. 56. PUnit: example (jenkins)     ...     def wait = new WebDriverWait(driver, 30)     wait.until ExpectedConditions.        presenceOfElementLocated (By.linkText('John Doe'))     ...   } } 01. 02. 03. 04. 05. 06. 07. 56
  57. 57. PUnit: example (svn) session {   tunnel ('127.0.0.1', 80) { int localPort ‐>     // Initilize repository connection data.     DAVRepositoryFactory.setup()     def url = SVNURL.create('http', null, '127.0.0.1',                  localPort, 'repos/cafebabe', true)     def repository = SVNRepositoryFactory.create(url)     println "Verifying SVN repository at ${url}"     ... 01. 02. 03. 04. 05. 06. 07. 08. 09. 57
  58. 58. PUnit: example (svn)     ...     // Setup credentials.     def authManager = SVNWCUtil.       createDefaultAuthenticationManager('joe', '123456')     repository.setAuthenticationManager(authManager)          // Verify repository is at revision 0.     assertEquals 0, repository.getLatestRevision()     ... 01. 02. 03. 04. 05. 06. 07. 08. 09. 58
  59. 59. PUnit: example (svn)     ...     // Commit first revision.     ISVNEditor editor = repository.       getCommitEditor("Initial commit.", null)     editor.with {       openRoot(‐1)       addFile('dummy.txt', null, ‐1)       applyTextDelta('dummy.txt', null)       def deltaGenerator = new SVNDeltaGenerator() 01. 02. 03. 04. 05. 06. 07. 08. 09. 59
  60. 60. PUnit: example (svn)       ...       def checksum = deltaGenerator.sendDelta('dummy.txt',          new ByteArrayInputStream("data".getBytes()),          editor, true)        closeFile('dummy.txt', checksum)       def commitInfo = closeEdit()       println commitInfo     }     ... 01. 02. 03. 04. 05. 06. 07. 08. 09. 60
  61. 61. PUnit: example (svn)     ...     // Verify repository is at revision 1 now.     assertEquals 1, repository.getLatestRevision()       } } 01. 02. 03. 04. 05. 61
  62. 62. PUnit: continuous integration 62
  63. 63. PUnit: Jenkins build 63
  64. 64. Summary 64
  65. 65. Sshoogr is... Battle­tested Groovy DSL for SSH connectivity Executable and portable scripting tool Easily integratable with any Java/Groovy library • • • 65
  66. 66. Sshoogr can be used for... Provisioning your servers and IoT devices Executing remote orchestration commands Testing and monitoring infrastructure state • • • 66
  67. 67. Next steps Resource definitions Command rollbacks Parallel execution XSS utilities Extend integration tests Better documentation • • • • • • 67
  68. 68. Seeking contributors! 68
  69. 69. Source code Sshoogr: https://github.com/aestasit/sshoogr Sshoogr Gradle: https://github.com/aestasit/sshoogr­gradle Groowin: https://github.com/aestasit/groowin Groowin Gradle: https://github.com/aestasit/groowin­gradle • • • • 69
  70. 70. Thank you! 70
  71. 71. Questions? 71

×