Ask Your Question
1

doubt in hiera data with rspec-puppet

asked 2016-02-19 03:29:03 -0500

Chutki gravatar image

Hi,

I have below manifests for user creation

class module::mod_usr {


$var_aa = {
  'userid' => {
     'ensure'       => 'present',
     'uid'      => '3333',
     'gid'              => 'group',
     'home'             => '/home/userid',
     'comment'          => '<=APP=>',
     'password'         => 'dsafsefr412sfd',
     'mode'             => '0700',
     'password_max_age' => '-1',
   }
 }
  create_resources('module::moddef', $var_aa)
}

The below is the rspec-puppet test case

describe 'module' do

    it { should contain_class('module') }
    it { should contain_class('module::mod_usr') }

  end
end

describe 'module::mod_usr' do

   it { should contain_module__moddef('userid') }
  end
end

My test cases passed

/opt/puppet/bin/ruby -S rspec spec/classes/test_spec.rb 
...

Finished in 0.405 seconds
3 examples, 0 failures

My doubts is, how test case "it { should contain_module__moddef('userid') }" passing all parameters of $var_aa variable.

If test case pass the "module::moddef" module, then test case result should be 4, because we do exec recourse in our "module::moddef" module. Please refer the below manifest.

define module::moddef (
 $ensure,
  $uid,
  $gid,
  $home,
  $shell,
  $comment,
  $password,
  $mode,
  $groups           = undef,
  $password_max_age = undef,
  $managehome       = undef,
  $user_name        = $title,
)

user { $user_name :
    ensure           => $ensure,
    uid              => $uid,
    gid              => $gid,
    groups           => $groups,
    home             => $home,
    shell            => $shell,
    comment          => $comment,
    password         => $password,
    password_max_age => $password_max_age,
    managehome       => $managehome,
  }

  exec { "${user_name} homedir":
    command => "cp -R /etc/skel ${home};
                chown -R ${uid}:${gid} ${home};
                chmod -R ${mode} ${home}",
    path    => '/bin',
    creates => $home,
    require => User[$user_name],
  }

So how do I ensure my test case pass exec resource by using "it { should contain_module__moddef('userid') }" test.

or should I write separate test case for "exec" resource.

I referred this from the url http://rnelson0.com/2014/12/31/puppet...

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
2

answered 2016-02-26 07:58:40 -0500

rnelson0 gravatar image

updated 2016-02-26 08:19:24 -0500

I would suggest a few guidelines:

  • One class is tested per spec file. This means you should make the files spec/classes/init_spec.rb, spec/classes/mod_usr_spec.rb, and spec/defines/moddef_spec.rb (note the last is a define, not a class, different location for clarity). Split the tests up appropriately.
  • Each class ONLY tests what it provides.

Let's take a look at a more complex example, a profile class that includes puppetlabs/apache.

class profile::apache {
  include ::apache
}

In this case, your profile rspec test should ONLY test whether it contains the class apache. The apache module has its own tests of all the things it includes (packages, users, etc.). This separation provides two benefits. 1) Your tests are not affected by underlying changes, either in the module or how you use it (i.e. if you test for the package 'httpd' and switch from EL to Debian, your tests will fail - though apache itself would work fine since IT knows). 2) You can more easily identify where problems occur.

Given that, your moddef subclass should have tests that look like this:

describe 'module::moddef' do
  let (:title) { 'rnelson0' }
  let (:params) do
    {
      :comment => 'Rob Nelson',
      :password => 'encryptedstring',
      # etc, etc.
    }
  end

  context 'using minimum params' do
    it { is_expected.to create_user('rnelson0').with({
      :comment => 'Rob Nelson',
      :password => 'encryptedstring',
      # etc, etc.
    }) }
    it { is_expected.to contain_exec ('rnelson0 homedir') }
  end

  context 'with more parameters' do
     # etc, etc.
  end
end

That tests the define thoroughly, and does not mix the implementation details with another class.

edit flag offensive delete link more

Comments

Thanks for an update. so, I need to write separate define class test case for all the modules where it use create_rseources(module::moddef). Because we refer "module::moddef" module more than 10 modules by create_resource().

Chutki gravatar imageChutki ( 2016-02-26 08:11:28 -0500 )edit

So I thought its quite tough to write the same "spec/defines/moddefspec.rb" rspec test case for all the modules.

Chutki gravatar imageChutki ( 2016-02-26 08:15:05 -0500 )edit

That's really helpful; thanks.

Alex Harvey gravatar imageAlex Harvey ( 2016-02-26 08:19:46 -0500 )edit

In classes that use module::moddef, you should check that they contain_module__moddef('title'). Remember that rspec-puppet is testing your code, not your implementation. 1 or 100 instances of module::moddef are essentially the same.

rnelson0 gravatar imagernelson0 ( 2016-02-26 08:48:33 -0500 )edit

Okay Thanks for your help. But it would be better if we have any special function in rspec-puppet like create_resource(). So we can directly use the function in class_spec.rb test file to pass hiera data. To implement that in my test case, should I start write any special ruby function for this.

Chutki gravatar imageChutki ( 2016-02-29 00:54:47 -0500 )edit
0

answered 2016-02-19 19:30:09 -0500

Each Rspec 'example' is a 'describe' / 'it' block. Your _spec.rb file has only three examples in it: it { should contain_class('module') }; it { should contain_class('module::mod_usr') }; and it { should contain_module__moddef('userid') }.

If you want to write another example that asserts that the catalog should contain an Exec resource you would write it { should contain_exec('...') }.

edit flag offensive delete link more

Comments

Thanks for an update. We have lvm module for build. lvm module has define file system creation manifest ( lv_fs.pp). In our build, many module refer this lv_fs.pp define manifest by using create_resources (). So in that case very tough write same lv_fs.pp test case for all modules.

Chutki gravatar imageChutki ( 2016-02-20 11:44:37 -0500 )edit

So do we have any other options in rspec-puppet to over come this.

Chutki gravatar imageChutki ( 2016-02-20 11:45:30 -0500 )edit

If your situation is you have one team adding resources in Hiera, and another trying to write rspec-puppet tests for them, that can't work. Each time you add a new resource in Hiera, you need to add a new rspec test - or you could just not bother to write a test for this.

Alex Harvey gravatar imageAlex Harvey ( 2016-02-20 20:40:38 -0500 )edit

Okay. 1) Is there any way that we can write single test case for lv_fs.pp and call those lv_fs.pp rspec-puppet test when required for its create_resources () test case or 2) can't we pass hiera data dynamically to lv_fs.pp rspec-puppet test case

Chutki gravatar imageChutki ( 2016-02-21 11:23:42 -0500 )edit

Yes, you can read in the Hiera data into a variable, and then iterate through that just as you do in your manifest.

Alex Harvey gravatar imageAlex Harvey ( 2016-02-21 18:21:07 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2016-02-19 03:29:03 -0500

Seen: 254 times

Last updated: Feb 26 '16