1 / 89

Let them configure!

Let them configure!. a sermon on reusability. Łukasz Langa. ambv at #python-dev (FreeNode IRC) @llanga on Twitter lukasz@langa.pl as a last resort. Robert M. Pirsig. „The solutions all are simple – after you have arrived at them.

genera
Download Presentation

Let them configure!

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Let them configure! a sermon on reusability

  2. Łukasz Langa ambvat #python-dev (FreeNode IRC) @llangaon Twitter lukasz@langa.plas a last resort

  3. Robert M. Pirsig „The solutions all are simple – after you have arrived at them. But they're simple only when you know already what they are.”

  4. four desirable characteristics of configuration

  5. COMPOSABLE

  6. READABLE

  7. EXCHANGEABLE

  8. DISCOVERABLE

  9. COMPOSABLEREADABLEEXCHANGEABLEDISCOVERABLE

  10. configuration format whirlwind tour

  11. Easy-ish formats [user] email = lukasz@langa.pl name= Łukasz Langa [push] default= current [color] branch= auto diff= auto interactive= auto status = auto [diff] external= git_vimdiff [pager] diff= [core] excludesfile= ~/.gitignore INI Apache nginx JSON

  12. Easy-ish formats Listen80 User apache Groupapache DocumentRoot"/var/www/vhosts/root" <Directory /> OptionsFollowSymLinks AllowOverrideNone </Directory> <Directory "/var/www/vhosts"> OptionsIndexesFollowSymLinksMultiViewsExecCGI AllowOverrideAll AddHandler php5-fastcgi .php Action php5-fastcgi /cgi-bin/php.fcgi Order allow,deny Allow from all </Directory> <IfModulemod_userdir.c> UserDirdisable </IfModule> Includeconf.d/*.conf INI Apache nginx JSON

  13. Easy-ish formats Listen80 User apache Groupapache DocumentRoot"/var/www/vhosts/root" <Directory /> OptionsFollowSymLinks AllowOverrideNone </Directory> <Directory "/var/www/vhosts"> OptionsIndexesFollowSymLinksMultiViewsExecCGI AllowOverrideAll AddHandler php5-fastcgi .php Action php5-fastcgi /cgi-bin/php.fcgi Order allow,deny Allow from all </Directory> <IfModulemod_userdir.c> UserDirdisable </IfModule> Includeconf.d/*.conf INI Apache nginx JSON What’s the difference: Options +IndexesIncludesMultiViews OptionsIndexesIncludesMultiViews

  14. Easy-ish formats server { listen 80; server_named.com *.d.com; rewrite ^ http://www.d.com $request_uri? permanent; } server { listen 80 default; server_namewww.d.com; indexindex.html; root /home/d.com; location /forum { rewrite forum(.*) http:// forum.d.com$1 permanent; } } INI Apache nginx JSON

  15. Easy-ish formats {   "production":{   "phpSettings":{     "display_startup_errors": false,       "display_errors": false     },     "includePaths":{        "library": "APPLICATION_PATH/../library"     },     "bootstrap":{       "path": "APPLICATION_PATH/Bootstrap.php",       "class": "Bootstrap"     },   "appnamespace": "Application", }, "staging":{ "_extends": "production" } } INI Apache nginx JSON

  16. Complex formats <configure xmlns="http://namespaces.zope.org/zope" xmlns:zmi="http://namespaces.zope.org/zmi" xmlns:browser="http://namespaces.zope.org/browser" > <browser:defaultView for="zope.i18n.interfaces.ITranslationService” name="index.html” /> <browser:view permission="zope.ManageServices" for="zope.i18n.interfaces.ITranslationService" factory="zope.app.browser.i18n.Translate" > <browser:pagename="index.html" attribute="index" /> </browser:view> <zmi:tabs for="zope.i18n.interfaces.ITranslationService"> <zmi:tablabel="Translate" action="@@index.html"/> </zmi:tabs> </configure> XML YAML

  17. Complex formats application: myappversion: 1runtime: python27api_version: 1threadsafe: truehandlers:- url: /script: home.app- url: /index\.htmlscript: home.app- url: /stylesheetsstatic_dir: stylesheets- url: /(.*\.(gif|png|jpg))static_files: static/\1upload: static/(.*\.(gif|png|jpg)) XML YAML

  18. Turing complete formats DEBUG = True TEMPLATE_DEBUG = DEBUG DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': '/tmp/project.db', 'USER': '', 'PASSWORD': '', 'HOST': '', 'PORT': '', } } import os.path MODULE_ROOT = \ os.path.dirname(os.path.realpath(__file__)) STATIC_ROOT = os.sep.join((MODULE_ROOT, 'static')) STATIC_URL = '/static/’ Python

  19. Awkward formats Feature: Addition In order to avoidmistakes As a mathslouch I want to be told the sum of twonumbers Scenario: Addtwonumbers Given I haveentered 50 into the calc And I haveentered 70 into the calc When I pressadd Then the resultshould be 120 Domain-Specific Languages SQLite Windows registry

  20. Awkward formats classdavids_black_co_at { hosting::user { rztt: realname => "Gerhard Schmitt", uid => 2001, admin => true; conny: realname => "Conny Schmitt", uid => 2002; oma: realname => "Oma Schmitt", uid => 2003; } # Installgit.black.co.at include git::daemon include git::web git::web::export { [manifests, "puppet-trunk"]: } hosting::database { "fogbugz": type => mysql } apache2::site { "local-fogbugz": source => "puppet://$servername/files/hosting/davids/sites/local-fogbugz" } } Domain-Specific Languages SQLite Windows registry

  21. Awkward formats # main.cf ... alias_maps = sqlite:/etc/postfix/sqlite-aliases.cf ... # sqliteconfig file for # local(8) aliases(5) lookups dbpath= /path/to/sqlite_database query= SELECT forw_addrFROM mxaliasesWHERE alias='%s’ AND status='paid' Domain-Specific Languages SQLite Windows registry

  22. Awkward formats sqlite> .tables directory handler log proxyserverstatistic filter host mimetyperoutesetting sqlite> select * from host; 1|1|0|localhost|localhost sqlite> selectcount(*) from mimetype; 850 sqlite> select * from server; 1|AC1F8236-5919-9D40-0F38DE9E5861|/logs/access.log|/logs/error.log|./|/run/mongrel2.pid|localhost|test|0.0.0.0|6767|0 Domain-Specific Languages SQLite Windows registry

  23. Awkward formats sqlite> .tables directory handler log proxyserverstatistic filter host mimetyperoutesetting sqlite> select * from host; 1|1|0|localhost|localhost sqlite> selectcount(*) from mimetype; 850 sqlite> select * from server; 1|AC1F8236-5919-9D40-0F38DE9E5861|/logs/access.log|/logs/error.log|./|/run/mongrel2.pid|localhost|test|0.0.0.0|6767|0 Domain-Specific Languages SQLite Windows registry #get s list of the availableservers to run   m2sh servers -dbtests/config.sqlite# seewhathosts a serverhas  m2sh hosts -dbtests/config.sqlite -server test # find out if a servernamed 'test' isrunning  m2sh running -dbtests/config.sqlite -name test  # start a serverwho'sdefault host is 'localhost'   m2sh start -dbtests/config.sqlite -host localhost

  24. Awkward formats Domain-Specific Languages SQLite Windows registry

  25. The worst format ever Your own format

  26. YOU WILL IMPOSE A LEARNING CURVE ON YOUR USERS

  27. YOUR DESIGN DECISIONS WILL BE UNINTUITIVE

  28. YOU WILL FAIL AT PARSING

  29. PEOPLE WILL START DEPENDING ON THE PARSER QUIRKS

  30. CONFIGURATION WRITTEN ONCE HAS TO BE SUPPORTED FOREVER

  31. Seeking balance one-size-fits-all vs. tweakable-beyond-recognition

  32. ambv@arrakis:~ $ wget-O - "https://www.dropbox.com/download?plat=lnx.x86_64" | tar xzf - --2012-10-20 11:24:22-- https://www.dropbox.com/download?plat=lnx.x86_64 Resolving www.dropbox.com... 199.47.217.171, 199.47.216.170, 199.47.216.171, ... Connecting to www.dropbox.com|199.47.217.171|:443... connected. HTTP request sent, awaiting response... 302 FOUND Location: https://dl-web.dropbox.com/u/17/dropbox-lnx.x86_64-1.4.17.tar.gz [following] --2012-10-20 11:24:23-- https://dl-web.dropbox.com/u/17/dropbox-lnx.x86_64-1.4.17.tar.gz Resolving dl-web.dropbox.com... 174.129.197.250, 174.129.199.91, 107.20.174.220, ... Connecting to dl-web.dropbox.com|174.129.197.250|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 19090076 (18M) [application/x-tar] Saving to: `STDOUT' 100%[=============================================================>] 19,090,076 1.23M/s in 17s 2012-10-20 11:24:42 (1.08 MB/s) - `-' saved [19090076/19090076]

  33. ambv@arrakis:~ $ wget -O - "https://www.dropbox.com/download?plat=lnx.x86_64" | tar xzf - 100%[======>] 19,090,076 1.23M/s in 17s ambv@arrakis:~ $ ./.dropbox-dist/dropboxd This client is not linked to any account... Please visit https://www.dropbox.com/cli_link?host_id=012345678&cl=en_US to link this machine.

  34. COMPOSABLEREADABLEEXCHANGEABLEDISCOVERABLE

  35. Excerpts from >>> import this Beautifulisbetterthanugly. Simple isbetterthancomplex. Flat isbetterthannested. Readabilitycounts. Thereshould be one(and preferablyonlyone) obviousway to do it.

  36. Sidenote. Go to: http://make-everything-ok.com/

  37. CONFIG != DATA

  38. Hard coding • Ananti-pattern • Likehardwiringcircuits • Configurationembedded in sourcecode

  39. Reverse hard coding • Source codeembedded in configuration • Alsoananti-pattern

  40. CONFIG != CODE

  41. Practical configurability DJANGo: settings.py

  42. Djangosettings.py Djangomixesdifferentkinds of settings • Framework behaviour • Application behaviour • Deployment-specificconfiguration • databases • caches • logging • paths • ADMINS • MANAGERS • DEBUG • Sensitive data • passwords • SECURE_KEY The problem from settings import * Orderedincrementalexecfile django-configurations INI basedconfiguration

  43. Djangosettings.py # settings.py # ... TIME_ZONE = 'Europe/Zurich' LANGUAGE_CODE = 'en-us' SECRET_KEY = 'secret' # ... from settings_local import * The problem from settings import * Orderedincrementalexecfile django-configurations INI basedconfiguration

More Related