<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Alex Tomkins - ansible</title>
    <link>https://www.alextomkins.com/tag/ansible/</link>
    <atom:link href="https://www.alextomkins.com/tag/ansible/feed.xml" rel="self" type="application/rss+xml" />
    <description>Posts tagged with ansible</description>
    <language>en</language>
    
    
    <item>
      <title>RUNLEVEL=1 apt-get install package alternative</title>
      <link>https://www.alextomkins.com/2018/03/runlevel-apt-get-install-package-alternative/</link>
      <guid>https://www.alextomkins.com/2018/03/runlevel-apt-get-install-package-alternative/</guid>
      <pubDate>Sat, 31 Mar 2018 17:25:00 +0000</pubDate>
      <description><![CDATA[<p>An old documented way of preventing services from starting immediately after installation in
Debian/Ubuntu is using the <code>RUNLEVEL</code> environment variable to trick the runlevel helper into
returning a response that the system isn't fully running, such as:</p>
<pre><code># RUNLEVEL=1 apt-get install nginx</code></pre>
<p>Sadly this doesn't work in newer versions of Debian/Ubuntu, the official way is to use the policy
helper script <code>/usr/sbin/policy-rc.d</code> and return a 101 exit code. This is a a bit more
inconvenient - having to temporarily create this file only to remove it after installing the
package.</p>
<p>Fortunately there is an alternative - <code>policyrcd-script-zg2</code>. Install the package:</p>
<pre><code>$ sudo apt-get install policyrcd-script-zg2</code></pre>
<p>Create a new script which returns a 101 exit code, I've created it as
<code>/usr/local/sbin/policy-donotstart</code>:</p>
<pre><code>#!/bin/sh
exit 101</code></pre>
<p>Then make it executable:</p>
<pre><code>$ sudo chmod 755 /usr/local/sbin/policy-donotstart</code></pre>
<p>When installing packages where you don't want the service to immediately start, use the <code>POLICYRCD</code>
environment variable:</p>
<pre><code># POLICYRCD=/usr/local/sbin/policy-donotstart apt-get install nginx</code></pre>
<p>The service will install, but you'll a message similar to:</p>
<pre><code>invoke-rc.d: policy-rc.d denied execution of start.</code></pre>
<p>For Ansible, you can add environment variables to any task:</p>
<pre><code>- name: Install nsd
  apt: pkg=nsd install_recommends=no
  environment:
    POLICYRCD: /usr/local/sbin/policy-donotstart</code></pre>
<p>Now you can safely install a package, configure it, and then start it once you've got all the
correct files in place - all with a convenient environment variable.</p>
]]></description>
    </item>
    
    
    
    
    
    
    
    
    <item>
      <title>Automating Ansible groups with Vagrant</title>
      <link>https://www.alextomkins.com/2016/09/automating-ansible-groups-with-vagrant/</link>
      <guid>https://www.alextomkins.com/2016/09/automating-ansible-groups-with-vagrant/</guid>
      <pubDate>Sat, 10 Sep 2016 21:57:00 +0000</pubDate>
      <description><![CDATA[<p><a href="https://www.vagrantup.com/">Vagrant</a> is a great tool for creating development environments and
testing deployment scripts, especially with <a href="https://www.ansible.com/">Ansible</a>. Testing an Ansible
playbook is can be as simple as <code>vagrant up</code>.</p>
<h1>The problem</h1>
<p>Ansible uses an inventory file to define the SSH details for each server, what groups a server
belongs to - which then allows you to run certain roles/playbooks on specific servers. However the
two options with Vagrant in dealing with the inventory file are rather limited.</p>
<p>The first option is the auto generated inventory, Vagrant will create a fresh inventory file based
on the servers listed in the Vagrantfile which are currently up and running. This inventory file
gets populated with the correct SSH details, however it means it starts with an empty inventory
file which is only populated by setting <code>ansible.groups</code>.</p>
<p>The second option is the static inventory, which Vagrant will use instead of creating a dynamic
inventory file. The downside with this would be duplicating the existing hosts file just to edit
the SSH details, as well as hardcoding the IP addresses of all your Vagrant virtual machines.</p>
<h1>The solution</h1>
<p>We can use the <a href="https://github.com/aisrael/ansibler">ansibler</a> Ruby gem to read the hosts file to
automatically populate <code>ansible.groups</code>.</p>
<p>Installation is easy, as Vagrant maintains plugins separately from other Ruby libraries:</p>
<pre><code>$ vagrant plugin install ansibler
Installing the 'ansibler' plugin. This can take a few minutes...
Installed the plugin 'ansibler (0.2.2)'!
</code></pre>
<p>Now we need to update the Vagrantfile. First of all we're going to read the existing hosts file,
and populate the <code>ANSIBLE_GROUPS</code> variable with a hash of all the groups:</p>
<pre><code>inventory = Ansible::Inventory.read_file('hosts')

ANSIBLE_GROUPS = {}

inventory.groups.each do |group|
    ANSIBLE_GROUPS["#{group.name}"] = group.hosts.map{ |host| host.name }
end</code></pre>
<p>Next up is updating the Ansible provisioner config:</p>
<pre><code>config.vm.provision "ansible" do |ansible|
    # ...
    ansible.groups = ANSIBLE_GROUPS
end</code></pre>
<p>And that's it!</p>
<p>Now that <code>ansible.groups</code> contains an exact copy of all the group config from your hosts file,
every time Vagrant creates a new dynamic inventory file it'll be populated with all the group
configuration from your main hosts file.</p>
]]></description>
    </item>
    
    
    
    
    
    
    
    
    
    
    
    
    
  </channel>
</rss>
