5

I want to use shell script output to validate the resource in guard condition.I am using below code still its not working.

bash "stampDisksuccess" do
                code <<-EOH
                whoami
        EOH
        user 'root'
        not_if {"`sudo sh /home/scripts/getStampedDisk.sh test`" == ''}
      end

Whether script(getStampedDisk.sh) returns blank message or some data, bash resource is getting executed. Where i am expecting it should not run when script returns blank data.

Correct me if anything missing.

SASI
  • 475
  • 2
  • 7
  • 16

1 Answers1

16

Let's dissect it:

not_if {"`sudo sh /home/scripts/getStampedDisk.sh test`" == ''}
  • Not_if ... quite obvious, it's the guard
  • { Block opening
  • "string opening
  • backticks opening
  • command
  • closing backticks and quote
  • == operator
  • '' constant empty string
  • } closing block

That's a lot of operations to test you have an empty string. The output from the backticks is not guaranteed to be really empty (it can have a newline for example) and then you compare it with an arbitrary empty string (not nil, it's a string with nothing). There's many way it can turn bad and it's quite hard to debug non printing characters.

However the shells have already an operator for this, it's -z for the usual bash.

Quoting bash documentation:

-z string
    True if the length of string is zero.

Another helper is $() to evaluate a command inside the script

Last one the [[ ]] construction to tell we're using an operator and not a command.

All together you end up with the command execution guard when expressed as string (Documentation on guards here)

not_if '[[ -z $(sudo sh /home/scripts/getStampedDisk.sh test) ]]' 

Quote from the guard documentation:

A guard attribute accepts either a string value or a Ruby block value:

  • A string is executed as a shell command. If the command returns 0, the guard is applied. If the command returns any other value, then the guard attribute is not applied.
  • A block is executed as Ruby code that must return either true or false. If the block returns true, the guard attribute is applied. If the block returns false, the guard attribute is not applied.

If you don't use ruby in the guard, don't use a block, you're just adding layers witch will get you in trouble, specifically when you try to compare non printable or empty strings and it's harder to debug, try to stick with standard shell commands if you need to call a command or a script, you can test it in console and be sure it is not the problem later.

Tom Fenech
  • 72,334
  • 12
  • 107
  • 141
Tensibai
  • 15,557
  • 1
  • 37
  • 57
  • Even though i used not_if '[[ -z sudo sh /home/scripts/getStampedDisk.sh test ]]' my resource is getting executed and guard not working. where output of shell script is blank. – SASI Apr 29 '15 at 12:56
  • is it really 0 length ? without knowing the inner of your .sh file it's hard to tell. – Tensibai Apr 29 '15 at 12:59
  • @SASI and you forgot the `$()` to give `-z` the output of your command and not the text of command itself. I edited my answer to correct this too. – Tensibai Apr 29 '15 at 13:03
  • Thanks Tensibai.. can you please tell me how to replace 'test' with attribute like not_if '[[ -z $(sudo sh /home/scripts/getStampedDisk.sh #{node[:test][:value]}) ]]' – SASI Apr 29 '15 at 13:15
  • 1
    @SASI just replace single quotes `'` by double quote `"` and ruby interpolation will work in the line. (Think accepting answers on your questions if they solve your problem) – Tensibai Apr 29 '15 at 13:16