{"id":7854,"date":"2013-04-18T15:27:54","date_gmt":"2013-04-18T13:27:54","guid":{"rendered":"https:\/\/blog.trifork.com\/?p=7854"},"modified":"2013-04-18T15:27:54","modified_gmt":"2013-04-18T13:27:54","slug":"ansible-simple-module","status":"publish","type":"post","link":"https:\/\/trifork.nl\/blog\/ansible-simple-module\/","title":{"rendered":"Ansible &#8211; Simple module"},"content":{"rendered":"<p>In this post, we&#8217;ll review Ansible module development.<br \/>\nI haven chosen to make a maven module; not very fancy, but it provides a good support for the subject.<br \/>\nThis module will execute a maven phase for a project (a pom.xml is designated).<br \/>\nYou can always refer to the Ansible <a href=\"http:\/\/ansible.cc\/docs\/moduledev.html\">Module Development<\/a> page.<\/p>\n<h2>Which language?<\/h2>\n<p>The de facto language in Ansible is Python (you benefit from the boilerplate), but any language can be used. The only requirement is being to be able to read\/write files and write to stdout.<br \/>\nWe will be using bash.<\/p>\n<h2>Module input<\/h2>\n<p>The maven module needs two parameters, the phase and the pom.xml location (pom).<br \/>\nFor non-Python modules, Ansible provides the parameters in a file (first parameter) with the following format:<br \/>\n<b>pom=\/home\/mohamed\/myproject\/pom.xml phase=test<\/b><\/p>\n<p>You then need to read this file and extract the parameters.<\/p>\n<p>In bash you can do that in two ways:<br \/>\n<b>source $1<\/b><\/p>\n<p>This can cause problems because the whole file is evaluated, so any code in there will be executed. In that case we trust that Ansible will not put any harmful stuf in there.<\/p>\n<p>You can also parse the file using sed (or any way you like):<br \/>\n<b>eval $(sed -e &#8220;s\/&#040;[a-z]<em>&#041;=&#040;[a-zA-Z0-9\\\/&#046;]<\/em>&#041;\/\\1=&#8217;\\2&#8217;\/g&#8221; $1)<\/b><br \/>\nThis is good enough for this exercise.<\/p>\n<p>We now have two variables (pom and phase) with the expected values.<br \/>\nWe can continue and execute the maven phase for the given project (pom.xml).<\/p>\n<h2>Module processing<\/h2>\n<p>Basically, we can check if the parameters have been provided and then execute the maven command:<\/p>\n<p><b><br \/>\n#!\/bin\/bash<\/b><\/p>\n<p>eval $(sed -e &#8220;s\/&#040;[a-z]<em>&#041;=&#040;[a-zA-Z0-9\\\/&#046;]<\/em>&#041;\/\\1=&#8217;\\2&#8217;\/g&#8221; $1)<\/p>\n<p>if [ -z &#8220;${pom}&#8221; ] || [ -z &#8220;${phase}&#8221; ]; then<br \/>\necho &#8216;failed=True msg=&#8221;Module needs pom file (pom) and phase name (phase)&#8221;&#8216;<br \/>\nexit 0;<br \/>\nfi<\/p>\n<p>maven-output=$(mktemp \/tmp\/ansible-maven.XXX)<br \/>\nmvn ${phase} -f ${pom} &gt; $maven-output 2&gt;&amp;1<br \/>\nif [ $? -ne 0 ]; then<br \/>\necho &#8220;failed=True msg=\\&#8221;Failed to execute maven ${phase} with ${pom}\\&#8221;&#8221;<br \/>\nexit 0<br \/>\nfi<\/p>\n<p>echo &#8220;changed=True&#8221;<br \/>\nexit 0<\/p>\n<p>In order to communicate the result, the module needs to return JSON.<br \/>\nTo simplify the JSON outputing step, Ansible allows to use key=value as output.<\/p>\n<h2>Module output<\/h2>\n<p>You noticed that an output is always returned. If an error happened, failed=True is returned as well as an error message.<br \/>\nIf everything went fine, changed=True is returned (or changed=False).<\/p>\n<p>If the maven command fails, a generic error message is returned. We can change that by parsing the content of maven-ansible and return only what we need.<\/p>\n<p>In some situations, your module doesn&#8217;t do anything (no action is needed). In that case you&#8217;ll need to return changed=False in order to let Ansible know that nothing happened (it is important if you need that for the rest of the tasks in your playbook).<\/p>\n<h2>Use it<\/h2>\n<p>You can run your module with the following command:<br \/>\n<b><br \/>\nansible buildservers -m maven -M \/home\/mohamed\/ansible\/mymodules\/ &#8211;args=&#8221;pom=\/home\/mohamed\/myproject\/pom.xml phase=test&#8221; -u mohamed -k<br \/>\n<\/b><br \/>\nIf it goes well, you get something like the following output:<br \/>\n<b><br \/>\nlocalhost | success &gt;&gt; {<br \/>\n&#8220;changed&#8221;: true<br \/>\n}<br \/>\n<\/b><\/p>\n<p>Otherwise:<br \/>\n<b><br \/>\nlocalhost | FAILED &gt;&gt; {<br \/>\n&#8220;failed&#8221;: true,<br \/>\n&#8220;msg&#8221;: &#8220;Failed to execute maven test with \/home\/mohamed\/myproject\/pom.xml&#8221;<br \/>\n}<br \/>\n<\/b><\/p>\n<p>To install the module put it in ANSIBLE_LIBRARY (by default it is in \/usr\/share\/ansible), and you can start using it inside your playbooks.<br \/>\nIt goes without saying that this module has some dependencies: an obvious one is the presence of maven. You can ensure that maven is installed by adding a task in your playbook before using this module.<\/p>\n<p><b>Conclusion<\/b><\/p>\n<p>Module development is as easy as what we briefly saw here, and in any language. That&#8217;s another point I wanted to make and that makes Ansible very nice to use.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post, we&#8217;ll review Ansible module development. I haven chosen to make a maven module; not very fancy, but it provides a good support for the subject. This module will execute a maven phase for a project (a pom.xml is designated). You can always refer to the Ansible Module Development page. Which language? The [&hellip;]<\/p>\n","protected":false},"author":83,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":""},"categories":[88,10,124],"tags":[332,115,220,86],"class_list":["post-7854","post","type-post","status-publish","format-standard","hentry","category-devops","category-development","category-system-administration","tag-ansible","tag-cloud","tag-configuration-management","tag-devops"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Ansible - Simple module - Trifork Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/trifork.nl\/blog\/ansible-simple-module\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ansible - Simple module - Trifork Blog\" \/>\n<meta property=\"og:description\" content=\"In this post, we&#8217;ll review Ansible module development. I haven chosen to make a maven module; not very fancy, but it provides a good support for the subject. This module will execute a maven phase for a project (a pom.xml is designated). You can always refer to the Ansible Module Development page. Which language? The [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/trifork.nl\/blog\/ansible-simple-module\/\" \/>\n<meta property=\"og:site_name\" content=\"Trifork Blog\" \/>\n<meta property=\"article:published_time\" content=\"2013-04-18T13:27:54+00:00\" \/>\n<meta name=\"author\" content=\"Mohamed El Moussaoui\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Mohamed El Moussaoui\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/trifork.nl\/blog\/ansible-simple-module\/\",\"url\":\"https:\/\/trifork.nl\/blog\/ansible-simple-module\/\",\"name\":\"Ansible - Simple module - Trifork Blog\",\"isPartOf\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#website\"},\"datePublished\":\"2013-04-18T13:27:54+00:00\",\"author\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/e83488f033bd62395bd3eb801ddf8972\"},\"breadcrumb\":{\"@id\":\"https:\/\/trifork.nl\/blog\/ansible-simple-module\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/trifork.nl\/blog\/ansible-simple-module\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/trifork.nl\/blog\/ansible-simple-module\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/trifork.nl\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ansible &#8211; Simple module\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/trifork.nl\/blog\/#website\",\"url\":\"https:\/\/trifork.nl\/blog\/\",\"name\":\"Trifork Blog\",\"description\":\"Keep updated on the technical solutions Trifork is working on!\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/trifork.nl\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/e83488f033bd62395bd3eb801ddf8972\",\"name\":\"Mohamed El Moussaoui\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d239ca3a713280c0c1b58648c249fd57?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d239ca3a713280c0c1b58648c249fd57?s=96&d=mm&r=g\",\"caption\":\"Mohamed El Moussaoui\"},\"url\":\"https:\/\/trifork.nl\/blog\/author\/mohamedm\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Ansible - Simple module - Trifork Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/trifork.nl\/blog\/ansible-simple-module\/","og_locale":"en_US","og_type":"article","og_title":"Ansible - Simple module - Trifork Blog","og_description":"In this post, we&#8217;ll review Ansible module development. I haven chosen to make a maven module; not very fancy, but it provides a good support for the subject. This module will execute a maven phase for a project (a pom.xml is designated). You can always refer to the Ansible Module Development page. Which language? The [&hellip;]","og_url":"https:\/\/trifork.nl\/blog\/ansible-simple-module\/","og_site_name":"Trifork Blog","article_published_time":"2013-04-18T13:27:54+00:00","author":"Mohamed El Moussaoui","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Mohamed El Moussaoui","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/trifork.nl\/blog\/ansible-simple-module\/","url":"https:\/\/trifork.nl\/blog\/ansible-simple-module\/","name":"Ansible - Simple module - Trifork Blog","isPartOf":{"@id":"https:\/\/trifork.nl\/blog\/#website"},"datePublished":"2013-04-18T13:27:54+00:00","author":{"@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/e83488f033bd62395bd3eb801ddf8972"},"breadcrumb":{"@id":"https:\/\/trifork.nl\/blog\/ansible-simple-module\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/trifork.nl\/blog\/ansible-simple-module\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/trifork.nl\/blog\/ansible-simple-module\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/trifork.nl\/blog\/"},{"@type":"ListItem","position":2,"name":"Ansible &#8211; Simple module"}]},{"@type":"WebSite","@id":"https:\/\/trifork.nl\/blog\/#website","url":"https:\/\/trifork.nl\/blog\/","name":"Trifork Blog","description":"Keep updated on the technical solutions Trifork is working on!","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/trifork.nl\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/e83488f033bd62395bd3eb801ddf8972","name":"Mohamed El Moussaoui","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d239ca3a713280c0c1b58648c249fd57?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d239ca3a713280c0c1b58648c249fd57?s=96&d=mm&r=g","caption":"Mohamed El Moussaoui"},"url":"https:\/\/trifork.nl\/blog\/author\/mohamedm\/"}]}},"_links":{"self":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/7854","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/users\/83"}],"replies":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/comments?post=7854"}],"version-history":[{"count":0,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/7854\/revisions"}],"wp:attachment":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/media?parent=7854"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/categories?post=7854"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/tags?post=7854"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}