# # Tasks to keep your repository in sync with your Chef Server # # Author:: Matthew Kent () # Copyright:: Copyright (c) 2010 Matthew Kent # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require 'moneta' require 'moneta/basic_file' REPO_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')) COOKBOOK_CACHE = File.join(REPO_ROOT, ".rake_update_cache/cookbooks") COOKBOOK_SEARCH = File.join(REPO_ROOT, "{cookbooks,site-cookbooks}/**/*") ROLES_CACHE = File.join(REPO_ROOT, ".rake_update_cache/roles") ROLES_SEARCH = File.join(REPO_ROOT, "roles/*.rb") desc "Upload cookbooks altered since last sync_cookbooks" task :sync_cookbooks do ran_once = false # gather cookbooks => files associations cookbooks = {} Dir.glob(COOKBOOK_SEARCH).each do |file| if File.file?(file) if file =~ %r{#{REPO_ROOT}/(.*?/(.*?)/.*)} relative = $1 cookbook = $2 if cookbooks[cookbook] cookbooks[cookbook] << relative else cookbooks[cookbook] = [ relative ] end end end end cache = Moneta::BasicFile.new(:path => COOKBOOK_CACHE) cookbooks.each do |cookbook, files| update = false knife_has_run = false files.each do |file| mtime = File.stat(File.expand_path(File.join(REPO_ROOT, file))).mtime key = "cookbook-#{file.gsub(/(#{File::SEPARATOR}|\.)/, '-')}" if cache[key] if mtime > cache[key] puts "cookbook[#{cookbook}] #{file} has been updated" update = true end else puts "cookbook[#{cookbook}] #{file} is new" update = true end if update # We only run the upload once as it's per cookbook but prior to setting # the cache key, so if it bails out we run correctly next time unless knife_has_run sh "knife cookbook upload #{cookbook}" knife_has_run = true ran_once = true end cache[key] = mtime end end end unless ran_once puts "No new or updated cookbooks" end end desc "Update roles altered since last sync_roles" task :sync_roles do ran_once = false current_files = [] Dir.glob(ROLES_SEARCH).each do |file| if File.file?(file) if file =~ %r{#{REPO_ROOT}/(.*)} current_files << $1 end end end cache = Moneta::BasicFile.new(:path => ROLES_CACHE) current_files.each do |file| mtime = File.stat(File.expand_path(File.join(REPO_ROOT, file))).mtime key = "role-#{file.gsub(/(#{File::SEPARATOR}|\.)/, '-')}" if cache[key] if mtime > cache[key] puts "role[#{file}] has been updated" update = true end else puts "role[#{file}] is new" update = true end if update sh "knife role from file #{file}" cache[key] = mtime ran_once = true end end unless ran_once puts "No new or updated roles" end end desc "Sync updated cookbooks and roles" task :sync => [ :sync_cookbooks, :sync_roles ]