summaryrefslogtreecommitdiff
path: root/lib/chef/knife/cookbook_site_install.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef/knife/cookbook_site_install.rb')
-rw-r--r--lib/chef/knife/cookbook_site_install.rb155
1 files changed, 155 insertions, 0 deletions
diff --git a/lib/chef/knife/cookbook_site_install.rb b/lib/chef/knife/cookbook_site_install.rb
new file mode 100644
index 0000000000..b2e0d84751
--- /dev/null
+++ b/lib/chef/knife/cookbook_site_install.rb
@@ -0,0 +1,155 @@
+#
+# Author:: Adam Jacob (<adam@opscode.com>)
+# Copyright:: Copyright (c) 2010 Opscode, Inc.
+# 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 'chef/knife'
+require 'shellwords'
+
+class Chef
+ class Knife
+
+ class CookbookSiteInstall < Knife
+
+ deps do
+ require 'chef/mixin/shell_out'
+ require 'chef/knife/core/cookbook_scm_repo'
+ require 'chef/cookbook/metadata'
+ end
+
+ banner "knife cookbook site install COOKBOOK [VERSION] (options)"
+ category "cookbook site"
+
+ option :no_deps,
+ :short => "-D",
+ :long => "--skip-dependencies",
+ :boolean => true,
+ :default => false,
+ :description => "Skips automatic dependency installation."
+
+ option :cookbook_path,
+ :short => "-o PATH:PATH",
+ :long => "--cookbook-path PATH:PATH",
+ :description => "A colon-separated path to look for cookbooks in",
+ :proc => lambda { |o| o.split(":") }
+
+ option :default_branch,
+ :short => "-B BRANCH",
+ :long => "--branch BRANCH",
+ :description => "Default branch to work with",
+ :default => "master"
+
+ option :use_current_branch,
+ :short => "-b",
+ :long => "--use-current-branch",
+ :description => "Use the current branch",
+ :boolean => true,
+ :default => false
+
+ attr_reader :cookbook_name
+ attr_reader :vendor_path
+
+ def run
+ extend Chef::Mixin::ShellOut
+
+ if config[:cookbook_path]
+ Chef::Config[:cookbook_path] = config[:cookbook_path]
+ else
+ config[:cookbook_path] = Chef::Config[:cookbook_path]
+ end
+
+ @cookbook_name = parse_name_args!
+ # Check to ensure we have a valid source of cookbooks before continuing
+ #
+ @install_path = File.expand_path(config[:cookbook_path].first)
+ ui.info "Installing #@cookbook_name to #{@install_path}"
+
+ @repo = CookbookSCMRepo.new(@install_path, ui, config)
+ #cookbook_path = File.join(vendor_path, name_args[0])
+ upstream_file = File.join(@install_path, "#{@cookbook_name}.tar.gz")
+
+ @repo.sanity_check
+ unless config[:use_current_branch]
+ @repo.reset_to_default_state
+ @repo.prepare_to_import(@cookbook_name)
+ end
+
+ downloader = download_cookbook_to(upstream_file)
+ clear_existing_files(File.join(@install_path, @cookbook_name))
+ extract_cookbook(upstream_file, downloader.version)
+
+ # TODO: it'd be better to store these outside the cookbook repo and
+ # keep them around, e.g., in ~/Library/Caches on OS X.
+ ui.info("removing downloaded tarball")
+ File.unlink(upstream_file)
+
+ if @repo.finalize_updates_to(@cookbook_name, downloader.version)
+ unless config[:use_current_branch]
+ @repo.reset_to_default_state
+ end
+ @repo.merge_updates_from(@cookbook_name, downloader.version)
+ else
+ unless config[:use_current_branch]
+ @repo.reset_to_default_state
+ end
+ end
+
+ unless config[:no_deps]
+ md = Chef::Cookbook::Metadata.new
+ md.from_file(File.join(@install_path, @cookbook_name, "metadata.rb"))
+ md.dependencies.each do |cookbook, version_list|
+ # Doesn't do versions.. yet
+ nv = self.class.new
+ nv.config = config
+ nv.name_args = [ cookbook ]
+ nv.run
+ end
+ end
+ end
+
+ def parse_name_args!
+ if name_args.empty?
+ ui.error("Please specify a cookbook to download and install.")
+ exit 1
+ elsif name_args.size >= 2
+ unless name_args.last.match(/^(\d+)(\.\d+){1,2}$/) and name_args.size == 2
+ ui.error("Installing multiple cookbooks at once is not supported.")
+ exit 1
+ end
+ end
+ name_args.first
+ end
+
+ def download_cookbook_to(download_path)
+ downloader = Chef::Knife::CookbookSiteDownload.new
+ downloader.config[:file] = download_path
+ downloader.name_args = name_args
+ downloader.run
+ downloader
+ end
+
+ def extract_cookbook(upstream_file, version)
+ ui.info("Uncompressing #{@cookbook_name} version #{version}.")
+ shell_out!("tar zxvf #{Shellwords.escape upstream_file}", :cwd => @install_path)
+ end
+
+ def clear_existing_files(cookbook_path)
+ ui.info("Removing pre-existing version.")
+ FileUtils.rmtree(cookbook_path) if File.directory?(cookbook_path)
+ end
+ end
+ end
+end