Cookbook sequentiality and variables

Hi,

I am modifying my first cookbook and have difficulties understanding how
processing of commands work in Chef. Consider an extract from the cookbook:

search(:users, ‘groups:sysadmin’) do |u|

execute “delete password” do
command "passwd -d #{u[‘id’]}"
only_if "test $(passwd -S #{u[‘id’]} | awk ‘{print $2}’) = L"
end

end

There are two users in sysadmin data bag: motiejus and gavin. IMHO loop should
be iterated twice. However, from chef-client logs I see this:

[Wed, 11 Apr 2012 20:58:24 +0100] INFO: Processing user[motiejus] action create (users::sysadmins line 42)
[Wed, 11 Apr 2012 20:58:24 +0100] DEBUG: Processing execute[delete password] on chef.src.gla.ac.uk
[Wed, 11 Apr 2012 20:58:24 +0100] INFO: Processing execute[delete password] action run (users::sysadmins line 52)
[Wed, 11 Apr 2012 20:58:24 +0100] DEBUG: sh(test $(passwd -S motiejus | awk '{print 2}') = L) [Wed, 11 Apr 2012 20:58:24 +0100] DEBUG: Skipping execute[delete password] due to only_if command `test (passwd -S motiejus | awk '{print 2}') = L` ... [Wed, 11 Apr 2012 20:59:26 +0100] DEBUG: Processing user[gavin] on chef.src.gla.ac.uk [Wed, 11 Apr 2012 20:59:26 +0100] INFO: Processing user[gavin] action create (users::sysadmins line 42) ... [Wed, 11 Apr 2012 20:59:26 +0100] DEBUG: Processing execute[delete password] on chef.src.gla.ac.uk [Wed, 11 Apr 2012 20:59:26 +0100] INFO: Processing execute[delete password] action run (users::sysadmins line 52) [Wed, 11 Apr 2012 20:59:26 +0100] DEBUG: sh(test (passwd -S motiejus | awk '{print 2}') = L) [Wed, 11 Apr 2012 20:59:26 +0100] DEBUG: Skipping execute[delete password] due to only_if command `test (passwd -S motiejus | awk ‘{print $2}’) = L`

Notice the command

test $(passwd -S motiejus | awk '{print $2}') = L

is executed twice. I expect it to be executed once “motiejus”, second time
"gavin". Any ideas why?

Another strange thing. If I replace
only_if "test $(passwd -S #{u[‘id’]} | awk ‘{print $2}’) = L"
to
only_if "true " + u[‘id’]

I see this in the logs:

[Wed, 11 Apr 2012 21:03:40 +0100] INFO: Processing execute[delete password] action run (users::sysadmins line 52)
[Wed, 11 Apr 2012 21:03:40 +0100] DEBUG: sh(true motiejus)
[Wed, 11 Apr 2012 21:03:40 +0100] DEBUG: sh(true gavin)
[Wed, 11 Apr 2012 21:03:41 +0100] INFO: execute[delete password] sh(passwd -d motiejus)
passwd: password expiry information changed.
[Wed, 11 Apr 2012 21:03:41 +0100] INFO: execute[delete password] ran successfully

[Wed, 11 Apr 2012 21:03:41 +0100] DEBUG: sh(true motiejus)
[Wed, 11 Apr 2012 21:03:41 +0100] DEBUG: sh(true gavin)
[Wed, 11 Apr 2012 21:03:41 +0100] INFO: execute[delete password] sh(passwd -d gavin)
passwd: password expiry information changed.
[Wed, 11 Apr 2012 21:03:41 +0100] INFO: execute[delete password] ran successfully

Why is sh(true ) executed twice? I expect it to run once for motiejus,
and once for gavin.

Do I utterly misunderstand how cookbook execution works? I would like to know
the details of compilation and execution, is there something more higher level
than source code for me to look at (I don’t have much experience with ruby, so
not that familiar with ruby metaprogramming)?

Chef 0.10.8 from opsocde apt repos on squeeze.

Thanks
Motiejus

Motiejus,

Resources that you create during the compilation phase to be executed by
the system later during the convergence phase are unique by their types
and names.

You created a resource of type execute with name "delete password". The
next time you call execute "delete password", it doesn't make a new
resource. Instead, it finds the resource with that type and name, and
reopens it so you can change resource attributes and add only-if/not-if
blocks and add actions. In the end, there is only one resource of type
execute with name "delete password".

Cheers,
Jay Feldblum

On Wed, Apr 11, 2012 at 4:09 PM, Motiejus Jakštys desired.mta@gmail.comwrote:

Hi,

I am modifying my first cookbook and have difficulties understanding how
processing of commands work in Chef. Consider an extract from the cookbook:

search(:users, 'groups:sysadmin') do |u|

execute "delete password" do
command "passwd -d #{u['id']}"
only_if "test $(passwd -S #{u['id']} | awk '{print $2}') = L"
end

end

There are two users in sysadmin data bag: motiejus and gavin. IMHO loop
should
be iterated twice. However, from chef-client logs I see this:

