chef-provisioning 0.15
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +207 -0
- data/LICENSE +201 -0
- data/README.md +260 -0
- data/Rakefile +6 -0
- data/lib/chef/provider/load_balancer.rb +77 -0
- data/lib/chef/provider/machine.rb +176 -0
- data/lib/chef/provider/machine_batch.rb +191 -0
- data/lib/chef/provider/machine_execute.rb +35 -0
- data/lib/chef/provider/machine_file.rb +54 -0
- data/lib/chef/provider/machine_image.rb +60 -0
- data/lib/chef/provisioning.rb +95 -0
- data/lib/chef/provisioning/action_handler.rb +68 -0
- data/lib/chef/provisioning/add_prefix_action_handler.rb +31 -0
- data/lib/chef/provisioning/chef_image_spec.rb +108 -0
- data/lib/chef/provisioning/chef_load_balancer_spec.rb +108 -0
- data/lib/chef/provisioning/chef_machine_spec.rb +84 -0
- data/lib/chef/provisioning/chef_provider_action_handler.rb +74 -0
- data/lib/chef/provisioning/chef_run_data.rb +139 -0
- data/lib/chef/provisioning/convergence_strategy.rb +28 -0
- data/lib/chef/provisioning/convergence_strategy/install_cached.rb +156 -0
- data/lib/chef/provisioning/convergence_strategy/install_msi.rb +58 -0
- data/lib/chef/provisioning/convergence_strategy/install_sh.rb +55 -0
- data/lib/chef/provisioning/convergence_strategy/no_converge.rb +39 -0
- data/lib/chef/provisioning/convergence_strategy/precreate_chef_objects.rb +183 -0
- data/lib/chef/provisioning/driver.rb +304 -0
- data/lib/chef/provisioning/image_spec.rb +72 -0
- data/lib/chef/provisioning/load_balancer_spec.rb +86 -0
- data/lib/chef/provisioning/machine.rb +112 -0
- data/lib/chef/provisioning/machine/basic_machine.rb +84 -0
- data/lib/chef/provisioning/machine/unix_machine.rb +278 -0
- data/lib/chef/provisioning/machine/windows_machine.rb +104 -0
- data/lib/chef/provisioning/machine_spec.rb +82 -0
- data/lib/chef/provisioning/recipe_dsl.rb +103 -0
- data/lib/chef/provisioning/transport.rb +95 -0
- data/lib/chef/provisioning/transport/ssh.rb +343 -0
- data/lib/chef/provisioning/transport/winrm.rb +151 -0
- data/lib/chef/provisioning/version.rb +5 -0
- data/lib/chef/resource/chef_data_bag_resource.rb +148 -0
- data/lib/chef/resource/load_balancer.rb +57 -0
- data/lib/chef/resource/machine.rb +124 -0
- data/lib/chef/resource/machine_batch.rb +78 -0
- data/lib/chef/resource/machine_execute.rb +28 -0
- data/lib/chef/resource/machine_file.rb +34 -0
- data/lib/chef/resource/machine_image.rb +35 -0
- data/lib/chef_metal.rb +1 -0
- metadata +217 -0
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'chef/provisioning'
|
2
|
+
require 'cheffish'
|
3
|
+
require 'chef/provisioning/load_balancer_spec'
|
4
|
+
|
5
|
+
class Chef
|
6
|
+
module Provisioning
|
7
|
+
#
|
8
|
+
# Specification for a image. Sufficient information to find and contact it
|
9
|
+
# after it has been set up.
|
10
|
+
#
|
11
|
+
class ChefLoadBalancerSpec < LoadBalancerSpec
|
12
|
+
def initialize(node, chef_server)
|
13
|
+
super(node)
|
14
|
+
@chef_server = chef_server
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Get a ImageSpec from the chef server. If the node does not exist on the
|
19
|
+
# server, it returns nil.
|
20
|
+
#
|
21
|
+
def self.get(name, chef_server = Cheffish.default_chef_server)
|
22
|
+
chef_api = Cheffish.chef_server_api(chef_server)
|
23
|
+
begin
|
24
|
+
data = chef_api.get("/data/loadbalancers/#{name}")
|
25
|
+
data['load_balancer_options'] = strings_to_symbols(data['load_balancer_options'])
|
26
|
+
ChefLoadBalancerSpec.new(data, chef_server)
|
27
|
+
rescue Net::HTTPServerException => e
|
28
|
+
if e.response.code == '404'
|
29
|
+
nil
|
30
|
+
else
|
31
|
+
raise
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Creates a new empty ImageSpec with the given name.
|
37
|
+
def self.empty(id, chef_server = Cheffish.default_chef_server)
|
38
|
+
ChefLoadBalancerSpec.new({ 'id' => id }, chef_server)
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Globally unique identifier for this image. Does not depend on the image's
|
43
|
+
# location or existence.
|
44
|
+
#
|
45
|
+
def id
|
46
|
+
ChefLoadBalancerSpec.id_from(chef_server, name)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.id_from(chef_server, name)
|
50
|
+
"#{chef_server[:chef_server_url]}/data/loadbalancers/#{name}"
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Save this node to the server. If you have significant information that
|
55
|
+
# could be lost, you should do this as quickly as possible. Data will be
|
56
|
+
# saved automatically for you after allocate_image and ready_image.
|
57
|
+
#
|
58
|
+
def save(action_handler)
|
59
|
+
# Save the node to the server.
|
60
|
+
_self = self
|
61
|
+
_chef_server = _self.chef_server
|
62
|
+
Chef::Provisioning.inline_resource(action_handler) do
|
63
|
+
chef_data_bag_item _self.name do
|
64
|
+
data_bag 'loadbalancers'
|
65
|
+
chef_server _chef_server
|
66
|
+
raw_data _self.load_balancer_data
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def delete(action_handler)
|
72
|
+
# Save the node to the server.
|
73
|
+
_self = self
|
74
|
+
_chef_server = _self.chef_server
|
75
|
+
Chef::Provisioning.inline_resource(action_handler) do
|
76
|
+
chef_data_bag_item _self.name do
|
77
|
+
data_bag 'loadbalancers'
|
78
|
+
chef_server _chef_server
|
79
|
+
action :destroy
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
protected
|
85
|
+
|
86
|
+
attr_reader :chef_server
|
87
|
+
|
88
|
+
#
|
89
|
+
# Chef API object for the given Chef server
|
90
|
+
#
|
91
|
+
def chef_api
|
92
|
+
Cheffish.server_api_for(chef_server)
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.strings_to_symbols(data)
|
96
|
+
if data.is_a?(Hash)
|
97
|
+
result = {}
|
98
|
+
data.each_pair do |key, value|
|
99
|
+
result[key.to_sym] = strings_to_symbols(value)
|
100
|
+
end
|
101
|
+
result
|
102
|
+
else
|
103
|
+
data
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require 'chef/provisioning'
|
3
|
+
require 'cheffish'
|
4
|
+
require 'chef/provisioning/machine_spec'
|
5
|
+
|
6
|
+
class Chef
|
7
|
+
module Provisioning
|
8
|
+
#
|
9
|
+
# Specification for a machine. Sufficient information to find and contact it
|
10
|
+
# after it has been set up.
|
11
|
+
#
|
12
|
+
class ChefMachineSpec < MachineSpec
|
13
|
+
def initialize(node, chef_server)
|
14
|
+
super(node)
|
15
|
+
@chef_server = chef_server
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# Get a MachineSpec from the chef server. If the node does not exist on the
|
20
|
+
# server, it returns nil.
|
21
|
+
#
|
22
|
+
def self.get(name, chef_server = Cheffish.default_chef_server)
|
23
|
+
chef_api = Cheffish.chef_server_api(chef_server)
|
24
|
+
begin
|
25
|
+
ChefMachineSpec.new(chef_api.get("/nodes/#{name}"), chef_server)
|
26
|
+
rescue Net::HTTPServerException => e
|
27
|
+
if e.response.code == '404'
|
28
|
+
nil
|
29
|
+
else
|
30
|
+
raise
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Creates a new empty MachineSpec with the given name.
|
36
|
+
def self.empty(name, chef_server = Cheffish.default_chef_server)
|
37
|
+
ChefMachineSpec.new({ 'name' => name, 'normal' => {} }, chef_server)
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Globally unique identifier for this machine. Does not depend on the machine's
|
42
|
+
# location or existence.
|
43
|
+
#
|
44
|
+
def id
|
45
|
+
ChefMachineSpec.id_from(chef_server, name)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.id_from(chef_server, name)
|
49
|
+
"#{chef_server[:chef_server_url]}/nodes/#{name}"
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# Save this node to the server. If you have significant information that
|
54
|
+
# could be lost, you should do this as quickly as possible. Data will be
|
55
|
+
# saved automatically for you after allocate_machine and ready_machine.
|
56
|
+
#
|
57
|
+
def save(action_handler)
|
58
|
+
if location && (!location.is_a?(Hash) || !location['driver_url'])
|
59
|
+
raise "Drivers must specify a canonical driver_url in machine_spec.location. Contact your driver's author."
|
60
|
+
end
|
61
|
+
# Save the node to the server.
|
62
|
+
_self = self
|
63
|
+
_chef_server = _self.chef_server
|
64
|
+
Chef::Provisioning.inline_resource(action_handler) do
|
65
|
+
chef_node _self.name do
|
66
|
+
chef_server _chef_server
|
67
|
+
raw_json _self.node
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
attr_reader :chef_server
|
75
|
+
|
76
|
+
#
|
77
|
+
# Chef API object for the given Chef server
|
78
|
+
#
|
79
|
+
def chef_api
|
80
|
+
Cheffish.server_api_for(chef_server)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Douglas Triggs (<doug@getchef.com>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2014, Chef, Inc.
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require 'chef/provisioning/action_handler'
|
20
|
+
|
21
|
+
# This is included in provisioning drivers to proxy from generic requests needed
|
22
|
+
# to specific driver actions
|
23
|
+
class Chef
|
24
|
+
module Provisioning
|
25
|
+
class ChefProviderActionHandler < ActionHandler
|
26
|
+
def initialize(provider)
|
27
|
+
@provider = provider
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :provider
|
31
|
+
|
32
|
+
def updated!
|
33
|
+
provider.new_resource.updated_by_last_action(true)
|
34
|
+
end
|
35
|
+
|
36
|
+
def should_perform_actions
|
37
|
+
!provider.run_context.config.why_run
|
38
|
+
end
|
39
|
+
|
40
|
+
def report_progress(description)
|
41
|
+
# TODO this seems wrong but Chef doesn't have another thing
|
42
|
+
provider.converge_by description do
|
43
|
+
# We already did the action, but we trust whoever told us that they did it.
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def performed_action(description)
|
48
|
+
provider.converge_by description do
|
49
|
+
# We already did the action, but we trust whoever told us that they did it.
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def perform_action(description, &block)
|
54
|
+
provider.converge_by(description, &block)
|
55
|
+
end
|
56
|
+
|
57
|
+
def open_stream(name, &block)
|
58
|
+
if provider.run_context.respond_to?(:open_stream)
|
59
|
+
provider.run_context.open_stream({ :name => name }, &block)
|
60
|
+
else
|
61
|
+
if block_given?
|
62
|
+
yield STDOUT
|
63
|
+
else
|
64
|
+
STDOUT
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def host_node
|
70
|
+
"#{provider.run_context.config[:chef_server_url]}/nodes/#{provider.run_context.node['name']}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'chef/mixin/deep_merge'
|
2
|
+
require 'cheffish/merged_config'
|
3
|
+
require 'chef/provisioning/chef_machine_spec'
|
4
|
+
|
5
|
+
class Chef
|
6
|
+
module Provisioning
|
7
|
+
class ChefRunData
|
8
|
+
|
9
|
+
def initialize(config)
|
10
|
+
@config = config
|
11
|
+
@drivers = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :config
|
15
|
+
attr_reader :drivers
|
16
|
+
attr_reader :current_driver
|
17
|
+
attr_accessor :current_machine_options
|
18
|
+
attr_accessor :current_load_balancer_options
|
19
|
+
attr_accessor :current_image_options
|
20
|
+
attr_accessor :current_data_center
|
21
|
+
|
22
|
+
def with_machine_options(value)
|
23
|
+
old_value = self.current_machine_options
|
24
|
+
self.current_machine_options = value
|
25
|
+
if block_given?
|
26
|
+
begin
|
27
|
+
yield
|
28
|
+
ensure
|
29
|
+
self.current_machine_options = old_value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def with_image_options(value)
|
35
|
+
old_value = self.current_image_options
|
36
|
+
self.current_image_options = value
|
37
|
+
if block_given?
|
38
|
+
begin
|
39
|
+
yield
|
40
|
+
ensure
|
41
|
+
self.current_image_options = old_value
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def with_data_center(value)
|
47
|
+
old_value = self.current_data_center
|
48
|
+
self.current_data_center = value
|
49
|
+
if block_given?
|
50
|
+
begin
|
51
|
+
yield
|
52
|
+
ensure
|
53
|
+
self.current_data_center = old_value
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def with_driver(driver, options = nil, &block)
|
59
|
+
if drivers[driver] && options
|
60
|
+
raise "Driver #{driver} has already been created, options #{options} would be ignored!"
|
61
|
+
end
|
62
|
+
@current_driver = driver
|
63
|
+
@current_driver_options = options
|
64
|
+
end
|
65
|
+
|
66
|
+
def current_driver
|
67
|
+
@current_driver || config[:driver]
|
68
|
+
end
|
69
|
+
|
70
|
+
def current_machine_options
|
71
|
+
if @current_machine_options
|
72
|
+
@current_machine_options
|
73
|
+
else
|
74
|
+
{}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def current_image_options
|
79
|
+
if @current_image_options
|
80
|
+
@current_image_options
|
81
|
+
else
|
82
|
+
{}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def add_machine_options(options, &block)
|
87
|
+
with_machine_options(Chef::Mixin::DeepMerge.hash_only_merge(current_machine_options, options), &block)
|
88
|
+
end
|
89
|
+
|
90
|
+
def driver_for(driver)
|
91
|
+
driver.is_a?(String) ? driver_for_url(driver) : driver
|
92
|
+
end
|
93
|
+
|
94
|
+
def connect_to_machine(name, chef_server = nil)
|
95
|
+
if name.is_a?(MachineSpec)
|
96
|
+
machine_spec = name
|
97
|
+
else
|
98
|
+
machine_spec = Chef::Provisioning::ChefMachineSpec.get(name, chef_server)
|
99
|
+
end
|
100
|
+
Chef::Provisioning.connect_to_machine(machine_spec, config)
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def driver_for_url(driver_url)
|
106
|
+
drivers[driver_url] ||= begin
|
107
|
+
if driver_url == @current_driver && @current_driver_options
|
108
|
+
# Use the driver options if available
|
109
|
+
merged_config = Cheffish::MergedConfig.new({ :driver_options => @current_driver_options }, config)
|
110
|
+
driver = Chef::Provisioning.driver_for_url(driver_url, merged_config)
|
111
|
+
else
|
112
|
+
driver = Chef::Provisioning.driver_for_url(driver_url, config)
|
113
|
+
end
|
114
|
+
# Check the canonicalized driver_url from the driver
|
115
|
+
if driver.driver_url != driver_url
|
116
|
+
if drivers[driver.driver_url] && @current_driver_options
|
117
|
+
raise "Canonical driver #{driver.driver_url} for #{driver_url} has already been created! Current options #{@current_driver_options} would be ignored."
|
118
|
+
end
|
119
|
+
drivers[driver.driver_url] ||= driver
|
120
|
+
else
|
121
|
+
driver
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def keys
|
127
|
+
result = (config.keys || {}).dup
|
128
|
+
Array(config.key_path) do |key_path|
|
129
|
+
Dir.entries(key_path).each do |key|
|
130
|
+
if File.extname(key) == '.pem'
|
131
|
+
result[File.basename(key)[0..-5]] ||= key
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
result
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Chef
|
2
|
+
module Provisioning
|
3
|
+
class ConvergenceStrategy
|
4
|
+
# convergence_options - a freeform hash of options to the converger.
|
5
|
+
# config - a Chef::Config-like object with global config like :log_level
|
6
|
+
def initialize(convergence_options, config)
|
7
|
+
@convergence_options = convergence_options || {}
|
8
|
+
@config = config
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :convergence_options
|
12
|
+
attr_reader :config
|
13
|
+
|
14
|
+
# Get the machine ready to converge, but do not converge.
|
15
|
+
def setup_convergence(action_handler, machine)
|
16
|
+
raise "setup_convergence not overridden on #{self.class}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def converge(action_handler, machine)
|
20
|
+
raise "converge not overridden on #{self.class}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def cleanup_convergence(action_handler, machine_spec)
|
24
|
+
raise "cleanup_convergence not overridden on #{self.class}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'chef/provisioning/convergence_strategy/precreate_chef_objects'
|
2
|
+
require 'pathname'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'digest/md5'
|
5
|
+
require 'thread'
|
6
|
+
require 'chef/http/simple'
|
7
|
+
|
8
|
+
class Chef
|
9
|
+
module Provisioning
|
10
|
+
class ConvergenceStrategy
|
11
|
+
class InstallCached < PrecreateChefObjects
|
12
|
+
# convergence_options is a hash of setup convergence_options, including:
|
13
|
+
# - :chef_server
|
14
|
+
# - :allow_overwrite_keys
|
15
|
+
# - :source_key, :source_key_path, :source_key_pass_phrase
|
16
|
+
# - :private_key_options
|
17
|
+
# - :ohai_hints
|
18
|
+
# - :public_key_path, :public_key_format
|
19
|
+
# - :admin, :validator
|
20
|
+
# - :chef_client_timeout
|
21
|
+
# - :client_rb_path, :client_pem_path
|
22
|
+
# - :chef_version, :prerelease, :package_cache_path
|
23
|
+
def initialize(convergence_options, config)
|
24
|
+
convergence_options = Cheffish::MergedConfig.new(convergence_options, {
|
25
|
+
:client_rb_path => '/etc/chef/client.rb',
|
26
|
+
:client_pem_path => '/etc/chef/client.pem'
|
27
|
+
})
|
28
|
+
super(convergence_options, config)
|
29
|
+
@chef_version ||= convergence_options[:chef_version]
|
30
|
+
@prerelease ||= convergence_options[:prerelease]
|
31
|
+
@package_cache_path ||= convergence_options[:package_cache_path] || "#{ENV['HOME']}/.chef/package_cache"
|
32
|
+
@package_cache = {}
|
33
|
+
@tmp_dir = '/tmp'
|
34
|
+
@chef_client_timeout = convergence_options.has_key?(:chef_client_timeout) ? convergence_options[:chef_client_timeout] : 120*60 # Default: 2 hours
|
35
|
+
FileUtils.mkdir_p(@package_cache_path)
|
36
|
+
@package_cache_lock = Mutex.new
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_reader :client_rb_path
|
40
|
+
attr_reader :client_pem_path
|
41
|
+
|
42
|
+
def setup_convergence(action_handler, machine)
|
43
|
+
super
|
44
|
+
|
45
|
+
# Install chef-client. TODO check and update version if not latest / not desired
|
46
|
+
if machine.execute_always('chef-client -v').exitstatus != 0
|
47
|
+
platform, platform_version, machine_architecture = machine.detect_os(action_handler)
|
48
|
+
package_file = download_package_for_platform(action_handler, machine, platform, platform_version, machine_architecture)
|
49
|
+
remote_package_file = "#{@tmp_dir}/#{File.basename(package_file)}"
|
50
|
+
machine.upload_file(action_handler, package_file, remote_package_file)
|
51
|
+
install_package(action_handler, machine, remote_package_file)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def converge(action_handler, machine)
|
56
|
+
super
|
57
|
+
|
58
|
+
action_handler.open_stream(machine.node['name']) do |stdout|
|
59
|
+
action_handler.open_stream(machine.node['name']) do |stderr|
|
60
|
+
command_line = "chef-client"
|
61
|
+
command_line << " -l #{config[:log_level].to_s}" if config[:log_level]
|
62
|
+
machine.execute(action_handler, command_line,
|
63
|
+
:stream_stdout => stdout,
|
64
|
+
:stream_stderr => stderr,
|
65
|
+
:timeout => @chef_client_timeout)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def download_package_for_platform(action_handler, machine, platform, platform_version, machine_architecture)
|
73
|
+
@package_cache_lock.synchronize do
|
74
|
+
@package_cache ||= {}
|
75
|
+
@package_cache[platform] ||= {}
|
76
|
+
@package_cache[platform][platform_version] ||= {}
|
77
|
+
@package_cache[platform][platform_version][machine_architecture] ||= { :lock => Mutex.new }
|
78
|
+
end
|
79
|
+
@package_cache[platform][platform_version][machine_architecture][:lock].synchronize do
|
80
|
+
if !@package_cache[platform][platform_version][machine_architecture][:file]
|
81
|
+
#
|
82
|
+
# Grab metadata
|
83
|
+
#
|
84
|
+
metadata = download_metadata_for_platform(machine, platform, platform_version, machine_architecture)
|
85
|
+
|
86
|
+
# Download actual package desired by metadata
|
87
|
+
package_file = "#{@package_cache_path}/#{URI(metadata['url']).path.split('/')[-1]}"
|
88
|
+
|
89
|
+
Chef::Provisioning.inline_resource(action_handler) do
|
90
|
+
remote_file package_file do
|
91
|
+
source metadata['url']
|
92
|
+
checksum metadata['sha256']
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
@package_cache[platform][platform_version][machine_architecture][:file] = package_file
|
97
|
+
end
|
98
|
+
end
|
99
|
+
@package_cache[platform][platform_version][machine_architecture][:file]
|
100
|
+
end
|
101
|
+
|
102
|
+
def download_metadata_for_platform(machine, platform, platform_version, machine_architecture)
|
103
|
+
#
|
104
|
+
# Figure out the URL to the metadata
|
105
|
+
#
|
106
|
+
metadata_url="https://www.opscode.com/chef/metadata"
|
107
|
+
metadata_url << "?v=#{@chef_version}"
|
108
|
+
metadata_url << "&prerelease=#{@prerelease ? 'true' : 'false'}"
|
109
|
+
metadata_url << "&p=#{platform.strip}"
|
110
|
+
metadata_url << "&pv=#{platform_version.strip}"
|
111
|
+
metadata_url << "&m=#{machine_architecture.strip}"
|
112
|
+
use_ssl = true
|
113
|
+
|
114
|
+
# solaris 9 lacks openssl, solaris 10 lacks recent enough credentials - your base O/S is completely insecure, please upgrade
|
115
|
+
if platform == 'solaris2' && (platform_version == '5.9' || platform_version == '5.10')
|
116
|
+
metadata_url.sub(/^https/, 'http')
|
117
|
+
use_ssl = false
|
118
|
+
end
|
119
|
+
|
120
|
+
# Download and parse the metadata
|
121
|
+
Chef::Log.debug("Getting metadata for machine #{machine.node['name']}: #{metadata_url}")
|
122
|
+
uri = URI(metadata_url)
|
123
|
+
metadata_str = Chef::HTTP::Simple.new(uri).get(uri)
|
124
|
+
metadata = {}
|
125
|
+
metadata_str.each_line do |line|
|
126
|
+
key, value = line.split("\t", 2)
|
127
|
+
metadata[key] = value
|
128
|
+
end
|
129
|
+
metadata
|
130
|
+
end
|
131
|
+
|
132
|
+
def install_package(action_handler, machine, remote_package_file)
|
133
|
+
extension = File.extname(remote_package_file)
|
134
|
+
result = case extension
|
135
|
+
when '.rpm'
|
136
|
+
machine.execute(action_handler, "rpm -Uvh --oldpackage --replacepkgs \"#{remote_package_file}\"")
|
137
|
+
when '.deb'
|
138
|
+
machine.execute(action_handler, "dpkg -i \"#{remote_package_file}\"")
|
139
|
+
when '.solaris'
|
140
|
+
machine.write_file(action_handler, "#{@tmp_dir}/nocheck", <<EOM)
|
141
|
+
conflict=nocheck
|
142
|
+
action=nocheck
|
143
|
+
mail=
|
144
|
+
EOM
|
145
|
+
machine.execute(action_handler, "pkgrm -a \"#{@tmp_dir}/nocheck\" -n chef")
|
146
|
+
machine.execute(action_handler, "pkgadd -n -d \"#{remote_package_file}\" -a \"#{@tmp_dir}/nocheck\" chef")
|
147
|
+
when '.sh'
|
148
|
+
machine.execute(action_handler, "sh \"#{remote_package_file}\"")
|
149
|
+
else
|
150
|
+
raise "Unknown package extension '#{extension}' for file #{remote_package_file}"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|