summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Keiser <john@johnkeiser.com>2015-12-09 11:54:53 -0800
committerJohn Keiser <john@johnkeiser.com>2015-12-09 13:02:18 -0800
commit010392858c2a3a036578b681085704ed1971ab21 (patch)
tree753775621a9f4a395aaa2c8fde8af5e4444f9c99
parent7159ea473ce08c0483e9597af5b4d2ef1996dc36 (diff)
downloadchef-jk/lazy-activation.tar.gz
Don't activate cheffish and chef-provisioning until its DSL is usedjk/lazy-activation
-rw-r--r--lib/chef/dsl/chef_provisioning.rb57
-rw-r--r--lib/chef/dsl/cheffish.rb64
-rw-r--r--lib/chef/dsl/resources.rb28
-rw-r--r--lib/chef/resources.rb7
-rw-r--r--spec/integration/client/client_spec.rb43
5 files changed, 191 insertions, 8 deletions
diff --git a/lib/chef/dsl/chef_provisioning.rb b/lib/chef/dsl/chef_provisioning.rb
new file mode 100644
index 0000000000..84a3db39c8
--- /dev/null
+++ b/lib/chef/dsl/chef_provisioning.rb
@@ -0,0 +1,57 @@
+#
+# Author:: John Keiser (<jkeiser@chef.io>)
+# Copyright:: Copyright (c) 2015 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.
+#
+
+class Chef
+ module DSL
+ # Lazy activation for the chef-provisioning gem. Specifically, we set up methods for
+ # each resource and DSL method in chef-provisioning which, when invoked, will
+ # require 'chef-provisioning' (which will define the actual method) and then call the
+ # method chef-provisioning defined.
+ module ChefProvisioning
+ %w(
+ add_machine_options
+ current_image_options
+ current_machine_options
+ load_balancer
+ machine_batch
+ machine_execute
+ machine_file
+ machine_image
+ machine
+ with_driver
+ with_image_options
+ with_machine_options
+ ).each do |method_name|
+ eval(<<-EOM, binding, __FILE__, __LINE__+1)
+ def #{method_name}(*args, &block)
+ Chef::DSL::ChefProvisioning.load_chef_provisioning
+ self.#{method_name}(*args, &block)
+ end
+ EOM
+ end
+
+ def self.load_chef_provisioning
+ # Remove all chef-provisioning methods; they will be added back in by chef-provisioning
+ public_instance_methods(false).each do |method_name|
+ remove_method(method_name)
+ end
+ require 'chef/provisioning'
+ end
+ end
+ end
+end
diff --git a/lib/chef/dsl/cheffish.rb b/lib/chef/dsl/cheffish.rb
new file mode 100644
index 0000000000..304c4df78a
--- /dev/null
+++ b/lib/chef/dsl/cheffish.rb
@@ -0,0 +1,64 @@
+#
+# Author:: John Keiser (<jkeiser@chef.io>)
+# Copyright:: Copyright (c) 2015 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.
+#
+
+class Chef
+ module DSL
+ # Lazy activation for the cheffish gem. Specifically, we set up methods for
+ # each resource and DSL method in cheffish which, when invoked, will
+ # require 'cheffish' (which will define the actual method) and then call the
+ # method cheffish defined.
+ module Cheffish
+ %w(
+ chef_acl
+ chef_client
+ chef_container
+ chef_data_bag
+ chef_environment
+ chef_group
+ chef_mirror
+ chef_node
+ chef_organization
+ chef_role
+ chef_user
+ private_key
+ public_key
+ with_chef_data_bag
+ with_chef_environment
+ with_chef_data_bag_item_encryption
+ with_chef_server
+ with_chef_local_server
+ get_private_key
+ ).each do |method_name|
+ eval(<<-EOM, binding, __FILE__, __LINE__+1)
+ def #{method_name}(*args, &block)
+ Chef::DSL::Cheffish.load_cheffish
+ self.#{method_name}(*args, &block)
+ end
+ EOM
+ end
+
+ def self.load_cheffish
+ # Remove all cheffish methods; they will be added back in by cheffish
+ public_instance_methods(false).each do |method_name|
+ remove_method(method_name)
+ end
+ require 'cheffish'
+ end
+ end
+ end
+end
diff --git a/lib/chef/dsl/resources.rb b/lib/chef/dsl/resources.rb
index 49588ed516..3d582dab6d 100644
--- a/lib/chef/dsl/resources.rb
+++ b/lib/chef/dsl/resources.rb
@@ -1,3 +1,23 @@
+#
+# Author:: John Keiser <jkeiser@chef.io>
+# Copyright:: Copyright (c) 2015 Chef Software, 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/dsl/cheffish'
+require 'chef/dsl/chef_provisioning'
+
class Chef
module DSL
#
@@ -7,6 +27,11 @@ class Chef
#
# @api private
module Resources
+ # Include the lazy loaders for cheffish and chef-provisioning, so that the
+ # resource DSL is there but the gems aren't activated yet.
+ include Chef::DSL::Cheffish
+ include Chef::DSL::ChefProvisioning
+
def self.add_resource_dsl(dsl_name)
begin
module_eval(<<-EOM, __FILE__, __LINE__+1)
@@ -24,7 +49,8 @@ class Chef
end
end
def self.remove_resource_dsl(dsl_name)
- remove_method(dsl_name) if method_defined?(dsl_name)
+ remove_method(dsl_name)
+ rescue NameError
end
end
end
diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb
index 70cb40f8db..6db0fc9d8d 100644
--- a/lib/chef/resources.rb
+++ b/lib/chef/resources.rb
@@ -82,10 +82,3 @@ require 'chef/resource/yum_package'
require 'chef/resource/lwrp_base'
require 'chef/resource/bff_package'
require 'chef/resource/zypper_package'
-
-begin
- # Optional resources chef_node, chef_client, machine, machine_image, etc.
- require 'cheffish'
- require 'chef/provisioning'
-rescue LoadError
-end
diff --git a/spec/integration/client/client_spec.rb b/spec/integration/client/client_spec.rb
index 41645adb9e..5e72a94065 100644
--- a/spec/integration/client/client_spec.rb
+++ b/spec/integration/client/client_spec.rb
@@ -340,6 +340,49 @@ EOM
end
end
+ when_the_repository "has a cookbook that uses cheffish resources" do
+ before do
+ file 'cookbooks/x/recipes/default.rb', <<-EOM
+ raise "Cheffish was loaded before we used any cheffish things!" if defined?(Cheffish::VERSION)
+ ran_block = false
+ got_server = with_chef_server 'https://blah.com' do
+ ran_block = true
+ run_context.cheffish.current_chef_server
+ end
+ raise "with_chef_server block was not run!" if !ran_block
+ raise "Cheffish was not loaded when we did cheffish things!" if !defined?(Cheffish::VERSION)
+ raise "current_chef_server did not return its value!" if got_server[:chef_server_url] != 'https://blah.com'
+ EOM
+ file 'config/client.rb', <<-EOM
+ local_mode true
+ cookbook_path "#{path_to('cookbooks')}"
+ EOM
+ end
+
+ it "the cheffish DSL is loaded lazily" do
+ command = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --no-fork", :cwd => chef_dir)
+ expect(command.exitstatus).to eql(0)
+ end
+ end
+
+ when_the_repository "has a cookbook that uses chef-provisioning resources" do
+ before do
+ file 'cookbooks/x/recipes/default.rb', <<-EOM
+ with_driver 'blah'
+ EOM
+ file 'config/client.rb', <<-EOM
+ local_mode true
+ cookbook_path "#{path_to('cookbooks')}"
+ EOM
+ end
+
+ it "the cheffish DSL tries to load but fails (because chef-provisioning is not there)" do
+ command = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --no-fork", :cwd => chef_dir)
+ expect(command.exitstatus).to eql(1)
+ expect(command.stdout).to match(/cannot load such file -- chef\/provisioning/)
+ end
+ end
+
when_the_repository "has a cookbook that generates deprecation warnings" do
before do
file 'cookbooks/x/recipes/default.rb', <<-EOM