Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

A ZF2 based command line interface for DevOps a...

A ZF2 based command line interface for DevOps automation

CLI usage is gaining importance in today's web application development and deployment landscape, with more tools leveraging it because it allows the automation of more complex, one-off tasks. In this session I will demonstrate the Zend Server Web API, and how we built a ZF2 application to consume using Zend\Console. This allowed us to create a tool which can be used from third party applications to automate tasks like deployment, configuration, import/export etc. Lots of code samples will be shown!

Slavey Karadzhov

October 10, 2013
Tweet

More Decks by Slavey Karadzhov

Other Decks in Programming

Transcript

  1. A ZF2 Based Command Line Interface For DevOps Automation. Slavey

    Karadzhov Senior Consultant Zend Technologies
  2. 2 •Name: Slavey Karadzhov (Славей Караджов) •Senior Technical Consultant and

    Trainer at Zend Technologies •Zend Framework (ZF) and PHP ZCE •Many years of PHP (v3,4 & 5), ZF and galaxy of programming languages (Python, Perl, Java, JavaScript,…). •Author of the “Learn ZF2” book ( http://learnzf2.com ) About me
  3. 3 •Zend Server WebAPI •Console Clients •Implementing Console Client In

    ZF2 •Usage •Composer Integration* •Demo •Questions & Answers Agenda
  4. 5 •Zend Server o Complete, enterprise-ready PHP Application Server for

    →Running →Deploying →Managing o Allows Third-Party integration o More at http://www.zend.com/en/products/server/ . Zend Server WebAPI
  5. 6 •The WebAPI o Remote control and automation of Zend

    Server features: →Deployment →Configuration →Management →Monitoring o Integration with 3rd Party →Using zs-manager →Your own WebAPI client Zend Server WebAPI
  6. 9 •Console Client o Command Line Interface client consuming the

    WebAPI •Advantages in terms of o Automation o Integration Console Clients
  7. 10 •Why yet another WebAPI command line client? o zs-manage

    →Part of Zend Server distribution →Not available in Windows →Hard to separate from Zend Server →Not super-easy to extend →Does not support all available methods o Java SDK →Java →Requires efforts to integrate Console Clients
  8. 11 •Requirements for a successful client o To run on

    every system where PHP >= 5.3 can run o To be small and self-contained o To be easy to use o To be super-easy to extend from a PHP programmer →Has powerful and yet easy declarative syntax to describe new commands →Allows adding high-level commands o Allows inline documentation of the commands Console Clients
  9. 13 •Why Zend Framework 2 (ZF2) o Zend\Console component -

    helps creation of console clients o Allows you to use only the components you need, without forcing you to have the complete framework o Has good composer support o Because ZF2 rocks! →ZF2 is popular →Easy code reuse — Our code can be valuable and freely used and extended from others →Allows writing lean and clean code (Implements ideas from Aspect Oriented Programming, Modular + Event driver architecture, etc.) Implementing Console Client in ZF2
  10. 14 •Minimum needed ZF2 components o Composer.json Implementing Console Client

    in ZF2 { "name": "zenddevops/webapi", require": { "php": ">=5.3.3", "zendframework/zend-serializer" : ">=2.0.0", "zendframework/zend-text" : ">=2.0.0", "zendframework/zend-mvc" : ">=2.0.0", "zendframework/zend-file" : ">=2.0.0", "zendframework/zend-console" : ">=2.0.0", "zendframework/zend-servicemanager" : ">=2.0.0", ... "zendframework/zend-stdlib" : ">=2.0.0", "zendframework/zend-view" : ">=2.0.0", "zendframework/zend-config" : ">=2.0.0", "zendframework/zend-http" : ">=2.0.0" }, }
  11. 15 •Command definitions as routes Implementing Console Client in ZF2

    'console' => array ( 'router' => array ( 'routes' => array ( //.. 'configurationImport' => array ( 'options' => array ( 'route' => 'configurationImport --configFile= [--ignoreSystemMismatch=]', 'defaults' => array ( 'controller' => 'webapi-api-controller', 'action' => 'configurationImport', 'apiMethod' => 'post' ), 'files'=>array('configFile‘), 'group' => 'configuration', 'info' => array ( 'Import a saved configuration snapshot into the server.', array('--configFile','The configuration snapshot file to import.'), //...
  12. 16 •Console Module Implementing Console Client in ZF2 class Module

    implements ConsoleUsageProviderInterface, ConsoleBannerProviderInterface { public function getConsoleUsage (Console $console) { //.. } public function getConsoleBanner (Console $console) { return 'ZendServerWebApi Client version 1.0'; } }
  13. 17 •Taking control Implementing Console Client in ZF2 class Module

    implements ConsoleUsageProviderInterface, ConsoleBannerProviderInterface { public function onBootstrap ($event) { $eventManager = $event->getApplication()->getEventManager(); $eventManager->attach(MvcEvent::EVENT_ROUTE, array($this, 'postRoute'), - 2); $eventManager->attach(MvcEvent::EVENT_FINISH, array($this, 'preFinish'), 100); } }
  14. 18 •Post-Processing Input Parameters Implementing Console Client in ZF2 class

    Module implements ConsoleUsageProviderInterface, ConsoleBannerProviderInterface { //... public function postRoute (MvcEvent $event) { //.. foreach ($config['console']['router']['routes'][$routeName]['options']['files'] as $param) { if ($value = $match->getParam($param)) { $match->setParam($param, $path->getAbsolute($value)); } } //… } //..
  15. 19 •In-Line Help Implementing Console Client in ZF2 class Module

    implements ConsoleUsageProviderInterface, ConsoleBannerProviderInterface { //... public function getConsoleUsage (Console $console) { $usage = array(); //.. foreach ($routes as $route) { $command = $route['options']['route']; $usage[] = "* $command"; if (isset($route['options']['info'])) { //… } } //.. return $usage; //..
  16. 20 •Using input parameters in Actions Implementing Console Client in

    ZF2 class ZpkController extends AbstractActionController { public function packAction() { $folder = $this->getRequest()->getParam('folder'); $destination = $this->getRequest()->getParam('destination'); //… } //..
  17. 21 •Outputting response in Actions Implementing Console Client in ZF2

    class ZpkController extends AbstractActionController { public function packAction() { //… $this->getResponse()->setContent($textContent); return $this->getResponse(); } //..
  18. 22 •Enabling debug mode Implementing Console Client in ZF2 class

    Module implements ConsoleBannerProviderInterface { public function getConfig () { $config = include __DIR__ . '/config/module.config.php'; if (!getenv('DEBUG')) { $config['view_manager']['exception_message'] = <<<EOT ====================================================================== The application has thrown an exception! ====================================================================== :className :message EOT; } return $config; }
  19. 23 •Separating own module code and dependant stuff o Using

    composer •Packing everything together o As phar file Implementing Console Client in ZF2 <?php //.. $pharPath = $buildRoot . "/$filename"; $phar = new \Phar($pharPath, 0, $filename); $phar->startBuffering(); //.. $phar->setStub($stub); $phar->stopBuffering(); //..
  20. 25 •Help system o Command groups →zs-client.phar –-help o Commands

    in specific group →Ex: Show all commands in the monitor group — zs-client.phar command:monitor o Specific command →zs-client.phar configurationExtensionsOn --help o All commands →zs-client.phar command:all Usage
  21. 26 •Target o zs-client.phar addTarget –-target=<name> --zsurl=.. –-zskey= •Packaging o

    Add deployment support to existing PHP code →zs-client.phar initZpk –-folder=../LegacyProjectFolder/ o Create package → zs-client.phar packZpk –-folder=../LegacyProjectFolder/ \ --destination=/tmp •Deployment o zs-client.phar installApp –-zpk=/tmp/application.zpk –-target=<name> --baseUri=<base-uri> --createVhost=TRUE Usage
  22. 27 •Configuration o Turning on or off extensions →zs-client.phar configurationExtensionsOff

    --extensions="mysql,gd,ftp" o Changing directives →zs-client.phar configurationStoreDirectives --directives="date.timezone=Europe/Berlin&allow_url_include=Off“ Usage
  23. 29 •Need to use the “composer” branch in git •Packaging

    o Create package → zs-client.phar packZpk –-folder=../LegacyProjectFolder/ \ --destination=/tmp \ --composer — Calculates the dependacies — Creates library packages — Sets the current application requirements — Creates the application package Composer Integration*
  24. 30 Composer Integration* ZPKS=`php bin/zs-client.php packZpk --folder="<folder-where-the-PHP-code-is>" \ --destination="<folder-where-the-package-will-be-created>" \

    --composer 2>/dev/null`; for i in $ZPKS; do php bin/zs-client.php installApp --zpk="$i" \ --target="<the-name-of-the-target>" \ --baseUri="<baseUri>" \ --userParams="APPLICATION_ENV=staging&DB_TYPE=mysql" done;