750 likes | 899 Views
Extending the Zend Server UI and WebAPI. Adding your own functionality to Zend Server Presented by Yonni Mendes with cats, spartans, pirates and Obama!. Before we start, kindly visit avast.yonman.net and install the listed applications & stuff!. Presented by Yonni Mendes, ZS6 UI Tech Leader.
E N D
Extending the Zend Server UI and WebAPI Adding your own functionality to Zend Server Presented by Yonni Mendes with cats, spartans, pirates and Obama! Before we start, kindly visit avast.yonman.net and install the listed applications & stuff! Presented by Yonni Mendes, ZS6 UI Tech Leader
Setup: what you should have • Zend Studio, or other IDE of choice • Zend Server • AhoyWorld zpk deployable • Tutorial package • Skeletons • Exercise snippets • Complete code • Recommended • Chrome: Dev HTTP Client or similar • Firefox: Firebug, live HTTP Headers or similar • Sqlite database manager of choice
Who and What is a Yonni • A restaurant in Los Angeles, California.Sadly, closed. • The UI Technological Leader for Zend Server • A semi-famous male model Also • A father • A gamer • A technologist Ask me about the extra thing you should know! Stuff you need: IDE Zend Server Ahoy World Chrome: Dev HTTP Firefox: Firebug, live HTTP Headers Sqlite database manager of choice
But first… Some exercises to get the bloodflowing Stand up please! Stuff you need: IDE Zend Server Ahoy World Chrome: Dev HTTP Firefox: Firebug, live HTTP Headers Sqlite database manager of choice
Topics • Create a basic 3rd party module • Understanding ZS6 • Under the Zend Server 6 hood • Beasts and common practices of ZS6 • Lets make our module do something • Some more modules thatare out there Stuff you need: IDE Zend Server Ahoy World Chrome: Dev HTTP Firefox: Firebug, live HTTP Headers Sqlite database manager of choice
Why extend ZS6? • Zend Server’s unique position • Zend Server’s existing platform & services And, for us, most importantly:B.W.C Stuff you need: IDE Zend Server Ahoy World Chrome: Dev HTTP Firefox: Firebug, live HTTP Headers Sqlite database manager of choice
The first steps: 3rd party module So you want to add some functionality...
A few ZF2 buzzwords These are a few devices we will need • ServiceManager, Factories • Merged config arrays • Modules, Module manager
We also want to control this toggle from other remote sources via WebAPI Our scenario • We have an application, “Ahoy World!” • Deploy it (https://github.com/YonmaN/AhoyWorld) • This application can be turned on and off • We want to allow a user logged into Zend Server to control this toggle directly from the UI
Andy the admin’s requirements • Access to toggle the application state • Anywhere, Anytime, not on a production port 80 • No access to those Creative Type People over at marketing • Human UI and API access • Must be secure • But: Do not create a new user authentication system, nor modify the existing one at Ahoy • In fact, do not modify AhoyWorld at all • Show some general app information too
Our Module: Avast • WebAPI will allow a client to: • Retrieve the current status of the site (on or off) • Toggle the current status of the site • Rely on external code that’s included into the module • UI will display the deployment information about our application • UI will only show a status indicator to the developer, nothing else • UI will show a toggle button that allows the admin to turn the site on or off
Functional requirements • ZF2 module, use ZF2 features, be ZF2 compliant • WebAPI will return both json and xml output • UI page will be integrated in the ZS6 ACL • UI page will show up in the navigation page • UI will be accessible only to a logged in user
Preparing to develop for ZS6 • Switch off opcode cache in Zend Server • Linux/mac: /usr/local/zend/gui/lighttpd/etc/conf.d/optimizerplus.ini • Windows: Through the UI (Configuration|Components) • Restart Zend Server • Throught the UI (localhost:10081) • Command line (<install_dir>/bin/zendctl.sh restart) • Recommended:open <install_dir>/gui as a php project in the IDE • Find the gui/vendor directory
Warning! Confusion ahead! • Zend Studio copies files • Changes may not apply • You may have to make some changes manually • Particularly, the vendor library changes
Creating a new module, the hard way • Create a new php project • zendframework/ZendSkeletonModule • Unzip into your workspace folder • Rename everything that needs renaming
Rename gotta rename • Folder names • in src • File names • Controller filename • view scripts • Controller class name
Create a new module, the easy way • Create a new php project • Unzip avast.yonman.net/Avast-00-Initial.zip Important: can you create a symbolic link? Recommended: add the Zend GUI project as a library to the new module project, in ‘include path’
Make a connection • In the Zend Server UI directory • link to ./vendor • Add ‘Avast’ to application.config.php • Open localhost:10081/ZendServer/Avast Note case sensitive URL Result: error :(
Necessary changes • Remove the entire router entry • Replace controllers entry 'invokables' => array( 'Avast' => 'Avast\Controller\AvastController', ), Result: Still error!
ACL entries and overrides • Pitfall: GUI will now return 404! • This is because of a bug in the ACL system • There is no resource called “Avast" and therefore no controller is found ... ergo 404 • ACL requires SQL entries • sqlite: var/db/gui.db or data/db/gui.db INSERT OR IGNORE INTO GUI_ACL_RESOURCES VALUES(NULL,'route:Avast'); INSERT OR IGNORE INTO GUI_ACL_PRIVILEGES VALUES(3, last_insert_rowid(), ''); (Place in sqls in a dedicated sql file - acl.sqlite.entries.sql) Result: localhost:10081/ZendServer/Avast should respond correctly Exercise Avast-01-acl
Installation process of your module • Unpack / link module into ./vendor • Add module name to application.config.php • Run SQLs • Copy any config.php files into ./config/autoload • Copy any public directory assets to the public direcotry (js, images, css)
Bask in the glory of your Module! Our module can now: • Display an empty page • Override navigation bar • Display app info & status indicator • Provide WebAPI control and monitor of Ahoy • Provide a UI button to control Ahoy
Avast ye landlubbers! Lets make things interesting
Our goal: Create a functioning, usable module for ZS6 Module will provide functionality in webapi Module will also provide a UI interface to use the above functionality Have fun! Lets grease those elbows! From here on: • Describe a tool or ZS6 subsystem and its use • Show its usage in the ZS6 codebase • Integrate it to some extent into your module
Files you might want to watch Linux • gui/lighttpd/logs/zend_server_ui.log • gui/lighttpd/logs/php.log Windows • logs/zend_server_ui.log • logs/php.log You can access both through the Zend Server UI (Overview|Logs)
ZF2: Navigation override • navigation.global.config.php • We wish to add a new Avast tab • Tab should use Avast controller Exercise: Override the navigation array in Avast/module.config.php Ask me about ZS6.2! Result: Navigation bar should show Avast tabs that can be used Exercise Avast-02-navigation
Calling the ZS databases • You’ll want to do this through our mappers • If you want to build a new mapper ... • ServiceManager and delegated Di • DbConnector::factory • Driver • Connection • Adapter • TableGateway • Mapper • Can also call ServiceManager->get('PDO') Ask me about ZS6.2!
Spotlight: Deployment\FilteredAccessMapper • Wraps another mapper, which wrapper yet another, foreign mapper. Good times. • Things of interest • FilteredAccessMapper::getMasterApplicationsByIds • Deployment\Application\Container Ask me about the big dirty lie!
An aside: Foreign code is a cruel mistress • Next we will implement • Avast UI has to show deployment information about “Ahoy World” • Use Deployment\FilteredAccessMapper class to retrieve and display data • Use foreign code carefully to avoid errors • Aggregate, don’t inherit • Avoid directly referring to foreign code directly Ask me why aggregate and not extend!
An aside: Integration in good practice Recommended approach: • Create an aggregating class for FilteredAccessMapper • Implement findAhoyApplication() code in class • Integrate your class into the controller Can go the extra mile - wrap the application container that is returned
Calling the database • Avast UI has to show deployment information about “Ahoy World” • Use Deployment\FilteredAccessMapper class to retrieve and display data Exercise: Integrate a call to retrieve all applications. Find ‘Ahoy World’ application data. Show this data in your view script. Ask me why there’s no native “getApplicationByName” method! Exercise Avast-03-applications
Add a visual status indicator Requirement: • UI will show a toggle status indicator for Ahoy World Thoughts on how to integrate with the AhoyWorld Application?
Meanwhile, in AhoyWorld <ahoyworld-url>/Status A restfull api returns the current application status JSON output: {"status":true}
Add a visual status indicator... Requirement: • UI will show a toggle status indicator for Ahoy World Exercise: Add a visual indicator for the current state. Retrieve state from AhoyAPI Status Result: Visual indicator will display correct application state Exercise Avast-04-StatusIndicator
Bask in the glory of your Module! Our module can now: • Display an empty page • Override navigation bar • Display app info & status indicator • Provide WebAPI control and monitor of Ahoy • Provide a UI button to control Ahoy
WebAPI ho! It’s not Zend Server if there’s no WebAPI
WebAPI: How does one use it • Create a request using Zend\Http\Client • Add an Accept header • application/vnd.zend.serverapi+json • Can be X-Accept too (Ask me why!) • Sign the request using SignatureGenerator • Date should be a GMT with specific format • Use key obtained in the WebAPI section of UI • Machines may have to have their clocks synched Good news: We don’t need any of the above Ask me Why!
Tools: Request simulation How’s about we sees us an example? • URL: localhost:10081/ZendServer/Api/getSystemInfo • Header: Accept: …. • To version or not to version? • application/vnd.zend.serverapi+json;version=1.5 • Output type? • Get or post? • Signed request or session hijacking? • Inspecting the response
WebAPI: avastAhoyStatus • WebAPI action to return the current state of Ahoy’s master directive • No parameters • Output: json and xml We want to create the avastAhoyStatus route & ACL … but how do we do that?
Create a WebAPI route Create a Literal route in module.config.php 'webapi_routes' => array( 'AvastWebAPI' => array( 'type' => 'Zend\Mvc\Router\Http\Literal', 'options' => array( 'route' => '/Api/example', 'defaults' => array( 'controller' => 'AvastWebAPI', 'action' => 'avastAhoyStatus', 'versions' => array('1.5'), ), )) ) ... Ask me about more route options! Tell me: what did I forget?
More ACL entries and overrides • ACL requires SQL entries • sqlite, db/gui.db INSERT OR IGNORE INTO GUI_ACL_RESOURCES VALUES(NULL,'route:AvastWebAPI'); INSERT OR IGNORE INTO GUI_ACL_PRIVILEGES VALUES(3, last_insert_rowid(), ''); • These queries have to be reapplied after upgrades • Controller names are case sensitive Ask me about exceptions!
avastAhoyStatus, cont’d Reminder: • WebAPI action to return the current state of Ahoy’s master directive • No parameters • Output: json and xml We want to create a controller and view scripts … but how do we do that?
Lets add a WebAPI controller • Class WebAPIController • Extends WebAPIActionController class • Add to controllers in module.config (AvastWebAPI_1-5) • Controller names are case sensitive • Action should be named as indicated by the route’s action parameter
Lets add a WebAPI view script • Actions need View scripts - one for each format • avast/web-api/1x5/<action>.pjson.phtml • avast/web-api/1x5/<action>.pxml.phtml • <action> has dashed inflection: avast-ahoy-status • Wrapped by layout.p<output>.phtml automatically • Create a string that “nestles” within the layout • View script has to include “responseData” wrapper element in json and xml
avastAhoyStatus, cont’d • WebAPI action to return the current state of Ahoy’s master directive • No parameters • Output: json and xml Exercise: Create the avastAhoyStatus webapi controller & action Exercise: Create json and xml view scripts Use dummy data for this exercise Result: avastAhoyStatus responds to requests
avastAhoyStatus functionality • Add functionality to our webapi action • Retrieve a boolean status • Pass it out to the view script Exercise: Use Integration Stub to retrieve status Replace the dummy data from the previous exercise Result: avastAhoyStatus should respond to requests with meaningful information Exercise Avast-05-avastAhoyStatus
WebAPI: avastAhoyToggle • WebAPI action to return the updated state of Ahoy’s master directive • Parameter: state • Output: json and xml Exercise: Create the avastAhoyToggle route Exercise: Create the avastAhoyToggle webapi Exercise: Create json and xml output, similar or identical to avastAhoyStatus Result: avastAhoyToggle responds to requests
WebAPI:avastAhoyToggle functionality • Add functionality to our webapi action • Collect a parameter and validate it • Pass the parameter to a toggle method Exercise: Use <ahoyworld-url>/Status/Toggle to change AhoyWorld’s status Result: calls to avastAhoyToggle affect AhoyWorld Exercise Avast-06-avastAhoyToggle
Bask in the glory of your Module! Our module can now: • Display an empty page • Override navigation bar • Display app info & status indicator • Provide WebAPI control and monitor of Ahoy • Provide a UI button to control Ahoy
Lets make our UI do a jig Shiver me timbers!