virtual madness @ etsy

28
Virtual Madness @ Etsy Nishan Subedi [email protected] @subedinishan

Upload: nishan-subedi

Post on 16-Jul-2015

115 views

Category:

Internet


2 download

TRANSCRIPT

Page 1: Virtual Madness @ Etsy

Virtual Madness @ Etsy

Nishan Subedi

[email protected]

@subedinishan

Page 2: Virtual Madness @ Etsy
Page 3: Virtual Madness @ Etsy

@subedinishan

~275 engineers

Page 4: Virtual Madness @ Etsy

@subedinishan

#devtools

• Infrastructure team

• <iframe>JS</iframe>

• Tooling

Page 5: Virtual Madness @ Etsy

@subedinishan

Virtual Madness - Pre Marionette

Page 6: Virtual Madness @ Etsy

@subedinishan

jQuery days(function (window, $) { $(function() { $("input.delete-host").change(function() { var hostname = $(this).attr('data-hostname'); if ($(this).is(':checked')) {

$('#div-vm-' + hostname).addClass('selected'); $('input#delete_dns-' + hostname).prop('checked', true); $('input#remove_disk-' + hostname).prop('checked', true); $('input#remove_autostart-' + hostname).prop('checked', true); } else { $('#div-vm-' + hostname).removeClass('selected'); if (!$('input#delete_dns-' + hostname).attr('disabled')) { $('input#delete_dns-' + hostname).prop('checked', false); $('input#remove_disk-' + hostname).prop('checked', false); $('input#remove_autostart-' + hostname).prop('checked', false); } } }); }); !})(window, jQuery);

Page 7: Virtual Madness @ Etsy

@subedinishan

PHP for templating<?php

