SlideShare una empresa de Scribd logo
1 de 25
Story of Puppet @eBay Classifieds Group
or how we came to the setup we use
Some bio or “Who is Vladimir”
  Sysadmin for eighteen years
  Currently in Solutions team of eCG’s marktplaats.nl
  All-round nerd
  Hobbyist programmer
Puppet at eBay Classifieds:
  9 countries
  13 platforms
  1 codebase
  1 change management process
Puppet at eBay Classifieds:
  We started adopting puppet in 2008
  Since then we had about 4 different iterations of “this is bloated and
  doesn’t work, let’s think more and re-do”
  Currently we believe we achieved a workable scenario where we:
     Enable teams to share and re-use puppet code
     Enforce the same code style and standards
     Allow for peer-reviews of the code, also enforce them


         “If it’s not in Puppet – it does not exist.”
What we are going to talk about:
•   Different iterations of puppet implementation at eCG
•   Go in-depth on the structure of the current one
•   Process around the codebase
•   Tools
“Bucket of recipes”




Puppet at eBay Classifieds (1st implementation):
    A bunch of modules without visible structure (server-role based)
    Relations between modules on any levels (includes, instantiations)
    One Subversion repository, where everyone works on trunk
What were the lessons learned?
   As puppet adoption grew, modules for different platforms started
    clashing (same, yet a bit different functionality)
   As number of modules and their dependencies grew people were
    afraid of making changes - dependency tree was very hard to follow
   Resulted in tons of duplicate code
   Change management was very risky – you commit something and
    it’s live
“Buckets of recipes”




Puppet at eBay Classifieds (2nd implementation):
    What did we improve?
       Release management with Subversion branching
       Better module grouping
What were the lessons learned?
   Waiting on releases is killing. If you need a change - you need it
    now, not in 2 or 3 days
   Provokes people to lock machines to their own puppet environment
   Surprises at times of the releases. For some people it was daytime,
    for others it was middle of the night
Puppet at eBay Classifieds (3rd implementation):
    What did we improve?
      Switched to Git
      Completely redesigned modules structure (more on this later)
      Introduced extlookup for data separation vs configuration logic
      Release more often
What were the lessons learned?
   When release process is human-dependent it will be a bottleneck
   Extlookup is nice, but in many places unreadable
Puppet at eBay Classifieds (4th implementation):
   What did we improve?
     Introduced Gerrit for code reviews
     Implemented automatic puppet-lint, template syntax and PEP8 checkers
     Introduced automated quorum votes for peer reviews
     Release as soon as your code passed checks and YOU need it live
     Further improved module tree structure
     Replaced extlookup with hiera
     Introduced puppetdb
So how does it look now?
   Four module levels
   One include direction           Config


   No includes on the same level
                                   Platform



                                    eCG



                                   Shared
Shared modules
     Shared modules are very basic, deploy one
     piece of software in its standard configuration (no   Config

     customization)
                                                           Platform
     Standalone. Includes no other modules
     Installs needed packages, basically
                                                            eCG
     Parameterized to allow configuration override
       Examples: apache, ntpd, activemq, mysql, postgres   Shared
eCG modules
    eCG modules add our specific eCG-wide
    approved customizations. Rule: it must play well    Config

    with majority of teams to make it
                                                        Platform
    Mostly include shared modules
    Never include each other
                                                         eCG
    Override default shared module configuration
    with eCG specific one via parameters                Shared

    May be parameterized to allow for configuration
    tweaks or overrides
      Examples: puppetmaster, nagios checks, collectd
      plugins
Platform modules
   Platform level introduces company-specific
   modules and configuration customizations
                                                Config
   May include eCG modules
   May include shared modules                   Platform

   Never include each other
                                                 eCG



                                                Shared
Config modules
   Config level introduces server-role specific
   modules
                                                  Config
    Are the starting point for our servers
   configuration
                                                  Platform
   May include platform, eCG or shared modules
                                                   eCG
   Never include each other
   Node definition must include config module     Shared
Why did we do it like this?
    Easy starting point. Look up a node, see its
   class, open the class – you see on one page
   how your server is configured on a global level         Config

    If you need to know more, dive deeper
                                                           Platform
    We enable code sharing, we do not enforce it
      If you see a module in shared you can use – use       eCG

      it. If you can’t use it, extend it in a backwards-
      compatible way or write other extension on an        Shared
      appropriate level
