summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAJ Christensen <aj@junglist.gen.nz>2009-06-06 10:19:23 +1200
committerAJ Christensen <aj@junglist.gen.nz>2009-06-08 11:39:48 +1200
commitc362c603e01d8393c14779f83cdc18a75b923c06 (patch)
tree737318e9ebf78d6fb3994cd520a44627d93e6b1f
parent8e1316cd96086f6a94ce2c0f65344250184a4fdc (diff)
downloadchef-c362c603e01d8393c14779f83cdc18a75b923c06.tar.gz
CHEF-330: Add verbose(r) error messages, specs; for JSON fetching
-rw-r--r--chef/lib/chef/application/client.rb23
-rw-r--r--chef/lib/chef/application/solo.rb24
-rw-r--r--chef/spec/unit/application/client_spec.rb2
-rw-r--r--chef/spec/unit/application/solo_spec.rb103
4 files changed, 137 insertions, 15 deletions
diff --git a/chef/lib/chef/application/client.rb b/chef/lib/chef/application/client.rb
index 1496a45f92..0e0e146fd3 100644
--- a/chef/lib/chef/application/client.rb
+++ b/chef/lib/chef/application/client.rb
@@ -20,6 +20,8 @@ require 'chef/client'
require 'chef/config'
require 'chef/daemon'
require 'chef/log'
+require 'net/http'
+require 'open-uri'
class Chef::Application::Client < Chef::Application
@@ -120,15 +122,22 @@ class Chef::Application::Client < Chef::Application
end
if Chef::Config[:json_attribs]
- require 'net/http'
- require 'open-uri'
+ begin
+ json_io = open(Chef::Config[:json_attribs])
+ rescue SocketError => error
+ Chef::Application.fatal!("I cannot connect to #{Chef::Config[:json_attribs]}", 2)
+ rescue Errno::ENOENT => error
+ Chef::Application.fatal!("I cannot find #{Chef::Config[:json_attribs]}", 2)
+ rescue Errno::EACCES => error
+ Chef::Application.fatal!("Permissions are incorrect on #{Chef::Config[:json_attribs]}. Please chmod a+r #{Chef::Config[:json_attribs]}", 2)
+ rescue Exception => error
+ Chef::Application.fatal!("Got an unexpected error reading #{Chef::Config[:json_attribs]}: #{error.message}", 2)
+ end
begin
- open(Chef::Config[:json_attribs]) do |json_io|
- @chef_client_json = JSON.parse(json_io.read)
- end
- rescue Exception
- Chef::Application.fatal!("Error parsing json attributes", 2)
+ @chef_client_json = JSON.parse(json_io.read)
+ rescue JSON::ParserError => error
+ Chef::Application.fatal!("Could not parse the provided JSON file (#{Chef::Config[:json_attribs]})!: " + error.message, 2)
end
end
end
diff --git a/chef/lib/chef/application/solo.rb b/chef/lib/chef/application/solo.rb
index 86eaba3d16..87a815fe88 100644
--- a/chef/lib/chef/application/solo.rb
+++ b/chef/lib/chef/application/solo.rb
@@ -20,6 +20,9 @@ require 'chef/client'
require 'chef/config'
require 'chef/daemon'
require 'chef/log'
+require 'net/http'
+require 'open-uri'
+require 'fileutils'
class Chef::Application::Solo < Chef::Application
@@ -72,8 +75,17 @@ class Chef::Application::Solo < Chef::Application
super
if Chef::Config[:json_attribs]
- require 'net/http'
- require 'open-uri'
+ begin
+ json_io = open(Chef::Config[:json_attribs])
+ rescue SocketError => error
+ Chef::Application.fatal!("I cannot connect to #{Chef::Config[:json_attribs]}", 2)
+ rescue Errno::ENOENT => error
+ Chef::Application.fatal!("I cannot find #{Chef::Config[:json_attribs]}", 2)
+ rescue Errno::EACCES => error
+ Chef::Application.fatal!("Permissions are incorrect on #{Chef::Config[:json_attribs]}. Please chmod a+r #{Chef::Config[:json_attribs]}", 2)
+ rescue Exception => error
+ Chef::Application.fatal!("Got an unexpected error reading #{Chef::Config[:json_attribs]}: #{error.message}", 2)
+ end
json_io = nil
begin
@@ -89,20 +101,18 @@ class Chef::Application::Solo < Chef::Application
end
begin
- @chef_solo_json = JSON.parse(json_io.read)
+ @chef_client_json = JSON.parse(json_io.read)
rescue JSON::ParserError => error
Chef::Application.fatal!("Could not parse the provided JSON file (#{Chef::Config[:json_attribs]})!: " + error.message, 2)
- exit 2
end
end
if Chef::Config[:recipe_url]
cookbooks_path = Chef::Config[:cookbook_path].detect{|e| e =~ /\/cookbooks\/*$/ }
recipes_path = File.expand_path(File.join(cookbooks_path, '..'))
- require 'net/http'
- require 'open-uri'
- require 'fileutils'
+ target_file = File.join(recipes_path, 'recipes.tgz')
+ Chef::Log.debug "Creating path #{recipes_path} to extract recipes into"
FileUtils.mkdir_p recipes_path
path = File.join(recipes_path, 'recipes.tgz')
File.open(path, 'wb') do |f|
diff --git a/chef/spec/unit/application/client_spec.rb b/chef/spec/unit/application/client_spec.rb
index 0f937a2bf4..ad20d0976d 100644
--- a/chef/spec/unit/application/client_spec.rb
+++ b/chef/spec/unit/application/client_spec.rb
@@ -76,7 +76,7 @@ describe Chef::Application::Client, "reconfigure" do
before do
Chef::Config.stub!(:[]).with(:json_attribs).and_return("/etc/chef/dna.json")
@json = mock("Tempfile", :read => {:a=>"b"}.to_json, :null_object => true)
- @app.stub!(:open).and_yield(@json)
+ @app.stub!(:open).with("/etc/chef/dna.json").and_return(@json)
end
it "should parse the json out of the file" do
diff --git a/chef/spec/unit/application/solo_spec.rb b/chef/spec/unit/application/solo_spec.rb
index e69de29bb2..19202a2533 100644
--- a/chef/spec/unit/application/solo_spec.rb
+++ b/chef/spec/unit/application/solo_spec.rb
@@ -0,0 +1,103 @@
+#
+# Author:: AJ Christensen (<aj@junglist.gen.nz>)
+# Copyright:: Copyright (c) 2008 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 File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
+
+describe Chef::Application::Solo, "initialize" do
+ before do
+ @app = Chef::Application::Solo.new
+ end
+
+ it "should create an instance of Chef::Application::Solo" do
+ @app.should be_kind_of(Chef::Application::Solo)
+ end
+end
+
+describe Chef::Application::Solo, "reconfigure" do
+ before do
+ @app = Chef::Application::Solo.new
+ @app.stub!(:configure_opt_parser).and_return(true)
+ @app.stub!(:configure_chef).and_return(true)
+ @app.stub!(:configure_logging).and_return(true)
+ Chef::Config.stub!(:[]).with(:recipe_url).and_return(false)
+ Chef::Config.stub!(:[]).with(:json_attribs).and_return(false)
+ end
+
+ it "should set solo mode to true" do
+ Chef::Config.should_receive(:[]=).with(:solo, true).and_return(true)
+ @app.reconfigure
+ end
+
+ describe "when the json_attribs configuration option is specified" do
+ before do
+ Chef::Config.stub!(:[]).with(:json_attribs).and_return("/etc/chef/dna.json")
+ @json = mock("Tempfile", :read => {:a=>"b"}.to_json, :null_object => true)
+ @app.stub!(:open).with("/etc/chef/dna.json").and_return(@json)
+ end
+
+ it "should parse the json out of the file" do
+ JSON.should_receive(:parse).with(@json.read)
+ @app.reconfigure
+ end
+ end
+
+ describe "when the recipe_url configuration option is specified" do
+ before do
+ Chef::Config.stub!(:[]).with(:cookbook_path).and_return("/tmp/chef-solo/cookbooks")
+ Chef::Config.stub!(:[]).with(:recipe_url).and_return("http://junglist.gen.nz/recipes.tgz")
+ FileUtils.stub!(:mkdir_p).and_return(true)
+ @tarfile = mock("Tempfile", :null_object => true, :read => "blah")
+ @app.stub!(:open).with("http://junglist.gen.nz/recipes.tgz").and_yield(@tarfile)
+ @target_file = mock("Tempfile", :null_object => true)
+ File.stub!(:open).with("/tmp/chef-solo/recipes.tgz", "wb").and_yield(@target_file)
+ Chef::Mixin::Command.stub!(:run_command).with({:command => "tar xzvfC /tmp/chef-solo/recipes.tgz /tmp/chef-solo"}).and_return(true)
+ end
+
+ it "should create the recipes path based on the parent of the cookbook path" do
+ FileUtils.should_receive(:mkdir_p).with("/tmp/chef-solo").and_return(true)
+ @app.reconfigure
+ end
+
+ it "should download the recipes" do
+ @app.should_receive(:open).with("http://junglist.gen.nz/recipes.tgz").and_yield(@tarfile)
+ @app.reconfigure
+ end
+
+ it "should write the recipes to the target path" do
+ @target_file.should_receive(:write).with("blah").and_return(true)
+ @app.reconfigure
+ end
+
+ it "should untar the target file to the parent of the cookbook path" do
+ Chef::Mixin::Command.should_receive(:run_command).with({:command => "tar xzvfC /tmp/chef-solo/recipes.tgz /tmp/chef-solo"}).and_return(true)
+ @app.reconfigure
+ end
+ end
+end
+
+describe Chef::Application::Solo, "setup_application" do
+ before do
+ @chef_client = mock("Chef::Client", :null_object => true)
+ Chef::Client.stub!(:new).and_return(@chef_client)
+ @app = Chef::Application::Solo.new
+ end
+
+ it "should instantiate a chef::client object" do
+ Chef::Client.should_receive(:new).and_return(@chef_client)
+ @app.setup_application
+ end
+end \ No newline at end of file