mbailey-chef 0.9.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +201 -0
- data/README.rdoc +172 -0
- data/bin/chef-client +26 -0
- data/bin/chef-solo +25 -0
- data/bin/knife +26 -0
- data/bin/shef +34 -0
- data/distro/README +2 -0
- data/distro/common/man/man1/chef-indexer.1 +42 -0
- data/distro/common/man/man1/chef-server-webui.1 +106 -0
- data/distro/common/man/man1/chef-server.1 +107 -0
- data/distro/common/man/man1/chef-solr-indexer.1 +55 -0
- data/distro/common/man/man1/chef-solr.1 +55 -0
- data/distro/common/man/man8/chef-client.8 +63 -0
- data/distro/common/man/man8/chef-solo.8 +57 -0
- data/distro/common/man/man8/chef-solr-rebuild.8 +37 -0
- data/distro/common/man/man8/knife.8 +1349 -0
- data/distro/common/man/man8/shef.8 +45 -0
- data/distro/common/markdown/README +3 -0
- data/distro/common/markdown/knife.mkd +832 -0
- data/distro/debian/etc/default/chef-client +4 -0
- data/distro/debian/etc/default/chef-server +9 -0
- data/distro/debian/etc/default/chef-server-webui +9 -0
- data/distro/debian/etc/default/chef-solr +7 -0
- data/distro/debian/etc/default/chef-solr-indexer +7 -0
- data/distro/debian/etc/init/chef-client.conf +17 -0
- data/distro/debian/etc/init/chef-server-webui.conf +17 -0
- data/distro/debian/etc/init/chef-server.conf +17 -0
- data/distro/debian/etc/init/chef-solr-indexer.conf +17 -0
- data/distro/debian/etc/init/chef-solr.conf +17 -0
- data/distro/debian/etc/init.d/chef-client +175 -0
- data/distro/debian/etc/init.d/chef-server +122 -0
- data/distro/debian/etc/init.d/chef-server-webui +123 -0
- data/distro/debian/etc/init.d/chef-solr +177 -0
- data/distro/debian/etc/init.d/chef-solr-indexer +176 -0
- data/distro/redhat/etc/init.d/chef-client +106 -0
- data/distro/redhat/etc/init.d/chef-server +112 -0
- data/distro/redhat/etc/init.d/chef-server-webui +112 -0
- data/distro/redhat/etc/init.d/chef-solr +104 -0
- data/distro/redhat/etc/init.d/chef-solr-indexer +104 -0
- data/distro/redhat/etc/logrotate.d/chef-client +8 -0
- data/distro/redhat/etc/logrotate.d/chef-server +8 -0
- data/distro/redhat/etc/logrotate.d/chef-server-webui +8 -0
- data/distro/redhat/etc/logrotate.d/chef-solr +8 -0
- data/distro/redhat/etc/logrotate.d/chef-solr-indexer +8 -0
- data/distro/redhat/etc/sysconfig/chef-client +15 -0
- data/distro/redhat/etc/sysconfig/chef-server +14 -0
- data/distro/redhat/etc/sysconfig/chef-server-webui +14 -0
- data/distro/redhat/etc/sysconfig/chef-solr +8 -0
- data/distro/redhat/etc/sysconfig/chef-solr-indexer +7 -0
- data/lib/chef/api_client.rb +264 -0
- data/lib/chef/application/agent.rb +18 -0
- data/lib/chef/application/client.rb +246 -0
- data/lib/chef/application/knife.rb +171 -0
- data/lib/chef/application/solo.rb +215 -0
- data/lib/chef/application.rb +127 -0
- data/lib/chef/applications.rb +4 -0
- data/lib/chef/certificate.rb +194 -0
- data/lib/chef/checksum.rb +182 -0
- data/lib/chef/checksum_cache.rb +173 -0
- data/lib/chef/client.rb +304 -0
- data/lib/chef/config.rb +240 -0
- data/lib/chef/cookbook/cookbook_collection.rb +44 -0
- data/lib/chef/cookbook/file_system_file_vendor.rb +54 -0
- data/lib/chef/cookbook/file_vendor.rb +48 -0
- data/lib/chef/cookbook/metadata/version.rb +87 -0
- data/lib/chef/cookbook/metadata.rb +500 -0
- data/lib/chef/cookbook/remote_file_vendor.rb +87 -0
- data/lib/chef/cookbook/syntax_check.rb +136 -0
- data/lib/chef/cookbook_loader.rb +227 -0
- data/lib/chef/cookbook_site_streaming_uploader.rb +244 -0
- data/lib/chef/cookbook_uploader.rb +103 -0
- data/lib/chef/cookbook_version.rb +930 -0
- data/lib/chef/couchdb.rb +239 -0
- data/lib/chef/daemon.rb +172 -0
- data/lib/chef/data_bag.rb +215 -0
- data/lib/chef/data_bag_item.rb +228 -0
- data/lib/chef/exceptions.rb +66 -0
- data/lib/chef/file_access_control.rb +140 -0
- data/lib/chef/file_cache.rb +218 -0
- data/lib/chef/handler/json_file.rb +58 -0
- data/lib/chef/handler.rb +206 -0
- data/lib/chef/index_queue/amqp_client.rb +113 -0
- data/lib/chef/index_queue/consumer.rb +76 -0
- data/lib/chef/index_queue/indexable.rb +76 -0
- data/lib/chef/index_queue.rb +29 -0
- data/lib/chef/knife/bootstrap/archlinux-gems.erb +44 -0
- data/lib/chef/knife/bootstrap/centos5-gems.erb +41 -0
- data/lib/chef/knife/bootstrap/client-install.vbs +80 -0
- data/lib/chef/knife/bootstrap/fedora13-gems.erb +38 -0
- data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +32 -0
- data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +43 -0
- data/lib/chef/knife/bootstrap/windows-gems.erb +34 -0
- data/lib/chef/knife/bootstrap.rb +181 -0
- data/lib/chef/knife/client_bulk_delete.rb +40 -0
- data/lib/chef/knife/client_create.rb +70 -0
- data/lib/chef/knife/client_delete.rb +45 -0
- data/lib/chef/knife/client_edit.rb +45 -0
- data/lib/chef/knife/client_list.rb +40 -0
- data/lib/chef/knife/client_reregister.rb +56 -0
- data/lib/chef/knife/client_show.rb +50 -0
- data/lib/chef/knife/configure.rb +140 -0
- data/lib/chef/knife/configure_client.rb +52 -0
- data/lib/chef/knife/cookbook_bulk_delete.rb +58 -0
- data/lib/chef/knife/cookbook_create.rb +209 -0
- data/lib/chef/knife/cookbook_delete.rb +143 -0
- data/lib/chef/knife/cookbook_download.rb +130 -0
- data/lib/chef/knife/cookbook_list.rb +41 -0
- data/lib/chef/knife/cookbook_metadata.rb +82 -0
- data/lib/chef/knife/cookbook_metadata_from_file.rb +40 -0
- data/lib/chef/knife/cookbook_show.rb +98 -0
- data/lib/chef/knife/cookbook_site_download.rb +58 -0
- data/lib/chef/knife/cookbook_site_list.rb +56 -0
- data/lib/chef/knife/cookbook_site_search.rb +51 -0
- data/lib/chef/knife/cookbook_site_share.rb +109 -0
- data/lib/chef/knife/cookbook_site_show.rb +57 -0
- data/lib/chef/knife/cookbook_site_unshare.rb +52 -0
- data/lib/chef/knife/cookbook_site_vendor.rb +133 -0
- data/lib/chef/knife/cookbook_test.rb +82 -0
- data/lib/chef/knife/cookbook_upload.rb +95 -0
- data/lib/chef/knife/data_bag_create.rb +59 -0
- data/lib/chef/knife/data_bag_delete.rb +48 -0
- data/lib/chef/knife/data_bag_edit.rb +50 -0
- data/lib/chef/knife/data_bag_from_file.rb +44 -0
- data/lib/chef/knife/data_bag_list.rb +43 -0
- data/lib/chef/knife/data_bag_show.rb +41 -0
- data/lib/chef/knife/ec2_instance_data.rb +46 -0
- data/lib/chef/knife/ec2_server_create.rb +216 -0
- data/lib/chef/knife/ec2_server_delete.rb +90 -0
- data/lib/chef/knife/ec2_server_list.rb +88 -0
- data/lib/chef/knife/exec.rb +52 -0
- data/lib/chef/knife/index_rebuild.rb +51 -0
- data/lib/chef/knife/node_bulk_delete.rb +43 -0
- data/lib/chef/knife/node_create.rb +47 -0
- data/lib/chef/knife/node_delete.rb +44 -0
- data/lib/chef/knife/node_edit.rb +44 -0
- data/lib/chef/knife/node_from_file.rb +42 -0
- data/lib/chef/knife/node_list.rb +41 -0
- data/lib/chef/knife/node_run_list_add.rb +64 -0
- data/lib/chef/knife/node_run_list_remove.rb +45 -0
- data/lib/chef/knife/node_show.rb +54 -0
- data/lib/chef/knife/rackspace_server_create.rb +156 -0
- data/lib/chef/knife/rackspace_server_delete.rb +57 -0
- data/lib/chef/knife/rackspace_server_list.rb +59 -0
- data/lib/chef/knife/recipe_list.rb +32 -0
- data/lib/chef/knife/role_bulk_delete.rb +44 -0
- data/lib/chef/knife/role_create.rb +52 -0
- data/lib/chef/knife/role_delete.rb +44 -0
- data/lib/chef/knife/role_edit.rb +45 -0
- data/lib/chef/knife/role_from_file.rb +46 -0
- data/lib/chef/knife/role_list.rb +40 -0
- data/lib/chef/knife/role_show.rb +51 -0
- data/lib/chef/knife/search.rb +94 -0
- data/lib/chef/knife/slicehost_images_list.rb +53 -0
- data/lib/chef/knife/slicehost_server_create.rb +103 -0
- data/lib/chef/knife/slicehost_server_delete.rb +61 -0
- data/lib/chef/knife/slicehost_server_list.rb +64 -0
- data/lib/chef/knife/ssh.rb +328 -0
- data/lib/chef/knife/status.rb +87 -0
- data/lib/chef/knife/terremark_server_create.rb +152 -0
- data/lib/chef/knife/terremark_server_delete.rb +87 -0
- data/lib/chef/knife/terremark_server_list.rb +77 -0
- data/lib/chef/knife/windows_bootstrap.rb +154 -0
- data/lib/chef/knife.rb +522 -0
- data/lib/chef/log.rb +61 -0
- data/lib/chef/mixin/check_helper.rb +31 -0
- data/lib/chef/mixin/checksum.rb +32 -0
- data/lib/chef/mixin/command/unix.rb +215 -0
- data/lib/chef/mixin/command/windows.rb +72 -0
- data/lib/chef/mixin/command.rb +220 -0
- data/lib/chef/mixin/convert_to_class_name.rb +63 -0
- data/lib/chef/mixin/create_path.rb +56 -0
- data/lib/chef/mixin/deep_merge.rb +225 -0
- data/lib/chef/mixin/deprecation.rb +65 -0
- data/lib/chef/mixin/find_preferred_file.rb +92 -0
- data/lib/chef/mixin/from_file.rb +50 -0
- data/lib/chef/mixin/language.rb +156 -0
- data/lib/chef/mixin/language_include_attribute.rb +61 -0
- data/lib/chef/mixin/language_include_recipe.rb +52 -0
- data/lib/chef/mixin/params_validate.rb +225 -0
- data/lib/chef/mixin/recipe_definition_dsl_core.rb +81 -0
- data/lib/chef/mixin/shell_out.rb +38 -0
- data/lib/chef/mixin/template.rb +95 -0
- data/lib/chef/mixin/xml_escape.rb +140 -0
- data/lib/chef/mixins.rb +16 -0
- data/lib/chef/monkey_patches/dir.rb +36 -0
- data/lib/chef/monkey_patches/string.rb +28 -0
- data/lib/chef/monkey_patches/tempfile.rb +64 -0
- data/lib/chef/node/attribute.rb +465 -0
- data/lib/chef/node.rb +601 -0
- data/lib/chef/openid_registration.rb +187 -0
- data/lib/chef/platform.rb +371 -0
- data/lib/chef/provider/breakpoint.rb +36 -0
- data/lib/chef/provider/cookbook_file.rb +100 -0
- data/lib/chef/provider/cron/solaris.rb +195 -0
- data/lib/chef/provider/cron.rb +186 -0
- data/lib/chef/provider/deploy/revision.rb +73 -0
- data/lib/chef/provider/deploy/timestamped.rb +33 -0
- data/lib/chef/provider/deploy.rb +319 -0
- data/lib/chef/provider/directory.rb +72 -0
- data/lib/chef/provider/env/windows.rb +75 -0
- data/lib/chef/provider/env.rb +152 -0
- data/lib/chef/provider/erl_call.rb +72 -0
- data/lib/chef/provider/execute.rb +58 -0
- data/lib/chef/provider/file.rb +213 -0
- data/lib/chef/provider/git.rb +211 -0
- data/lib/chef/provider/group/dscl.rb +121 -0
- data/lib/chef/provider/group/gpasswd.rb +53 -0
- data/lib/chef/provider/group/groupadd.rb +78 -0
- data/lib/chef/provider/group/pw.rb +84 -0
- data/lib/chef/provider/group/usermod.rb +57 -0
- data/lib/chef/provider/group/windows.rb +79 -0
- data/lib/chef/provider/group.rb +133 -0
- data/lib/chef/provider/http_request.rb +122 -0
- data/lib/chef/provider/ifconfig.rb +132 -0
- data/lib/chef/provider/link.rb +161 -0
- data/lib/chef/provider/log.rb +54 -0
- data/lib/chef/provider/mdadm.rb +91 -0
- data/lib/chef/provider/mount/mount.rb +232 -0
- data/lib/chef/provider/mount/windows.rb +80 -0
- data/lib/chef/provider/mount.rb +117 -0
- data/lib/chef/provider/ohai.rb +41 -0
- data/lib/chef/provider/package/apt.rb +110 -0
- data/lib/chef/provider/package/dpkg.rb +112 -0
- data/lib/chef/provider/package/easy_install.rb +114 -0
- data/lib/chef/provider/package/freebsd.rb +123 -0
- data/lib/chef/provider/package/macports.rb +105 -0
- data/lib/chef/provider/package/pacman.rb +101 -0
- data/lib/chef/provider/package/portage.rb +124 -0
- data/lib/chef/provider/package/rpm.rb +101 -0
- data/lib/chef/provider/package/rubygems.rb +462 -0
- data/lib/chef/provider/package/solaris.rb +127 -0
- data/lib/chef/provider/package/yum-dump.py +128 -0
- data/lib/chef/provider/package/yum.rb +222 -0
- data/lib/chef/provider/package/zypper.rb +133 -0
- data/lib/chef/provider/package.rb +160 -0
- data/lib/chef/provider/remote_directory.rb +140 -0
- data/lib/chef/provider/remote_file.rb +120 -0
- data/lib/chef/provider/route.rb +195 -0
- data/lib/chef/provider/ruby_block.rb +33 -0
- data/lib/chef/provider/script.rb +55 -0
- data/lib/chef/provider/service/arch.rb +109 -0
- data/lib/chef/provider/service/debian.rb +105 -0
- data/lib/chef/provider/service/freebsd.rb +156 -0
- data/lib/chef/provider/service/gentoo.rb +54 -0
- data/lib/chef/provider/service/init.rb +71 -0
- data/lib/chef/provider/service/redhat.rb +60 -0
- data/lib/chef/provider/service/simple.rb +118 -0
- data/lib/chef/provider/service/solaris.rb +85 -0
- data/lib/chef/provider/service/upstart.rb +192 -0
- data/lib/chef/provider/service/windows.rb +129 -0
- data/lib/chef/provider/service.rb +128 -0
- data/lib/chef/provider/subversion.rb +159 -0
- data/lib/chef/provider/template.rb +105 -0
- data/lib/chef/provider/user/dscl.rb +280 -0
- data/lib/chef/provider/user/pw.rb +113 -0
- data/lib/chef/provider/user/useradd.rb +137 -0
- data/lib/chef/provider/user/windows.rb +124 -0
- data/lib/chef/provider/user.rb +187 -0
- data/lib/chef/provider.rb +124 -0
- data/lib/chef/providers.rb +91 -0
- data/lib/chef/recipe.rb +130 -0
- data/lib/chef/resource/apt_package.rb +34 -0
- data/lib/chef/resource/bash.rb +33 -0
- data/lib/chef/resource/breakpoint.rb +35 -0
- data/lib/chef/resource/cookbook_file.rb +45 -0
- data/lib/chef/resource/cron.rb +188 -0
- data/lib/chef/resource/csh.rb +33 -0
- data/lib/chef/resource/deploy.rb +371 -0
- data/lib/chef/resource/deploy_revision.rb +35 -0
- data/lib/chef/resource/directory.rb +76 -0
- data/lib/chef/resource/dpkg_package.rb +34 -0
- data/lib/chef/resource/easy_install_package.rb +41 -0
- data/lib/chef/resource/env.rb +58 -0
- data/lib/chef/resource/erl_call.rb +83 -0
- data/lib/chef/resource/execute.rb +127 -0
- data/lib/chef/resource/file.rb +92 -0
- data/lib/chef/resource/freebsd_package.rb +35 -0
- data/lib/chef/resource/gem_package.rb +49 -0
- data/lib/chef/resource/git.rb +36 -0
- data/lib/chef/resource/group.rb +70 -0
- data/lib/chef/resource/http_request.rb +61 -0
- data/lib/chef/resource/ifconfig.rb +134 -0
- data/lib/chef/resource/link.rb +78 -0
- data/lib/chef/resource/log.rb +62 -0
- data/lib/chef/resource/macports_package.rb +29 -0
- data/lib/chef/resource/mdadm.rb +82 -0
- data/lib/chef/resource/mount.rb +135 -0
- data/lib/chef/resource/ohai.rb +40 -0
- data/lib/chef/resource/package.rb +80 -0
- data/lib/chef/resource/pacman_package.rb +33 -0
- data/lib/chef/resource/perl.rb +33 -0
- data/lib/chef/resource/portage_package.rb +33 -0
- data/lib/chef/resource/python.rb +33 -0
- data/lib/chef/resource/remote_directory.rb +109 -0
- data/lib/chef/resource/remote_file.rb +83 -0
- data/lib/chef/resource/route.rb +135 -0
- data/lib/chef/resource/rpm_package.rb +34 -0
- data/lib/chef/resource/ruby.rb +33 -0
- data/lib/chef/resource/ruby_block.rb +40 -0
- data/lib/chef/resource/scm.rb +146 -0
- data/lib/chef/resource/script.rb +60 -0
- data/lib/chef/resource/service.rb +160 -0
- data/lib/chef/resource/solaris_package.rb +36 -0
- data/lib/chef/resource/subversion.rb +36 -0
- data/lib/chef/resource/template.rb +69 -0
- data/lib/chef/resource/timestamped_deploy.rb +31 -0
- data/lib/chef/resource/user.rb +130 -0
- data/lib/chef/resource/yum_package.rb +43 -0
- data/lib/chef/resource.rb +523 -0
- data/lib/chef/resource_collection/stepable_iterator.rb +124 -0
- data/lib/chef/resource_collection.rb +217 -0
- data/lib/chef/resource_definition.rb +67 -0
- data/lib/chef/resource_definition_list.rb +38 -0
- data/lib/chef/resources.rb +64 -0
- data/lib/chef/rest/auth_credentials.rb +78 -0
- data/lib/chef/rest/cookie_jar.rb +31 -0
- data/lib/chef/rest/rest_request.rb +188 -0
- data/lib/chef/rest.rb +394 -0
- data/lib/chef/role.rb +287 -0
- data/lib/chef/run_context.rb +110 -0
- data/lib/chef/run_list/run_list_expansion.rb +172 -0
- data/lib/chef/run_list/run_list_item.rb +78 -0
- data/lib/chef/run_list.rb +150 -0
- data/lib/chef/run_status.rb +121 -0
- data/lib/chef/runner.rb +107 -0
- data/lib/chef/sandbox.rb +153 -0
- data/lib/chef/search/query.rb +60 -0
- data/lib/chef/shef/ext.rb +568 -0
- data/lib/chef/shef/model_wrapper.rb +120 -0
- data/lib/chef/shef/shef_rest.rb +28 -0
- data/lib/chef/shef/shef_session.rb +271 -0
- data/lib/chef/shef.rb +325 -0
- data/lib/chef/shell_out.rb +413 -0
- data/lib/chef/streaming_cookbook_uploader.rb +201 -0
- data/lib/chef/tasks/chef_repo.rake +256 -0
- data/lib/chef/util/file_edit.rb +122 -0
- data/lib/chef/util/windows/net_group.rb +101 -0
- data/lib/chef/util/windows/net_use.rb +121 -0
- data/lib/chef/util/windows/net_user.rb +198 -0
- data/lib/chef/util/windows/volume.rb +59 -0
- data/lib/chef/util/windows.rb +56 -0
- data/lib/chef/version.rb +21 -0
- data/lib/chef/webui_user.rb +231 -0
- data/lib/chef.rb +39 -0
- metadata +533 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Author:: Daniel DeLeo (<dan@opscode.com>)
|
|
3
|
+
# Copyright:: Copyright (c) 2010 Opscode, Inc.
|
|
4
|
+
# License:: Apache License, Version 2.0
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
require 'chef/resource/apt_package'
|
|
20
|
+
require 'chef/resource/bash'
|
|
21
|
+
require 'chef/resource/breakpoint'
|
|
22
|
+
require 'chef/resource/cookbook_file'
|
|
23
|
+
require 'chef/resource/cron'
|
|
24
|
+
require 'chef/resource/csh'
|
|
25
|
+
require 'chef/resource/deploy'
|
|
26
|
+
require 'chef/resource/deploy_revision'
|
|
27
|
+
require 'chef/resource/directory'
|
|
28
|
+
require 'chef/resource/dpkg_package'
|
|
29
|
+
require 'chef/resource/easy_install_package'
|
|
30
|
+
require 'chef/resource/env'
|
|
31
|
+
require 'chef/resource/erl_call'
|
|
32
|
+
require 'chef/resource/execute'
|
|
33
|
+
require 'chef/resource/file'
|
|
34
|
+
require 'chef/resource/freebsd_package'
|
|
35
|
+
require 'chef/resource/gem_package'
|
|
36
|
+
require 'chef/resource/git'
|
|
37
|
+
require 'chef/resource/group'
|
|
38
|
+
require 'chef/resource/http_request'
|
|
39
|
+
require 'chef/resource/ifconfig'
|
|
40
|
+
require 'chef/resource/link'
|
|
41
|
+
require 'chef/resource/log'
|
|
42
|
+
require 'chef/resource/macports_package'
|
|
43
|
+
require 'chef/resource/mdadm'
|
|
44
|
+
require 'chef/resource/mount'
|
|
45
|
+
require 'chef/resource/ohai'
|
|
46
|
+
require 'chef/resource/package'
|
|
47
|
+
require 'chef/resource/pacman_package'
|
|
48
|
+
require 'chef/resource/perl'
|
|
49
|
+
require 'chef/resource/portage_package'
|
|
50
|
+
require 'chef/resource/python'
|
|
51
|
+
require 'chef/resource/remote_directory'
|
|
52
|
+
require 'chef/resource/remote_file'
|
|
53
|
+
require 'chef/resource/rpm_package'
|
|
54
|
+
require 'chef/resource/route'
|
|
55
|
+
require 'chef/resource/ruby'
|
|
56
|
+
require 'chef/resource/ruby_block'
|
|
57
|
+
require 'chef/resource/scm'
|
|
58
|
+
require 'chef/resource/script'
|
|
59
|
+
require 'chef/resource/service'
|
|
60
|
+
require 'chef/resource/subversion'
|
|
61
|
+
require 'chef/resource/template'
|
|
62
|
+
require 'chef/resource/timestamped_deploy'
|
|
63
|
+
require 'chef/resource/user'
|
|
64
|
+
require 'chef/resource/yum_package'
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
|
3
|
+
# Author:: Thom May (<thom@clearairturbulence.org>)
|
|
4
|
+
# Author:: Nuo Yan (<nuo@opscode.com>)
|
|
5
|
+
# Author:: Christopher Brown (<cb@opscode.com>)
|
|
6
|
+
# Author:: Christopher Walters (<cw@opscode.com>)
|
|
7
|
+
# Author:: Daniel DeLeo (<dan@opscode.com>)
|
|
8
|
+
# Copyright:: Copyright (c) 2009, 2010 Opscode, Inc.
|
|
9
|
+
# License:: Apache License, Version 2.0
|
|
10
|
+
#
|
|
11
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
# you may not use this file except in compliance with the License.
|
|
13
|
+
# You may obtain a copy of the License at
|
|
14
|
+
#
|
|
15
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
#
|
|
17
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
# See the License for the specific language governing permissions and
|
|
21
|
+
# limitations under the License.
|
|
22
|
+
#
|
|
23
|
+
require 'chef/exceptions'
|
|
24
|
+
require 'mixlib/authentication/signedheaderauth'
|
|
25
|
+
|
|
26
|
+
class Chef
|
|
27
|
+
class REST
|
|
28
|
+
class AuthCredentials
|
|
29
|
+
attr_reader :key_file, :client_name, :key, :raw_key
|
|
30
|
+
|
|
31
|
+
def initialize(client_name=nil, key_file=nil)
|
|
32
|
+
@client_name, @key_file = client_name, key_file
|
|
33
|
+
load_signing_key if sign_requests?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def sign_requests?
|
|
37
|
+
!!key_file
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def signature_headers(request_params={})
|
|
41
|
+
raise ArgumentError, "Cannot sign the request without a client name, check that :node_name is assigned" if client_name.nil?
|
|
42
|
+
Chef::Log.debug("Signing the request as #{client_name}")
|
|
43
|
+
|
|
44
|
+
# params_in = {:http_method => :GET, :path => "/clients", :body => "", :host => "localhost"}
|
|
45
|
+
request_params = request_params.dup
|
|
46
|
+
request_params[:timestamp] = Time.now.utc.iso8601
|
|
47
|
+
request_params[:user_id] = client_name
|
|
48
|
+
host = request_params.delete(:host) || "localhost"
|
|
49
|
+
|
|
50
|
+
sign_obj = Mixlib::Authentication::SignedHeaderAuth.signing_object(request_params)
|
|
51
|
+
signed = sign_obj.sign(key).merge({:host => host})
|
|
52
|
+
signed.inject({}){|memo, kv| memo["#{kv[0].to_s.upcase}"] = kv[1];memo}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def load_signing_key
|
|
58
|
+
begin
|
|
59
|
+
@raw_key = IO.read(key_file).strip
|
|
60
|
+
rescue SystemCallError, IOError => e
|
|
61
|
+
Chef::Log.fatal "Failed to read the private key #{key_file}: #{e.inspect}, #{e.backtrace}"
|
|
62
|
+
raise Chef::Exceptions::PrivateKeyMissing, "I cannot read #{key_file}, which you told me to use to sign requests!"
|
|
63
|
+
end
|
|
64
|
+
assert_valid_key_format!(@raw_key)
|
|
65
|
+
@key = OpenSSL::PKey::RSA.new(@raw_key)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def assert_valid_key_format!(raw_key)
|
|
69
|
+
unless (raw_key =~ /\A-----BEGIN RSA PRIVATE KEY-----$/) && (raw_key =~ /^-----END RSA PRIVATE KEY-----\Z/)
|
|
70
|
+
msg = "The file #{key_file} does not contain a correctly formatted private key.\n"
|
|
71
|
+
msg << "The key file should begin with '-----BEGIN RSA PRIVATE KEY-----' and end with '-----END RSA PRIVATE KEY-----'"
|
|
72
|
+
raise Chef::Exceptions::InvalidPrivateKey, msg
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
|
3
|
+
# Author:: Thom May (<thom@clearairturbulence.org>)
|
|
4
|
+
# Author:: Nuo Yan (<nuo@opscode.com>)
|
|
5
|
+
# Author:: Christopher Brown (<cb@opscode.com>)
|
|
6
|
+
# Author:: Christopher Walters (<cw@opscode.com>)
|
|
7
|
+
# Author:: Daniel DeLeo (<dan@opscode.com>)
|
|
8
|
+
# Copyright:: Copyright (c) 2009, 2010 Opscode, Inc.
|
|
9
|
+
# License:: Apache License, Version 2.0
|
|
10
|
+
#
|
|
11
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
# you may not use this file except in compliance with the License.
|
|
13
|
+
# You may obtain a copy of the License at
|
|
14
|
+
#
|
|
15
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
#
|
|
17
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
# See the License for the specific language governing permissions and
|
|
21
|
+
# limitations under the License.
|
|
22
|
+
#
|
|
23
|
+
require 'singleton'
|
|
24
|
+
|
|
25
|
+
class Chef
|
|
26
|
+
class REST
|
|
27
|
+
class CookieJar < Hash
|
|
28
|
+
include Singleton
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
|
3
|
+
# Author:: Thom May (<thom@clearairturbulence.org>)
|
|
4
|
+
# Author:: Nuo Yan (<nuo@opscode.com>)
|
|
5
|
+
# Author:: Christopher Brown (<cb@opscode.com>)
|
|
6
|
+
# Author:: Christopher Walters (<cw@opscode.com>)
|
|
7
|
+
# Author:: Daniel DeLeo (<dan@opscode.com>)
|
|
8
|
+
# Copyright:: Copyright (c) 2009, 2010 Opscode, Inc.
|
|
9
|
+
# License:: Apache License, Version 2.0
|
|
10
|
+
#
|
|
11
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
# you may not use this file except in compliance with the License.
|
|
13
|
+
# You may obtain a copy of the License at
|
|
14
|
+
#
|
|
15
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
#
|
|
17
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
# See the License for the specific language governing permissions and
|
|
21
|
+
# limitations under the License.
|
|
22
|
+
#
|
|
23
|
+
require 'uri'
|
|
24
|
+
require 'net/http'
|
|
25
|
+
require 'chef/rest/cookie_jar'
|
|
26
|
+
require 'chef/version'
|
|
27
|
+
|
|
28
|
+
class Chef
|
|
29
|
+
class REST
|
|
30
|
+
class RESTRequest
|
|
31
|
+
attr_reader :method, :url, :headers, :http_client, :http_request
|
|
32
|
+
|
|
33
|
+
def initialize(method, url, req_body, base_headers={})
|
|
34
|
+
@method, @url = method, url
|
|
35
|
+
@request_body = nil
|
|
36
|
+
@cookies = CookieJar.instance
|
|
37
|
+
configure_http_client
|
|
38
|
+
build_headers(base_headers)
|
|
39
|
+
configure_http_request(req_body)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def host
|
|
43
|
+
@url.host
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def port
|
|
47
|
+
@url.port
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def query
|
|
51
|
+
@url.query
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def path
|
|
55
|
+
@url.path.empty? ? "/" : @url.path
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def call
|
|
59
|
+
hide_net_http_bug do
|
|
60
|
+
http_client.request(http_request) do |response|
|
|
61
|
+
store_cookie(response)
|
|
62
|
+
yield response if block_given?
|
|
63
|
+
response
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def config
|
|
69
|
+
Chef::Config
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def hide_net_http_bug
|
|
75
|
+
yield
|
|
76
|
+
rescue NoMethodError => e
|
|
77
|
+
# http://redmine.ruby-lang.org/issues/show/2708
|
|
78
|
+
# http://redmine.ruby-lang.org/issues/show/2758
|
|
79
|
+
if e.to_s =~ /#{Regexp.escape(%q|undefined method `closed?' for nil:NilClass|)}/
|
|
80
|
+
Chef::Log.debug("rescued error in http connect, re-raising as Errno::ECONNREFUSED to hide bug in net/http")
|
|
81
|
+
Chef::Log.debug("#{e.class.name}: #{e.to_s}")
|
|
82
|
+
Chef::Log.debug(e.backtrace.join("\n"))
|
|
83
|
+
raise Errno::ECONNREFUSED, "Connection refused attempting to contact #{url.scheme}://#{host}:#{port}"
|
|
84
|
+
else
|
|
85
|
+
raise
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def store_cookie(response)
|
|
90
|
+
if response['set-cookie']
|
|
91
|
+
@cookies["#{host}:#{port}"] = response['set-cookie']
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def build_headers(headers)
|
|
96
|
+
@headers = headers.dup
|
|
97
|
+
# TODO: need to set accept somewhere else
|
|
98
|
+
# headers.merge!('Accept' => "application/json") unless raw
|
|
99
|
+
@headers['X-Chef-Version'] = ::Chef::VERSION
|
|
100
|
+
|
|
101
|
+
if @cookies.has_key?("#{host}:#{port}")
|
|
102
|
+
@headers['Cookie'] = @cookies["#{host}:#{port}"]
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
#adapted from buildr/lib/buildr/core/transports.rb
|
|
107
|
+
def proxy_uri
|
|
108
|
+
proxy = Chef::Config["#{url.scheme}_proxy"]
|
|
109
|
+
proxy = URI.parse(proxy) if String === proxy
|
|
110
|
+
excludes = Chef::Config[:no_proxy].to_s.split(/\s*,\s*/).compact
|
|
111
|
+
excludes = excludes.map { |exclude| exclude =~ /:\d+$/ ? exclude : "#{exclude}:*" }
|
|
112
|
+
return proxy unless excludes.any? { |exclude| File.fnmatch(exclude, "#{host}:#{port}") }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def configure_http_client
|
|
116
|
+
http_proxy = proxy_uri
|
|
117
|
+
if http_proxy.nil?
|
|
118
|
+
@http_client = Net::HTTP.new(host, port)
|
|
119
|
+
else
|
|
120
|
+
Chef::Log.debug("using #{http_proxy.host}:#{http_proxy.port} for proxy")
|
|
121
|
+
user = Chef::Config["#{url.scheme}_proxy_user"]
|
|
122
|
+
pass = Chef::Config["#{url.scheme}_proxy_pass"]
|
|
123
|
+
@http_client = Net::HTTP.Proxy(http_proxy.host, http_proxy.port, user, pass).new(host, port)
|
|
124
|
+
end
|
|
125
|
+
if url.scheme == "https"
|
|
126
|
+
@http_client.use_ssl = true
|
|
127
|
+
if config[:ssl_verify_mode] == :verify_none
|
|
128
|
+
@http_client.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
129
|
+
elsif config[:ssl_verify_mode] == :verify_peer
|
|
130
|
+
@http_client.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
131
|
+
end
|
|
132
|
+
if config[:ssl_ca_path]
|
|
133
|
+
unless ::File.exist?(config[:ssl_ca_path])
|
|
134
|
+
raise Chef::Exceptions::ConfigurationError, "The configured ssl_ca_path #{config[:ssl_ca_path]} does not exist"
|
|
135
|
+
end
|
|
136
|
+
@http_client.ca_path = config[:ssl_ca_path]
|
|
137
|
+
elsif config[:ssl_ca_file]
|
|
138
|
+
unless ::File.exist?(config[:ssl_ca_file])
|
|
139
|
+
raise Chef::Exceptions::ConfigurationError, "The configured ssl_ca_file #{config[:ssl_ca_file]} does not exist"
|
|
140
|
+
end
|
|
141
|
+
@http_client.ca_file = config[:ssl_ca_file]
|
|
142
|
+
end
|
|
143
|
+
if (config[:ssl_client_cert] || config[:ssl_client_key])
|
|
144
|
+
unless (config[:ssl_client_cert] && config[:ssl_client_key])
|
|
145
|
+
raise Chef::Exceptions::ConfigurationError, "You must configure ssl_client_cert and ssl_client_key together"
|
|
146
|
+
end
|
|
147
|
+
unless ::File.exists?(config[:ssl_client_cert])
|
|
148
|
+
raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_cert #{config[:ssl_client_cert]} does not exist"
|
|
149
|
+
end
|
|
150
|
+
unless ::File.exists?(config[:ssl_client_key])
|
|
151
|
+
raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_key #{config[:ssl_client_key]} does not exist"
|
|
152
|
+
end
|
|
153
|
+
@http_client.cert = OpenSSL::X509::Certificate.new(::File.read(config[:ssl_client_cert]))
|
|
154
|
+
@http_client.key = OpenSSL::PKey::RSA.new(::File.read(config[:ssl_client_key]))
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
@http_client.read_timeout = config[:rest_timeout]
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def configure_http_request(request_body=nil)
|
|
163
|
+
req_path = "#{path}"
|
|
164
|
+
req_path << "?#{query}" if query
|
|
165
|
+
|
|
166
|
+
@http_request = case method.to_s.downcase
|
|
167
|
+
when "get"
|
|
168
|
+
Net::HTTP::Get.new(req_path, headers)
|
|
169
|
+
when "post"
|
|
170
|
+
Net::HTTP::Post.new(req_path, headers)
|
|
171
|
+
when "put"
|
|
172
|
+
Net::HTTP::Put.new(req_path, headers)
|
|
173
|
+
when "delete"
|
|
174
|
+
Net::HTTP::Delete.new(req_path, headers)
|
|
175
|
+
when "head"
|
|
176
|
+
Net::HTTP::Head.new(req_path, headers)
|
|
177
|
+
else
|
|
178
|
+
raise ArgumentError, "You must provide :GET, :PUT, :POST, :DELETE or :HEAD as the method"
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
@http_request.body = request_body if (request_body && @http_request.request_body_permitted?)
|
|
182
|
+
# Optionally handle HTTP Basic Authentication
|
|
183
|
+
@http_request.basic_auth(url.user, url.password) if url.user
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
data/lib/chef/rest.rb
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
|
3
|
+
# Author:: Thom May (<thom@clearairturbulence.org>)
|
|
4
|
+
# Author:: Nuo Yan (<nuo@opscode.com>)
|
|
5
|
+
# Author:: Christopher Brown (<cb@opscode.com>)
|
|
6
|
+
# Author:: Christopher Walters (<cw@opscode.com>)
|
|
7
|
+
# Copyright:: Copyright (c) 2009, 2010 Opscode, Inc.
|
|
8
|
+
# License:: Apache License, Version 2.0
|
|
9
|
+
#
|
|
10
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
11
|
+
# you may not use this file except in compliance with the License.
|
|
12
|
+
# You may obtain a copy of the License at
|
|
13
|
+
#
|
|
14
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
15
|
+
#
|
|
16
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
17
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
18
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
19
|
+
# See the License for the specific language governing permissions and
|
|
20
|
+
# limitations under the License.
|
|
21
|
+
#
|
|
22
|
+
|
|
23
|
+
require 'net/https'
|
|
24
|
+
require 'uri'
|
|
25
|
+
require 'json'
|
|
26
|
+
require 'tempfile'
|
|
27
|
+
require 'chef/api_client'
|
|
28
|
+
require 'chef/rest/auth_credentials'
|
|
29
|
+
require 'chef/rest/rest_request'
|
|
30
|
+
require 'chef/monkey_patches/string'
|
|
31
|
+
|
|
32
|
+
class Chef
|
|
33
|
+
# == Chef::REST
|
|
34
|
+
# Chef's custom REST client with built-in JSON support and RSA signed header
|
|
35
|
+
# authentication.
|
|
36
|
+
class REST
|
|
37
|
+
attr_reader :auth_credentials
|
|
38
|
+
attr_accessor :url, :cookies, :sign_on_redirect, :redirect_limit
|
|
39
|
+
|
|
40
|
+
# Create a REST client object. The supplied +url+ is used as the base for
|
|
41
|
+
# all subsequent requests. For example, when initialized with a base url
|
|
42
|
+
# http://localhost:4000, a call to +get_rest+ with 'nodes' will make an
|
|
43
|
+
# HTTP GET request to http://localhost:4000/nodes
|
|
44
|
+
def initialize(url, client_name=Chef::Config[:node_name], signing_key_filename=Chef::Config[:client_key], options={})
|
|
45
|
+
@url = url
|
|
46
|
+
@cookies = CookieJar.instance
|
|
47
|
+
@default_headers = options[:headers] || {}
|
|
48
|
+
@auth_credentials = AuthCredentials.new(client_name, signing_key_filename)
|
|
49
|
+
@sign_on_redirect, @sign_request = true, true
|
|
50
|
+
@redirects_followed = 0
|
|
51
|
+
@redirect_limit = 10
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def signing_key_filename
|
|
55
|
+
@auth_credentials.key_file
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def client_name
|
|
59
|
+
@auth_credentials.client_name
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def signing_key
|
|
63
|
+
@auth_credentials.raw_key
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Register the client
|
|
67
|
+
def register(name=Chef::Config[:node_name], destination=Chef::Config[:client_key])
|
|
68
|
+
if (File.exists?(destination) && !File.writable?(destination))
|
|
69
|
+
raise Chef::Exceptions::CannotWritePrivateKey, "I cannot write your private key to #{destination} - check permissions?"
|
|
70
|
+
end
|
|
71
|
+
nc = Chef::ApiClient.new
|
|
72
|
+
nc.name(name)
|
|
73
|
+
|
|
74
|
+
catch(:done) do
|
|
75
|
+
retries = config[:client_registration_retries] || 5
|
|
76
|
+
0.upto(retries) do |n|
|
|
77
|
+
begin
|
|
78
|
+
response = nc.save(true, true)
|
|
79
|
+
Chef::Log.debug("Registration response: #{response.inspect}")
|
|
80
|
+
raise Chef::Exceptions::CannotWritePrivateKey, "The response from the server did not include a private key!" unless response.has_key?("private_key")
|
|
81
|
+
# Write out the private key
|
|
82
|
+
file = ::File.open(destination, File::WRONLY|File::EXCL|File::CREAT, 0600)
|
|
83
|
+
file.print(response["private_key"])
|
|
84
|
+
file.close
|
|
85
|
+
throw :done
|
|
86
|
+
rescue IOError
|
|
87
|
+
raise Chef::Exceptions::CannotWritePrivateKey, "I cannot write your private key to #{destination}"
|
|
88
|
+
rescue Net::HTTPFatalError => e
|
|
89
|
+
Chef::Log.warn("Failed attempt #{n} of #{retries+1} on client creation")
|
|
90
|
+
raise unless e.response.code == "500"
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
true
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Send an HTTP GET request to the path
|
|
99
|
+
#
|
|
100
|
+
# Using this method to +fetch+ a file is considered deprecated.
|
|
101
|
+
#
|
|
102
|
+
# === Parameters
|
|
103
|
+
# path:: The path to GET
|
|
104
|
+
# raw:: Whether you want the raw body returned, or JSON inflated. Defaults
|
|
105
|
+
# to JSON inflated.
|
|
106
|
+
def get_rest(path, raw=false, headers={})
|
|
107
|
+
if raw
|
|
108
|
+
streaming_request(create_url(path), headers)
|
|
109
|
+
else
|
|
110
|
+
api_request(:GET, create_url(path), headers)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Send an HTTP DELETE request to the path
|
|
115
|
+
def delete_rest(path, headers={})
|
|
116
|
+
api_request(:DELETE, create_url(path), headers)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Send an HTTP POST request to the path
|
|
120
|
+
def post_rest(path, json, headers={})
|
|
121
|
+
api_request(:POST, create_url(path), headers, json)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Send an HTTP PUT request to the path
|
|
125
|
+
def put_rest(path, json, headers={})
|
|
126
|
+
api_request(:PUT, create_url(path), headers, json)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Streams a download to a tempfile, then yields the tempfile to a block.
|
|
130
|
+
# After the download, the tempfile will be closed and unlinked.
|
|
131
|
+
# If you rename the tempfile, it will not be deleted.
|
|
132
|
+
# Beware that if the server streams infinite content, this method will
|
|
133
|
+
# stream it until you run out of disk space.
|
|
134
|
+
def fetch(path, headers={})
|
|
135
|
+
streaming_request(create_url(path), headers) {|tmp_file| yield tmp_file }
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def create_url(path)
|
|
139
|
+
if path =~ /^(http|https):\/\//
|
|
140
|
+
URI.parse(path)
|
|
141
|
+
else
|
|
142
|
+
URI.parse("#{@url}/#{path}")
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def sign_requests?
|
|
147
|
+
auth_credentials.sign_requests? && @sign_request
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# ==== DEPRECATED
|
|
151
|
+
# Use +api_request+ instead
|
|
152
|
+
#--
|
|
153
|
+
# Actually run an HTTP request. First argument is the HTTP method,
|
|
154
|
+
# which should be one of :GET, :PUT, :POST or :DELETE. Next is the
|
|
155
|
+
# URL, then an object to include in the body (which will be converted with
|
|
156
|
+
# .to_json). The limit argument is unused, it is present for backwards
|
|
157
|
+
# compatibility. Configure the redirect limit with #redirect_limit=
|
|
158
|
+
# instead.
|
|
159
|
+
#
|
|
160
|
+
# Typically, you won't use this method -- instead, you'll use one of
|
|
161
|
+
# the helper methods (get_rest, post_rest, etc.)
|
|
162
|
+
#
|
|
163
|
+
# Will return the body of the response on success.
|
|
164
|
+
def run_request(method, url, headers={}, data=false, limit=nil, raw=false)
|
|
165
|
+
json_body = data ? data.to_json : nil
|
|
166
|
+
headers = build_headers(method, url, headers, json_body, raw)
|
|
167
|
+
|
|
168
|
+
tf = nil
|
|
169
|
+
|
|
170
|
+
retriable_rest_request(method, url, json_body, headers) do |rest_request|
|
|
171
|
+
|
|
172
|
+
res = rest_request.call do |response|
|
|
173
|
+
if raw
|
|
174
|
+
tf = stream_to_tempfile(url, response)
|
|
175
|
+
else
|
|
176
|
+
response.read_body
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
if res.kind_of?(Net::HTTPSuccess)
|
|
181
|
+
if res['content-type'] =~ /json/
|
|
182
|
+
response_body = res.body.chomp
|
|
183
|
+
JSON.parse(response_body)
|
|
184
|
+
else
|
|
185
|
+
if method == :HEAD
|
|
186
|
+
true
|
|
187
|
+
elsif raw
|
|
188
|
+
tf
|
|
189
|
+
else
|
|
190
|
+
res.body
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
elsif res.kind_of?(Net::HTTPFound) or res.kind_of?(Net::HTTPMovedPermanently)
|
|
194
|
+
follow_redirect {run_request(:GET, create_url(res['location']), {}, false, nil, raw)}
|
|
195
|
+
elsif res.kind_of?(Net::HTTPNotModified)
|
|
196
|
+
false
|
|
197
|
+
else
|
|
198
|
+
if res['content-type'] =~ /json/
|
|
199
|
+
exception = JSON.parse(res.body)
|
|
200
|
+
msg = "HTTP Request Returned #{res.code} #{res.message}: "
|
|
201
|
+
msg << (exception["error"].respond_to?(:join) ? exception["error"].join(", ") : exception["error"].to_s)
|
|
202
|
+
Chef::Log.warn(msg)
|
|
203
|
+
end
|
|
204
|
+
res.error!
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Runs an HTTP request to a JSON API. File Download not supported.
|
|
210
|
+
def api_request(method, url, headers={}, data=false)
|
|
211
|
+
json_body = data ? data.to_json : nil
|
|
212
|
+
headers = build_headers(method, url, headers, json_body)
|
|
213
|
+
|
|
214
|
+
retriable_rest_request(method, url, json_body, headers) do |rest_request|
|
|
215
|
+
response = rest_request.call {|r| r.read_body}
|
|
216
|
+
|
|
217
|
+
if response.kind_of?(Net::HTTPSuccess)
|
|
218
|
+
if response['content-type'] =~ /json/
|
|
219
|
+
JSON.parse(response.body.chomp)
|
|
220
|
+
else
|
|
221
|
+
Chef::Log.warn("Expected JSON response, but got content-type '#{response['content-type']}'")
|
|
222
|
+
response.body
|
|
223
|
+
end
|
|
224
|
+
elsif redirect_location = redirected_to(response)
|
|
225
|
+
follow_redirect {api_request(:GET, create_url(redirect_location))}
|
|
226
|
+
else
|
|
227
|
+
if response['content-type'] =~ /json/
|
|
228
|
+
exception = JSON.parse(response.body)
|
|
229
|
+
msg = "HTTP Request Returned #{response.code} #{response.message}: "
|
|
230
|
+
msg << (exception["error"].respond_to?(:join) ? exception["error"].join(", ") : exception["error"].to_s)
|
|
231
|
+
Chef::Log.warn(msg)
|
|
232
|
+
end
|
|
233
|
+
response.error!
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# Makes a streaming download request. <b>Doesn't speak JSON.</b>
|
|
239
|
+
# Streams the response body to a tempfile. If a block is given, it's
|
|
240
|
+
# passed to Tempfile.open(), which means that the tempfile will automatically
|
|
241
|
+
# be unlinked after the block is executed.
|
|
242
|
+
#
|
|
243
|
+
# If no block is given, the tempfile is returned, which means it's up to
|
|
244
|
+
# you to unlink the tempfile when you're done with it.
|
|
245
|
+
def streaming_request(url, headers, &block)
|
|
246
|
+
headers = build_headers(:GET, url, headers, nil, true)
|
|
247
|
+
retriable_rest_request(:GET, url, nil, headers) do |rest_request|
|
|
248
|
+
tempfile = nil
|
|
249
|
+
response = rest_request.call do |r|
|
|
250
|
+
if block_given? && r.kind_of?(Net::HTTPSuccess)
|
|
251
|
+
begin
|
|
252
|
+
tempfile = stream_to_tempfile(url, r, &block)
|
|
253
|
+
yield tempfile
|
|
254
|
+
ensure
|
|
255
|
+
tempfile.close!
|
|
256
|
+
end
|
|
257
|
+
else
|
|
258
|
+
tempfile = stream_to_tempfile(url, r)
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
if response.kind_of?(Net::HTTPSuccess)
|
|
262
|
+
tempfile
|
|
263
|
+
elsif redirect_location = redirected_to(response)
|
|
264
|
+
# TODO: test tempfile unlinked when following redirects.
|
|
265
|
+
tempfile && tempfile.close!
|
|
266
|
+
follow_redirect {streaming_request(create_url(redirect_location), {}, &block)}
|
|
267
|
+
else
|
|
268
|
+
tempfile && tempfile.close!
|
|
269
|
+
response.error!
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def retriable_rest_request(method, url, req_body, headers)
|
|
275
|
+
rest_request = Chef::REST::RESTRequest.new(method, url, req_body, headers)
|
|
276
|
+
|
|
277
|
+
Chef::Log.debug("Sending HTTP Request via #{method} to #{url.host}:#{url.port}#{rest_request.path}")
|
|
278
|
+
|
|
279
|
+
http_attempts = 0
|
|
280
|
+
|
|
281
|
+
begin
|
|
282
|
+
http_attempts += 1
|
|
283
|
+
|
|
284
|
+
res = yield rest_request
|
|
285
|
+
|
|
286
|
+
rescue Errno::ECONNREFUSED
|
|
287
|
+
if http_retry_count - http_attempts + 1 > 0
|
|
288
|
+
Chef::Log.error("Connection refused connecting to #{url.host}:#{url.port} for #{rest_request.path}, retry #{http_attempts}/#{http_retry_count}")
|
|
289
|
+
sleep(http_retry_delay)
|
|
290
|
+
retry
|
|
291
|
+
end
|
|
292
|
+
raise Errno::ECONNREFUSED, "Connection refused connecting to #{url.host}:#{url.port} for #{rest_request.path}, giving up"
|
|
293
|
+
rescue Timeout::Error
|
|
294
|
+
if http_retry_count - http_attempts + 1 > 0
|
|
295
|
+
Chef::Log.error("Timeout connecting to #{url.host}:#{url.port} for #{rest_request.path}, retry #{http_attempts}/#{http_retry_count}")
|
|
296
|
+
sleep(http_retry_delay)
|
|
297
|
+
retry
|
|
298
|
+
end
|
|
299
|
+
raise Timeout::Error, "Timeout connecting to #{url.host}:#{url.port} for #{rest_request.path}, giving up"
|
|
300
|
+
rescue Net::HTTPServerException
|
|
301
|
+
if res.kind_of?(Net::HTTPForbidden)
|
|
302
|
+
if http_retry_count - http_attempts + 1 > 0
|
|
303
|
+
Chef::Log.error("Received 403 Forbidden against #{url.host}:#{url.port} for #{rest_request.path}, retry #{http_attempts}/#{http_retry_count}")
|
|
304
|
+
sleep(http_retry_delay)
|
|
305
|
+
retry
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
raise
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def authentication_headers(method, url, json_body=nil)
|
|
313
|
+
request_params = {:http_method => method, :path => url.path, :body => json_body, :host => "#{url.host}:#{url.port}"}
|
|
314
|
+
request_params[:body] ||= ""
|
|
315
|
+
auth_credentials.signature_headers(request_params)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def http_retry_delay
|
|
319
|
+
config[:http_retry_delay]
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def http_retry_count
|
|
323
|
+
config[:http_retry_count]
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def config
|
|
327
|
+
Chef::Config
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def follow_redirect
|
|
331
|
+
raise Chef::Exceptions::RedirectLimitExceeded if @redirects_followed >= redirect_limit
|
|
332
|
+
@redirects_followed += 1
|
|
333
|
+
Chef::Log.debug("Following redirect #{@redirects_followed}/#{redirect_limit}")
|
|
334
|
+
if @sign_on_redirect
|
|
335
|
+
yield
|
|
336
|
+
else
|
|
337
|
+
@sign_request = false
|
|
338
|
+
yield
|
|
339
|
+
end
|
|
340
|
+
ensure
|
|
341
|
+
@redirects_followed = 0
|
|
342
|
+
@sign_request = true
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
private
|
|
346
|
+
|
|
347
|
+
def redirected_to(response)
|
|
348
|
+
if response.kind_of?(Net::HTTPFound) || response.kind_of?(Net::HTTPMovedPermanently)
|
|
349
|
+
response['location']
|
|
350
|
+
else
|
|
351
|
+
nil
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def build_headers(method, url, headers={}, json_body=false, raw=false)
|
|
356
|
+
headers = @default_headers.merge(headers)
|
|
357
|
+
headers['Accept'] = "application/json" unless raw
|
|
358
|
+
headers["Content-Type"] = 'application/json' if json_body
|
|
359
|
+
headers['Content-Length'] = json_body.bytesize.to_s if json_body
|
|
360
|
+
headers.merge!(authentication_headers(method, url, json_body)) if sign_requests?
|
|
361
|
+
headers
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def stream_to_tempfile(url, response)
|
|
365
|
+
tf = Tempfile.open("chef-rest")
|
|
366
|
+
if RUBY_PLATFORM =~ /mswin|mingw32|windows/
|
|
367
|
+
tf.binmode #required for binary files on Windows platforms
|
|
368
|
+
end
|
|
369
|
+
Chef::Log.debug("Streaming download from #{url.to_s} to tempfile #{tf.path}")
|
|
370
|
+
# Stolen from http://www.ruby-forum.com/topic/166423
|
|
371
|
+
# Kudos to _why!
|
|
372
|
+
size, total = 0, response.header['Content-Length'].to_i
|
|
373
|
+
response.read_body do |chunk|
|
|
374
|
+
tf.write(chunk)
|
|
375
|
+
size += chunk.size
|
|
376
|
+
if Chef::Log.verbose
|
|
377
|
+
if size == 0
|
|
378
|
+
Chef::Log.debug("#{url.path} done (0 length file)")
|
|
379
|
+
elsif total == 0
|
|
380
|
+
Chef::Log.debug("#{url.path} (zero content length or no Content-Length header)")
|
|
381
|
+
else
|
|
382
|
+
Chef::Log.debug("#{url.path}" + " %d%% done (%d of %d)" % [(size * 100) / total, size, total])
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
tf.close
|
|
387
|
+
tf
|
|
388
|
+
rescue Exception
|
|
389
|
+
tf.close!
|
|
390
|
+
raise
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
end
|
|
394
|
+
end
|