{"id":53648,"date":"2021-03-16T15:12:19","date_gmt":"2021-03-16T09:42:19","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=53648"},"modified":"2021-03-18T10:28:09","modified_gmt":"2021-03-18T04:58:09","slug":"simplified-aem-automation-with-curl-and-ruby","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/simplified-aem-automation-with-curl-and-ruby\/","title":{"rendered":"Simplified AEM Automation with cURL and RUBY"},"content":{"rendered":"<p>Administrators often need to automate or simplify common tasks within any system. In Adobe Experience Manager (AEM), managing users, installing packages, and managing OSGi bundles are some of the tasks where automation is commonly required.<br \/>\nBecause of the RESTful nature of the Sling framework upon which AEM is built, most of the tasks can be reduced to a URL call. cURL can be used to execute such URL calls and can be proved as a useful tool for automation inside an AEM environment.<\/p>\n<h1 style=\"font-size: 22px;\"><b>What is cURL?<\/b><\/h1>\n<p>cURL stands for Client for URL and is an open-source command-line tool used to perform URL manipulations. It supports a wide range of internet protocols including HTTP, HTTPS, FTP, FTPS, SCP, SFTP, TFTP, LDAP, DAP, DICT, TELNET, FILE, IMAP, POP3, SMTP, and RTSP.<br \/>\nOriginally released in 1997, cURL is a well-established and widely-used tool for providing or receiving data using the URL syntax.<\/p>\n<h1 style=\"font-size: 22px;\"><b>Installation<\/b><\/h1>\n<p>cURL comes by default in most of the systems, however, it can be downloaded and installed from the link <a href=\"https:\/\/curl.se\/download.html\" target=\"_blank\">here<\/a>.<br \/>\nWindows users need to ensure that they have appended the environment variable \u2018path\u2019 with the path of the bin where cURL is installed. The stepwise process is mentioned below.<\/p>\n<ol>\n<li>Open the Start Search, type in \u201cenv\u201d, and choose \u201cEdit the system environment variables\u201d.<\/li>\n<li>Click the \u201cEnvironment Variable\u201d button.<\/li>\n<li>Under the \u201cSystem Variables\u201d section (the lower half), find the row with \u201cPath\u201d in the first column, and click edit.<\/li>\n<li>The \u201cEdit environment variable\u201d UI will appear. Click on \u201cNew\u201d and type in the new path you want to add.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h1 style=\"font-size: 22px;\"><b>cURL for AEM<\/b><\/h1>\n<p>Since AEM follows REST architecture, cURL can execute most tasks using a URL call.<br \/>\ncURL can be handy when it comes to content manipulation tasks such as activating pages, starting workflows and operational tasks such as package management and managing users. In addition you can create your own cURL commands for most of the tasks in AEM.<br \/>\nThe official link for some common AEM cURL commands is <a href=\"https:\/\/helpx.adobe.com\/experience-manager\/6-3\/sites\/administering\/using\/curl.html#CommonOperationalAEMcURLCommands\" target=\"_blank\">here<\/a>.<br \/>\nA <a href=\"https:\/\/github.com\/paulrohrbeck\/aem-links\/blob\/master\/curl_cheatsheet.md\" target=\"_blank\">cheat sheet<\/a> is also available for reference.<\/p>\n<h1 style=\"font-size: 22px;\"><b>Building a cURL command for AEM<\/b><\/h1>\n<p>cURL commands can be built for most operations in AEM such as triggering workflows, checking OSGi configurations, triggering JMX commands, creating replication agents, etc.<br \/>\nTo find the exact command needed for a particular operation, use the developer tools in your browser to capture the POST call to the server when you perform the AEM operation manually.<br \/>\nNow, let\u2019s see how to create the cURL command for giving path specific read\/modify access to a user.<\/p>\n<ol>\n<li>Prepare the action you wish to invoke within AEM. In our case, we have proceeded to the \/useradmin page to manage users.<br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-53652 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/1.jpg\" alt=\"1\" width=\"7122\" height=\"3482\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/1.jpg 7122w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/1-300x146.jpg 300w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/1-1024x500.jpg 1024w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/1-624x305.jpg 624w\" sizes=\"(max-width: 7122px) 100vw, 7122px\" \/><\/li>\n<li>Go to the developer console or Right click and select inspect and then go to the network tab.<br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-53654 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/2.jpg\" alt=\"2\" width=\"7156\" height=\"3754\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/2.jpg 7156w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/2-300x157.jpg 300w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/2-1024x537.jpg 1024w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/2-624x327.jpg 624w\" sizes=\"(max-width: 7156px) 100vw, 7156px\" \/><\/li>\n<li>Select the permissions that you want to give to the user for the specified path and then click save. Here, we will proceed with read\/modify permissions for \/etc path (observe the POST call).<br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-53655 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/3.jpg\" alt=\"3\" width=\"7228\" height=\"3601\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/3.jpg 7228w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/3-300x149.jpg 300w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/3-1024x510.jpg 1024w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/3-624x310.jpg 624w\" sizes=\"(max-width: 7228px) 100vw, 7228px\" \/><\/li>\n<li>Copy the URL from the POST call in the header section.<br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-53657 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/4.jpg\" alt=\"4\" width=\"7228\" height=\"3601\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/4.jpg 7228w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/4-300x149.jpg 300w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/4-1024x510.jpg 1024w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/4-624x310.jpg 624w\" sizes=\"(max-width: 7228px) 100vw, 7228px\" \/><br \/>\nRequest payload from request section. This will be the data parameter for our cURL command.<br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-53658 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/5.jpg\" alt=\"5\" width=\"7228\" height=\"3251\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/5.jpg 7228w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/5-300x134.jpg 300w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/5-1024x460.jpg 1024w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/5-624x280.jpg 624w\" sizes=\"(max-width: 7228px) 100vw, 7228px\" \/><\/li>\n<li>Execute the cURL command via command line and view the response.<br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-53659 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/6.jpg\" alt=\"6\" width=\"6791\" height=\"1315\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/6.jpg 6791w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/6-300x58.jpg 300w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/6-1024x198.jpg 1024w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/6-624x120.jpg 624w\" sizes=\"(max-width: 6791px) 100vw, 6791px\" \/><br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-53660 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/7.jpg\" alt=\"7\" width=\"7122\" height=\"4573\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/7.jpg 7122w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/7-300x192.jpg 300w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/7-1024x657.jpg 1024w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/7-624x400.jpg 624w\" sizes=\"(max-width: 7122px) 100vw, 7122px\" \/><br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-53661 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/8.jpg\" alt=\"8\" width=\"7122\" height=\"6936\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/8.jpg 7122w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/8-300x292.jpg 300w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/8-1024x997.jpg 1024w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/8-624x607.jpg 624w\" sizes=\"(max-width: 7122px) 100vw, 7122px\" \/><\/li>\n<\/ol>\n<h1 style=\"font-size: 22px;\"><b>Moving beyond cURL<\/b><\/h1>\n<p>Although cURL is the go-to tool for administration API testing in AEM and has a lot of documentation established around it, it has its flaws in terms of automation and dependency to shell. These flaws can create obstacles while writing server- independent and complex scripts.<\/p>\n<h1 style=\"font-size: 22px; margin-bottom: 10px;\"><b>Challenges with cURL<\/b><\/h1>\n<ul>\n<li><b>Inconsistent response payload types<\/b><br \/>\ncURL response types vary in terms of usage. This creates a lack of uniformity when writing scripts that utilize response payloads. As seen in the last example above, the response for updating permission was in <b>HTML<\/b>.<br \/>\nHowever, the response for activating an OSGi bundle, for example, is in <b>JSON<\/b>.<br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-53662 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/9.jpg\" alt=\"9\" width=\"6791\" height=\"730\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/9.jpg 6791w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/9-300x32.jpg 300w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/9-1024x110.jpg 1024w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/9-624x67.jpg 624w\" sizes=\"(max-width: 6791px) 100vw, 6791px\" \/><br \/>\nAnd the response for listing packages in crx is in <b>XML<\/b>.<br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-53663 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/10.jpg\" alt=\"10\" width=\"7121\" height=\"5902\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/10.jpg 7121w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/10-300x248.jpg 300w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/10-1024x848.jpg 1024w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/10-624x517.jpg 624w\" sizes=\"(max-width: 7121px) 100vw, 7121px\" \/><\/li>\n<li><b>Unreliable status codes<\/b><br \/>\nSome of the status codes that are returned as a response are occasionally unreliable. Here are some examples:<\/p>\n<ul style=\"margin-top: -20px;\">\n<li>http 200 with empty response body\u2028 when authentication is invalid<\/li>\n<li>http 200 with error message in html response body\u2028 when old password is incorrect<\/li>\n<\/ul>\n<\/li>\n<li style=\"padding-top: 16px;\"><b>Serverless<\/b><br \/>\ncURL is dependent on access to shell and lacks integration with Serverless frameworks.<\/li>\n<\/ul>\n<h1 style=\"font-size: 22px; padding-top: 24px;\"><b>The Way Forward: OpenAPI (Swagger) for AEM<\/b><\/h1>\n<p>Swagger AEM is an OpenAPI specification for Adobe Experience Manager, which can be used to generate API clients in 30 programming languages.<br \/>\nThese API clients, in turn, are useful for integrating AEM with a number of technology stacks. From setting OSGI configuration using provisioning tools such as Puppet, to deploying AEM packages using voice via Google Assistant. The possibilities are endless. <b>Ruby_aem<\/b> is one option that can solve the cURL AEM challenges.<\/p>\n<h1 style=\"font-size: 22px;\"><b>What makes Ruby_aem a viable solution?<\/b><\/h1>\n<ol>\n<li>Resource Oriented Design<\/li>\n<li>Further abstraction away from endpoints<\/li>\n<li>Error and response objects<\/li>\n<li>Additional custom APIs<\/li>\n<\/ol>\n<h1 style=\"font-size: 20px;\">Installation<\/h1>\n<p>The steps are illustrated below.<br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-53664 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/111.jpg\" alt=\"11\" width=\"6791\" height=\"1387\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/111.jpg 6791w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/111-300x61.jpg 300w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/111-1024x209.jpg 1024w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/111-624x127.jpg 624w\" sizes=\"(max-width: 6791px) 100vw, 6791px\" \/><\/p>\n<h1 style=\"font-size: 20px;\">Result Handling<\/h1>\n<p>Ruby_aem allows for much better result handling due to its uniform response payloads which are parsed beforehand. Also, it is endpoint free.<br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-53665 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/12.jpg\" alt=\"12\" width=\"7122\" height=\"7198\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/12.jpg 7122w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/12-296x300.jpg 296w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/12-1013x1024.jpg 1013w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/12-624x630.jpg 624w\" sizes=\"(max-width: 7122px) 100vw, 7122px\" \/><\/p>\n<h1 style=\"font-size: 20px;\">Error Handling<\/h1>\n<p>Better error and edge case handling allows us to write more robust scripts. Additionally, unlike cURL, ruby is a first class programming language which gives us much more flexibility and freedom.<br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-53666 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/13.jpg\" alt=\"13\" width=\"7122\" height=\"6834\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2021\/03\/13.jpg 7122w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/13-300x287.jpg 300w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/13-1024x982.jpg 1024w, \/blog\/wp-ttn-blog\/uploads\/2021\/03\/13-624x598.jpg 624w\" sizes=\"(max-width: 7122px) 100vw, 7122px\" \/><\/p>\n<h1 style=\"font-size: 20px;\">Serverless<\/h1>\n<p>Ruby_aem is only part of the available client library support for Swagger_aem. Swagger_aem also houses support for java, python and javascript for AEM. This allows us to move forward from the dependency on shell.<\/p>\n<h1 style=\"font-size: 20px;\"><b>Key Features of Ruby_aem<\/b><\/h1>\n<ul>\n<li>Wait until login page is ready<\/li>\n<li>Wait until AEM health check is passed<\/li>\n<li>Bundle start, stop<\/li>\n<li>Con\ufb01guration property create<\/li>\n<li>Replication, reverse replication, and \ufb02ush agents create, update, delete<\/li>\n<li>User and group create and delete<\/li>\n<li>Add user and group to a group<\/li>\n<li>Node create and delete<\/li>\n<li>Package create, update, delete, upload, install, uninstall, replicate, list, versions<\/li>\n<li>Path activate<\/li>\n<li>Repository block, unblock<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h1 style=\"font-size: 22px;\"><b>Conclusion<\/b><\/h1>\n<p>All in all, cURL and Ruby_aem both have their uses in AEM. Although cURL is a much easier tool to pick up on the go and use for testing out APIs or hitting URLs, it is still lacking in some areas. For complex automation, Ruby_aem provides a more comprehensive pool of utilities.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Administrators often need to automate or simplify common tasks within any system. In Adobe Experience Manager (AEM), managing users, installing packages, and managing OSGi bundles are some of the tasks where automation is commonly required. Because of the RESTful nature of the Sling framework upon which AEM is built, most of the tasks can be [&hellip;]<\/p>\n","protected":false},"author":1234,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":90},"categories":[3887,3109],"tags":[3598,4858],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/53648"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1234"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=53648"}],"version-history":[{"count":4,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/53648\/revisions"}],"predecessor-version":[{"id":53668,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/53648\/revisions\/53668"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=53648"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=53648"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=53648"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}