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,35 @@
|
|
1
|
+
require 'chef/provider/lwrp_base'
|
2
|
+
require 'chef/provisioning/chef_provider_action_handler'
|
3
|
+
require 'chef/provisioning/machine'
|
4
|
+
|
5
|
+
class Chef
|
6
|
+
class Provider
|
7
|
+
class MachineExecute < Chef::Provider::LWRPBase
|
8
|
+
|
9
|
+
def action_handler
|
10
|
+
@action_handler ||= Chef::Provisioning::ChefProviderActionHandler.new(self)
|
11
|
+
end
|
12
|
+
|
13
|
+
use_inline_resources
|
14
|
+
|
15
|
+
def whyrun_supported?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def machine
|
20
|
+
@machine ||= begin
|
21
|
+
if new_resource.machine.kind_of?(Chef::Provisioning::Machine)
|
22
|
+
new_resource.machine
|
23
|
+
else
|
24
|
+
run_context.chef_provisioning.connect_to_machine(new_resource.machine, new_resource.chef_server)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
action :run do
|
30
|
+
machine.execute(action_handler, new_resource.command)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'chef/provider/lwrp_base'
|
2
|
+
require 'chef/provisioning/chef_provider_action_handler'
|
3
|
+
require 'chef/provisioning/machine'
|
4
|
+
|
5
|
+
class Chef
|
6
|
+
class Provider
|
7
|
+
class MachineFile < Chef::Provider::LWRPBase
|
8
|
+
|
9
|
+
def action_handler
|
10
|
+
@action_handler ||= Chef::Provisioning::ChefProviderActionHandler.new(self)
|
11
|
+
end
|
12
|
+
|
13
|
+
use_inline_resources
|
14
|
+
|
15
|
+
def whyrun_supported?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def machine
|
20
|
+
@machine ||= begin
|
21
|
+
if new_resource.machine.kind_of?(Chef::Provisioning::Machine)
|
22
|
+
new_resource.machine
|
23
|
+
else
|
24
|
+
run_context.chef_provisioning.connect_to_machine(new_resource.machine, new_resource.chef_server)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
action :upload do
|
30
|
+
if new_resource.content
|
31
|
+
machine.write_file(action_handler, new_resource.path, new_resource.content)
|
32
|
+
else
|
33
|
+
machine.upload_file(action_handler, new_resource.local_path, new_resource.path)
|
34
|
+
end
|
35
|
+
|
36
|
+
attributes = {}
|
37
|
+
attributes[:group] = new_resource.group if new_resource.group
|
38
|
+
attributes[:owner] = new_resource.owner if new_resource.owner
|
39
|
+
attributes[:mode] = new_resource.mode if new_resource.mode
|
40
|
+
|
41
|
+
machine.set_attributes(action_handler, new_resource.path, attributes)
|
42
|
+
end
|
43
|
+
|
44
|
+
action :download do
|
45
|
+
machine.download_file(action_handler, new_resource.path, new_resource.local_path)
|
46
|
+
end
|
47
|
+
|
48
|
+
action :delete do
|
49
|
+
machine.delete_file(action_handler, new_resource.path)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'chef/provider/lwrp_base'
|
2
|
+
require 'chef/provider/chef_node'
|
3
|
+
require 'openssl'
|
4
|
+
require 'chef/provisioning/chef_provider_action_handler'
|
5
|
+
require 'chef/provisioning/chef_image_spec'
|
6
|
+
|
7
|
+
class Chef
|
8
|
+
class Provider
|
9
|
+
class MachineImage < Chef::Provider::LWRPBase
|
10
|
+
|
11
|
+
def action_handler
|
12
|
+
@action_handler ||= Chef::Provisioning::ChefProviderActionHandler.new(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def load_current_resource
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get the driver specified in the resource
|
19
|
+
def new_driver
|
20
|
+
@new_driver ||= run_context.chef_provisioning.driver_for(new_resource.driver)
|
21
|
+
end
|
22
|
+
|
23
|
+
action :create do
|
24
|
+
# Get the image mapping on the server (from name to image-id)
|
25
|
+
image_spec = Chef::Provisioning::ChefImageSpec.get(new_resource.name, new_resource.chef_server) ||
|
26
|
+
Chef::Provisioning::ChefImageSpec.empty(new_resource.name, new_resource.chef_server)
|
27
|
+
if image_spec.location
|
28
|
+
# TODO check for real existence and maybe update
|
29
|
+
else
|
30
|
+
#
|
31
|
+
# Create a new image
|
32
|
+
#
|
33
|
+
image_spec.machine_options = new_resource.machine_options
|
34
|
+
create_image(image_spec)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
action :destroy do
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_image(image_spec)
|
42
|
+
# 1. Create the exemplar machine
|
43
|
+
machine_provider = Chef::Provider::Machine.new(new_resource, run_context)
|
44
|
+
machine_provider.load_current_resource
|
45
|
+
machine_provider.action_converge
|
46
|
+
|
47
|
+
# 2. Create the image
|
48
|
+
new_driver.allocate_image(action_handler, image_spec, new_resource.image_options,
|
49
|
+
machine_provider.machine_spec)
|
50
|
+
|
51
|
+
# 3. Save the linkage from name -> image id
|
52
|
+
image_spec.save(action_handler)
|
53
|
+
|
54
|
+
# 4. Wait for image to be ready
|
55
|
+
new_driver.ready_image(action_handler, image_spec, new_resource.image_options)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Include recipe basics so require 'chef/provisioning' will load everything
|
2
|
+
require 'chef/provisioning/recipe_dsl'
|
3
|
+
require 'chef/server_api'
|
4
|
+
require 'cheffish/basic_chef_client'
|
5
|
+
require 'cheffish/merged_config'
|
6
|
+
|
7
|
+
class Chef
|
8
|
+
module Provisioning
|
9
|
+
def self.inline_resource(action_handler, &block)
|
10
|
+
events = ActionHandlerForward.new(action_handler)
|
11
|
+
Cheffish::BasicChefClient.converge_block(nil, events, &block)
|
12
|
+
end
|
13
|
+
|
14
|
+
class ActionHandlerForward < Chef::EventDispatch::Base
|
15
|
+
def initialize(action_handler)
|
16
|
+
@action_handler = action_handler
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :action_handler
|
20
|
+
|
21
|
+
def resource_update_applied(resource, action, update)
|
22
|
+
prefix = action_handler.should_perform_actions ? "" : "Would "
|
23
|
+
update = Array(update).flatten.map { |u| "#{prefix}#{u}"}
|
24
|
+
action_handler.performed_action(update)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Helpers for driver inflation
|
29
|
+
@@registered_driver_classes = {}
|
30
|
+
def self.register_driver_class(name, driver)
|
31
|
+
@@registered_driver_classes[name] = driver
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.default_driver(config = Cheffish.profiled_config)
|
35
|
+
driver_for_url(config[:driver], config)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.driver_for_url(driver_url, config = Cheffish.profiled_config, allow_different_config = false)
|
39
|
+
#
|
40
|
+
# Create and cache the driver
|
41
|
+
#
|
42
|
+
#
|
43
|
+
# Figure out the driver class
|
44
|
+
#
|
45
|
+
scheme = driver_url.split(':', 2)[0]
|
46
|
+
begin
|
47
|
+
require "chef/provisioning/driver_init/#{scheme}"
|
48
|
+
rescue LoadError => e
|
49
|
+
require "chef_metal/driver_init/#{scheme}"
|
50
|
+
end
|
51
|
+
driver_class = @@registered_driver_classes[scheme]
|
52
|
+
|
53
|
+
#
|
54
|
+
# Merge in any driver-specific config
|
55
|
+
#
|
56
|
+
if config[:drivers] && config[:drivers][driver_url]
|
57
|
+
config = Cheffish::MergedConfig.new(config[:drivers][driver_url], config)
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# Canonicalize the URL
|
62
|
+
#
|
63
|
+
canonicalized_url, canonicalized_config = driver_class.canonicalize_url(driver_url, config)
|
64
|
+
config = canonicalized_config if canonicalized_config
|
65
|
+
|
66
|
+
#
|
67
|
+
# Merge in config from the canonicalized URL if it is different
|
68
|
+
#
|
69
|
+
if canonicalized_url != driver_url
|
70
|
+
if config[:drivers] && config[:drivers][canonicalized_url]
|
71
|
+
config = Cheffish::MergedConfig.new(config[:drivers][canonicalized_url], config)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
driver_class.from_url(canonicalized_url, config)
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.connect_to_machine(machine_spec, config = Cheffish.profiled_config)
|
79
|
+
chef_server = Cheffish.default_chef_server(config)
|
80
|
+
if machine_spec.is_a?(String)
|
81
|
+
machine_spec = ChefMachineSpec.get(machine_spec, chef_server)
|
82
|
+
end
|
83
|
+
driver = driver_for_url(machine_spec.driver_url, config)
|
84
|
+
if driver
|
85
|
+
machine_options = { :convergence_options => { :chef_server => chef_server } }
|
86
|
+
machine_options = Cheffish::MergedConfig.new(config[:machine_options], machine_options) if config[:machine_options]
|
87
|
+
driver.connect_to_machine(machine_spec, machine_options)
|
88
|
+
else
|
89
|
+
nil
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
ChefMetal = Chef::Provisioning
|
@@ -0,0 +1,68 @@
|
|
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
|
+
# This is the generic action handler
|
20
|
+
class Chef
|
21
|
+
module Provisioning
|
22
|
+
class ActionHandler
|
23
|
+
|
24
|
+
# This should be replaced with whatever records the update; by default it
|
25
|
+
# essentially does nothing here.
|
26
|
+
def updated!
|
27
|
+
@updated = true
|
28
|
+
end
|
29
|
+
|
30
|
+
def should_perform_actions
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
def report_progress(description)
|
35
|
+
Array(description).each { |d| puts d }
|
36
|
+
end
|
37
|
+
|
38
|
+
def performed_action(description)
|
39
|
+
Array(description).each { |d| puts d }
|
40
|
+
end
|
41
|
+
|
42
|
+
# This should perform the actual action (e.g., converge) if there is an
|
43
|
+
# action that needs to be done.
|
44
|
+
def perform_action(description)
|
45
|
+
if should_perform_actions
|
46
|
+
result = yield
|
47
|
+
else
|
48
|
+
result = nil
|
49
|
+
end
|
50
|
+
performed_action(description)
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
# Open a stream which can be printed to and closed
|
55
|
+
def open_stream(name)
|
56
|
+
if block_given?
|
57
|
+
yield STDOUT
|
58
|
+
else
|
59
|
+
STDOUT
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# A URL identifying the host node. nil if no such node.
|
64
|
+
def host_node
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'chef/provisioning/action_handler'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
module Provisioning
|
5
|
+
class AddPrefixActionHandler
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def initialize(action_handler, prefix)
|
9
|
+
@action_handler = action_handler
|
10
|
+
@prefix = prefix
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :action_handler
|
14
|
+
attr_reader :prefix
|
15
|
+
|
16
|
+
def_delegators :@action_handler, :should_perform_actions, :updated!, :open_stream, :host_node
|
17
|
+
|
18
|
+
def report_progress(description)
|
19
|
+
action_handler.report_progress(Array(description).flatten.map { |d| "#{prefix}#{d}" })
|
20
|
+
end
|
21
|
+
|
22
|
+
def performed_action(description)
|
23
|
+
action_handler.performed_action(Array(description).flatten.map { |d| "#{prefix}#{d}" })
|
24
|
+
end
|
25
|
+
|
26
|
+
def perform_action(description, &block)
|
27
|
+
action_handler.perform_action(Array(description).flatten.map { |d| "#{prefix}#{d}" }, &block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'chef/provisioning'
|
2
|
+
require 'cheffish'
|
3
|
+
require 'chef/provisioning/image_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 ChefImageSpec < ImageSpec
|
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/images/#{name}")
|
25
|
+
data['machine_options'] = strings_to_symbols(data['machine_options'])
|
26
|
+
ChefImageSpec.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
|
+
ChefImageSpec.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
|
+
ChefImageSpec.id_from(chef_server, name)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.id_from(chef_server, name)
|
50
|
+
"#{chef_server[:chef_server_url]}/data/images/#{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 'images'
|
65
|
+
chef_server _chef_server
|
66
|
+
raw_data _self.image_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 'images'
|
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
|