<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Trifork Blog</title>
	<atom:link href="http://blog.trifork.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.trifork.com</link>
	<description>Keep updated on what we&#039;re doing!</description>
	<lastBuildDate>Wed, 22 May 2013 12:22:18 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Elasticsearch server book review</title>
		<link>http://blog.trifork.com/2013/05/22/elasticsearch-server-book-review/</link>
		<comments>http://blog.trifork.com/2013/05/22/elasticsearch-server-book-review/#comments</comments>
		<pubDate>Wed, 22 May 2013 12:22:18 +0000</pubDate>
		<dc:creator>Luca Cavanna</dc:creator>
				<category><![CDATA[Elasticsearch]]></category>
		<category><![CDATA[elasticsearch]]></category>

		<guid isPermaLink="false">http://blog.trifork.com/?p=8000</guid>
		<description><![CDATA[I recently read the ElasticSearch server book published by Packt Publishing. It was a pleasant reading, really interesting even though I was already familiar with the product. So here is a quick synopsis of the book &#38; it's content. Not one of my usual blogs but nonetheless something I wanted to share. Writing a book about [...]]]></description>
				<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-8001" style="float: left;" alt="elasticsearch server" src="http://blog.trifork.com/wp-content/uploads/2013/05/elasticsearch-server-cover.png" width="175" height="213" /></p>
<p>I recently read the <a href="http://link.packtpub.com/LNlA2f">ElasticSearch server</a> book published by <a href="http://www.packtpub.com/">Packt Publishing</a>. It was a pleasant reading, really interesting even though I was already familiar with the product. So here is a quick synopsis of the book &amp; it's content. Not one of my usual blogs but nonetheless something I wanted to share.</p>
<p>Writing a book about Elasticsearch turns out not to be easy. There are in fact lots of features and gems that would need to be discussed, something that's really hard to do in a book with a reasonable number of pages. Also, the product is rapidly evolving, which makes it extremely hard to keep up with it and come up with up-to-date content.</p>
<p>I think this book brings something that was missing until now in the Elasticsearch ecosystem, since it goes from installing the product and setting it up to using it in real life, describing also potential issues and their solutions. Also, it doesn't neglect the needed technical details about the underlying Lucene library and search in general.</p>
<p><strong>Chapter 1: Getting started with Elasticsearch cluster</strong></p>
<p>The first chapter gives an overview of Elasticsearch, how to install it and how to use it, and goes rapidly and surprisingly into detail about all the supported data types and text analyzers available, to then describe the distributed nature of Elasticsearch and some best practices like using index <a href="http://www.elasticsearch.org/guide/reference/api/admin-indices-templates/">templates</a> and <a href="http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/">aliases</a>.</p>
<p><strong>Chapter 2: Searching your data</strong></p>
<p>The second chapter explains how to search against the available indexes and find results. It contains an overview of the queries that the Elasticsearch query DSL offers, together with examples and all the available query options.</p>
<p><strong>Chapter 3: Extending your structure and search</strong></p>
<p>The third chapter goes more into detail about search. It describes how to highlight the relevant parts of the search results, together with real examples on different ways to implement the auto-complete feature, how to index binary content and how to search for geographic locations.</p>
<p><strong>Chapter 4: Make your search better</strong></p>
<p>The fourth chapter goes ahead describing the <a href="http://www.elasticsearch.org/guide/reference/api/admin-indices-analyze/">analyze</a> and <a href="http://www.elasticsearch.org/guide/reference/api/explain/">explain</a> api, great tools to understand how the text analysis and documents scoring work. The next topic is boosting and the different ways to implement it, either at index time or query time. This chapter contains also a real example on how to handle multilanguage content and an overview of all the span queries available, in other words the queries that take token positions and their proximity into account.</p>
<p><strong>Chapter 5: Combining indexing, analysis and search</strong></p>
<p>The fifth chapter starts with a really hot topic nowadays: document relations. It goes over the out-of-the-box support for json nested objects, to then describe nested documents and parent-child. The final and really interesting topic for the chapter is how data flows into Elasticsearch using rivers and how to index data as fast as possible through batch indexing.</p>
<p><strong>Chapter 6: Beyond searching</strong></p>
<p>As the title said, the sixth chapter goes beyond search and describes other features that Elasticsearch offers, among which <a href="http://www.elasticsearch.org/guide/reference/api/search/facets/">faceting</a> is definitely the most important one. In fact, there are many companies using Elasticsearch only for analytics through facets, without any full-text search in their applications. When it comes to facets it's great to have a look not only at the needed json request, but at the obtained response too and the different numbers depending on the type of facet used. Other features discussed in this chapter are <a href="http://www.elasticsearch.org/guide/reference/api/more-like-this/">more like this</a> and the <a href="http://www.elasticsearch.org/2011/02/08/percolator/">percolator</a>.</p>
<p><strong>Chapter 7: Administrating your cluster</strong></p>
<p>The seventh chapter explains how to administer an Elasticsearch cluster, mainly using the cluster api and the existing user interfaces or plugins that make use of them.</p>
<p><strong>Chapter 8: Dealing with problems</strong></p>
<p>The last chapter is all about tackling potential issues with Elasticsearch, looking at the logs and using an API like <a href="http://www.elasticsearch.org/guide/reference/api/validate/">validate query</a> and <a href="http://www.elasticsearch.org/guide/reference/api/admin-indices-warmers/">indices warmup</a>.</p>
<p>I think <a href="http://link.packtpub.com/LNlA2f">ElasticSearch server</a> is a good fit not only for beginners, but also for people who already know the product and want to get more familiar with it. The reason is that it covers quite a lot, and if you haven't used Elasticsearch extensively there's a good chance you have missed some of its goodness!</p>
<p>The parts that I liked the most are the ones that contain real examples and practical hints. That's why I would have loved to see even more of them, especially about document relations, the query DSL and the percolator, and I don't mean basic ones but real cases and tips, together with a "Go to production" chapter containing suggestions about all the settings that one should change before going to production.</p>
<p>Hope this helped anyone that might be considering to get some extra product insight, promise my next blog will be diving into cool features of the actual product again!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.trifork.com/2013/05/22/elasticsearch-server-book-review/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Erlang User Conference 2013: Building Massively Scalable Fault-tolerant Systems</title>
		<link>http://blog.trifork.com/2013/05/17/the-erlang-user-conference-2013-building-massively-scalable-fault-tolerant-systems/</link>
		<comments>http://blog.trifork.com/2013/05/17/the-erlang-user-conference-2013-building-massively-scalable-fault-tolerant-systems/#comments</comments>
		<pubDate>Fri, 17 May 2013 09:09:33 +0000</pubDate>
		<dc:creator>Francesco Cesarini</dc:creator>
				<category><![CDATA[Custom Development]]></category>
		<category><![CDATA[Erlang]]></category>

		<guid isPermaLink="false">http://blog.trifork.com/?p=7986</guid>
		<description><![CDATA[As Founder &#38; Technical Director of Erlang Solutions I just wanted to share with you that between June 13th &#38; 14th, the Erlang User Conference will open its doors to over 40 speakers and more than 300 delegates from all over the world in Stockholm. They will be discussing hot-topics such as Multi-core, Big Data, Cloud, [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://erlangsolutions.com/"><img class="wp-image-7989 alignleft" style="margin: 5px;" alt="ESLlogo" src="http://blog.trifork.com/wp-content/uploads/2013/05/ESLlogo.jpg" width="268" height="160" /></a>As Founder &amp; Technical Director of <a href="https://www.erlang-solutions.com/" target="_blank">Erlang Solutions</a> I just wanted to share with you that between June 13th &amp; 14th, the <a href="https://www.erlang-factory.com/conference/ErlangUserConference2013" target="_blank">Erlang User Conference</a> will open its doors to over 40 speakers and more than 300 delegates from all over the world in Stockholm. They will be discussing hot-topics such as Multi-core, Big Data, Cloud, Embedded, NoSQL and the future of the Web.</p>
<p>For those who aren't aware, the <a href="http://www.erlang.org/" target="_blank">Erlang Programming</a> language and middleware was designed to build massively parallel, scalable and fault tolerant systems uniquely suited for multi-core architectures and the Cloud. Due to the latest increase in the use and adoption of the Erlang programming language, this year the Programme Committee was pleasantly surprised by a record number of talk submissions.  In fact, a fourth track had to be added on both days and an additional talk to all tracks on the first day, making it the largest Erlang User Conference to date. The conference will feature 8 tracks: ‘Erlang and the Beam VM’, ‘Cool Tools and Gadgets 1’, ‘Big Data, Big Databases and Next Generation Analytics’, ‘Scalable Fault-Tolerant Architectures’, ‘Cool Tools and Gadgets 2’, ‘The Internet of Things’, ‘Agile and Test-Driven Development’, ‘Load regulation and Back Pressure’.</p>
<p>The <a href="https://www.erlang-factory.com/conference/ErlangUserConference2013" target="_blank">Erlang User Conferenc</a>e is not only the biggest Erlang event in Europe, but also the oldest. It has been running each year since 1994, with one gap year in 1996, when the first version of OTP was created. In 2013, companies such as Campanja, Ericsson, Klarna, Basho, Erlang Solutions, Tail-f, Spil Games and prestigious research institutes such as the The Swedish Institute of Computing Science and Uppsala University will be represented at the event.</p>
<p>On the first day of the event the inventors of the Erlang programming language <a href="https://www.erlang-factory.com/conference/ErlangUserConference2013/speakers/MikeWilliams" target="_blank">Mike Williams</a>, <a href="https://www.erlang-factory.com/conference/ErlangUserConference2013/speakers/RobertVirding" target="_blank">Robert Virding</a> and <a href="https://www.erlang-factory.com/conference/ErlangUserConference2013/speakers/joearmstrong" target="_blank">Joe Armstrong</a> will be giving a joint keynote about the past, present and especially the future of Erlang. The keynote talks in the second day will be provided by <a href="https://www.erlang-factory.com/conference/ErlangUserConference2013/speakers/ClaesWikstrom" target="_blank">Claes Wikström</a>, author of Yaws and Mnesia and by <a href="https://www.erlang-factory.com/conference/ErlangUserConference2013/speakers/BruceTate" target="_blank">Bruce Tate</a> - author of 'Seven Languages in Seven Weeks'. Other well-known Erlang experts talking at the conference include Steve Vinoski, Eric Merritt, Ulf Wiger, Henning Diedrich, ErikStenman, Pavlo Baron, Mahesh Paolini- Subramanya, Zach Kessin, Patrick Nyblom, Kostis Sagonas and many more. A full list of our <a href="https://www.erlang-factory.com/conference/ErlangUserConference2013/speakers" target="_blank">fantastic speakers</a> is available on our <a href="https://www.erlang-factory.com/" target="_blank">conference website</a>.</p>
<p>Among other topics, speakers will present, evaluate and illustrate with case studies tools and frameworks such as the ChicagoBoss web framework, the Disco MapReduce project, the distributed Riak database, the Elixir programming language running on top of the ErlangVM, the Erlang mode on the IntelliJ editor, and QuickCheck -the property based testing tool.</p>
<p>In short, the Erlang User Conference will be the best place in Europe to learn more about Erlang and its use cases and get to know everything about the latest projects and innovations in the world of Erlang from leading Erlang experts.</p>
<p>You can take advantage of a 25% discount when you register on the <a href="http://www.erlang-factory.com/conference/ErlangUserConference2013" target="_blank">website</a> using the discount code TRIFORK. I hope to see you there!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.trifork.com/2013/05/17/the-erlang-user-conference-2013-building-massively-scalable-fault-tolerant-systems/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Eventual Consistency</title>
		<link>http://blog.trifork.com/2013/05/16/eventual-consistency/</link>
		<comments>http://blog.trifork.com/2013/05/16/eventual-consistency/#comments</comments>
		<pubDate>Thu, 16 May 2013 07:16:58 +0000</pubDate>
		<dc:creator>Rune Skou Larsen</dc:creator>
				<category><![CDATA[Custom Development]]></category>
		<category><![CDATA[NoSQL]]></category>

		<guid isPermaLink="false">http://blog.trifork.com/?p=7968</guid>
		<description><![CDATA[Once in a while, an idea emerges that is contrary to the way we have grown accustomed to doing things. Eventual consistency is such an idea, and the way we used to build datastores was with SQL and ACID transactions. So whats wrong with that? Too many generals Information always flows as messages using a [...]]]></description>
				<content:encoded><![CDATA[<p>Once in a while, an idea emerges that is contrary to the way we have grown accustomed to doing things. Eventual consistency is such an idea, and the way we used to build datastores was with SQL and ACID transactions.</p>
<p>So whats wrong with that?</p>
<h2>Too many generals</h2>
<p dir="ltr">Information always flows as messages using a medium - not transactions. Atomic transactions spanning multiple systems is an abstraction that doesn’t really exist in real life. It’s impossible to guarantee the atomicity of a distributed transaction as proved by the <a href="http://en.wikipedia.org/wiki/Two_Generals%27_Problem">Two_Generals%27_Problem</a>. The more generals - or partitions of a distributed system - the worse the problem. Not knowing the entire truth, is thus a fact of life that each partition must deal with, and therefore we need to ensure that the knowledge of all partitions converges when they send messages to eachother. This is eventual consistency.</p>
<h2>Eventual Consistency in Real Life</h2>
<p>Finance has always embraced eventual consistency. Money transfer is - contrary to popular belief - not done by transactions, but is an elaborate process where the money is first withdrawn from one account and after some time deposited at another account. Meanwhile the system is inconsistent for the outside observer, due to money being “in movement”. When the money arrives, eventually, the system will again be consistent.</p>
<p><span style="font-size: 13px; line-height: 19px;">If I send a cheque by mail when I have enough money on my account, but it turns out I have insufficient funds, when the receiver tries to cash it, a conflict arises due to balance information being slow and inconsistent. The entire system still manages because we have processes for resolving conflicts. In this case the cheque bounces.</span></p>
<p><span style="font-size: 13px; line-height: 19px;">It turns out, that in all cases of distributed updates to an object predating computerisation, eventual consistency is the norm, and conflict resolution processes exist. Medical records is another example where information from many sources about the same patient arrive out of order and is eventually reconciled.</span></p>
<p>Early computerisation changed this by building monolithic systems to model the truth about something - and when the system was not available, users had to wait or go back to the old and robust processes without computers.</p>
<h2>Physical limitations</h2>
<p dir="ltr">Consider the physics of sending information. Disregarding exotic theories involving multiple timelines, information cannot move faster than light. This would lead to a paradox, where you could make a phone call into the past with a so-called <a href="http://en.wikipedia.org/wiki/Tachyonic_antitelephone">Tachyonic_antitelephone</a>.</p>
<p><span style="font-size: 13px; line-height: 19px;">In the globally connected world, location and travel of information imposes very real limitations on the availability of up-to-date data. Connections drop, systems go down, sometimes entire data centers go offline for extended periods of times, and come back up using a restored, old version of data. When building highly distributed systems, these limitations cannot be sanely abstracted away in underlying distributed databases. The ugly head of reality will either cause distributed transactions to crumble write availability, or make cracks in the flawed illusion that all users always see up-to-date data.</span></p>
<p dir="ltr"><strong>Dealing with eventual consistency</strong></p>
<p dir="ltr">It is the gut instinct of every programmer to avoid complexity by abstraction. Since the old abstractions of transactions and a perfectly up-to-date database don’t scale to distributed systems with high write availability, we need eventual consistency as theoretical basis and new abstractions and techniques for handling it. Luckily this has been the subject of academia for decades, and recently the NoSQL movement has pioneered numerous small and large-scale eventually consistency systems drawing many real-life experiences, which will be the topic of my next blog entry.</p>
<address><span style="font-size: 13px; line-height: 19px;">Rune Skou Larsen</span></address>
<address>NoSQL evangelist @Trifork</address>
]]></content:encoded>
			<wfw:commentRss>http://blog.trifork.com/2013/05/16/eventual-consistency/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Happy life with Legacy Systems</title>
		<link>http://blog.trifork.com/2013/05/14/happy-life-with-legacy-systems/</link>
		<comments>http://blog.trifork.com/2013/05/14/happy-life-with-legacy-systems/#comments</comments>
		<pubDate>Tue, 14 May 2013 10:00:32 +0000</pubDate>
		<dc:creator>Sven Johann</dc:creator>
				<category><![CDATA[Custom Development]]></category>

		<guid isPermaLink="false">http://blog.trifork.com/?p=7946</guid>
		<description><![CDATA[I want to give you a little introduction to my latest InfoQ article on Technical Debt, which I wrote together with my former colleague Eberhard Wolff. We work with new, small and cool systems, but also with large and old systems (= these systems were really valuable over many many years!). Large means 50 to [...]]]></description>
				<content:encoded><![CDATA[<p dir="ltr">I want to give you a little introduction to my latest <a href="http://www.infoq.com/articles/managing-technical-debt">InfoQ article</a> on Technical Debt, which I wrote together with my former colleague Eberhard Wolff. We work with new, small and cool systems, but also with large and old systems (= these systems were really valuable over many many years!). Large means 50 to 500 men years resulting in several millions lines of code (LoC) using hundreds of database tables. Old means, that some of these systems have been started in the last century and still use technologies like Visual Basic 6, EJB 2.x, Struts 1.x, PL/SQL or XDoclet, and are connected to COBOL-based systems, just to name a few things which were cool 10-35 years ago, but are now seen as cruelties if you have to add features to such a system.<b><b> </b></b></p>
<p dir="ltr">These systems have also seen many developers come and go, developing good stuff and, especially under time pressure, bad stuff. All these systems have a reasonable amount of Technical Debt (which is unavoidable). While working on these systems, we found that the usual “Technical Debt is a disease” complaining strategy is neither helpful nor correct. Some architects deal very well with this problem, resulting in 10 year old systems, which are still in a really good shape. Other architects didn’t deal well with it, so the development of business-critical systems really slowed down, sometimes whole development organizations come to a stand-still. The problem is then, that you cannot throw away a 2 mio LoC business-critical system and develop it anew. That’s too expensive and too risky. You have to pay the interest of Technical Debt in terms of slow delivery of features. This shows, that not only developers suffer under Technical Debt, but also the business side, who waits for features a way too long. In fast paced environments, that can almost kill businesses!<b><b> </b></b></p>
<p dir="ltr">In our <a href="http://www.infoq.com/articles/managing-technical-debt">InfoQ article</a> we give you a nice overview what Technical Debt is really about. We found a surprisingly long list of of stakeholders - a software developer is only one of many. After explaining various ways how to identify Technical Debt, we head to the most important part: how to effectively deal with it. We give practical advice by debating the pros and cons of various successful strategies. Finally, we show when it could be useful to just pay the interest, to do debt conversion or to pay back the debt. We think, if you deal with large and successful (=old) systems, you should have a look at the article and leave us and the community your thoughts for further discussion.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.trifork.com/2013/05/14/happy-life-with-legacy-systems/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>10,9,8, the countdown to Mars has started...</title>
		<link>http://blog.trifork.com/2013/04/22/1098-the-countdown-to-mars-has-started/</link>
		<comments>http://blog.trifork.com/2013/04/22/1098-the-countdown-to-mars-has-started/#comments</comments>
		<pubDate>Mon, 22 Apr 2013 16:48:09 +0000</pubDate>
		<dc:creator>Byron Voorbach</dc:creator>
				<category><![CDATA[Big Data & Search]]></category>
		<category><![CDATA[Custom Development]]></category>
		<category><![CDATA[MongoDB]]></category>

		<guid isPermaLink="false">http://blog.trifork.com/?p=7928</guid>
		<description><![CDATA[A big congratulations to one of our customers Mars One who this afternoon announced the start of their astronaut selection program at a press conference in New York. For those of you who have not heard heard of them, Mars One is a not-for-profit organization that will establish a permanent human settlement on Mars in 2023 [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://blog.trifork.com/2013/04/22/1098-the-countdown-to-mars-has-started/logo_marsone/" rel="attachment wp-att-7932"><img class="size-full wp-image-7932 alignleft" alt="logo_marsone" src="http://blog.trifork.com/wp-content/uploads/2013/04/logo_marsone.png" width="218" height="61" /></a>A big congratulations to one of our customers <a href="http://applicants.mars-one.com/" target="_blank">Mars One</a> who this afternoon announced the start of their astronaut selection program at a press conference in New York.</p>
<p>For those of you who have not heard heard of them, Mars One is a not-for-profit organization that will establish a permanent human settlement on Mars in 2023 through the integration of existing, readily available technologies from industry leaders world-wide. Unique in its approach, Mars One intends to fund this decade-long endeavor by involving the whole world as the audience of an interactive, televised broadcast of every aspect of this mission, from launch to landing to living on Mars.</p>
<p>Over the last few months Trifork has been working together with the team at Mars One to build a global platform that will support <strong>Astronaut Selection Program</strong>. A scalable site has been developed which expects applications from hundreds, perhaps thousands more likely even millions of applicants in the coming months from all across the world.</p>
<p>Using the services from SoftLayer, MongoDB, Bits on the Run and a lot of other cool technologies and services, we've been able to create a very robust website which will make everyone across the world  able to participate in this great journey.</p>
<p>You can watch the press conference on Youtube: <a title="Watch the press conference" href="http://www.youtube.com/watch?v=WJNGH4NZJ4U">http://www.youtube.com/watch?v=WJNGH4NZJ4U</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.trifork.com/2013/04/22/1098-the-countdown-to-mars-has-started/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ansible - Simple module</title>
		<link>http://blog.trifork.com/2013/04/18/ansible-simple-module/</link>
		<comments>http://blog.trifork.com/2013/04/18/ansible-simple-module/#comments</comments>
		<pubDate>Thu, 18 Apr 2013 13:27:54 +0000</pubDate>
		<dc:creator>Mohamed El Moussaoui</dc:creator>
				<category><![CDATA[Custom Development]]></category>
		<category><![CDATA[System Administration]]></category>
		<category><![CDATA[ansible]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Configuration Management]]></category>

		<guid isPermaLink="false">http://blog.trifork.com/?p=7854</guid>
		<description><![CDATA[In this post, we'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 [...]]]></description>
				<content:encoded><![CDATA[<p>In this post, we'll review Ansible module development.<br />
I haven chosen to make a maven module; not very fancy, but it provides a good support for the subject.<br />
This module will execute a maven phase for a project (a pom.xml is designated).<br />
You can always refer to the Ansible <a href="http://ansible.cc/docs/moduledev.html">Module Development</a> page.</p>
<h2>Which language?</h2>
<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 />
We will be using bash.</p>
<h2>Module input</h2>
<p>The maven module needs two parameters, the phase and the pom.xml location (pom).<br />
For non-Python modules, Ansible provides the parameters in a file (first parameter) with the following format:<br />
<b>pom=/home/mohamed/myproject/pom.xml phase=test</b></p>
<p>You then need to read this file and extract the parameters.</p>
<p>In bash you can do that in two ways:<br />
<b>source $1</b></p>
<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>
<p>You can also parse the file using sed (or any way you like):<br />
<b>eval $(sed -e "s/<span class='MathJax_Preview'>\([a-z]*\)</span>=<span class='MathJax_Preview'>\([a-zA-Z0-9\/\.]*\)</span>/\1='\2'/g" $1)</b><br />
This is good enough for this exercise.</p>
<p>We now have two variables (pom and phase) with the expected values.<br />
We can continue and execute the maven phase for the given project (pom.xml).</p>
<h2>Module processing</h2>
<p>Basically, we can check if the parameters have been provided and then execute the maven command:</p>
<p><b><br />
#!/bin/bash</p>
<p>eval $(sed -e "s/<span class='MathJax_Preview'>\([a-z]*\)</span>=<span class='MathJax_Preview'>\([a-zA-Z0-9\/\.]*\)</span>/\1='\2'/g" $1)</p>
<p>if [ -z "${pom}" ] || [ -z "${phase}" ]; then<br />
echo 'failed=True msg="Module needs pom file (pom) and phase name (phase)"'<br />
exit 0;<br />
fi</p>
<p>maven-output=$(mktemp /tmp/ansible-maven.XXX)<br />
mvn ${phase} -f ${pom} &gt; $maven-output 2&gt;&amp;1<br />
if [ $? -ne 0 ]; then<br />
echo "failed=True msg=\"Failed to execute maven ${phase} with ${pom}\""<br />
exit 0<br />
fi</p>
<p>echo "changed=True"<br />
exit 0<br />
</b></p>
<p>In order to communicate the result, the module needs to return JSON.<br />
To simplify the JSON outputing step, Ansible allows to use key=value as output.</p>
<h2>Module output</h2>
<p>You noticed that an output is always returned. If an error happened, failed=True is returned as well as an error message.<br />
If everything went fine, changed=True is returned (or changed=False).</p>
<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>
<p>In some situations, your module doesn't do anything (no action is needed). In that case you'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>
<h2>Use it</h2>
<p>You can run your module with the following command:<br />
<b><br />
ansible buildservers -m maven -M /home/mohamed/ansible/mymodules/ --args="pom=/home/mohamed/myproject/pom.xml phase=test" -u mohamed -k<br />
</b><br />
If it goes well, you get something like the following output:<br />
<b><br />
localhost | success &gt;&gt; {<br />
"changed": true<br />
}<br />
</b></p>
<p>Otherwise:<br />
<b><br />
localhost | FAILED &gt;&gt; {<br />
"failed": true,<br />
"msg": "Failed to execute maven test with /home/mohamed/myproject/pom.xml"<br />
}<br />
</b></p>
<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 />
It 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>
<p><b>Conclusion</b></p>
<p>Module development is as easy as what we briefly saw here, and in any language. That's another point I wanted to make and that makes Ansible very nice to use.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.trifork.com/2013/04/18/ansible-simple-module/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fun combining Java, JavaScript and elastic.js within the elasticshell</title>
		<link>http://blog.trifork.com/2013/04/11/fun-combining-java-javascript-and-elastic-js-within-the-elasticshell/</link>
		<comments>http://blog.trifork.com/2013/04/11/fun-combining-java-javascript-and-elastic-js-within-the-elasticshell/#comments</comments>
		<pubDate>Thu, 11 Apr 2013 09:46:17 +0000</pubDate>
		<dc:creator>Luca Cavanna</dc:creator>
				<category><![CDATA[Custom Development]]></category>
		<category><![CDATA[Elasticsearch]]></category>
		<category><![CDATA[elastic.js]]></category>
		<category><![CDATA[elasticsearch]]></category>
		<category><![CDATA[elasticshell]]></category>

		<guid isPermaLink="false">http://blog.trifork.com/?p=7780</guid>
		<description><![CDATA[I recently wrote a couple of articles about the elasticshell, the command line shell for Elasticsearch that I created. If you haven't heard about it, it's a json friendly command line tool that allows to quickly interact with Elasticsearch: you can easily index documents, execute queries and make use of all the API that Elasticsearch [...]]]></description>
				<content:encoded><![CDATA[<p><a style="float: right;" href="http://github.com/javanna/elasticshell"><img src="http://blog.trifork.com/wp-content/uploads/2013/03/logo-elasticshell-150x150.png" alt="elasticshell" width="150" height="150" class="alignright size-full wp-image-7922" /></a><br />
I recently wrote a <a href="http://blog.trifork.com/2013/03/06/introducing-the-elasticshell/">couple</a> of <a href="http://blog.trifork.com/2013/03/07/searching-with-the-elasticshell/">articles</a> about the <a href="https://github.com/javanna/elasticshell">elasticshell</a>, the command line shell for <a href="http://www.elasticsearch.org/">Elasticsearch</a> that I created. If you haven't heard about it, it's a json friendly command line tool that allows to quickly interact with Elasticsearch: you can easily index documents, execute queries and make use of all the API that Elasticsearch provides. It allows for more advanced usecases as well, since it exposes the power and flexibility of both JavaScript and Java. That's scary, isn't it? Let's see what this means...<br />
<span id="more-7780"></span></p>
<p>If you have a bit of experience with Elasticsearch you know how cool its <a href="http://www.elasticsearch.org/guide/reference/query-dsl/">query DSL</a> is. You might also have realized that even though you start with simple queries, you most likely end up with big json objects containing different nested queries, filters, facets, highlighting and so on. That's why I thought the elasticshell should make it easier to compose queries and execute them. I wasn't totally satisfied about how you could do it using the first <a href="http://dl.bintray.com/content/javanna/elasticsearch-tools/release/org/elasticsearch/elasticshell/0.20.5-BETA/elasticshell-0.20.5-BETA.zip?direct">BETA release</a>, since it used to require some knowledge of the <a href="http://www.elasticsearch.org/guide/reference/java-api/">Elasticsearch Java API</a> in order to build queries without having to manually write plain json objects. That's why I worked on a couple of nice new features that are going to help a lot when it comes to querying Elasticsearch.</p>
<p><strong>The <code>toJson</code> command</strong><br />
A cool addition is the <code>toJson</code> command, that allows to create a json object not only from a string, but directly from a <code><a href="http://www.elasticsearch.org/guide/reference/java-api/query-dsl-queries/">QueryBuilder</a></code> object too (and more). I'm talking about Java objects here, instances of classes that are part of Elasticsearch itself, which we can convert to native json in a single call. Let's see how this feature makes it easier to combine plain json queries with the ones generated through the Java API. Let's start copy pasting a multi match query taken from the <a href="http://www.elasticsearch.org/guide/reference/query-dsl/multi-match-query/">Elasticsearch documentation</a> and adapting it to our needs obtaining the following result:</p>
<pre class="brush: jscript; gutter: false; title: ; notranslate">
{
  &quot;query&quot;: {
    &quot;multi_match&quot;: {
      &quot;query&quot;: &quot;elasticshell&quot;,
        &quot;fields&quot;: [
          &quot;title^2&quot;,
          &quot;content&quot;
        ]
      }
  }
}
</pre>
<p>After that we want to add a facet to the existing query, but we don't remember exactly the right json syntax. The <a href="http://www.elasticsearch.org/guide/reference/java-api/facets/">FacetBuilders</a> object provided with the Java API comes to the rescue, together with the available auto-suggestions:</p>
<pre class="brush: jscript; gutter: false; title: ; notranslate">
&gt; var facetBuilder = FacetBuilders.termsFacet('author').field('author');
</pre>
<p>If we now print the created object we do see some json, but that's still a java object and we only see its string representation (literally the output of its <code>toString</code> method). We can now parse it as a json like this:</p>
<pre class="brush: jscript; gutter: false; title: ; notranslate">
&gt; var facet=toJson(facetBuilder);
</pre>
<p>What we obtained is a json object that we can combine with the existing search request like this:</p>
<pre class="brush: jscript; gutter: false; title: ; notranslate">
&gt; search.facets=facet
</pre>
<p>Let's check what happened in our search object:</p>
<pre class="brush: jscript; gutter: false; title: ; notranslate">
&gt; search
{
  &quot;query&quot;: {
    &quot;multi_match&quot;: {
      &quot;query&quot;: &quot;elasticshell&quot;,
      &quot;fields&quot;: [
        &quot;title^2&quot;,
        &quot;content&quot;
      ]
    }
  },
  &quot;facets&quot;: {
    &quot;author&quot;: {
      &quot;terms&quot;: {
        &quot;field&quot;: &quot;author&quot;,
        &quot;size&quot;: 10
      }
    }
  }
}
</pre>
<p>What's the trick? The Elasticsearch classes whose content can be represented as json usually implement the internal <code><a href="https://github.com/elasticsearch/elasticsearch/blob/master/src/main/java/org/elasticsearch/common/xcontent/ToXContent.java">ToXContent</a></code> interface. The <code>toJson</code> command just accepts <code>ToXContent</code> objects as argument and it's able to convert them to json objects, native within the shell.</p>
<p><strong>The best is yet to come</strong><br />
The <code>toJson</code> command helps but I thought it's not enough. Some knowledge about the Java API is still required, and there are other ways to interact with Elasticsearch. What if you don't know the Java API? Maybe you know the widely used JavaScript API, also known as <a href="http://www.fullscale.co/elasticjs/">elastic.js</a>? You can just download it and load it using the <code>load</code> command, providing the location where the library is located on disk:</p>
<pre class="brush: jscript; gutter: false; title: ; notranslate">
&gt; load('/home/luca/Desktop/elastic.js');
</pre>
<p>Here it is, let's now type <code>ejs.</code>, the namespace that elastic.js uses, followed by the tab key to see what the suggestions look like:</p>
<pre class="brush: jscript; gutter: false; title: ; notranslate">
&gt; ejs.
AndFilter()                 BoolFilter()
BoolQuery()                 BoostingQuery()
CommonTermsQuery()          ConstantScoreQuery()
CustomBoostFactorQuery()    CustomFiltersScoreQuery()
CustomScoreQuery()          DateHistogramFacet()
DisMaxQuery()               Document()
ExistsFilter()              FieldMaskingSpanQuery()
FieldQuery()                FilteredQuery()
FilterFacet()               FuzzyLikeThisFieldQuery()
FuzzyLikeThisQuery()        FuzzyQuery()
GeoBboxFilter()             GeoDistanceFacet()
GeoDistanceFilter()         GeoDistanceRangeFilter()
GeoPoint()                  GeoPolygonFilter()
GeoShapeFilter()            GeoShapeQuery()
HasChildFilter()            HasChildQuery()
HasParentFilter()           HasParentQuery()
</pre>
<p>Wow, that means we can start creating queries using <a href="http://docs.fullscale.co/elasticjs/">elastic.js</a>. Let's initialize a new search request and add a simple <a href="http://www.elasticsearch.org/guide/reference/query-dsl/term-query/">term query</a> to it.</p>
<pre class="brush: jscript; gutter: false; title: ; notranslate">
&gt; var req=ejs.Request();
&gt; req.query(ejs.TermQuery('title','elasticshell'));
</pre>
<p>Once our query is ready to go, we only need to send it to Elasticsearch. We can use the internal <code>_self</code> function to read the underlying query json object and send it to elasticsearch as we normally do within the elasticshell:</p>
<pre class="brush: jscript; gutter: false; title: ; notranslate">
&gt; es.search(req._self());
</pre>
<p><strong>Load anything you need, at startup too</strong><br />
What's really cool about the <code>load</code> command is that it allows to load any external javascript code. That means it's possible to load custom scripts that contain documents, queries, or even functions that we frequently use within the elasticshell. It's also possible to execute arbitrary commands at startup adding the <code>.elasticshellrc.js</code> file to the user home directory. Those commands don't necessarily need to be javascript, they can be whatever command that's valid within the elasticshell, even Java code!</p>
<p><strong>Let's wrap it up</strong><br />
In this article I showed you some creative ways to compose and run Elasticsearch queries using the elasticshell. You can either use the <code>toJson</code> command to combine the Java API with plain json queries, or the great elastic.js library if you're not a Java guy. The described features are available in the <a href="http://dl.bintray.com/content/javanna/elasticsearch-tools/release/org/elasticsearch/elasticshell/0.90.0.RC2/elasticshell-0.90.0.RC2.zip?direct">latest</a> elasticshell release: there are three active development branches at the moment that contain the same features but work with a different version of Elasticsearch: <a href="http://dl.bintray.com/content/javanna/elasticsearch-tools/release/org/elasticsearch/elasticshell/0.19.12-RC/elasticshell-0.19.12-RC.zip?direct">0.19</a>, <a href="http://dl.bintray.com/content/javanna/elasticsearch-tools/release/org/elasticsearch/elasticshell/0.20.6-RC/elasticshell-0.20.6-RC.zip?direct">0.20</a> and the brand new <a href="https://bintray.com/version/show/general/javanna/elasticsearch-tools/elasticshell/0.90.0.RC2">0.90</a>. If you have any questions feel free to get in touch with me and it would also be great to know how you progress with its use too.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.trifork.com/2013/04/11/fun-combining-java-javascript-and-elastic-js-within-the-elasticshell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ansible - Example playbook to setup Jenkins slave</title>
		<link>http://blog.trifork.com/2013/04/02/ansible-example-playbook-to-setup-jenkins-slave/</link>
		<comments>http://blog.trifork.com/2013/04/02/ansible-example-playbook-to-setup-jenkins-slave/#comments</comments>
		<pubDate>Tue, 02 Apr 2013 12:20:37 +0000</pubDate>
		<dc:creator>Mohamed El Moussaoui</dc:creator>
				<category><![CDATA[Custom Development]]></category>
		<category><![CDATA[System Administration]]></category>
		<category><![CDATA[ansible]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Configuration Management]]></category>
		<category><![CDATA[jenkins]]></category>
		<category><![CDATA[playbook]]></category>

		<guid isPermaLink="false">http://blog.trifork.com/?p=7656</guid>
		<description><![CDATA[As mentioned in my previous post about Ansible, we will now proceed with writing an Ansible playbook. Playbooks are files containing instructions that can be processed by Ansible, they are written in yaml. For this blog post I will show you how to create a playbook that will setup a remote computer as a Jenkins [...]]]></description>
				<content:encoded><![CDATA[<p>As mentioned in my <a href="http://blog.trifork.com/2013/03/26/ansible-next-generation-configuration-management/">previous post about Ansible</a>, we will now proceed with writing an Ansible playbook. Playbooks are files containing instructions that can be processed by Ansible, they are written in <a href="http://www.yaml.org">yaml</a>. For this blog post I will show you how to create a playbook that will setup a remote computer as a Jenkins slave.</p>
<h2>What do we need?</h2>
<p>We need some components to get a computer execute Jenkins jobs:</p>
<ul>
<li>JVM 7</li>
<li>A dedicated user that will run the Jenkins agent</li>
<li>Subversion</li>
<li>Maven (with our configuation)</li>
<li>Jenkins <a href="https://wiki.jenkins-ci.org/display/JENKINS/Swarm+Plugin" target="_blank">Swarm Plugin and Client</a></li>
</ul>
<h2>Why Jenkins Swarm Plugin</h2>
<p>We use the Swarm Plugin, because it allows a slave to auto-discover a master and join it automatically. We hence don't need any actions on the master.</p>
<h2>JDK7</h2>
<p>We now proceed with adding the JDK7 installation task. We will not use any package version (for example dedicate Ubuntu PPA or RedHat/Fedora repos), we will use the JDK7 archive from oracle.com.<br />
There multiple steps required:</p>
<p>* We need wget to be install. This is needed to download the JDK<br />
* To download the JDK you need to accept terms, we can't do that in a batch run so we need to wrap a wget call in a shell script to send extra HTTP headers<br />
* Set the platform wide JDK links (java and jar executable)</p>
<h3>Install wget</h3>
<p>We want to verify that wget is installed on the remote computer and if not install it from the distribution repos. To install packages, there are modules available, <a href="http://ansible.cc/docs/modules.html#apt">yum</a> and <a href="http://ansible.cc/docs/modules.html#apt">apt</a> (There are others but we will focus on these).<br />
To be able to run the correct task depending on the ansible_pkg_mgr value we can use only_id:</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Install wget package (Debian based)
    action: apt pkg='wget' state=installed
    only_if: &quot;'$ansible_pkg_mgr' == 'apt'&quot;

  - name: Install wget package (RedHat based)
    action: yum name='wget' state=installed
    only_if: &quot;'$ansible_pkg_mgr' == 'yum'&quot;
</pre>
<h3>Download JDK7</h3>
<p>To download JDK7 from oracle.com, we need to accept the terms but we can't do that in a batch, so we need to skip that:</p>
<p>Create a script contains the wget call:</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash

wget --no-cookies --header &quot;Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com&quot; http://download.oracle.com/otn-pub/java/jdk/7/$1 -O $1
</pre>
<p>The parameter is the archive name.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Copy download JDK7 script
    copy: src=files/download-jdk7.sh dest=/tmp mode=0555

  - name: Download JDK7 (Ubuntu)
    action: command creates=${jvm_folder}/jdk1.7.0 chdir=${jvm_folder} /tmp/download-jdk7.sh $jdk_archive
</pre>
<p>These two tasks copy the script to /tmp and then execute it. $jdk_archive is a variable containing the archive name, it can be different depending on the distribution and the architecture.</p>
<p>Ansible provide a way to load variable files:</p>
<pre class="brush: bash; title: ; notranslate">
  vars_files:

    - [ &quot;vars/defaults.yml&quot; ]
    - [ &quot;vars/$ansible_distribution-$ansible_architecture.yml&quot;, &quot;vars/$ansible_distribution.yml&quot; ]
</pre>
<p>This will load the file vars/defauts.yml (Note that all these file are written in <a href="http://www.yaml.org/">yaml</a>) and then look for the file vars/$ansible_distribution-$ansible_architecture.yml.<br />
The variables are replaced by the their value on the remote computer voor example on an Ubuntu 32bits on i386 distribution, Ansible will look for the file vars/Ubuntu-i386.yml. If it doesn't find it, it will fallback to vars/Ubuntu.yml.</p>
<p>Examples, Ubuntu-i386.yml would contain:</p>
<pre class="brush: bash; title: ; notranslate">
---
jdk_archive: jdk-7-linux-i586.tar.gz
</pre>
<p>Fedora-i686.yml would contain:</p>
<pre class="brush: bash; title: ; notranslate">
---
jdk_archive: jdk-7-linux-i586.rpm
</pre>
<h3>Unpack/Install JDK</h3>
<p>You notice that for Ubuntu we use the tar.gz archive but for Fedora we use an rpm archive. That means the the installation of the JDK will be different depending on the distribution.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Unpack JDK7
    action: command creates=${jvm_folder}/jdk1.7.0 chdir=${jvm_folder} tar zxvf ${jvm_folder}/$jdk_archive --owner=root
    register: jdk_installed
    only_if: &quot;'$ansible_pkg_mgr' == 'apt'&quot;

  - name: Install JDK7 RPM package
    action: command creates=${jvm_folder}/latest chdir=${jvm_folder} rpm --force -Uvh ${jvm_folder}/$jdk_archive
    register: jdk_installed
    only_if: &quot;'$ansible_pkg_mgr' == 'yum'&quot;
</pre>
<p>On ubuntu, we just unpack the downloaded archive but for fedora we install it using rpm.<br />
You might want to review the condition (only_if) particularly if you use SuSE.<br />
jvm_folder is just an extra variable that can be global of per distribution, you need to place if in a vars file.<br />
Note that the <a href="http://ansible.cc/docs/modules.html#command">command</a> module take a 'creates' parameter. It is useful if you don't want to rerun the command, the module that the file or directory provided via this parameter exits, if it does it will skip that task.<br />
In this task, we use register. With register you can store the result of a task into a variable (in this case we called it jdk_installed).</p>
<h3>Set links</h3>
<p>To be able to make the java and jar executables accessible to anybody (particularly our jenkins user) from anywhere, we set symbolic links (actually we just install an alternative).</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Set java link
    action: command update-alternatives --install /usr/bin/java java ${jvm_folder}/jdk1.7.0/bin/java 1
    only_if: '${jdk_installed.changed}'

  - name: Set jar link
    action: command update-alternatives --install /usr/bin/jar jar ${jvm_folder}/jdk1.7.0/bin/jar 1
    only_if: '${jdk_installed.changed}'
</pre>
<p>Here we reuse the stored register, jdk_installed. We can access the changed attribute, if the unpacking/installation of the JDK did do something then changed will be true and the update-alternatives command will be ran.</p>
<h3>Cleanup</h3>
<p>To keep things clean, you can remove the downloaded archive using the <a href="http://ansible.cc/docs/modules.html#file">file</a> module.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Remove JDK7 archive
    file: path=${jvm_folder}/$jdk_archive state=absent
</pre>
<p>We are done with the JDK.</p>
<p>Obviously you might want to reuse this process in other playbooks. Ansible let you do that.<br />
Just create a file with all this task and include it in a playbook.</p>
<pre class="brush: bash; title: ; notranslate">
- include: tasks/jdk7-tasks.yml jvm_folder=${jvm_folder} jdk_archive=${jdk_archive}
</pre>
<h2>jenkins user</h2>
<h3>Creation</h3>
<p>With the <a href="http://ansible.cc/docs/modules.html#name">name</a> module, the can easily handle users.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Create jenkins user
    user: name=jenkins comment=&quot;Jenkins slave user&quot; home=${jenkins_home} shell=/bin/bash
</pre>
<p>The variable jenkins_home can be defined in one of the vars files.</p>
<h3>Password less from Jenkins master</h3>
<p>We first create the .ssh in the jenkins home directory with the correct rights. And then with the <a href="http://ansible.cc/docs/modules.html#authorized_key">authorized_key</a> module, we can add the public of the jenkins user on the jenkins master to the authorized keys of the jenkins user (on the new slave). And then we verify that the new authorized_keys file has the correct rights.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Create .ssh folder
    file: path=${jenkins_home}/.ssh state=directory mode=0700 owner=jenkins

  - name: Add passwordless connection for jenkins
    authorized_key: user=jenkins key=&quot;xxxxxxxxxxxxxx jenkins@master&quot;

  - name: Update authorized_keys rights
    file: path=${jenkins_home}/.ssh/authorized_keys state=file mode=0600 owner=jenkins
</pre>
<p>If you want jenkins to execute any command as sudo without the need of providing a password (basically updating /etc/sudoers), the module <a href="http://ansible.cc/docs/modules.html#lineinfile">lineinfile</a> can do that for you.<br />
That module checks 'regexp' against 'dest', if it matches it doesn't do anything if not, it adds 'line' to 'dest'.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Tomcat can run any command with no password
    lineinfile: &quot;line='tomcat ALL=NOPASSWD: ALL' dest=/etc/sudoers regexp='^tomcat'&quot;
</pre>
<h2>Subversion</h2>
<p>This one is straight forward.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Install subversion package (Debian based)
    action: apt pkg='subversion' state=installed
    only_if: &quot;'$ansible_pkg_mgr' == 'apt'&quot;

  - name: Install subversion package (RedHat based)
    action: yum name='subversion' state=installed
    only_if: &quot;'$ansible_pkg_mgr' == 'yum'&quot;
</pre>
<h2>Maven</h2>
<p>We will put maven under /opt so we first need to create that directory.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Create /opt directory
    file: path=/opt state=directory
</pre>
<p>We then download the maven3 archive, this time it is more simple, we can directly use the <a href="http://ansible.cc/docs/modules.html#get_url">get_url</a> module.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Download Maven3
    get_url: dest=/opt/maven3.tar.gz url=http://apache.proserve.nl/maven/maven-3/3.0.4/binaries/apache-maven-3.0.4-bin.tar.gz
</pre>
<p>We can then unpack the archive and create a symbolic link to the maven location.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Unpack Maven3
    action: command creates=/opt/maven chdir=/opt tar zxvf /opt/maven3.tar.gz

  - name: Create Maven3 directory link
    file: path=/opt/maven src=/opt/apache-maven-3.0.4 state=link
</pre>
<p>We use again update-alternatives to make mvn accessible platform wide.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Set mvn link
    action: command update-alternatives --install /usr/bin/mvn mvn /opt/maven/bin/mvn 1
</pre>
<p>We put in place out settings.xml by creating the .m2 directory on the remote computer and copying a settings.xml (we backup any already existing settings.xml).</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Create .m2 folder
    file: path=${jenkins_home}/.m2 state=directory owner=jenkins

  - name: Copy maven configuration
    copy: src=files/settings.xml dest=${jenkins_home}/.m2/ backup=yes
</pre>
<p>Clean things up.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Remove Maven3 archive
    file: path=/opt/maven3.tar.gz state=absent
</pre>
<h2>Swarm client</h2>
<p>You first need to install the Swarm plugin as mentioned <a href="https://wiki.jenkins-ci.org/display/JENKINS/Swarm+Plugin">here</a>.<br />
Then you can proceed with the client installation.</p>
<p>First create the jenkins slave working directory.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Create Jenkins slave directory
    file: path=${jenkins_home}/jenkins-slave state=directory owner=jenkins
</pre>
<p>Download the Swarm Client.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Download Jenkins Swarm Client
    get_url: dest=${jenkins_home}/swarm-client-1.8-jar-with-dependencies.jar url=http://maven.jenkins-ci.org/content/repositories/releases/org/jenkins-ci/plugins/swarm-client/1.8/swarm-client-1.8-jar-with-dependencies.jar owner=jenkins
</pre>
<p>When you start the swarm client, it will connect to the master and the master will automatically create a new node for it.<br />
There are a couple of parameters to start the client. You still need to provided a login/password in order to authenticate. You obviously want this information to be parameterizable.</p>
<p>First we need a script/configuration to start the swarm client at boot time (systemv, upstart or systemd it is up to you). In that script/configuration, you need to add the swarm client run command:</p>
<pre class="brush: bash; title: ; notranslate">
java -jar {{jenkins_home}}/swarm-client-1.8-jar-with-dependencies.jar -name {{jenkins_slave_name}} -password {{jenkins_password}} -username {{jenkins_username}} -fsroot {{jenkins_home}}/jenkins-slave -master https://jenkins.trifork.nl -disableSslVerification &amp;&gt; {{jenkins_home}}/swarm-client.log &amp;
</pre>
<p>Then using the <a href="http://ansible.cc/docs/modules.html#template">template</a> module, to process the script/configuration template (using <a href="http://jinja.pocoo.org/docs/">Jinja2</a>) into a file that will be put on a given location.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Install swarm client script
    template: src=templates/jenkins-swarm-client.tmpl dest=/etc/init.d/jenkins-swarm-client mode=0700
</pre>
<p>The file mode is 700 because we have a login/password in that file, we don't want people (that can log on the remote computer) to be able to see that.</p>
<p>Instead of putting jenkins_username and jenkins_password in vars files, you can prompt for them.</p>
<pre class="brush: bash; title: ; notranslate">
  vars_prompt:

    - name: jenkins_username
      prompt: &quot;What is your jenkins user?&quot;
      private: no
    - name: jenkins_password
      prompt: &quot;What is your jenkins password?&quot;
      private: yes
</pre>
<p>And then you can verify that they have been set.</p>
<pre class="brush: bash; title: ; notranslate">
  - fail: msg=&quot;Missing parameters!&quot;
    when_string: $jenkins_username == '' or $jenkins_password == ''
</pre>
<p>You can now start the swarm client using the <a href="http://ansible.cc/docs/modules.html#service">service</a> module and enable it to start at boot time.</p>
<pre class="brush: bash; title: ; notranslate">
  - name: Start Jenkins swarm client
    action: service name=jenkins-swarm-client state=started enabled=yes
</pre>
<h2>Run it!</h2>
<pre class="brush: bash; title: ; notranslate">
ansible-playbook jenkins.yml --extra-vars &quot;host=myhost user=myuser&quot; --ask-sudo-pass
</pre>
<p>By passing '--ask-sudo-pass', you tell Ansible that 'myuser' requires a password to be typed in order to be able to run the tasks in the playbook.<br />
'--extra-vars' will pass on a list of viriables to the playbook. The begining of the playbook will look like this:</p>
<pre class="brush: bash; title: ; notranslate">
---
 
- hosts: $host
  user: $user
  sudo: yes

</pre>
<p>'sudo: yes' tells Ansible to run all tasks as root but it acquires the privileges via sudo.<br />
You can also use 'sudo_user: admin', if you want Ansible to run the command to sudo to admin instead of root.<br />
Note that if you don't need facts, you can add 'gather_facts: no', this will spend up the playbook execution but that requires that you know everything you need about the remote computer.</p>
<h2>Conclusion</h2>
<p>The playbook is ready. You can now easily add new nodes for new Jenkins slaves thanks to Ansible.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.trifork.com/2013/04/02/ansible-example-playbook-to-setup-jenkins-slave/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Schedule GOTO Amsterdam 18-20 June is LIVE!</title>
		<link>http://blog.trifork.com/2013/03/29/schedule-goto-amsterdam-18-20-june-is-live/</link>
		<comments>http://blog.trifork.com/2013/03/29/schedule-goto-amsterdam-18-20-june-is-live/#comments</comments>
		<pubDate>Fri, 29 Mar 2013 10:15:41 +0000</pubDate>
		<dc:creator>Daphne Keislair</dc:creator>
				<category><![CDATA[Conference]]></category>
		<category><![CDATA[Custom Development]]></category>

		<guid isPermaLink="false">http://blog.trifork.com/?p=7698</guid>
		<description><![CDATA[Yes, the schedule is NOW live and available for you to indulge in. Our speaker line up includes Linda Rising, Martin Fowler, Erik Meijer, Brian LeRoux, David Crockford and many others... Time is ticking, only 2 weeks left for early bird rate Get your tickets NOW before April 12th and don't miss out on what we [...]]]></description>
				<content:encoded><![CDATA[<p>Yes, the schedule is <a href="http://gotocon.com/amsterdam-2013/schedule/index.jsp" target="_blank">NOW live</a> and available for you to <a href="http://gotocon.com/amsterdam-2013/schedule/index.jsp" target="_blank">i</a>ndulge in. Our speaker line up includes Linda Rising, Martin Fowler, Erik Meijer, Brian LeRoux, David Crockford and many others...</p>
<p><strong>Time is ticking, only 2 weeks left for early bird rate</strong></p>
<p>Get your<a href="https://secure.trifork.com/amsterdam-2013/registration/" target="_blank"> tickets NOW</a> before April 12th and don't miss out on what we expect to be one of the biggest and best GOTO Amsterdam conferences to date.</p>
<p><strong>Date in the diary; GOTO NIGHT on Thursday April 4th and Tuesday May 14th</strong></p>
<p><strong></strong><a href="http://gotocon.com/amsterdam-2013/upcomingevents/" target="_blank">Join us</a> at one of the FREE GOTO Nights coming up, more on the presentations on the <a href="http://gotocon.com/amsterdam-2013/upcomingevents/" target="_blank">website</a> and don't forget to reserve your seat.</p>
<p><a href="https://secure.trifork.com/amsterdam-2013/freeevent/index.jsp?eventOID=5331" target="_blank"><img class="size-full wp-image-7700 alignleft" alt="GOTO_night_Amsterdam_April_4" src="http://blog.trifork.com/wp-content/uploads/2013/03/GOTO_night_Amsterdam_April_4.png" width="660" height="250" /></a></p>
<p><a href="https://secure.trifork.com/amsterdam-2013/freeevent/index.jsp?eventOID=5335" target="_blank"><img class="size-full wp-image-7701 alignleft" style="margin-top: 10px;margin-bottom: 10px" alt="GOTO_night_Amsterdam3" src="http://blog.trifork.com/wp-content/uploads/2013/03/GOTO_night_Amsterdam3.png" width="660" height="250" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.trifork.com/2013/03/29/schedule-goto-amsterdam-18-20-june-is-live/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bash - A few commands to use again and again</title>
		<link>http://blog.trifork.com/2013/03/28/bash-a-few-commands-to-use-again-and-again/</link>
		<comments>http://blog.trifork.com/2013/03/28/bash-a-few-commands-to-use-again-and-again/#comments</comments>
		<pubDate>Thu, 28 Mar 2013 17:42:42 +0000</pubDate>
		<dc:creator>Frank Scholten</dc:creator>
				<category><![CDATA[Custom Development]]></category>
		<category><![CDATA[System Administration]]></category>
		<category><![CDATA[Bash]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Open Source]]></category>

		<guid isPermaLink="false">http://blog.trifork.com/?p=7453</guid>
		<description><![CDATA[Introduction These days I spend a lot of time in the bash shell. I use it for ad-hoc scripting or driving several Linux boxes. In my current project we set up a continuous delivery environment and migrate code onto it. I lift code from CVS to SVN, mavenize Ant builds and funnel artifacts into Nexus. [...]]]></description>
				<content:encoded><![CDATA[<p><b>Introduction</b></p>
<p>These days I spend a lot of time in the bash shell. I use it for ad-hoc scripting or driving several Linux boxes. In my current project we set up a <a href="http://en.wikipedia.org/wiki/Continuous_delivery">continuous delivery</a> environment and migrate code onto it. I lift code from CVS to SVN, mavenize Ant builds and funnel artifacts into Nexus. One script I wrote determines if a jar that was checked into a CVS source tree exists in Nexus or not. This check can be done via the <a href="http://www.sonatype.com/people/2012/07/learning-the-nexus-rest-api-read-the-docs-or-fire-up-a-browser/">Nexus REST API</a>. More on this script at the end of the blog. But first let's have a look at a few bash commands that I use all the time in day-to-day bash usage, in no particular order.</p>
<ol>
<li><b>find</b></li>
<p>Find searches files recursively in the current directory.</p>
<p><code>$ find -name *.jar</code></p>
<p>This command lists all jars in the current directory, recursively. We use this command to figure out if a source tree has jars. If this is the case we add them to Nexus and to the pom as part of the migration from Ant to Maven.</p>
<p><code>$ find -name *.jar -exec sha1sum {} \;</code></p>
<p>Find combined with exec is very powerful. This command lists the jars and computes sha1sum for each of them. The shasum command is put directly after the -exec flag. The {} will be replaced with the jar that is found. The \; is an escaped semicolon for find to figure out when the command ends.</p>
<li><b>for</b></li>
<p>For loops are often the basis of my shell scripts. I start with a for loop that just echoes some values to the terminal so I can check if it works and then go from there.</p>
<p><code><br />
$ for i in $(cat items.txt); do echo $i; done;<br />
</code></p>
<p>The for loop keywords should be followed by either a newline or an ';'. When the for loop is OK I will add more commands between the do and done blocks. Note that I could have also used find -exec but if I have a script that is more than a one-liner I prefer a for loop for readability.</p>
<li><b>tr</b></li>
<p>Transliterate. You can use this to get rid of certain characters or replace them, piecewise.</p>
<p>$ echo 'Com_Acme_Library' | tr '_A-Z' '.a-z'</p>
<p>Lowercases and replaces underscores with dots.</p>
<li><b>awk</b></li>
<p><code><br />
$ echo 'one two three' | awk '{ print $2, $3 }'<br />
</code></p>
<p>Prints the second and third column of the output. Awk is of course a full blown programming language but I tend to use this snippets like this a lot for selecting columns from the output of another command.</p>
<li><b>sed</b></li>
<p>Stream EDitor. A complete tool on its own, yet I use it mostly for small substitutions.</p>
<p><code><br />
$ cat 'foo bar baz' | sed -e 's/foo/quux/'<br />
</code></p>
<p>Replaces foo with quux.</p>
<li><b>xargs</b></li>
<p>Run a command on every line of input on standard in.</p>
<p><code><br />
$ cat jars.txt | xargs -n1 sha1sum<br />
</code></p>
<p>Run sha1sum on every line in the file. This is another for loop or find -exec alternative. I use this when I have a long pipeline of commands in a oneliner and want to process every line in the end result.</p>
<li><b>grep</b></li>
<p>Here are some grep features you might not know:</p>
<p><code>$ grep -A3 -B3 keyword data.txt</code></p>
<p>This will list the match of the keyword in data.txt including 3 lines after (-A3) and 3 lines before (-B3) the match.</p>
<p><code>$ grep -v keyword data.txt</code></p>
<p>Inverse match. Match everything except keyword.</p>
<li><b>sort</b></li>
<p>Sort is another command often used at the end of a pipeline. For numerical sorting use</p>
<p><code>$ sort -n</code></p>
<li><b>Reverse search (CTRL-R)</b></li>
<p>This one isn't a real command but it's really useful. Instead of typing history and looking up a previous command, press CTRL-R,<br />
start typing and have bash autocomplete your history. Use escape to quit reverse search mode. When you press CTRL-R your prompt will look like this:</p>
<p><code>(reverse-i-search)`': </code></p>
<li><b>!!</b></li>
<p>Pronounced 'bang-bang'. Repeats the previous command. Here is the cool thing:</p>
<p><code>$ !!:s/foo/bar</code></p>
<p>This repeats the previous command, but with foo replaced by bar. Useful if you entered a long command with a typo. Instead of manually replacing one of the arguments replace it this way.</p>
<p></o></p>
<p><b>Bash script - checking artifacts in Nexus</b></p>
<p>Below is the script I talked about. It loops over every jar and dll file in the current directory, calls Nexus via wget and optionally outputs a pom dependency snippet. It also adds a status column at the end of the output, either an OK or a KO, which makes the output easy to grep for further processing.</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash

ok=0
jars=0

for jar in $(find $(pwd) 2&amp;&gt;/dev/null -name '*.jar' -o -name '*.dll')
do
((jars+=1))

output=$(basename $jar)-pom.xml
sha1=$(sha1sum $jar | awk '{print $1}')

response=$(curl -s http://oss.sonatype.org/service/local/data_index?sha1=$sha1)

if [[ $response =~ groupId ]]; then
((ok+=1))
echo &quot;findjars $jar OK&quot;
echo &quot;&quot; &gt;&gt; &quot;$output&quot;
echo &quot;$response&quot; | grep groupId -A3 -m1 &gt;&gt; &quot;$output&quot;
echo &quot;&quot; &gt;&gt; &quot;$output&quot;
else
echo &quot;findjars $jar KO&quot;
fi

done

if [[ $jars &gt; 0 ]]; then
echo &quot;findjars Found $ok/$jars jars/dlls. See -pom.xml file for XML snippet&quot;
exit 1
fi
</pre>
<p><b>Conclusions</b></p>
<p>It is amazing what you can do in terms of scripting when you combine just these commands via pipes and redirection! It's like a <a href="http://en.wikipedia.org/wiki/Pareto_principle">Pareto's law</a> of shell scripting, 20% of the features of bash and related tools provide 80% of the results. The basis of most scripts can be a for loop. Inside the for loop the resulting data can be transliterated, grepped, replaced by sed and finally run through another program via xargs.</p>
<p><b>References</b></p>
<p><a href="http://bashcookbook.com/">The Bash Cookbook</a> is a great overview of how to solve solutions to common problems using bash. It also teaches good bash coding style.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.trifork.com/2013/03/28/bash-a-few-commands-to-use-again-and-again/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
