Check for existing directory fails in Ruby + Chef

20,438

Solution 1

I was not so attentive earlier, I thought you are checking for file existence in not_if or only_if block. Your problem is similar to the one in this question: Chef LWRP - defs/resources execution order. See the detailed explanation there.

Your problem is that !File.exist?("/vol/postgres/data") code gets executed straight away - (because it's pure ruby), before any resource is executed and thus before the postgress is installed.

The solution should be to move the check to not_if block.

execute "mv /var/lib/postgresql/9.1/main /vol/postgres/data" do
  not_if { File.exist?("/vol/postgres/data") }
end

Solution 2

Use this block of code :

execute "name" do
    command "mv /var/lib/postgresql/9.1/main /vol/postgres/data"
    not_if { ::File.exists?("/vol/postgres/data")}
end

OR

you can also use

execute "name" do
    command "mv /var/lib/postgresql/9.1/main /vol/postgres/data"
    creates "/vol/postgres/data"
end

Both will run the command only if /vol/postgres/data is not present in the file system. If you want to run block of commands then use something like this,

bash 'name' do
  not_if { ::File.exists?("/vol/postgres/data") }
  cwd "/"
  code <<-EOH
  mv /var/lib/postgresql/9.1/main /vol/postgres/data
  #any other bash commands 
  #any other bash commands
  EOH
end

Solution 3

I use

!::File.directory?(::File.join('path/to/directory', 'directory_name'))

Solution 4

To test if a directory exists you can use an equvivalent of File.exists which is Dir.exist:

Dir.exist?("/vol/postgres/data")

As others pointed out, you should use not_if or only_if instead of using plain Ruby condition, so I'm not going to explain it again. Check Draco's answer for details.

execute "mv /var/lib/postgresql/9.1/main /vol/postgres/data" do
  not_if { Dir.exist?("/vol/postgres/data") }
end
Share:
20,438
Bart van Heukelom
Author by

Bart van Heukelom

Professional software developer, online games, full stack but mostly backend. Electronics tinkerer. Maker. Freelance. See LinkedIn for more details. My UUID is 96940759-b98b-4673-b573-6aa6e38272c0

Updated on July 09, 2022

Comments

  • Bart van Heukelom
    Bart van Heukelom over 1 year

    This is my piece of Ruby in a Chef recipe:

    # if datadir doesn't exist, move over the default one
    if !File.exist?("/vol/postgres/data")
        execute "mv /var/lib/postgresql/9.1/main /vol/postgres/data"
    end
    

    The result is:

    Executing mv /var/lib/postgresql/9.1/main /vol/postgres/data
    mv: inter-device move failed: `/var/lib/postgresql/9.1/main' to `/vol/postgres/data/main'; unable to remove target: Is a directory
    

    I know that /vol/postgres/data exists and is a directory, yet it still attempts to execute the mv. Why?

    Just to be sure, running the following standalone Ruby script on the same machine outputs "nomv":

    if !File.exist?("/vol/postgres/data")
    print "mv"
    else
    print "nomv"
    end