hartmantis / chef-dk-chef

A Chef cookbook for the Chef Development Kit
12 stars 19 forks source link

ChefDK gets installed on every Chef run #56

Open hrak opened 8 years ago

hrak commented 8 years ago

The cookbook currently installs ChefDK on every Chef run. In our env where chef runs as a daemon, this means a dpkg -i /var/chef/cache/chefdk_0.10.0-1_amd64.deb every half hour. The cookbook needs a check to see if the requested version is already installed, or if latest > installed version.

grimm26 commented 8 years ago

for debian/ubuntu anyway, you can pass the --skip-same-version option to dpkg. Just gotta find similar settings for others...

grimm26 commented 8 years ago

or have the remote_file resource notify the package resource so it only runs the package install when remote_file is run for a new download.

rmoriz commented 8 years ago

this is really a nasty issue.

howdoicomputer commented 8 years ago

I just ended up doing this:

chef_dk 'default' do
  global_shell_init true
  version '0.18.30'
  action :install

  not_if '/opt/chefdk/bin/chef --version | grep 0.18.30'
end
oskarpearson commented 8 years ago

We've just encountered this too. The one side-effect of this is that /usr/bin/chef disappears and then re-appears every time chef runs:

oskar@...:~$ while true ; do date ; ls -al /usr/bin/chef ; sleep 0.1 ; done
lrwxrwxrwx 1 root root 20 Oct 21 12:26 /usr/bin/chef -> /opt/chefdk/bin/chef
Fri Oct 21 12:41:01 UTC 2016
lrwxrwxrwx 1 root root 20 Oct 21 12:26 /usr/bin/chef -> /opt/chefdk/bin/chef
Fri Oct 21 12:41:01 UTC 2016
lrwxrwxrwx 1 root root 20 Oct 21 12:26 /usr/bin/chef -> /opt/chefdk/bin/chef
... all fine ...
lrwxrwxrwx 1 root root 20 Oct 21 12:26 /usr/bin/chef -> /opt/chefdk/bin/chef
Fri Oct 21 12:41:01 UTC 2016
lrwxrwxrwx 1 root root 20 Oct 21 12:26 /usr/bin/chef -> /opt/chefdk/bin/chef
Fri Oct 21 12:41:01 UTC 2016
ls: cannot access /usr/bin/chef: No such file or directory
Fri Oct 21 12:41:01 UTC 2016
ls: cannot access /usr/bin/chef: No such file or directory
Fri Oct 21 12:41:01 UTC 2016
ls: cannot access /usr/bin/chef: No such file or directory
Fri Oct 21 12:41:01 UTC 2016
ls: cannot access /usr/bin/chef: No such file or directory
Fri Oct 21 12:41:04 UTC 2016
ls: cannot access /usr/bin/chef: No such file or directory
Fri Oct 21 12:41:04 UTC 2016
lrwxrwxrwx 1 root root 20 Oct 21 12:41 /usr/bin/chef -> /opt/chefdk/bin/chef
Fri Oct 21 12:41:04 UTC 2016
lrwxrwxrwx 1 root root 20 Oct 21 12:41 /usr/bin/chef -> /opt/chefdk/bin/chef
Fri Oct 21 12:41:04 UTC 2016
eyalzek commented 8 years ago

To chime in, sometimes the installation fails randomly, causing all the binary symlinks to disappear... Does anyone have a proper workaround for this without fixing the version?

pudge commented 8 years ago

I am trying this, which seems like it does the right thing (but it's a little bit fragile), basically:

# chef_dk resource reinstalls the DK every time it is run.  this bash script
# checks the version of the installed and the available versions, and outputs the
# result to a temp file, which the chef_dk resource has a guard on.
# there is a small potential race condition, for the temp file.
# and it picks a specific OS/version to ask about, which will break some day,
# when the DK for that version doesn't match what you want to install for a
# given machine.
bash 'check_version' do
  code <<-EOH
    install_version=$(chef --version 2>/dev/null | grep '^Chef Development Kit Version' | /usr/bin/perl -pe 's|^.+?: ([\\d.]+).*$|$1|;')
    avail_version=$(curl -sL 'https://omnitruck.chef.io/stable/chefdk/metadata?p=ubuntu&pv=12.04&m=x86_64&v=latest' | grep ^url | perl -pe 's|^.+/chefdk_([\\d.]+).+$|$1|')
    if [[ ! "$install_version" || ("$install_version" != "$avail_version") ]]; then
        echo false > /tmp/chefdk_uptodate
    else
        echo true > /tmp/chefdk_uptodate
    fi
    EOH
end

chef_dk 'MarChefDK' do
  action :install
  not_if 'grep true /tmp/chefdk_uptodate'
end
eyalzek commented 8 years ago

I like the idea! I tried something similar, but with ruby code instead because it feels a bit more right to me:

chefdk_guard = ::File.join(Chef::Config[:file_cache_path], 'chefdk-guard')

ruby_block 'check chefdk version' do
  action :run
  block do
    require 'fileutils'
    if !::File.exist? '/opt/chefdk/bin/chef'
      create_guard = false
    else
      require 'open-uri'
      installed_version = `/opt/chefdk/bin/chef --version | cut -d: -f2 | head -n1 | tr -d [:space:]`
      res = open("https://omnitruck.chef.io/stable/chefdk/metadata"\
        "?p=#{node['platform']}"\
        "&pv=#{node['platform_version']}"\
        "&m=#{node['kernel']['machine']}&v=latest")
      available_version = res.string.split(/\t/)[-1]
      create_guard = installed_version == available_version
    end
    if create_guard
      ::FileUtils::touch chefdk_guard
    else
      ::FileUtils::rm_f chefdk_guard
    end
  end
end

chef_dk 'default' do
  action :install
  not_if { ::File.exist? chefdk_guard }
end

I tried to pass action :nothing to the chef_dk resource at first and notify :install when needed, thus avoiding the creation of the guard, but unfortunately chef_dk doesn't support action :nothing :\

Regardless, this seems to achieve what's needed.