Hiera
   Great way to separate code from data
   Company-based structure
   Lookup path based on facts to allow company data separation
   while keeping the same source tree
    :datadir: /var/lib/hiera/%{environment}/%{companyprefix}

    Inside company dirs a variety of fact-based lookups to allow for
   fine-grained data structures
PuppetDB
   Much faster catalog compilations for huge catalogs (nagios
  server with 200k resources)
   REST API to talk to for inventory and searches
   Many brilliant ways to (ab)use it
     Stores all facts (can be used to feed CMDBs)
     Stores most recent catalog (can be used for inspections)
     POC we are running - internal Puppet naginator module is very slow,
     collection of exported resources takes about 15 minutes. We use
     PuppetDB to generate the same nagios configs in just under 8
     seconds
     “If there is data, it can be used”. PuppetDB is a central data store.
     Love.
So all good, but how does this work in practice?
       Local       Test the change
                                       Push to Gerrit   Code review   Merge
    environment   with --environment




     Per-user environments on puppetmasters
     Make the change in your own env
     Test it from your own env
     Push to Gerrit
     Ask team members to review
     Merge
Gerrit
     Great code review tool (https://code.google.com/p/gerrit/)
     Acts as a Git server with fine-grained access control
     Each commit is a separate change, that requires votes for
     approvals
     Votes can be +1 for Code Review, +2 for change approval
     No +2 – no merge
     We use voting system with auto +2
         Depending on platform size or number of platforms affected by the
         change more votes are needed to get a change through
         Each change can be “pushed through” in case of an emergency
More Gerrit goodies
     Allows for post-push hooks
       Puppet-lint
       Ruby templates parsing
       PEP8 (we love Python)
     Each change is separately checked out by hooks and tested
    for syntax or other obvious errors
    Concept of “one commit – one change” forces people to create
    atomic changes that are easy to revert in case of errors
     Keeping it all in the same system, even if you decide to split Git
    repositories still makes work done by colleagues VISIBLE
Gerrit and puppetmasters
     Master is automatically pulled by crons on puppetmasters
     Gerrit disallows pushing directly to master
    Even if you force-merge a change, it makes your change
    VISIBLE and easily REVERTIBLE
     Takes about half a minute extra time
     Ensures you didn’t slack out on syntax checkers
To sum it all up
     There is no single structure that fits every company
     Puppet code is like any other code
        Write
        Use
        Refactor if needed
     Layered modules structure can work well in many cases
      Complementary tooling around Puppet is a life- (and time-)
     saver
        Lint(s), Gerrit, PuppetDB
Work to be done in our house
     Approval process improvements
       Better quorum schemas
       Easier ways of code style and syntax checking
       See that people don’t leave changes “hanging”
     Integrate Gerrit with corporate GitHub
     Work more with community
       Open source some generic shared modules
       Offer changes to PuppetForge modules
     POC with Vagrant for puppet code testing
Questions?
Thank you!
 Special thanks to:

 • PuppetLabs and eCG for the opportunity to speak here
 • Teams of eCG for bearing with me all these years
 • You all for attending and listening

 You can reach me by:
 • Mailing to favoretti@gmail.com
 • Following me on GitHub
   (https://github.com/favoretti)

We are hiring!
Visit http://ebayclassifiedsgroup.com/careers
for more info.

Más contenido relacionado

La actualidad más candente

An Introduction to Maven
An Introduction to MavenAn Introduction to Maven
An Introduction to Maven
Vadym Lotar
 
Maven Presentation - SureFire vs FailSafe
Maven Presentation - SureFire vs FailSafeMaven Presentation - SureFire vs FailSafe
Maven Presentation - SureFire vs FailSafe
Holasz Kati
 

La actualidad más candente (20)

An introduction to Maven
An introduction to MavenAn introduction to Maven
An introduction to Maven
 
Puppetizing Your Organization
Puppetizing Your OrganizationPuppetizing Your Organization
Puppetizing Your Organization
 
Maven for Dummies
Maven for DummiesMaven for Dummies
Maven for Dummies
 
Yocto project
Yocto projectYocto project
Yocto project
 
Developing Selenium tests with JUnit 5
Developing Selenium tests with JUnit 5Developing Selenium tests with JUnit 5
Developing Selenium tests with JUnit 5
 
基於 Flow & Path 的 MVP 架構
基於 Flow & Path 的 MVP 架構基於 Flow & Path 的 MVP 架構
基於 Flow & Path 的 MVP 架構
 
Develop Gwt application in TDD
Develop Gwt application in TDDDevelop Gwt application in TDD
Develop Gwt application in TDD
 
An Introduction to Maven
An Introduction to MavenAn Introduction to Maven
An Introduction to Maven
 
Unit Test Android Without Going Bald
Unit Test Android Without Going BaldUnit Test Android Without Going Bald
Unit Test Android Without Going Bald
 
An Introduction to Maven Part 1
An Introduction to Maven Part 1An Introduction to Maven Part 1
An Introduction to Maven Part 1
 
Using Maven 2
Using Maven 2Using Maven 2
Using Maven 2
 
Maven 2 features
Maven 2 featuresMaven 2 features
Maven 2 features
 
Modulesync- How vox pupuli manages 133 modules, Tim Meusel
Modulesync- How vox pupuli manages 133 modules, Tim MeuselModulesync- How vox pupuli manages 133 modules, Tim Meusel
Modulesync- How vox pupuli manages 133 modules, Tim Meusel
 
Apache maven 2 overview
Apache maven 2 overviewApache maven 2 overview
Apache maven 2 overview
 
Maven Presentation - SureFire vs FailSafe
Maven Presentation - SureFire vs FailSafeMaven Presentation - SureFire vs FailSafe
Maven Presentation - SureFire vs FailSafe
 
Tools For Software Engineering
Tools For Software EngineeringTools For Software Engineering
Tools For Software Engineering
 
Java Builds with Maven and Ant
Java Builds with Maven and AntJava Builds with Maven and Ant
Java Builds with Maven and Ant
 
Containers, Docker, and Security: State Of The Union (LinuxCon and ContainerC...
Containers, Docker, and Security: State Of The Union (LinuxCon and ContainerC...Containers, Docker, and Security: State Of The Union (LinuxCon and ContainerC...
Containers, Docker, and Security: State Of The Union (LinuxCon and ContainerC...
 
Maven 3 Overview
Maven 3  OverviewMaven 3  Overview
Maven 3 Overview
 
Introduction to maven, its configuration, lifecycle and relationship to JS world
Introduction to maven, its configuration, lifecycle and relationship to JS worldIntroduction to maven, its configuration, lifecycle and relationship to JS world
Introduction to maven, its configuration, lifecycle and relationship to JS world
 

Destacado

NOAH conference 2011 - Jacob Aqraou presentation
NOAH conference 2011 - Jacob Aqraou presentationNOAH conference 2011 - Jacob Aqraou presentation
NOAH conference 2011 - Jacob Aqraou presentation
eBay Classifieds Group
 

Destacado (10)

Ebay
EbayEbay
Ebay
 
Next Generation Classifieds - ICMA 2010
Next Generation Classifieds - ICMA 2010Next Generation Classifieds - ICMA 2010
Next Generation Classifieds - ICMA 2010
 
The Future of Classifieds - ICMA 2010
The Future of Classifieds - ICMA 2010The Future of Classifieds - ICMA 2010
The Future of Classifieds - ICMA 2010
 
Jacob Aqraou - The future of mobile commerce - NOAH presentation
Jacob Aqraou - The future of mobile commerce - NOAH presentationJacob Aqraou - The future of mobile commerce - NOAH presentation
Jacob Aqraou - The future of mobile commerce - NOAH presentation
 
eBay Classifieds Group - NOAH15 London
eBay Classifieds Group - NOAH15 LondoneBay Classifieds Group - NOAH15 London
eBay Classifieds Group - NOAH15 London
 
NOAH conference 2011 - Jacob Aqraou presentation
NOAH conference 2011 - Jacob Aqraou presentationNOAH conference 2011 - Jacob Aqraou presentation
NOAH conference 2011 - Jacob Aqraou presentation
 
eBay Classifieds Talent Management- Aileen O'Toole
eBay Classifieds Talent Management- Aileen O'TooleeBay Classifieds Talent Management- Aileen O'Toole
eBay Classifieds Talent Management- Aileen O'Toole
 
Xamarin Mobile Leaders Summit | Solving the Unique Challenges in Mobile DevOps
Xamarin Mobile Leaders Summit | Solving the Unique Challenges in Mobile DevOpsXamarin Mobile Leaders Summit | Solving the Unique Challenges in Mobile DevOps
Xamarin Mobile Leaders Summit | Solving the Unique Challenges in Mobile DevOps
 
Olx
OlxOlx
Olx
 
The Science of Memorable Presentations
The Science of Memorable PresentationsThe Science of Memorable Presentations
The Science of Memorable Presentations
 

Similar a Puppet camp amsterdam

It’s 2021. Why are we -still- rebooting for patches? A look at Live Patching.
It’s 2021. Why are we -still- rebooting for patches? A look at Live Patching.It’s 2021. Why are we -still- rebooting for patches? A look at Live Patching.
It’s 2021. Why are we -still- rebooting for patches? A look at Live Patching.
All Things Open
 
DevOps - Interview Question.pdf
DevOps - Interview Question.pdfDevOps - Interview Question.pdf
DevOps - Interview Question.pdf
MinhTrnNht7
 
Git Tutorial A Comprehensive Guide for Beginners.pdf
Git Tutorial A Comprehensive Guide for Beginners.pdfGit Tutorial A Comprehensive Guide for Beginners.pdf
Git Tutorial A Comprehensive Guide for Beginners.pdf
uzair
 

Similar a Puppet camp amsterdam (20)

Reproducibility in artificial intelligence
Reproducibility in artificial intelligenceReproducibility in artificial intelligence
Reproducibility in artificial intelligence
 
It’s 2021. Why are we -still- rebooting for patches? A look at Live Patching.
It’s 2021. Why are we -still- rebooting for patches? A look at Live Patching.It’s 2021. Why are we -still- rebooting for patches? A look at Live Patching.
It’s 2021. Why are we -still- rebooting for patches? A look at Live Patching.
 
Portable infrastructure with puppet
Portable infrastructure with puppetPortable infrastructure with puppet
Portable infrastructure with puppet
 
Frankenstein's IDE: NetBeans and OSGi
Frankenstein's IDE: NetBeans and OSGiFrankenstein's IDE: NetBeans and OSGi
Frankenstein's IDE: NetBeans and OSGi
 
DevOps - Interview Question.pdf
DevOps - Interview Question.pdfDevOps - Interview Question.pdf
DevOps - Interview Question.pdf
 
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013
 
Git Tutorial A Comprehensive Guide for Beginners.pdf
Git Tutorial A Comprehensive Guide for Beginners.pdfGit Tutorial A Comprehensive Guide for Beginners.pdf
Git Tutorial A Comprehensive Guide for Beginners.pdf
 
Mete Atamel "Resilient microservices with kubernetes"
Mete Atamel "Resilient microservices with kubernetes"Mete Atamel "Resilient microservices with kubernetes"
Mete Atamel "Resilient microservices with kubernetes"
 
Working with Modules - Henrik Lindberg - PuppetCamp Europe '11
Working with Modules - Henrik Lindberg - PuppetCamp Europe '11Working with Modules - Henrik Lindberg - PuppetCamp Europe '11
Working with Modules - Henrik Lindberg - PuppetCamp Europe '11
 
Kubernetes 101
Kubernetes 101Kubernetes 101
Kubernetes 101
 
DevOps #EMERSONEDUARDORODRIGUES EMERSON EDUARDO RODRIGUES
DevOps #EMERSONEDUARDORODRIGUES EMERSON EDUARDO RODRIGUESDevOps #EMERSONEDUARDORODRIGUES EMERSON EDUARDO RODRIGUES
DevOps #EMERSONEDUARDORODRIGUES EMERSON EDUARDO RODRIGUES
 
Resilient microservices with Kubernetes - Mete Atamel - Codemotion Rome 2017
Resilient microservices with Kubernetes - Mete Atamel - Codemotion Rome 2017Resilient microservices with Kubernetes - Mete Atamel - Codemotion Rome 2017
Resilient microservices with Kubernetes - Mete Atamel - Codemotion Rome 2017
 
PuppetConf 2016: A Tale of Two Hierarchies: Group Policy & Puppet – Matt Ston...
PuppetConf 2016: A Tale of Two Hierarchies: Group Policy & Puppet – Matt Ston...PuppetConf 2016: A Tale of Two Hierarchies: Group Policy & Puppet – Matt Ston...
PuppetConf 2016: A Tale of Two Hierarchies: Group Policy & Puppet – Matt Ston...
 
Git essential training & sharing self
Git essential training & sharing selfGit essential training & sharing self
Git essential training & sharing self
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository world
 
Introduction to Github action Presentation
Introduction to Github action PresentationIntroduction to Github action Presentation
Introduction to Github action Presentation
 
.Net OSS Ci & CD with Jenkins - JUC ISRAEL 2013
.Net OSS Ci & CD with Jenkins - JUC ISRAEL 2013 .Net OSS Ci & CD with Jenkins - JUC ISRAEL 2013
.Net OSS Ci & CD with Jenkins - JUC ISRAEL 2013
 
My "Perfect" Toolchain Setup for Grails Projects
My "Perfect" Toolchain Setup for Grails ProjectsMy "Perfect" Toolchain Setup for Grails Projects
My "Perfect" Toolchain Setup for Grails Projects
 
Scaling Puppet Usage to a Global Organization
Scaling Puppet Usage to a Global OrganizationScaling Puppet Usage to a Global Organization
Scaling Puppet Usage to a Global Organization
 
Git & dev ops come together, right now!
Git & dev ops come together, right now!Git & dev ops come together, right now!
Git & dev ops come together, right now!
 

Puppet camp amsterdam

  • 1. Story of Puppet @eBay Classifieds Group or how we came to the setup we use
  • 2. Some bio or “Who is Vladimir” Sysadmin for eighteen years Currently in Solutions team of eCG’s marktplaats.nl All-round nerd Hobbyist programmer
  • 3. Puppet at eBay Classifieds: 9 countries 13 platforms 1 codebase 1 change management process
  • 4. Puppet at eBay Classifieds: We started adopting puppet in 2008 Since then we had about 4 different iterations of “this is bloated and doesn’t work, let’s think more and re-do” Currently we believe we achieved a workable scenario where we: Enable teams to share and re-use puppet code Enforce the same code style and standards Allow for peer-reviews of the code, also enforce them “If it’s not in Puppet – it does not exist.”
  • 5. What we are going to talk about: • Different iterations of puppet implementation at eCG • Go in-depth on the structure of the current one • Process around the codebase • Tools
  • 6. “Bucket of recipes” Puppet at eBay Classifieds (1st implementation): A bunch of modules without visible structure (server-role based) Relations between modules on any levels (includes, instantiations) One Subversion repository, where everyone works on trunk What were the lessons learned?  As puppet adoption grew, modules for different platforms started clashing (same, yet a bit different functionality)  As number of modules and their dependencies grew people were afraid of making changes - dependency tree was very hard to follow  Resulted in tons of duplicate code  Change management was very risky – you commit something and it’s live
  • 7. “Buckets of recipes” Puppet at eBay Classifieds (2nd implementation): What did we improve? Release management with Subversion branching Better module grouping What were the lessons learned?  Waiting on releases is killing. If you need a change - you need it now, not in 2 or 3 days  Provokes people to lock machines to their own puppet environment  Surprises at times of the releases. For some people it was daytime, for others it was middle of the night
  • 8. Puppet at eBay Classifieds (3rd implementation): What did we improve? Switched to Git Completely redesigned modules structure (more on this later) Introduced extlookup for data separation vs configuration logic Release more often What were the lessons learned?  When release process is human-dependent it will be a bottleneck  Extlookup is nice, but in many places unreadable
  • 9. Puppet at eBay Classifieds (4th implementation): What did we improve? Introduced Gerrit for code reviews Implemented automatic puppet-lint, template syntax and PEP8 checkers Introduced automated quorum votes for peer reviews Release as soon as your code passed checks and YOU need it live Further improved module tree structure Replaced extlookup with hiera Introduced puppetdb
  • 10. So how does it look now? Four module levels One include direction Config No includes on the same level Platform eCG Shared
  • 11. Shared modules Shared modules are very basic, deploy one piece of software in its standard configuration (no Config customization) Platform Standalone. Includes no other modules Installs needed packages, basically eCG Parameterized to allow configuration override Examples: apache, ntpd, activemq, mysql, postgres Shared
  • 12. eCG modules eCG modules add our specific eCG-wide approved customizations. Rule: it must play well Config with majority of teams to make it Platform Mostly include shared modules Never include each other eCG Override default shared module configuration with eCG specific one via parameters Shared May be parameterized to allow for configuration tweaks or overrides Examples: puppetmaster, nagios checks, collectd plugins
  • 13. Platform modules Platform level introduces company-specific modules and configuration customizations Config May include eCG modules May include shared modules Platform Never include each other eCG Shared
  • 14. Config modules Config level introduces server-role specific modules Config Are the starting point for our servers configuration Platform May include platform, eCG or shared modules eCG Never include each other Node definition must include config module Shared
  • 15. Why did we do it like this? Easy starting point. Look up a node, see its class, open the class – you see on one page how your server is configured on a global level Config If you need to know more, dive deeper Platform We enable code sharing, we do not enforce it If you see a module in shared you can use – use eCG it. If you can’t use it, extend it in a backwards- compatible way or write other extension on an Shared appropriate level
  • 16. Hiera Great way to separate code from data Company-based structure Lookup path based on facts to allow company data separation while keeping the same source tree :datadir: /var/lib/hiera/%{environment}/%{companyprefix} Inside company dirs a variety of fact-based lookups to allow for fine-grained data structures
  • 17. PuppetDB Much faster catalog compilations for huge catalogs (nagios server with 200k resources) REST API to talk to for inventory and searches Many brilliant ways to (ab)use it Stores all facts (can be used to feed CMDBs) Stores most recent catalog (can be used for inspections) POC we are running - internal Puppet naginator module is very slow, collection of exported resources takes about 15 minutes. We use PuppetDB to generate the same nagios configs in just under 8 seconds “If there is data, it can be used”. PuppetDB is a central data store. Love.
  • 18. So all good, but how does this work in practice? Local Test the change Push to Gerrit Code review Merge environment with --environment Per-user environments on puppetmasters Make the change in your own env Test it from your own env Push to Gerrit Ask team members to review Merge
  • 19. Gerrit Great code review tool (https://code.google.com/p/gerrit/) Acts as a Git server with fine-grained access control Each commit is a separate change, that requires votes for approvals Votes can be +1 for Code Review, +2 for change approval No +2 – no merge We use voting system with auto +2 Depending on platform size or number of platforms affected by the change more votes are needed to get a change through Each change can be “pushed through” in case of an emergency
  • 20. More Gerrit goodies Allows for post-push hooks Puppet-lint Ruby templates parsing PEP8 (we love Python) Each change is separately checked out by hooks and tested for syntax or other obvious errors Concept of “one commit – one change” forces people to create atomic changes that are easy to revert in case of errors Keeping it all in the same system, even if you decide to split Git repositories still makes work done by colleagues VISIBLE
  • 21. Gerrit and puppetmasters Master is automatically pulled by crons on puppetmasters Gerrit disallows pushing directly to master Even if you force-merge a change, it makes your change VISIBLE and easily REVERTIBLE Takes about half a minute extra time Ensures you didn’t slack out on syntax checkers
  • 22. To sum it all up There is no single structure that fits every company Puppet code is like any other code Write Use Refactor if needed Layered modules structure can work well in many cases Complementary tooling around Puppet is a life- (and time-) saver Lint(s), Gerrit, PuppetDB
  • 23. Work to be done in our house Approval process improvements Better quorum schemas Easier ways of code style and syntax checking See that people don’t leave changes “hanging” Integrate Gerrit with corporate GitHub Work more with community Open source some generic shared modules Offer changes to PuppetForge modules POC with Vagrant for puppet code testing
  • 25. Thank you! Special thanks to: • PuppetLabs and eCG for the opportunity to speak here • Teams of eCG for bearing with me all these years • You all for attending and listening You can reach me by: • Mailing to favoretti@gmail.com • Following me on GitHub (https://github.com/favoretti) We are hiring! Visit http://ebayclassifiedsgroup.com/careers for more info.