0

We are setting up a cluster using Apache Ambari.

Our Chef run is interrupted by the need to use Ambari to provision the Hadoop cluster. Current installs are a three part process:

  1. Initial Chef run to prep OS.
  2. Use Ambari to configure (and later manage) Hadoop cluster.
  3. Post-Ambari configs using a second Chef run.

I searched similar questions, but answers all revolved around using resources that included guard attributes for conditionals. The second run uses a series of resources that do not accept guard attributes.

I've been working around this by using execute commands and "not_if"/"only_if" guards. Example:

%w{package1 package2 package3 package4}.each do |package|
  execute "Install #{package}" do
    command "yum install #{package}"
    user 'root'
    only_if { ::File.exists?("/etc/yum.repos.d/ambari.repo")}
  end
end

But this gets tedious to write for each resource. There has got to be a better way.

Is there a standard or "best" practice for executing all remaining code (or select resources) in a recipe if one conditional is met?

I thought about wrapping in a Ruby block and using notifies, but blocks seem declarative. I'm not sure how best to set them up to "do x if y, else nothing", or even if that's the right tool for the job?

ruby_block "Check for Ambari.repo" do
  block do
    File.exists?("/etc/yum.repos.d/ambari.repo")
  end
  notifies :run "execute[package]" :immediately
end

%w{package1 package2 package3 package4}.each do |package|
      execute "Install #{package}" do
        command "yum install #{package}"
        user 'root'
        action :nothing
      end
end
1
  • 1
    Why guard at all? yum_repository and package (action :install) are idempotent. (As a last resort, see "First-run Resources")
    – sr_
    Jun 24, 2014 at 7:32

2 Answers 2

0

You are asking for an if block so why not just use an if block?

if File.exists?("/etc/yum.repos.d/ambari.repo")
  %w{package1 package2}.each do |pkg|
    package pkg
  end

  ... do some other stuff here if you want...
end

The default action for package is install so you don't need the full block in this case.

0

CHEF is (by design) declarative, describing the target state. That said, a sequence of blocks as below should accomplish what you want to succeed...

# Ensure needed packages are installed
package %w{package1 package2 package3 package4} do
  action :install
  only_if { ::File.exists?("/etc/yum.repos.d/ambari.repo") }
end

# Conditional Block#1
if ( condition#1 )
  <some chef or ruby block>
end

# Conditional Block#2
if ( condition#2 )
  <some chef or ruby block>
end

If you explain more the rest of steps that you need, I will be able to give more specific guidance. e.g. run a conditional CHEF and/or Ruby block when a service is up and running.

Maybe have a look at the documentation of the ruby_block or these examples of conditional CHEF blocks https://stackoverflow.com/questions/46914926/chef-run-install-block-based-on-variable-condition.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .