Ruby by the River

Ruby by the River

3f51727357dd2eeb7fbb59993e0fca29?s=128

Jason Frame

June 29, 2012
Tweet

Transcript

  1. Ruby by the River Saturday, 1 June 13

  2. Riverside Museum Saturday, 1 June 13

  3. eIntros Saturday, 1 June 13

  4. Street 1 Saturday, 1 June 13

  5. Car Wall Saturday, 1 June 13

  6. Motorbike Wall Saturday, 1 June 13

  7. Ship Conveyor Saturday, 1 June 13

  8. Clippers/Telegram Boys Saturday, 1 June 13

  9. Technical Summary • 8 major “Key Attract” installations • 37

    eIntros • 6 eStorybooks • 17 public information screens • ~150 Mac Minis Saturday, 1 June 13
  10. Architecture Rails CMS Scheduler RCP Daemon StoryPlayer Mac Mini Role

    specific service Role specific service Role specific service Saturday, 1 June 13
  11. CMS • Venue as content tree • Page per exhibit

    • Content type/class per exhibit type • Revision and publishing controls • Data collection Saturday, 1 June 13
  12. Polar • Lots of content types • Requirements changing daily

    • Declarative JS API for declaring editable content types • Recursive Saturday, 1 June 13
  13. Component Example Polar.createComponent('eintro_page') .container(true) .childLocation('intro_pictures', {only: 'image'}) .childLocation('in_focus', {only: ['image',

    'video', 'audio', 'gallery', 'group', 'cardetails']}) .hasPadding() .hadBorder() .property('eintro_type', { type: 'select', caption: 'eIntro Type', choices: ['Large object', 'Key attract', 'Story in focus', 'Game play'] }) .methods({ render: function() { /* ... */ }, ready: function() { var self = this, this.$tinymce = this.$body.tinymce(tinyMCEOptions.options("tinymce-eintro", {oninit: function(ed) { ed.setContent((self.$object && self.$object.body) || ''); }})); }, _serializeComponent: function() { return { title : this.$title.val(), body : this.$tinymce.tinymce().getContent(), feedback_intro : this.$feedback_intro.val() }; }, _unserializeComponent: function(obj) { this.$title.val(obj.title); this.$feedback_intro.val(obj.feedback_intro); } }); Saturday, 1 June 13
  14. Component Example Saturday, 1 June 13

  15. Component Example Saturday, 1 June 13

  16. StoryPlayer/RCP • Cocoa-based Webkit wrapper • Plugin architecture for hardware

    support • Javascript/Cocoa bridge • RCP daemon for remote system control • Crash on error, restart Saturday, 1 June 13
  17. Scheduler • Ruby daemon implementing custom UDP messaging protocol Saturday,

    1 June 13
  18. Scheduler • Ruby daemon implementing custom UDP messaging protocol •

    Declarative Ruby API for defining available actions Saturday, 1 June 13
  19. Scheduler • Ruby daemon implementing custom UDP messaging protocol •

    Declarative Ruby API for defining available actions • Actions assembled into timed groups called templates Saturday, 1 June 13
  20. Scheduler • Ruby daemon implementing custom UDP messaging protocol •

    Declarative Ruby API for defining available actions • Actions assembled into timed groups called templates • Single API defines both user interface and behaviour Saturday, 1 June 13
  21. Saturday, 1 June 13

  22. Scheduler namespace :opennms do action(:create_outage, :description => 'OpenNMS - Create

    Outage') do |action| action.param(:hosts, :string, :required => true) action.proc = lambda do |app, params| hosts = parse_hosts(params) `/opt/55/bin/update-opennms-outages sleep #{hosts.join(' ')}` end end end namespace :system do rcp_request_action(:sleep, :description => 'System Sleep') do |action| action.proc = lambda do |app, params| hosts = parse_hosts(params) hosts.each { |h| app[:arp_cache].update(h) } ::ShowControl::RCP::Request.command(RCP_CMD_ID_SYS_SLEEP) end end end Saturday, 1 June 13
  23. Fluent API design Saturday, 1 June 13

  24. Fluent API design • Convergent design Saturday, 1 June 13

  25. Fluent API design • Convergent design • Allow customisation with

    lambdas Saturday, 1 June 13
  26. Fluent API design • Convergent design • Allow customisation with

    lambdas • Don’t abstract everything Saturday, 1 June 13
  27. Fluent API design • Convergent design • Allow customisation with

    lambdas • Don’t abstract everything • Make common tasks easy, but nothing impossible Saturday, 1 June 13
  28. Messy Leaves! action.proc = lambda do |app, params| payload =

    [ RCP_CMD_ID_AUDIO_GAIN, 1, params[:gain] ].pack('nnC') ::ShowControl::RCP::Request.command(RCP_CMD_ID_AUDIO_SET_OUTPUT_GAIN, payload) end action.proc = lambda do |app, params| payload = [ RCP_CMD_ID_AUDIO_GAIN, 1, params[:gain] ].pack('nnC') ::ShowControl::RCP::Request.command(RCP_CMD_ID_AUDIO_SET_OUTPUT_GAIN, payload) end this.$title = this._makeBlock( {inner:false, tail:false, title:'eIntro title'} ) .append('<input type="text"/>') .insertBefore(this.$html.$tail) .find("input"); this.$body = this._makeBlock( {inner:false, tail:false, title:'eIntro body'} ) .append('<textarea />') .insertBefore(this.$html.$tail) .find("textarea"); this.$intro_pictures = this._makeChildContainer('intro_pictures', {padding: true, border: true, title: 'Introduction images'} ) .insertBefore(this.$html.$tail); Saturday, 1 June 13
  29. Riverside Museum Saturday, 1 June 13

  30. Saturday, 1 June 13

  31. Saturday, 1 June 13

  32. Saturday, 1 June 13

  33. Challenges Saturday, 1 June 13

  34. 1. Network • Unreliable network Saturday, 1 June 13

  35. 1. Network • Unreliable network • Machine identification Saturday, 1

    June 13
  36. Daily Occurrence <erno> hm. I've lost a machine.. literally _lost_.

    it responds to ping, it works completely, I just can't figure out where in my apartment it is. http://bash.org/?5273 Saturday, 1 June 13
  37. 1. Network • Unreliable network • Machine identification • No

    switching/routing Saturday, 1 June 13
  38. Exhibit: Crash Saturday, 1 June 13

  39. 1. Network • Unreliable network • Machine identification • No

    switching/routing • DNS Saturday, 1 June 13
  40. 1. Network • Unreliable network • Machine identification • Switching/routing

    • DNS • No remote access - either in or out Saturday, 1 June 13
  41. Saturday, 1 June 13

  42. 1. Network • Unreliable network • Machine identification • No

    switching/routing • DNS • No remote access - either in or out Saturday, 1 June 13
  43. 2. Closed Systems Saturday, 1 June 13

  44. 2. Closed Systems Assertion: Attempting to fix a low level

    problem from a higher level is futile Saturday, 1 June 13
  45. Warning! Car Analogy Incoming Saturday, 1 June 13

  46. 2. Closed Systems Assertion: Attempting to fix a low level

    problem from a higher level is futile Saturday, 1 June 13
  47. 2. Closed Systems • Turning machines on Saturday, 1 June

    13
  48. 2. Closed Systems • Turning machines on • HTML5 application

    manifest Saturday, 1 June 13
  49. 2. Closed Systems • Turning machines on • HTML5 application

    manifest • HTML5 video playback Saturday, 1 June 13
  50. Exhibit: Ship Conveyor Saturday, 1 June 13

  51. 2. Closed Systems • Turning machines on • HTML5 application

    manifest • HTML5 video playback Saturday, 1 June 13
  52. 2. Closed Systems • Turning machines on • HTML5 application

    manifest • HTML5 video playback • Embedded devices Saturday, 1 June 13
  53. 2. Closed Systems • Turning machines on • HTML5 application

    manifest • HTML5 video playback • Embedded devices • EOL hardware Saturday, 1 June 13
  54. 2. Closed Systems - Takeaways • Strive to reduce to

    the number of closed systems in your deployment Saturday, 1 June 13
  55. 2. Closed Systems - Takeaways • Strive to reduce to

    the number of closed systems in your deployment • Be aware of the available tools for diagnosing problems at the lowest level necessary Saturday, 1 June 13
  56. 2. Closed Systems - Takeaways • Strive to reduce to

    the number of closed systems in your deployment • Be aware of the available tools for diagnosing problems at the lowest level necessary • Build a degree of leniency into systems you develop for others to integrate with Saturday, 1 June 13
  57. 3. System Imaging • Had to develop baseline system image

    for all machines in the museum Saturday, 1 June 13
  58. 3. System Imaging • Had to develop baseline system image

    for all machines in the museum • 3rd party contractors required image to develop their interactives Saturday, 1 June 13
  59. 3. System Imaging • Had to develop baseline system image

    for all machines in the museum • 3rd party contractors required image to develop their interactives • Machines had to be interchangeable Saturday, 1 June 13
  60. 3. System Imaging • Had to develop baseline system image

    for all machines in the museum • 3rd party contractors required image to develop their interactives • Machines had to be interchangeable • Theory vs Reality Saturday, 1 June 13
  61. world.xml • Idea: every machine can be substituted into any

    role • Global XML file specifies roles by DNS name • Roles define which plists launchd should start on boot • world.xml retrieved from central at boot time Saturday, 1 June 13
  62. System Triage • As new systems appeared online, we would

    “triage” them • All systems based on same image, so all had the same Bonjour hostname on boot • Map serial numbers to hostnames • Set hostname, bring image up to date, reboot Saturday, 1 June 13
  63. That sounds tedious. Saturday, 1 June 13

  64. • ad hoc, informally-specified implementation of half of Capistrano and

    half of Puppet makitzo Saturday, 1 June 13
  65. • ad hoc, informally-specified implementation of half of Capistrano and

    half of Puppet • control multiple SSH hosts makitzo Saturday, 1 June 13
  66. • ad hoc, informally-specified implementation of half of Capistrano and

    half of Puppet • control multiple SSH hosts • CLI querying for operating on subset of hosts makitzo Saturday, 1 June 13
  67. makitzo - host querying jason@ratchet $ ./makitzo --host foo jason@ratchet

    $ ./makitzo --host foo --host bar jason@ratchet $ ./makitzo --host carwall-* jason@ratchet $ ./makitzo --role carwall --role bikewall Saturday, 1 June 13
  68. • ad hoc, informally-specified implementation of half of Capistrano and

    half of Puppet • control multiple SSH hosts • CLI querying for operating on subset of hosts • built-in command DSL makitzo Saturday, 1 June 13
  69. makitzo - command DSL module Makitzo; module SSH; module Commands

    module Apple def shutdown_at(time) sudo do unless exec("pmset schedule shutdown \"#{time}\"").success? logger.error("couldn't set poweroff time") return false end end true end end end; end; end Saturday, 1 June 13
  70. makitzo - command DSL jason@ratchet $ ./makitzo --host foo --host

    bar exec shutdown_at 18:00:00 Saturday, 1 June 13
  71. • ad hoc, informally-specified implementation of half of Capistrano and

    half of Puppet • control multiple SSH hosts • CLI querying for operating on subset of hosts • built-in command DSL • migrations makitzo Saturday, 1 June 13
  72. • Reconfiguration of development environment • New system triaging •

    Compare output of commands between multiple hosts • Update systems - git pull • Update systems - migrations makitzo - uses Saturday, 1 June 13
  73. • Best-effort makitzo - migrations Saturday, 1 June 13

  74. • Best-effort • Rails-style syntax makitzo - migrations Saturday, 1

    June 13
  75. makitzo - migrations class InstallUsbSerialDriver < ::Makitzo::Migrations::Migration role :mac_mini def

    up scp_upload(local_migration_file("FTDIUSBSerialDriver_10_4_10_5_10_6.mpkg.zip"), remote_migration_file("FTDIUSBSerialDriver_10_4_10_5_10_6.mpkg.zip")) exec "cd #{remote_directory}; unzip FTDIUSBSerialDriver_10_4_10_5_10_6.mpkg.zip" sudo { install_pkg remote_migration_file('FTDIUSBSerialDriver_10_4_10_5_10_6.mpkg') } end end Saturday, 1 June 13
  76. • Best-effort • Rails-style syntax • Temporary working area makitzo

    - migrations Saturday, 1 June 13
  77. • Best-effort • Rails-style syntax • Temporary working area •

    Per-host store (slow) or centralised makitzo - migrations Saturday, 1 June 13
  78. http://github.com/jaz303/makitzo Saturday, 1 June 13

  79. 1 year in 3 lines: • Awesome project Saturday, 1

    June 13
  80. 1 year in 3 lines: • Awesome project • Awesome

    people Saturday, 1 June 13
  81. 1 year in 3 lines: • Awesome project • Awesome

    people • Never again Saturday, 1 June 13
  82. Questions etc. Saturday, 1 June 13

  83. Photo Credits • Amy Jackson (@octobrrr) • Tom Beddard (@subblue)

    • Andy Magee http://www.flickr.com/photos/ amagee3/ • “Anne” http://www.flickr.com/photos/ilike/ • “Ianan” http://www.flickr.com/photos/ianan/ Saturday, 1 June 13