[Wed, 11 Apr 2012 20:58:24 +0100] INFO: Processing user[motiejus] action
create (users::sysadmins line 42)
[Wed, 11 Apr 2012 20:58:24 +0100] DEBUG: Processing execute[delete
password] on chef.src.gla.ac.uk
[Wed, 11 Apr 2012 20:58:24 +0100] INFO: Processing execute[delete
password] action run (users::sysadmins line 52)
[Wed, 11 Apr 2012 20:58:24 +0100] DEBUG: sh(test $(passwd -S motiejus |
awk '{print $2}') = L)
[Wed, 11 Apr 2012 20:58:24 +0100] DEBUG: Skipping execute[delete password]
due to only_if command test $(passwd -S motiejus | awk '{print $2}') = L
...
[Wed, 11 Apr 2012 20:59:26 +0100] DEBUG: Processing user[gavin] on
chef.src.gla.ac.uk
[Wed, 11 Apr 2012 20:59:26 +0100] INFO: Processing user[gavin] action
create (users::sysadmins line 42)
...
[Wed, 11 Apr 2012 20:59:26 +0100] DEBUG: Processing execute[delete
password] on chef.src.gla.ac.uk
[Wed, 11 Apr 2012 20:59:26 +0100] INFO: Processing execute[delete
password] action run (users::sysadmins line 52)
[Wed, 11 Apr 2012 20:59:26 +0100] DEBUG: sh(test $(passwd -S motiejus |
awk '{print $2}') = L)
[Wed, 11 Apr 2012 20:59:26 +0100] DEBUG: Skipping execute[delete password]
due to only_if command test $(passwd -S motiejus | awk '{print $2}') = L

Notice the command

test $(passwd -S motiejus | awk '{print $2}') = L

is executed twice. I expect it to be executed once "motiejus", second time
"gavin". Any ideas why?

Another strange thing. If I replace
only_if "test $(passwd -S #{u['id']} | awk '{print $2}') = L"
to
only_if "true " + u['id']

I see this in the logs:

[Wed, 11 Apr 2012 21:03:40 +0100] INFO: Processing execute[delete
password] action run (users::sysadmins line 52)
[Wed, 11 Apr 2012 21:03:40 +0100] DEBUG: sh(true motiejus)
[Wed, 11 Apr 2012 21:03:40 +0100] DEBUG: sh(true gavin)
[Wed, 11 Apr 2012 21:03:41 +0100] INFO: execute[delete password] sh(passwd
-d motiejus)
passwd: password expiry information changed.
[Wed, 11 Apr 2012 21:03:41 +0100] INFO: execute[delete password] ran
successfully
...
[Wed, 11 Apr 2012 21:03:41 +0100] DEBUG: sh(true motiejus)
[Wed, 11 Apr 2012 21:03:41 +0100] DEBUG: sh(true gavin)
[Wed, 11 Apr 2012 21:03:41 +0100] INFO: execute[delete password] sh(passwd
-d gavin)
passwd: password expiry information changed.
[Wed, 11 Apr 2012 21:03:41 +0100] INFO: execute[delete password] ran
successfully

Why is sh(true ) executed twice? I expect it to run once for
motiejus,
and once for gavin.

Do I utterly misunderstand how cookbook execution works? I would like to
know
the details of compilation and execution, is there something more higher
level
than source code for me to look at (I don't have much experience with
ruby, so
not that familiar with ruby metaprogramming)?

Chef 0.10.8 from opsocde apt repos on squeeze.

Thanks
Motiejus

On Wed, Apr 11, 2012 at 06:16:18PM -0400, Jay Feldblum wrote:

Motiejus,

Resources that you create during the compilation phase to be executed by
the system later during the convergence phase are unique by their types
and names.

You created a resource of type execute with name "delete password". The
next time you call execute "delete password", it doesn't make a new
resource. Instead, it finds the resource with that type and name, and
reopens it so you can change resource attributes and add only-if/not-if
blocks and add actions. In the end, there is only one resource of type
execute with name "delete password".

I looked for a way to execute a query without creating a resource, but didn't
find one. I looked at apt and chef-client cookbooks for an example and tried to
google for it. All "executions" are handled when creating an "execute" named block.

OK, clearer, thanks. So once string is evaluated in the resource, it will stay
like this.

This is what I came up with:

execute "delete password for " + u['id'] do
command "passwd -d #{u['id']}"
only_if "test $(passwd -S #{u['id']} | awk '{print $2}') = L"
end

I don't like it. Is there a better way to do it, or is it the way to do it?

Jay, thanks for your explanations. :slight_smile: A tutorial or higher-level documentation
would be useful here, so I wouldn't ask those kind of basic questions. We'll
see what I can do about it when I learn chef.

Motiejus

Motiejus,

That looks fine to me.

Cheers,
Jay

On Thu, Apr 12, 2012 at 2:10 AM, Motiejus Jakštys desired.mta@gmail.comwrote:

On Wed, Apr 11, 2012 at 06:16:18PM -0400, Jay Feldblum wrote:

Motiejus,

Resources that you create during the compilation phase to be executed by
the system later during the convergence phase are unique by their types
and names.

You created a resource of type execute with name "delete password". The
next time you call execute "delete password", it doesn't make a new
resource. Instead, it finds the resource with that type and name, and
reopens it so you can change resource attributes and add only-if/not-if
blocks and add actions. In the end, there is only one resource of type
execute with name "delete password".

I looked for a way to execute a query without creating a resource, but
didn't
find one. I looked at apt and chef-client cookbooks for an example and
tried to
google for it. All "executions" are handled when creating an "execute"
named block.

OK, clearer, thanks. So once string is evaluated in the resource, it will
stay
like this.

This is what I came up with:

execute "delete password for " + u['id'] do
command "passwd -d #{u['id']}"
only_if "test $(passwd -S #{u['id']} | awk '{print $2}') = L"
end

I don't like it. Is there a better way to do it, or is it the way to do it?

Jay, thanks for your explanations. :slight_smile: A tutorial or higher-level
documentation
would be useful here, so I wouldn't ask those kind of basic questions.
We'll
see what I can do about it when I learn chef.

Motiejus