include('templates/filters.php'); $extra_head = <<<HEAD <script type="text/javascript" src="https://www.google.com/jsapi"></script> <script type="text/javascript"> google.load('visualization', '1.0', {'packages':['corechart']}); function drawVisualization() { var guest_data = google.visualization.arrayToDataTable([ $format_virt_counts ]); google.setOnLoadCallback(drawVisualization); </script> HEAD; ?> <h2>Subnet Capacity</h2> <?php foreach ($graph_data AS $host_name => $host_data) : ?> <h3><a href="<?php echo $host_data['page_url']; ?>" target="blank"><?php echo $host_name ?></a></h3> <?php if (!empty($host_data['graphs'])) : ?> <ul class="host_graphs"> <?php foreach ($host_data['graphs'] AS $host_graph) : ?> <li><?php echo $host_graph; ?></li> <?php endforeach ?> </ul> <?php endif ?> <script> get_guest_graphs('<?php echo $host_name; ?>');

Page 8: Virtual Madness @ Etsy

@subedinishan

PHP for templating<?php include('templates/filters.php');

$extra_head = <<<HEAD <script type="text/javascript" src="https://www.google.com/jsapi"></script> <script type="text/javascript"> google.load('visualization', '1.0', {'packages':['corechart']}); function drawVisualization() { var guest_data = google.visualization.arrayToDataTable([

$format_virt_counts ]); google.setOnLoadCallback(drawVisualization); </script> HEAD; ?> <h2>Subnet Capacity</h2> <?php foreach ($graph_data AS $host_name => $host_data) : ?> <h3><a href="<?php echo $host_data['page_url']; ?>" target="blank"><?php echo $host_name ?></a></h3> <?php if (!empty($host_data['graphs'])) : ?> <ul class="host_graphs"> <?php foreach ($host_data['graphs'] AS $host_graph) : ?> <li><?php echo $host_graph; ?></li> <?php endforeach ?> </ul>

Page 9: Virtual Madness @ Etsy

@subedinishan

Concerns• We “understand” vanilla Javascript

• Method chain hell

• Yet another framework

Page 10: Virtual Madness @ Etsy

@subedinishan

If we can build it, so can you!

Page 11: Virtual Madness @ Etsy

@subedinishan

Technologies

Page 12: Virtual Madness @ Etsy

@subedinishan

Page 13: Virtual Madness @ Etsy

@subedinishan

Example - streamervar VmsManager = new Marionette.Application({ onStart: function() { // Start websocket connection this.socket = io.connect('//'+ document.location.hostname +':8008', { transports: ['websocket', 'xhr-polling'], secure: true }); this.socket.on('logdata', _.bind(this.onServerLog, this)); }, onServerLog: function(data) { this.logs.push(new this.Entities.Log(data)); }, onServerLogSubscribe: function(channel) { this.socket.emit('subscribe', channel); } navigate: function(route, options) { options || (options = {}); Backbone.history.navigate(route, options); }, hideStreamer: function() { this.streamRegion.currentView.$el.hide(); }, showStreamer: function() { this.streamRegion.currentView.$el.show(); } });

Page 14: Virtual Madness @ Etsy

@subedinishan

Example - FilteredCollection

this.filteredVms = VmsManager.Entities.FilteredCollection({ collection: options.collection, filterFunction: function(filterCriterion) { var criterion = filterCriterion.query.toLowerCase(); return function(vms) { if( vms.get("hostname").toLowerCase().indexOf(criterion) !== -1 && (vms.get("type") == filterCriterion.type || 'all' == filterCriterion.type) ) { return vms; } }; } });

Page 15: Virtual Madness @ Etsy

@subedinishan

Example - message queuevar VmsManager = new Marionette.Application({ onStart: function() { // Start a message queue this.messageQueue = new this.Entities.Messages(); this.messageRegion.show(new this.VmsApp.Message.Messages({ collection: this.messageQueue })); onMessage: function(options) { this.messageQueue.push(new this.Entities.Message(options)); }, }); !!Entities.Message = Backbone.Model.extend({ defaults: { type: 'info', timeout: 2000, isDismissible: true, message: 'Nothing to see here' } });

Page 16: Virtual Madness @ Etsy

@subedinishan

Message - view Message.Message = Marionette.ItemView.extend({ template: 'message', className: function() { var val = ' alert col-md-12'; val += ' alert-' + this.model.get('type'); if (this.model.get('isDismissible')) { val += ' alert-dismissible '; } return val; }, onShow: function() { if (this.model.get('timeout') !== 0) { // Model not used after flash message display // so, set up a timeout for cleanup _.delay(_.bind(this.cleanup, this), this.model.get('timeout')); } }, cleanup: function() { var timeout = this.model.get('timeout'); this.$el.fadeOut(timeout/2); // We rely on the fadeOut successfully completing in timeout*2 time _.delay(_.bind(this.model.destroy, this.model), timeout*2); _.delay(_.bind(this.destroy, this), timeout*2); } }); Message.Messages = Marionette.CollectionView.extend({ childView: Message.Message });

Page 17: Virtual Madness @ Etsy

@subedinishan

Examples - DSL Add.Vm = Marionette.ItemView.extend({ template: 'create', className: 'panel panel-default alert col-md-12', ui: { create: ".js-create-vm", size: "#size", search: "#search", base_role: "#base_role", role_add: ".js-role-add", primary: "#primary", ldap: "#ldap", }, bindings: { '#ldap': 'ldap', '#base_role': 'base_role', '#version': 'version', '#hostname': 'hostname', '#search': 'search', '#size': 'size', '#virt': 'virt', '#primary': 'primary', }, events: { "click @ui.create": "submitClicked", "change @ui.size": "sizeChanged", "click @ui.search": "searchClicked", "change @ui.base_role": "baseRoleChanged", "click @ui.role_add": "roleAdd", "change @ui.ldap": "ldapChanged", }, initialize: function() { this.model.fetch({success: this.render}); this.stickit(); var fetchingVms = VmsManager.request("vms:entities"); $.when(fetchingVms).done(_.bind(this.entitiesFetched, this));

Page 18: Virtual Madness @ Etsy

@subedinishan

Template loading// Override Marionette template loading and compiling to use our template loader. _.extend(Backbone.Marionette.TemplateCache.prototype, { compileTemplate: function(template) { return template; }, ! loadTemplate: function(templateId) { var contents = raw_template_cache[templateId]; return function(data) { return Mustache.render(contents, data, function(name) { return raw_template_cache[name]; }); }; } }); !

Page 19: Virtual Madness @ Etsy

@subedinishan

Template loading - PHPclass TemplateHelper extends HelperBase { const DIRECTORY = "templates/"; const EXTENSION = ".mustache"; ! protected function get_template_names() { return glob(self::DIRECTORY . '*' . self::EXTENSION); } ! protected function to_array() { $return = []; foreach ($this->get_template_names() as $template_name) { $key = str_replace(self::EXTENSION, '', $template_name); $key = str_replace(self::DIRECTORY, '', $key); $return[$key] = file_get_contents($template_name); } return $return; } ! public function generate_template_javascript_variable() { return '<script language="javascript" type="text/javascript"> var raw_template_cache = ' . json_encode($this->to_array()) . ' </script>'; } } !

Page 20: Virtual Madness @ Etsy

@subedinishan

Template Loading - PHP!!!!$app->get('/v2/.*?', function() use ($app) { echo $app->helper('Template')->generate_template_javascript_variable(); $page_object = new WebBase(); echo $page_object->render('base'); });

Page 21: Virtual Madness @ Etsy

@subedinishan

Modals

Page 22: Virtual Madness @ Etsy

@subedinishan

Modal - inside ItemView this.confirmationModal = new BootstrapDialog({ title: 'Are you sure?', message: 'Do you really want to delete ' + this.model.get('hostname') + '?', type: BootstrapDialog.TYPE_DANGER, buttons: [{ label: 'DELETE', action: function(dialog){ parentScope.model.destroy({ success: function(model, response) { VmsManager.Common.Notifier.success(response, { fail: "VM deletion failed with response: " + response.message, success: "Delete VM successful", undef:"Delete VM came back with response" + JSON.stringify(response) }); }, error: function(model, response) { VmsManager.Common.Notifier.error(response, { error: "VM Deletion failed with response: " + JSON.stringify(response) }); } }); dialog.close(); } }], onhidden: function() { VmsManager.trigger('streamer:show'); VmsManager.trigger("vm:destroy"); VmsManager.trigger("log:subscribe", Etsy.data.username + "-delete"); }

Page 23: Virtual Madness @ Etsy

@subedinishan

Marionette JS• active and helpful community

• great upgrade support

• adopted in the company

• plug and play - able to glue things together

• CollectionView

Page 24: Virtual Madness @ Etsy

@subedinishan

Future of Marionette @ Etsy• Behaviors

• Skeletor - build once, use everywhere

• Migration

• Adoption

Page 25: Virtual Madness @ Etsy

@subedinishan

What worked?

• Simplify implementation

• Simplify abstractions

• Leverage existing resources

• Create additional resources

Page 26: Virtual Madness @ Etsy

@subedinishan

Get your learning on

Page 27: Virtual Madness @ Etsy

@subedinishan

Questions? !

We’re Hiring! etsy.com/careers

Page 28: Virtual Madness @ Etsy

@subedinishan

Referenceshttps://avatars3.githubusercontent.com/u/1522517?v=3&s=460