chef 0.8.16 → 0.9.0.a3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of chef might be problematic. Click here for more details.
- data/bin/shef +1 -0
- data/distro/common/man/man1/chef-server-webui.1 +106 -0
- data/distro/common/man/man1/chef-server.1 +0 -1
- 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 +4 -2
- data/distro/common/man/man8/chef-solo.8 +1 -2
- data/distro/common/man/man8/chef-solr-rebuild.8 +37 -0
- data/distro/common/man/man8/knife.8 +668 -266
- data/distro/common/man/man8/shef.8 +45 -0
- data/distro/common/markdown/README +3 -0
- data/distro/common/markdown/knife.mkd +520 -0
- data/distro/debian/etc/default/chef-client +4 -0
- data/distro/debian/etc/default/chef-server +6 -0
- data/distro/debian/etc/default/chef-server-webui +6 -0
- data/distro/debian/etc/default/chef-solr +4 -0
- data/distro/debian/etc/default/chef-solr-indexer +4 -0
- data/distro/debian/etc/init.d/chef-client +41 -41
- data/distro/debian/etc/init.d/chef-server +10 -10
- data/distro/debian/etc/init.d/chef-server-webui +121 -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 +76 -48
- data/distro/redhat/etc/init.d/chef-server +85 -51
- data/distro/redhat/etc/init.d/chef-server-webui +85 -51
- data/distro/redhat/etc/init.d/chef-solr +77 -49
- data/distro/redhat/etc/init.d/chef-solr-indexer +77 -48
- 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 +9 -4
- data/distro/redhat/etc/sysconfig/chef-server +10 -6
- data/distro/redhat/etc/sysconfig/chef-server-webui +10 -6
- data/distro/redhat/etc/sysconfig/chef-solr +3 -4
- data/distro/redhat/etc/sysconfig/chef-solr-indexer +3 -3
- data/lib/chef.rb +16 -5
- data/lib/chef/application/knife.rb +2 -2
- data/lib/chef/application/solo.rb +1 -7
- data/lib/chef/cache/checksum.rb +12 -5
- data/lib/chef/cache/file_cache_by_checksum.rb +52 -0
- data/lib/chef/checksum.rb +115 -0
- data/lib/chef/client.rb +193 -185
- data/lib/chef/config.rb +9 -1
- data/lib/chef/cookbook/cookbook_collection.rb +43 -0
- data/lib/chef/cookbook/file_system_file_vendor.rb +53 -0
- data/lib/chef/cookbook/file_vendor.rb +47 -0
- data/lib/chef/cookbook/metadata.rb +34 -35
- data/lib/chef/cookbook/metadata/version.rb +1 -1
- data/lib/chef/cookbook_loader.rb +70 -45
- data/lib/chef/cookbook_version.rb +760 -0
- data/lib/chef/couchdb.rb +8 -5
- data/lib/chef/data_bag_item.rb +5 -5
- data/lib/chef/exceptions.rb +10 -0
- data/lib/chef/file_access_control.rb +134 -0
- data/lib/chef/handler.rb +62 -0
- data/lib/chef/handler/json_file.rb +47 -0
- data/lib/chef/knife.rb +14 -2
- data/lib/chef/knife/bootstrap.rb +126 -0
- data/lib/chef/knife/cookbook_bulk_delete.rb +1 -1
- data/lib/chef/knife/cookbook_delete.rb +4 -4
- data/lib/chef/knife/cookbook_download.rb +57 -26
- data/lib/chef/knife/cookbook_metadata.rb +2 -2
- data/lib/chef/knife/cookbook_show.rb +30 -11
- data/lib/chef/knife/cookbook_upload.rb +113 -86
- data/lib/chef/knife/ec2_server_create.rb +146 -0
- data/lib/chef/knife/ec2_server_delete.rb +84 -0
- data/lib/chef/knife/ec2_server_list.rb +82 -0
- data/lib/chef/knife/status.rb +51 -0
- data/lib/chef/mixin/language_include_attribute.rb +16 -11
- data/lib/chef/mixin/language_include_recipe.rb +15 -16
- data/lib/chef/mixin/recipe_definition_dsl_core.rb +17 -20
- data/lib/chef/mixin/shell_out.rb +38 -0
- data/lib/chef/mixins.rb +1 -1
- data/lib/chef/node.rb +190 -63
- data/lib/chef/node/attribute.rb +92 -78
- data/lib/chef/platform.rb +24 -4
- data/lib/chef/provider.rb +28 -10
- data/lib/chef/provider/breakpoint.rb +2 -2
- data/lib/chef/provider/cookbook_file.rb +96 -0
- data/lib/chef/provider/cron.rb +2 -2
- data/lib/chef/provider/deploy.rb +12 -10
- data/lib/chef/provider/env.rb +152 -0
- data/lib/chef/provider/env/windows.rb +75 -0
- data/lib/chef/provider/file.rb +10 -14
- data/lib/chef/provider/group.rb +15 -2
- data/lib/chef/provider/group/dscl.rb +17 -25
- data/lib/chef/provider/group/gpasswd.rb +6 -3
- data/lib/chef/provider/group/pw.rb +3 -7
- data/lib/chef/provider/group/windows.rb +79 -0
- data/lib/chef/provider/link.rb +4 -5
- data/lib/chef/provider/mdadm.rb +25 -18
- data/lib/chef/provider/mount/mount.rb +28 -27
- data/lib/chef/provider/package.rb +35 -35
- data/lib/chef/provider/package/dpkg.rb +13 -10
- data/lib/chef/provider/package/easy_install.rb +6 -6
- data/lib/chef/provider/package/freebsd.rb +17 -51
- data/lib/chef/provider/package/rpm.rb +1 -1
- data/lib/chef/provider/package/rubygems.rb +391 -74
- data/lib/chef/provider/package/yum.rb +2 -2
- data/lib/chef/provider/package/zypper.rb +2 -1
- data/lib/chef/provider/remote_directory.rb +60 -83
- data/lib/chef/provider/remote_file.rb +17 -66
- data/lib/chef/provider/script.rb +20 -9
- data/lib/chef/provider/service.rb +23 -30
- data/lib/chef/provider/service/arch.rb +3 -3
- data/lib/chef/provider/service/debian.rb +22 -17
- data/lib/chef/provider/service/freebsd.rb +4 -4
- data/lib/chef/provider/service/init.rb +2 -2
- data/lib/chef/provider/service/redhat.rb +14 -16
- data/lib/chef/provider/service/simple.rb +7 -3
- data/lib/chef/provider/service/solaris.rb +85 -0
- data/lib/chef/provider/service/upstart.rb +12 -7
- data/lib/chef/provider/service/windows.rb +2 -2
- data/lib/chef/provider/template.rb +133 -118
- data/lib/chef/provider/user.rb +34 -17
- data/lib/chef/provider/user/dscl.rb +117 -114
- data/lib/chef/provider/user/windows.rb +124 -0
- data/lib/chef/providers.rb +7 -0
- data/lib/chef/recipe.rb +39 -20
- data/lib/chef/resource.rb +47 -52
- data/lib/chef/resource/apt_package.rb +4 -4
- data/lib/chef/resource/bash.rb +4 -4
- data/lib/chef/resource/cookbook_file.rb +45 -0
- data/lib/chef/resource/cron.rb +3 -3
- data/lib/chef/resource/csh.rb +4 -4
- data/lib/chef/resource/deploy.rb +3 -3
- data/lib/chef/resource/directory.rb +4 -4
- data/lib/chef/resource/dpkg_package.rb +4 -4
- data/lib/chef/resource/easy_install_package.rb +3 -3
- data/lib/chef/resource/env.rb +58 -0
- data/lib/chef/resource/erl_call.rb +3 -3
- data/lib/chef/resource/execute.rb +3 -3
- data/lib/chef/resource/file.rb +3 -3
- data/lib/chef/resource/freebsd_package.rb +3 -3
- data/lib/chef/resource/gem_package.rb +17 -9
- data/lib/chef/resource/git.rb +3 -3
- data/lib/chef/resource/group.rb +3 -3
- data/lib/chef/resource/http_request.rb +4 -4
- data/lib/chef/resource/ifconfig.rb +3 -3
- data/lib/chef/resource/link.rb +3 -3
- data/lib/chef/resource/log.rb +2 -2
- data/lib/chef/resource/macports_package.rb +2 -2
- data/lib/chef/resource/mdadm.rb +3 -3
- data/lib/chef/resource/mount.rb +2 -2
- data/lib/chef/resource/package.rb +4 -4
- data/lib/chef/resource/pacman_package.rb +4 -4
- data/lib/chef/resource/perl.rb +4 -4
- data/lib/chef/resource/portage_package.rb +4 -4
- data/lib/chef/resource/python.rb +4 -4
- data/lib/chef/resource/remote_directory.rb +3 -3
- data/lib/chef/resource/remote_file.rb +26 -3
- data/lib/chef/resource/route.rb +3 -3
- data/lib/chef/resource/ruby.rb +3 -3
- data/lib/chef/resource/ruby_block.rb +3 -2
- data/lib/chef/resource/scm.rb +7 -5
- data/lib/chef/resource/script.rb +4 -4
- data/lib/chef/resource/service.rb +3 -3
- data/lib/chef/resource/subversion.rb +4 -2
- data/lib/chef/resource/template.rb +3 -3
- data/lib/chef/resource/user.rb +3 -3
- data/lib/chef/resource/yum_package.rb +3 -3
- data/lib/chef/resource_collection.rb +9 -5
- data/lib/chef/resources.rb +2 -0
- data/lib/chef/rest.rb +4 -0
- data/lib/chef/role.rb +2 -0
- data/lib/chef/run_context.rb +108 -0
- data/lib/chef/run_list.rb +75 -98
- data/lib/chef/run_list/run_list_expansion.rb +156 -0
- data/lib/chef/run_list/run_list_item.rb +71 -0
- data/lib/chef/runner.rb +58 -61
- data/lib/chef/sandbox.rb +147 -0
- data/lib/chef/shef.rb +4 -3
- data/lib/chef/shef/ext.rb +12 -4
- data/lib/chef/shef/shef_session.rb +27 -23
- data/lib/chef/shell_out.rb +375 -0
- data/lib/chef/util/windows.rb +56 -0
- data/lib/chef/util/windows/net_group.rb +101 -0
- data/lib/chef/util/windows/net_user.rb +198 -0
- data/lib/chef/version.rb +20 -0
- metadata +112 -22
- data/lib/chef/compile.rb +0 -158
- data/lib/chef/cookbook.rb +0 -201
- data/lib/chef/mixin/generate_url.rb +0 -58
@@ -48,14 +48,14 @@ class Chef
|
|
48
48
|
@current_resource.version(nil)
|
49
49
|
|
50
50
|
# get the currently installed version if installed
|
51
|
+
package_version = nil
|
51
52
|
if install_check(@new_resource.package_name)
|
52
53
|
command = "python -c \"import #{@new_resource.package_name}; print #{@new_resource.package_name}.__path__\""
|
53
|
-
pid, stdin, stdout, stderr
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
package_version = nil
|
54
|
+
status = popen4(command) do |pid, stdin, stdout, stderr|
|
55
|
+
install_location = stdout.readline
|
56
|
+
install_location[/\S\S(.*)\/(.*)-(.*)-py(.*).egg\S/]
|
57
|
+
package_version = $3
|
58
|
+
end
|
59
59
|
end
|
60
60
|
|
61
61
|
if package_version == @new_resource.version
|
@@ -18,13 +18,14 @@
|
|
18
18
|
#
|
19
19
|
|
20
20
|
require 'chef/provider/package'
|
21
|
-
require 'chef/mixin/
|
21
|
+
require 'chef/mixin/shell_out'
|
22
22
|
require 'chef/resource/package'
|
23
23
|
|
24
24
|
class Chef
|
25
25
|
class Provider
|
26
26
|
class Package
|
27
27
|
class Freebsd < Chef::Provider::Package
|
28
|
+
include Chef::Mixin::ShellOut
|
28
29
|
|
29
30
|
def initialize(*args)
|
30
31
|
super
|
@@ -32,19 +33,8 @@ class Chef
|
|
32
33
|
end
|
33
34
|
|
34
35
|
def current_installed_version
|
35
|
-
|
36
|
-
|
37
|
-
stdout.each do |line|
|
38
|
-
case line
|
39
|
-
when /^#{package_name}-(.+)/
|
40
|
-
return $1
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
unless status.exitstatus == 0 || status.exitstatus == 1
|
45
|
-
raise Chef::Exceptions::Package, "#{command} failed - #{status.inspect}!"
|
46
|
-
end
|
47
|
-
nil
|
36
|
+
pkg_info = shell_out!("pkg_info -E \"#{package_name}*\"", :env => nil, :returns => [0,1])
|
37
|
+
pkg_info.stdout[/^#{package_name}-(.+)/, 1]
|
48
38
|
end
|
49
39
|
|
50
40
|
def port_path
|
@@ -58,27 +48,17 @@ class Chef
|
|
58
48
|
"/usr/ports/#{@new_resource.package_name}"
|
59
49
|
# Otherwise look up the path to the ports directory using 'whereis'
|
60
50
|
else
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
when /^#{@new_resource.package_name}:\s+(.+)$/
|
65
|
-
return $1
|
66
|
-
end
|
67
|
-
end
|
51
|
+
whereis = shell_out!("whereis -s #{@new_resource.package_name}", :env => nil)
|
52
|
+
unless path = whereis.stdout[/^#{@new_resource.package_name}:\s+(.+)$/, 1]
|
53
|
+
raise Chef::Exceptions::Package, "Could not find port with the name #{@new_resource.package_name}"
|
68
54
|
end
|
69
|
-
|
55
|
+
path
|
70
56
|
end
|
71
57
|
end
|
72
58
|
|
73
59
|
def ports_makefile_variable_value(variable)
|
74
|
-
|
75
|
-
|
76
|
-
return stdout.readline.strip
|
77
|
-
end
|
78
|
-
unless status.exitstatus == 0 || status.exitstatus == 1
|
79
|
-
raise Chef::Exceptions::Package, "#{command} failed - #{status.inspect}!"
|
80
|
-
end
|
81
|
-
nil
|
60
|
+
make_v = shell_out!("make -V #{variable}", :cwd => port_path, :env => nil, :returns => [0,1])
|
61
|
+
make_v.stdout.strip.split($\).first # $\ is the line separator, i.e., newline
|
82
62
|
end
|
83
63
|
|
84
64
|
def ports_candidate_version
|
@@ -114,26 +94,15 @@ class Chef
|
|
114
94
|
unless @current_resource.version
|
115
95
|
case @new_resource.source
|
116
96
|
when /^ports$/
|
117
|
-
|
118
|
-
:command => "make -DBATCH install",
|
119
|
-
:cwd => "#{port_path}"
|
120
|
-
)
|
97
|
+
shell_out!("make -DBATCH install", :cwd => port_path, :env => nil).status
|
121
98
|
when /^http/, /^ftp/
|
122
|
-
|
123
|
-
:command => "pkg_add -r #{package_name}",
|
124
|
-
:environment => { "PACKAGESITE" => @new_resource.source }
|
125
|
-
)
|
99
|
+
shell_out!("pkg_add -r #{package_name}", :env => { "PACKAGESITE" => @new_resource.source, 'LC_ALL' => nil }).status
|
126
100
|
Chef::Log.info("Installed package #{package_name} from: #{@new_resource.source}")
|
127
101
|
when /^\//
|
128
|
-
|
129
|
-
:command => "pkg_add #{@new_resource.name}",
|
130
|
-
:environment => { "PKG_PATH" => @new_resource.source }
|
131
|
-
)
|
102
|
+
shell_out!("pkg_add #{@new_resource.name}", :env => { "PKG_PATH" => @new_resource.source , 'LC_ALL'=>nil}).status
|
132
103
|
Chef::Log.info("Installed package #{@new_resource.name} from: #{@new_resource.source}")
|
133
104
|
else
|
134
|
-
|
135
|
-
:command => "pkg_add -r #{latest_link_name}"
|
136
|
-
)
|
105
|
+
shell_out!("pkg_add -r #{latest_link_name}", :env => nil).status
|
137
106
|
Chef::Log.info("Installed package #{package_name}")
|
138
107
|
end
|
139
108
|
end
|
@@ -142,15 +111,12 @@ class Chef
|
|
142
111
|
def remove_package(name, version)
|
143
112
|
# a version is mandatory
|
144
113
|
if version
|
145
|
-
|
146
|
-
:command => "pkg_delete #{package_name}-#{version}"
|
147
|
-
)
|
114
|
+
shell_out!("pkg_delete #{package_name}-#{version}", :env => nil).status
|
148
115
|
else
|
149
|
-
|
150
|
-
:command => "pkg_delete #{package_name}-#{@current_resource.version}"
|
151
|
-
)
|
116
|
+
shell_out!("pkg_delete #{package_name}-#{@current_resource.version}", :env => nil).status
|
152
117
|
end
|
153
118
|
end
|
119
|
+
|
154
120
|
end
|
155
121
|
end
|
156
122
|
end
|
@@ -1,14 +1,15 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
-
#
|
3
|
+
# Author:: Daniel DeLeo (<dan@opscode.com>)
|
4
|
+
# Copyright:: Copyright (c) 2008, 2010 Opscode, Inc.
|
4
5
|
# License:: Apache License, Version 2.0
|
5
6
|
#
|
6
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
8
|
# you may not use this file except in compliance with the License.
|
8
9
|
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
+
#
|
10
11
|
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
+
#
|
12
13
|
# Unless required by applicable law or agreed to in writing, software
|
13
14
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
15
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -20,113 +21,429 @@ require 'chef/provider/package'
|
|
20
21
|
require 'chef/mixin/command'
|
21
22
|
require 'chef/resource/package'
|
22
23
|
|
24
|
+
# Class methods on Gem are defined in rubygems
|
25
|
+
require 'rubygems'
|
26
|
+
# Ruby 1.9's gem_prelude can interact poorly with loading the full rubygems
|
27
|
+
# explicitly like this. Make sure rubygems/specification is always last in this
|
28
|
+
# list
|
29
|
+
require 'rubygems/version'
|
30
|
+
require 'rubygems/dependency'
|
31
|
+
require 'rubygems/spec_fetcher'
|
32
|
+
require 'rubygems/platform'
|
33
|
+
require 'rubygems/format'
|
34
|
+
require 'rubygems/dependency_installer'
|
35
|
+
require 'rubygems/uninstaller'
|
36
|
+
require 'rubygems/specification'
|
37
|
+
|
23
38
|
class Chef
|
24
39
|
class Provider
|
25
40
|
class Package
|
26
|
-
class Rubygems < Chef::Provider::Package
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
41
|
+
class Rubygems < Chef::Provider::Package
|
42
|
+
class GemEnvironment
|
43
|
+
# HACK: trigger gem config load early. Otherwise it can get lazy
|
44
|
+
# loaded during operations where we've set Gem.sources to an
|
45
|
+
# alternate value and overwrite it with the defaults.
|
46
|
+
Gem.configuration
|
47
|
+
|
48
|
+
DEFAULT_UNINSTALLER_OPTS = {:ignore => true, :executables => true}
|
49
|
+
|
50
|
+
##
|
51
|
+
# The paths where rubygems should search for installed gems.
|
52
|
+
# Implemented by subclasses.
|
53
|
+
def gem_paths
|
54
|
+
raise NotImplementedError
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# A rubygems source index containing the list of gemspecs for all
|
59
|
+
# available gems in the gem installation.
|
60
|
+
# Implemented by subclasses
|
61
|
+
# === Returns
|
62
|
+
# Gem::SourceIndex
|
63
|
+
def gem_source_index
|
64
|
+
raise NotImplementedError
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Lists the installed versions of +gem_name+, constrained by the
|
69
|
+
# version spec in +gem_dep+
|
70
|
+
# === Arguments
|
71
|
+
# Gem::Dependency +gem_dep+ is a Gem::Dependency object, its version
|
72
|
+
# specification constrains which gems are returned.
|
73
|
+
# === Returns
|
74
|
+
# [Gem::Specification] an array of Gem::Specification objects
|
75
|
+
def installed_versions(gem_dep)
|
76
|
+
gem_source_index.search(gem_dep)
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Yields to the provided block with rubygems' source list set to the
|
81
|
+
# list provided. Always resets the list when the block returns or
|
82
|
+
# raises an exception.
|
83
|
+
def with_gem_sources(*sources)
|
84
|
+
sources.compact!
|
85
|
+
original_sources = Gem.sources
|
86
|
+
Gem.sources = sources unless sources.empty?
|
87
|
+
yield
|
88
|
+
ensure
|
89
|
+
Gem.sources = original_sources
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Determines the candidate version for a gem from a .gem file on disk
|
94
|
+
# and checks if it matches the version contraints in +gem_dependency+
|
95
|
+
# === Returns
|
96
|
+
# Gem::Version a singular gem version object is returned if the gem
|
97
|
+
# is available
|
98
|
+
# nil returns nil if the gem on disk doesn't match the
|
99
|
+
# version constraints for +gem_dependency+
|
100
|
+
def candidate_version_from_file(gem_dependency, source)
|
101
|
+
spec = Gem::Format.from_file_by_path(source).spec
|
102
|
+
if spec.satisfies_requirement?(gem_dependency)
|
103
|
+
logger.debug {"found candidate gem version #{spec.version} from local gem package #{source}"}
|
104
|
+
spec.version
|
105
|
+
else
|
106
|
+
# This is probably going to end badly...
|
107
|
+
logger.warn { "The gem package #{source} does not satisfy the requirements #{gem_dependency.to_s}" }
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Finds the newest version that satisfies the constraints of
|
114
|
+
# +gem_dependency+. The version is determined from the cache or a
|
115
|
+
# round-trip to the server as needed. The architecture and gem
|
116
|
+
# sources will be set before making the query.
|
117
|
+
# === Returns
|
118
|
+
# Gem::Version a singular gem version object is returned if the gem
|
119
|
+
# is available
|
120
|
+
# nil returns nil if the gem could not be found
|
121
|
+
def candidate_version_from_remote(gem_dependency, *sources)
|
122
|
+
raise NotImplementedError
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Find the newest gem version available from Gem.sources that satisfies
|
127
|
+
# the constraints of +gem_dependency+
|
128
|
+
def find_newest_remote_version(gem_dependency, *sources)
|
129
|
+
# DependencyInstaller sorts the results such that the last one is
|
130
|
+
# always the one it considers best.
|
131
|
+
spec_with_source = dependency_installer.find_gems_with_sources(gem_dependency).last
|
132
|
+
|
133
|
+
spec = spec_with_source && spec_with_source[0]
|
134
|
+
version = spec && spec_with_source[0].version
|
135
|
+
if version
|
136
|
+
logger.debug { "Found gem #{spec.name} version #{version} for platform #{spec.platform} from #{spec_with_source[1]}" }
|
137
|
+
version
|
138
|
+
else
|
139
|
+
source_list = sources.compact.empty? ? "[#{Gem.sources.join(', ')}]" : "[#{sources.join(', ')}]"
|
140
|
+
logger.warn { "Failed to find gem #{gem_dependency} from #{source_list}" }
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
##
|
146
|
+
# Installs a gem via the rubygems ruby API.
|
147
|
+
# === Options
|
148
|
+
# :sources rubygems servers to use
|
149
|
+
# Other options are passed to Gem::DependencyInstaller.new
|
150
|
+
def install(gem_dependency, options={})
|
151
|
+
with_gem_sources(*options.delete(:sources)) do
|
152
|
+
dependency_installer(options).install(gem_dependency)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
##
|
157
|
+
# Uninstall the gem +gem_name+ via the rubygems ruby API. If
|
158
|
+
# +gem_version+ is provided, only that version will be uninstalled.
|
159
|
+
# Otherwise, all versions are uninstalled.
|
160
|
+
# === Options
|
161
|
+
# Options are passed to Gem::Uninstaller.new
|
162
|
+
def uninstall(gem_name, gem_version=nil, opts={})
|
163
|
+
gem_version ? opts[:version] = gem_version : opts[:all] = true
|
164
|
+
uninstaller(gem_name, opts).uninstall
|
165
|
+
end
|
166
|
+
|
167
|
+
def dependency_installer(opts={})
|
168
|
+
Gem::DependencyInstaller.new(opts)
|
169
|
+
end
|
170
|
+
|
171
|
+
def uninstaller(gem_name, opts={})
|
172
|
+
Gem::Uninstaller.new(gem_name, DEFAULT_UNINSTALLER_OPTS.merge(opts))
|
34
173
|
end
|
174
|
+
|
175
|
+
private
|
176
|
+
|
177
|
+
def logger
|
178
|
+
Chef::Log.logger
|
179
|
+
end
|
180
|
+
|
35
181
|
end
|
36
182
|
|
37
|
-
|
38
|
-
|
39
|
-
|
183
|
+
class CurrentGemEnvironment < GemEnvironment
|
184
|
+
|
185
|
+
def gem_paths
|
186
|
+
Gem.path
|
187
|
+
end
|
188
|
+
|
189
|
+
def gem_source_index
|
190
|
+
Gem.source_index
|
191
|
+
end
|
192
|
+
|
193
|
+
def candidate_version_from_remote(gem_dependency, *sources)
|
194
|
+
with_gem_sources(*sources) do
|
195
|
+
find_newest_remote_version(gem_dependency, *sources)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
40
199
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
200
|
+
|
201
|
+
class AlternateGemEnvironment < GemEnvironment
|
202
|
+
JRUBY_PLATFORM = /(:?universal|x86_64|x86)\-java\-[0-9\.]+/
|
203
|
+
|
204
|
+
def self.gempath_cache
|
205
|
+
@gempath_cache ||= {}
|
206
|
+
end
|
207
|
+
|
208
|
+
def self.platform_cache
|
209
|
+
@platform_cache ||= {}
|
210
|
+
end
|
211
|
+
|
212
|
+
include Chef::Mixin::ShellOut
|
213
|
+
|
214
|
+
attr_reader :gem_binary_location
|
215
|
+
|
216
|
+
def initialize(gem_binary_location)
|
217
|
+
@gem_binary_location = gem_binary_location
|
218
|
+
end
|
219
|
+
|
220
|
+
def gem_paths
|
221
|
+
if self.class.gempath_cache.key?(@gem_binary_location)
|
222
|
+
self.class.gempath_cache[@gem_binary_location]
|
223
|
+
else
|
224
|
+
# shellout! is a fork/exec which won't work on windows
|
225
|
+
shell_style_paths = shell_out!("#{@gem_binary_location} env gempath").stdout
|
226
|
+
# on windows, the path separator is (usually? always?) semicolon
|
227
|
+
paths = shell_style_paths.split(::File::PATH_SEPARATOR).map { |path| path.strip }
|
228
|
+
self.class.gempath_cache[@gem_binary_location] = paths
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def gem_source_index
|
233
|
+
@source_index ||= Gem::SourceIndex.from_gems_in(*gem_paths.map { |p| p + '/specifications' })
|
234
|
+
end
|
235
|
+
|
236
|
+
##
|
237
|
+
# Attempt to detect the correct platform settings for the target gem
|
238
|
+
# environment.
|
239
|
+
#
|
240
|
+
# In practice, this only makes a difference if different versions are
|
241
|
+
# available depending on platform, and only if the target gem
|
242
|
+
# environment has a radically different platform (i.e., jruby), so we
|
243
|
+
# just try to detect jruby and fall back to the current platforms
|
244
|
+
# (Gem.platforms) if we don't detect it.
|
245
|
+
#
|
246
|
+
# === Returns
|
247
|
+
# [String|Gem::Platform] returns an array of Gem::Platform-compatible
|
248
|
+
# objects, i.e., Strings that are valid for Gem::Platform or actual
|
249
|
+
# Gem::Platform objects.
|
250
|
+
def gem_platforms
|
251
|
+
if self.class.platform_cache.key?(@gem_binary_location)
|
252
|
+
self.class.platform_cache[@gem_binary_location]
|
253
|
+
else
|
254
|
+
gem_environment = shell_out!("#{@gem_binary_location} env").stdout
|
255
|
+
if jruby = gem_environment[JRUBY_PLATFORM]
|
256
|
+
self.class.platform_cache[@gem_binary_location] = ['ruby', Gem::Platform.new(jruby)]
|
57
257
|
else
|
58
|
-
|
59
|
-
Chef::Log.debug("#{@new_resource.package_name} at version #{iv}")
|
60
|
-
@current_resource.version(iv)
|
258
|
+
self.class.platform_cache[@gem_binary_location] = Gem.platforms
|
61
259
|
end
|
62
260
|
end
|
63
261
|
end
|
64
|
-
|
65
|
-
|
66
|
-
|
262
|
+
|
263
|
+
def with_gem_platforms(*alt_gem_platforms)
|
264
|
+
alt_gem_platforms.flatten!
|
265
|
+
original_gem_platforms = Gem.platforms
|
266
|
+
Gem.platforms = alt_gem_platforms
|
267
|
+
yield
|
268
|
+
ensure
|
269
|
+
Gem.platforms = original_gem_platforms
|
67
270
|
end
|
68
|
-
|
69
|
-
@current_resource
|
70
|
-
end
|
71
271
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
stdout.each_line do |line|
|
77
|
-
next unless installed_versions = gem_list_parse(line)
|
78
|
-
Chef::Log.debug("candidate_version: remote rubygem(s) available: #{installed_versions.inspect}")
|
79
|
-
|
80
|
-
unless installed_versions.empty?
|
81
|
-
Chef::Log.debug("candidate_version: setting install candidate version to #{installed_versions.first}")
|
82
|
-
@candidate_version = installed_versions.first
|
272
|
+
def candidate_version_from_remote(gem_dependency, *sources)
|
273
|
+
with_gem_sources(*sources) do
|
274
|
+
with_gem_platforms(*gem_platforms) do
|
275
|
+
find_newest_remote_version(gem_dependency, *sources)
|
83
276
|
end
|
84
277
|
end
|
278
|
+
end
|
279
|
+
|
280
|
+
end
|
281
|
+
|
282
|
+
include Chef::Mixin::ShellOut
|
283
|
+
|
284
|
+
attr_reader :gem_env
|
285
|
+
|
286
|
+
def logger
|
287
|
+
Chef::Log.logger
|
288
|
+
end
|
289
|
+
|
290
|
+
def initialize(new_resource, run_context=nil)
|
291
|
+
super
|
292
|
+
if new_resource.gem_binary
|
293
|
+
if new_resource.options && new_resource.options.kind_of?(Hash)
|
294
|
+
msg = "options cannot be given as a hash when using an explicit gem_binary\n"
|
295
|
+
msg << "in #{new_resource} from #{new_resource.source_line}"
|
296
|
+
raise ArgumentError, msg
|
297
|
+
end
|
298
|
+
@gem_env = AlternateGemEnvironment.new(new_resource.gem_binary)
|
299
|
+
else
|
300
|
+
@gem_env = CurrentGemEnvironment.new
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def gem_dependency
|
305
|
+
Gem::Dependency.new(@new_resource.package_name, @new_resource.version)
|
306
|
+
end
|
307
|
+
|
308
|
+
def source_is_remote?
|
309
|
+
return true if @new_resource.source.nil?
|
310
|
+
URI.parse(@new_resource.source).absolute?
|
311
|
+
end
|
312
|
+
|
313
|
+
def current_version
|
314
|
+
#raise 'todo'
|
315
|
+
# If one or more matching versions are installed, the newest of them
|
316
|
+
# is the current version
|
317
|
+
if !matching_installed_versions.empty?
|
318
|
+
gemspec = matching_installed_versions.last
|
319
|
+
logger.debug { "Found installed gem #{gemspec.name} version #{gemspec.version} matching #{gem_dependency}"}
|
320
|
+
gemspec
|
321
|
+
# If no version matching the requirements exists, the latest installed
|
322
|
+
# version is the current version.
|
323
|
+
elsif !all_installed_versions.empty?
|
324
|
+
gemspec = all_installed_versions.last
|
325
|
+
logger.debug { "Newest installed version of gem #{gemspec.name} is #{gemspec.version}" }
|
326
|
+
gemspec
|
327
|
+
else
|
328
|
+
logger.debug { "No installed version found for #{gem_dependency.to_s}"}
|
329
|
+
nil
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
def matching_installed_versions
|
334
|
+
@matching_installed_versions ||= @gem_env.installed_versions(gem_dependency)
|
335
|
+
end
|
336
|
+
|
337
|
+
def all_installed_versions
|
338
|
+
@all_installed_versions ||= begin
|
339
|
+
@gem_env.installed_versions(Gem::Dependency.new(gem_dependency.name))
|
340
|
+
end
|
341
|
+
end
|
85
342
|
|
343
|
+
def gem_sources
|
344
|
+
@new_resource.source ? [@new_resource.source, 'http://rubygems.org'] : nil
|
345
|
+
end
|
346
|
+
|
347
|
+
def load_current_resource
|
348
|
+
@current_resource = Chef::Resource::Package::GemPackage.new(@new_resource.name)
|
349
|
+
@current_resource.package_name(@new_resource.package_name)
|
350
|
+
if current_spec = current_version
|
351
|
+
@current_resource.version(current_spec.version.to_s)
|
86
352
|
end
|
353
|
+
@current_resource
|
354
|
+
end
|
87
355
|
|
88
|
-
|
89
|
-
|
356
|
+
def candidate_version
|
357
|
+
@candidate_version ||= begin
|
358
|
+
if target_version_already_installed?
|
359
|
+
nil
|
360
|
+
elsif source_is_remote?
|
361
|
+
@gem_env.candidate_version_from_remote(gem_dependency, *gem_sources).to_s
|
362
|
+
else
|
363
|
+
@gem_env.candidate_version_from_file(gem_dependency, @new_resource.source).to_s
|
364
|
+
end
|
90
365
|
end
|
91
|
-
@candidate_version
|
92
366
|
end
|
93
|
-
|
367
|
+
|
368
|
+
def target_version_already_installed?
|
369
|
+
return false unless @current_resource && @current_resource.version
|
370
|
+
return false if @current_resource.version.nil?
|
371
|
+
# in the future we could support squiggly requirements like "~> 1.2.0"
|
372
|
+
# for now, the behavior when using anything other than exact
|
373
|
+
# requirements is undefined.
|
374
|
+
Gem::Requirement.new(@new_resource.version).satisfied_by?(Gem::Version.new(@current_resource.version))
|
375
|
+
end
|
376
|
+
|
377
|
+
##
|
378
|
+
# Installs the gem, using either the gems API or shelling out to `gem`
|
379
|
+
# according to the following criteria:
|
380
|
+
# 1. Use gems API (Gem::DependencyInstaller) by default
|
381
|
+
# 2. shell out to `gem install` when a String of options is given
|
382
|
+
# 3. use gems API with options if a hash of options is given
|
94
383
|
def install_package(name, version)
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
384
|
+
if source_is_remote? && @new_resource.gem_binary.nil?
|
385
|
+
if @new_resource.options.nil?
|
386
|
+
@gem_env.install(gem_dependency, :sources => gem_sources)
|
387
|
+
elsif @new_resource.options.kind_of?(Hash)
|
388
|
+
options = @new_resource.options
|
389
|
+
options[:sources] = gem_sources
|
390
|
+
@gem_env.install(gem_dependency, options)
|
391
|
+
else
|
392
|
+
install_via_gem_command(name, version)
|
393
|
+
end
|
394
|
+
elsif @new_resource.gem_binary.nil?
|
395
|
+
@gem_env.install(@new_resource.source)
|
396
|
+
else
|
397
|
+
install_via_gem_command(name,version)
|
398
|
+
end
|
399
|
+
true
|
400
|
+
end
|
401
|
+
|
402
|
+
def gem_binary_path
|
403
|
+
@new_resource.gem_binary || 'gem'
|
404
|
+
end
|
405
|
+
|
406
|
+
def install_via_gem_command(name, version)
|
407
|
+
src = @new_resource.source && " --source=#{@new_resource.source} --source=http://rubygems.org"
|
408
|
+
shell_out!("#{gem_binary_path} install #{name} -q --no-rdoc --no-ri -v \"#{version}\"#{src}#{opts}", :env=>nil)
|
409
|
+
end
|
410
|
+
|
104
411
|
def upgrade_package(name, version)
|
105
412
|
install_package(name, version)
|
106
413
|
end
|
107
|
-
|
414
|
+
|
108
415
|
def remove_package(name, version)
|
416
|
+
if @new_resource.gem_binary.nil?
|
417
|
+
if @new_resource.options.nil?
|
418
|
+
@gem_env.uninstall(name, version)
|
419
|
+
elsif @new_resource.options.kind_of?(Hash)
|
420
|
+
@gem_env.uninstall(name, version, @new_resource.options)
|
421
|
+
else
|
422
|
+
uninstall_via_gem_command(name, version)
|
423
|
+
end
|
424
|
+
else
|
425
|
+
uninstall_via_gem_command(name, version)
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
def uninstall_via_gem_command(name, version)
|
109
430
|
if version
|
110
|
-
|
111
|
-
:command => "#{gem_binary_path} uninstall #{name} -q -v \"#{version}\""
|
112
|
-
)
|
431
|
+
shell_out!("#{gem_binary_path} uninstall #{name} -q -x -I -v \"#{version}\"#{opts}", :env=>nil)
|
113
432
|
else
|
114
|
-
|
115
|
-
:command => "#{gem_binary_path} uninstall #{name} -q -a"
|
116
|
-
)
|
433
|
+
shell_out!("#{gem_binary_path} uninstall #{name} -q -x -I -a#{opts}", :env=>nil)
|
117
434
|
end
|
118
435
|
end
|
119
|
-
|
436
|
+
|
120
437
|
def purge_package(name, version)
|
121
438
|
remove_package(name, version)
|
122
439
|
end
|
123
|
-
|
440
|
+
|
124
441
|
private
|
125
|
-
|
442
|
+
|
126
443
|
def opts
|
127
444
|
expand_options(@new_resource.options)
|
128
445
|
end
|
129
|
-
|
446
|
+
|
130
447
|
end
|
131
448
|
end
|
132
449
|
end
|