cheffish 1.4.1 → 1.4.2
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 +4 -4
- data/LICENSE +201 -201
- data/README.md +120 -120
- data/Rakefile +23 -23
- data/lib/chef/provider/chef_acl.rb +439 -439
- data/lib/chef/provider/chef_client.rb +53 -53
- data/lib/chef/provider/chef_container.rb +55 -55
- data/lib/chef/provider/chef_data_bag.rb +55 -55
- data/lib/chef/provider/chef_data_bag_item.rb +278 -278
- data/lib/chef/provider/chef_environment.rb +83 -83
- data/lib/chef/provider/chef_group.rb +83 -83
- data/lib/chef/provider/chef_mirror.rb +169 -169
- data/lib/chef/provider/chef_node.rb +87 -87
- data/lib/chef/provider/chef_organization.rb +155 -155
- data/lib/chef/provider/chef_resolved_cookbooks.rb +46 -46
- data/lib/chef/provider/chef_role.rb +84 -84
- data/lib/chef/provider/chef_user.rb +59 -59
- data/lib/chef/provider/private_key.rb +225 -225
- data/lib/chef/provider/public_key.rb +88 -88
- data/lib/chef/resource/chef_acl.rb +69 -69
- data/lib/chef/resource/chef_client.rb +48 -48
- data/lib/chef/resource/chef_container.rb +22 -22
- data/lib/chef/resource/chef_data_bag.rb +22 -22
- data/lib/chef/resource/chef_data_bag_item.rb +121 -121
- data/lib/chef/resource/chef_environment.rb +77 -77
- data/lib/chef/resource/chef_group.rb +53 -53
- data/lib/chef/resource/chef_mirror.rb +52 -52
- data/lib/chef/resource/chef_node.rb +22 -22
- data/lib/chef/resource/chef_organization.rb +69 -69
- data/lib/chef/resource/chef_resolved_cookbooks.rb +35 -35
- data/lib/chef/resource/chef_role.rb +110 -110
- data/lib/chef/resource/chef_user.rb +56 -56
- data/lib/chef/resource/private_key.rb +48 -48
- data/lib/chef/resource/public_key.rb +25 -25
- data/lib/cheffish/actor_provider_base.rb +131 -131
- data/lib/cheffish/basic_chef_client.rb +184 -184
- data/lib/cheffish/chef_provider_base.rb +246 -246
- data/lib/cheffish/chef_run.rb +162 -162
- data/lib/cheffish/chef_run_data.rb +19 -19
- data/lib/cheffish/chef_run_listener.rb +30 -30
- data/lib/cheffish/key_formatter.rb +113 -113
- data/lib/cheffish/merged_config.rb +94 -94
- data/lib/cheffish/recipe_dsl.rb +157 -157
- data/lib/cheffish/rspec/chef_run_support.rb +83 -83
- data/lib/cheffish/rspec/matchers/be_idempotent.rb +16 -16
- data/lib/cheffish/rspec/matchers/emit_no_warnings_or_errors.rb +15 -15
- data/lib/cheffish/rspec/matchers/have_updated.rb +37 -37
- data/lib/cheffish/rspec/matchers/partially_match.rb +63 -63
- data/lib/cheffish/rspec/matchers.rb +4 -4
- data/lib/cheffish/rspec/recipe_run_wrapper.rb +78 -59
- data/lib/cheffish/rspec/repository_support.rb +108 -108
- data/lib/cheffish/rspec.rb +8 -8
- data/lib/cheffish/server_api.rb +52 -52
- data/lib/cheffish/version.rb +3 -3
- data/lib/cheffish/with_pattern.rb +21 -21
- data/lib/cheffish.rb +235 -235
- data/spec/functional/fingerprint_spec.rb +64 -64
- data/spec/functional/merged_config_spec.rb +19 -19
- data/spec/functional/server_api_spec.rb +13 -13
- data/spec/integration/chef_acl_spec.rb +879 -879
- data/spec/integration/chef_client_spec.rb +105 -105
- data/spec/integration/chef_container_spec.rb +33 -33
- data/spec/integration/chef_group_spec.rb +309 -309
- data/spec/integration/chef_mirror_spec.rb +491 -491
- data/spec/integration/chef_node_spec.rb +786 -786
- data/spec/integration/chef_organization_spec.rb +226 -226
- data/spec/integration/chef_role_spec.rb +78 -78
- data/spec/integration/chef_user_spec.rb +85 -85
- data/spec/integration/private_key_spec.rb +399 -399
- data/spec/integration/recipe_dsl_spec.rb +28 -28
- data/spec/integration/rspec/converge_spec.rb +183 -183
- data/spec/support/key_support.rb +29 -29
- data/spec/support/spec_support.rb +15 -15
- data/spec/unit/get_private_key_spec.rb +131 -131
- data/spec/unit/recipe_run_wrapper_spec.rb +37 -37
- metadata +3 -2
@@ -1,83 +1,83 @@
|
|
1
|
-
require 'cheffish/chef_provider_base'
|
2
|
-
require 'chef/resource/chef_environment'
|
3
|
-
require 'chef/chef_fs/data_handler/environment_data_handler'
|
4
|
-
|
5
|
-
class Chef
|
6
|
-
class Provider
|
7
|
-
class ChefEnvironment < Cheffish::ChefProviderBase
|
8
|
-
provides :chef_environment
|
9
|
-
|
10
|
-
def whyrun_supported?
|
11
|
-
true
|
12
|
-
end
|
13
|
-
|
14
|
-
action :create do
|
15
|
-
differences = json_differences(current_json, new_json)
|
16
|
-
|
17
|
-
if current_resource_exists?
|
18
|
-
if differences.size > 0
|
19
|
-
description = [ "update environment #{new_resource.name} at #{rest.url}" ] + differences
|
20
|
-
converge_by description do
|
21
|
-
rest.put("environments/#{new_resource.name}", normalize_for_put(new_json))
|
22
|
-
end
|
23
|
-
end
|
24
|
-
else
|
25
|
-
description = [ "create environment #{new_resource.name} at #{rest.url}" ] + differences
|
26
|
-
converge_by description do
|
27
|
-
rest.post("environments", normalize_for_post(new_json))
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
action :delete do
|
33
|
-
if current_resource_exists?
|
34
|
-
converge_by "delete environment #{new_resource.name} at #{rest.url}" do
|
35
|
-
rest.delete("environments/#{new_resource.name}")
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def load_current_resource
|
41
|
-
begin
|
42
|
-
@current_resource = json_to_resource(rest.get("environments/#{new_resource.name}"))
|
43
|
-
rescue Net::HTTPServerException => e
|
44
|
-
if e.response.code == "404"
|
45
|
-
@current_resource = not_found_resource
|
46
|
-
else
|
47
|
-
raise
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def augment_new_json(json)
|
53
|
-
# Apply modifiers
|
54
|
-
json['default_attributes'] = apply_modifiers(new_resource.default_attribute_modifiers, json['default_attributes'])
|
55
|
-
json['override_attributes'] = apply_modifiers(new_resource.override_attribute_modifiers, json['override_attributes'])
|
56
|
-
json
|
57
|
-
end
|
58
|
-
|
59
|
-
#
|
60
|
-
# Helpers
|
61
|
-
#
|
62
|
-
|
63
|
-
def resource_class
|
64
|
-
Chef::Resource::ChefEnvironment
|
65
|
-
end
|
66
|
-
|
67
|
-
def data_handler
|
68
|
-
Chef::ChefFS::DataHandler::EnvironmentDataHandler.new
|
69
|
-
end
|
70
|
-
|
71
|
-
def keys
|
72
|
-
{
|
73
|
-
'name' => :name,
|
74
|
-
'description' => :description,
|
75
|
-
'cookbook_versions' => :cookbook_versions,
|
76
|
-
'default_attributes' => :default_attributes,
|
77
|
-
'override_attributes' => :override_attributes
|
78
|
-
}
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
1
|
+
require 'cheffish/chef_provider_base'
|
2
|
+
require 'chef/resource/chef_environment'
|
3
|
+
require 'chef/chef_fs/data_handler/environment_data_handler'
|
4
|
+
|
5
|
+
class Chef
|
6
|
+
class Provider
|
7
|
+
class ChefEnvironment < Cheffish::ChefProviderBase
|
8
|
+
provides :chef_environment
|
9
|
+
|
10
|
+
def whyrun_supported?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
action :create do
|
15
|
+
differences = json_differences(current_json, new_json)
|
16
|
+
|
17
|
+
if current_resource_exists?
|
18
|
+
if differences.size > 0
|
19
|
+
description = [ "update environment #{new_resource.name} at #{rest.url}" ] + differences
|
20
|
+
converge_by description do
|
21
|
+
rest.put("environments/#{new_resource.name}", normalize_for_put(new_json))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
else
|
25
|
+
description = [ "create environment #{new_resource.name} at #{rest.url}" ] + differences
|
26
|
+
converge_by description do
|
27
|
+
rest.post("environments", normalize_for_post(new_json))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
action :delete do
|
33
|
+
if current_resource_exists?
|
34
|
+
converge_by "delete environment #{new_resource.name} at #{rest.url}" do
|
35
|
+
rest.delete("environments/#{new_resource.name}")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def load_current_resource
|
41
|
+
begin
|
42
|
+
@current_resource = json_to_resource(rest.get("environments/#{new_resource.name}"))
|
43
|
+
rescue Net::HTTPServerException => e
|
44
|
+
if e.response.code == "404"
|
45
|
+
@current_resource = not_found_resource
|
46
|
+
else
|
47
|
+
raise
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def augment_new_json(json)
|
53
|
+
# Apply modifiers
|
54
|
+
json['default_attributes'] = apply_modifiers(new_resource.default_attribute_modifiers, json['default_attributes'])
|
55
|
+
json['override_attributes'] = apply_modifiers(new_resource.override_attribute_modifiers, json['override_attributes'])
|
56
|
+
json
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Helpers
|
61
|
+
#
|
62
|
+
|
63
|
+
def resource_class
|
64
|
+
Chef::Resource::ChefEnvironment
|
65
|
+
end
|
66
|
+
|
67
|
+
def data_handler
|
68
|
+
Chef::ChefFS::DataHandler::EnvironmentDataHandler.new
|
69
|
+
end
|
70
|
+
|
71
|
+
def keys
|
72
|
+
{
|
73
|
+
'name' => :name,
|
74
|
+
'description' => :description,
|
75
|
+
'cookbook_versions' => :cookbook_versions,
|
76
|
+
'default_attributes' => :default_attributes,
|
77
|
+
'override_attributes' => :override_attributes
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -1,83 +1,83 @@
|
|
1
|
-
require 'cheffish/chef_provider_base'
|
2
|
-
require 'chef/resource/chef_group'
|
3
|
-
require 'chef/chef_fs/data_handler/group_data_handler'
|
4
|
-
|
5
|
-
class Chef
|
6
|
-
class Provider
|
7
|
-
class ChefGroup < Cheffish::ChefProviderBase
|
8
|
-
provides :chef_group
|
9
|
-
|
10
|
-
def whyrun_supported?
|
11
|
-
true
|
12
|
-
end
|
13
|
-
|
14
|
-
action :create do
|
15
|
-
differences = json_differences(current_json, new_json)
|
16
|
-
|
17
|
-
if current_resource_exists?
|
18
|
-
if differences.size > 0
|
19
|
-
description = [ "update group #{new_resource.name} at #{rest.url}" ] + differences
|
20
|
-
converge_by description do
|
21
|
-
rest.put("groups/#{new_resource.name}", normalize_for_put(new_json))
|
22
|
-
end
|
23
|
-
end
|
24
|
-
else
|
25
|
-
description = [ "create group #{new_resource.name} at #{rest.url}" ] + differences
|
26
|
-
converge_by description do
|
27
|
-
rest.post("groups", normalize_for_post(new_json))
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
action :delete do
|
33
|
-
if current_resource_exists?
|
34
|
-
converge_by "delete group #{new_resource.name} at #{rest.url}" do
|
35
|
-
rest.delete("groups/#{new_resource.name}")
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def load_current_resource
|
41
|
-
begin
|
42
|
-
@current_resource = json_to_resource(rest.get("groups/#{new_resource.name}"))
|
43
|
-
rescue Net::HTTPServerException => e
|
44
|
-
if e.response.code == "404"
|
45
|
-
@current_resource = not_found_resource
|
46
|
-
else
|
47
|
-
raise
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def augment_new_json(json)
|
53
|
-
# Apply modifiers
|
54
|
-
json['users'] |= new_resource.users
|
55
|
-
json['clients'] |= new_resource.clients
|
56
|
-
json['groups'] |= new_resource.groups
|
57
|
-
json['users'] -= new_resource.remove_users
|
58
|
-
json['clients'] -= new_resource.remove_clients
|
59
|
-
json['groups'] -= new_resource.remove_groups
|
60
|
-
json
|
61
|
-
end
|
62
|
-
|
63
|
-
#
|
64
|
-
# Helpers
|
65
|
-
#
|
66
|
-
|
67
|
-
def resource_class
|
68
|
-
Chef::Resource::ChefGroup
|
69
|
-
end
|
70
|
-
|
71
|
-
def data_handler
|
72
|
-
Chef::ChefFS::DataHandler::GroupDataHandler.new
|
73
|
-
end
|
74
|
-
|
75
|
-
def keys
|
76
|
-
{
|
77
|
-
'name' => :name,
|
78
|
-
'groupname' => :name
|
79
|
-
}
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
1
|
+
require 'cheffish/chef_provider_base'
|
2
|
+
require 'chef/resource/chef_group'
|
3
|
+
require 'chef/chef_fs/data_handler/group_data_handler'
|
4
|
+
|
5
|
+
class Chef
|
6
|
+
class Provider
|
7
|
+
class ChefGroup < Cheffish::ChefProviderBase
|
8
|
+
provides :chef_group
|
9
|
+
|
10
|
+
def whyrun_supported?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
action :create do
|
15
|
+
differences = json_differences(current_json, new_json)
|
16
|
+
|
17
|
+
if current_resource_exists?
|
18
|
+
if differences.size > 0
|
19
|
+
description = [ "update group #{new_resource.name} at #{rest.url}" ] + differences
|
20
|
+
converge_by description do
|
21
|
+
rest.put("groups/#{new_resource.name}", normalize_for_put(new_json))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
else
|
25
|
+
description = [ "create group #{new_resource.name} at #{rest.url}" ] + differences
|
26
|
+
converge_by description do
|
27
|
+
rest.post("groups", normalize_for_post(new_json))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
action :delete do
|
33
|
+
if current_resource_exists?
|
34
|
+
converge_by "delete group #{new_resource.name} at #{rest.url}" do
|
35
|
+
rest.delete("groups/#{new_resource.name}")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def load_current_resource
|
41
|
+
begin
|
42
|
+
@current_resource = json_to_resource(rest.get("groups/#{new_resource.name}"))
|
43
|
+
rescue Net::HTTPServerException => e
|
44
|
+
if e.response.code == "404"
|
45
|
+
@current_resource = not_found_resource
|
46
|
+
else
|
47
|
+
raise
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def augment_new_json(json)
|
53
|
+
# Apply modifiers
|
54
|
+
json['users'] |= new_resource.users
|
55
|
+
json['clients'] |= new_resource.clients
|
56
|
+
json['groups'] |= new_resource.groups
|
57
|
+
json['users'] -= new_resource.remove_users
|
58
|
+
json['clients'] -= new_resource.remove_clients
|
59
|
+
json['groups'] -= new_resource.remove_groups
|
60
|
+
json
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# Helpers
|
65
|
+
#
|
66
|
+
|
67
|
+
def resource_class
|
68
|
+
Chef::Resource::ChefGroup
|
69
|
+
end
|
70
|
+
|
71
|
+
def data_handler
|
72
|
+
Chef::ChefFS::DataHandler::GroupDataHandler.new
|
73
|
+
end
|
74
|
+
|
75
|
+
def keys
|
76
|
+
{
|
77
|
+
'name' => :name,
|
78
|
+
'groupname' => :name
|
79
|
+
}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -1,169 +1,169 @@
|
|
1
|
-
require 'chef/provider/lwrp_base'
|
2
|
-
require 'chef/chef_fs/file_pattern'
|
3
|
-
require 'chef/chef_fs/file_system'
|
4
|
-
require 'chef/chef_fs/parallelizer'
|
5
|
-
require 'chef/chef_fs/file_system/chef_server_root_dir'
|
6
|
-
require 'chef/chef_fs/file_system/chef_repository_file_system_root_dir'
|
7
|
-
|
8
|
-
class Chef
|
9
|
-
class Provider
|
10
|
-
class ChefMirror < Chef::Provider::LWRPBase
|
11
|
-
provides :chef_mirror
|
12
|
-
|
13
|
-
def whyrun_supported?
|
14
|
-
true
|
15
|
-
end
|
16
|
-
|
17
|
-
action :upload do
|
18
|
-
with_modified_config do
|
19
|
-
copy_to(local_fs, remote_fs)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
action :download do
|
24
|
-
with_modified_config do
|
25
|
-
copy_to(remote_fs, local_fs)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def with_modified_config
|
30
|
-
# pre-Chef-12 ChefFS reads versioned_cookbooks out of Chef::Config instead of
|
31
|
-
# taking it as an input, so we need to modify it for the duration of copy_to
|
32
|
-
@old_versioned_cookbooks = Chef::Config.versioned_cookbooks
|
33
|
-
# If versioned_cookbooks is explicitly set, set it.
|
34
|
-
if !new_resource.versioned_cookbooks.nil?
|
35
|
-
Chef::Config.versioned_cookbooks = new_resource.versioned_cookbooks
|
36
|
-
|
37
|
-
# If new_resource.chef_repo_path is set, versioned_cookbooks defaults to true.
|
38
|
-
# Otherwise, it stays at its current Chef::Config value.
|
39
|
-
elsif new_resource.chef_repo_path
|
40
|
-
Chef::Config.versioned_cookbooks = true
|
41
|
-
end
|
42
|
-
|
43
|
-
begin
|
44
|
-
yield
|
45
|
-
ensure
|
46
|
-
Chef::Config.versioned_cookbooks = @old_versioned_cookbooks
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def copy_to(src_root, dest_root)
|
51
|
-
if new_resource.concurrency && new_resource.concurrency <= 0
|
52
|
-
raise "chef_mirror.concurrency must be above 0! Was set to #{new_resource.concurrency}"
|
53
|
-
end
|
54
|
-
# Honor concurrency
|
55
|
-
Chef::ChefFS::Parallelizer.threads = (new_resource.concurrency || 10) - 1
|
56
|
-
|
57
|
-
# We don't let the user pass absolute paths; we want to reserve those for
|
58
|
-
# multi-org support (/organizations/foo).
|
59
|
-
if new_resource.path[0] == '/'
|
60
|
-
raise "Absolute paths in chef_mirror not yet supported."
|
61
|
-
end
|
62
|
-
# Copy!
|
63
|
-
path = Chef::ChefFS::FilePattern.new("/#{new_resource.path}")
|
64
|
-
ui = CopyListener.new(self)
|
65
|
-
error = Chef::ChefFS::FileSystem.copy_to(path, src_root, dest_root, nil, options, ui, proc { |p| p.path })
|
66
|
-
|
67
|
-
if error
|
68
|
-
raise "Errors while copying:#{ui.errors.map { |e| "#{e}\n" }.join('')}"
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def local_fs
|
73
|
-
# If chef_repo_path is set to a string, put it in the form it usually is in
|
74
|
-
# chef config (:chef_repo_path, :node_path, etc.)
|
75
|
-
path_config = new_resource.chef_repo_path
|
76
|
-
if path_config.is_a?(Hash)
|
77
|
-
chef_repo_path = path_config.delete(:chef_repo_path)
|
78
|
-
elsif path_config
|
79
|
-
chef_repo_path = path_config
|
80
|
-
path_config = {}
|
81
|
-
else
|
82
|
-
chef_repo_path = Chef::Config.chef_repo_path
|
83
|
-
path_config = Chef::Config
|
84
|
-
end
|
85
|
-
chef_repo_path = Array(chef_repo_path).flatten
|
86
|
-
|
87
|
-
# Go through the expected object paths and figure out the local paths for each.
|
88
|
-
case repo_mode
|
89
|
-
when 'hosted_everything'
|
90
|
-
object_names = %w(acls clients cookbooks containers data_bags environments groups nodes roles)
|
91
|
-
else
|
92
|
-
object_names = %w(clients cookbooks data_bags environments nodes roles users)
|
93
|
-
end
|
94
|
-
|
95
|
-
object_paths = {}
|
96
|
-
object_names.each do |object_name|
|
97
|
-
variable_name = "#{object_name[0..-2]}_path" # cookbooks -> cookbook_path
|
98
|
-
if path_config[variable_name.to_sym]
|
99
|
-
paths = Array(path_config[variable_name.to_sym]).flatten
|
100
|
-
else
|
101
|
-
paths = chef_repo_path.map { |path| ::File.join(path, object_name) }
|
102
|
-
end
|
103
|
-
object_paths[object_name] = paths.map { |path| ::File.expand_path(path) }
|
104
|
-
end
|
105
|
-
|
106
|
-
# Set up the root dir
|
107
|
-
Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir.new(object_paths)
|
108
|
-
end
|
109
|
-
|
110
|
-
def remote_fs
|
111
|
-
config = {
|
112
|
-
:chef_server_url => new_resource.chef_server[:chef_server_url],
|
113
|
-
:node_name => new_resource.chef_server[:options][:client_name],
|
114
|
-
:client_key => new_resource.chef_server[:options][:signing_key_filename],
|
115
|
-
:repo_mode => repo_mode,
|
116
|
-
:versioned_cookbooks => Chef::Config.versioned_cookbooks
|
117
|
-
}
|
118
|
-
Chef::ChefFS::FileSystem::ChefServerRootDir.new("remote", config)
|
119
|
-
end
|
120
|
-
|
121
|
-
def repo_mode
|
122
|
-
new_resource.chef_server[:chef_server_url] =~ /\/organizations\// ? 'hosted_everything' : 'everything'
|
123
|
-
end
|
124
|
-
|
125
|
-
def options
|
126
|
-
result = {
|
127
|
-
:purge => new_resource.purge,
|
128
|
-
:freeze => new_resource.freeze,
|
129
|
-
:diff => new_resource.no_diff,
|
130
|
-
:dry_run => whyrun_mode?
|
131
|
-
}
|
132
|
-
result[:diff] = !result[:diff]
|
133
|
-
result[:repo_mode] = repo_mode
|
134
|
-
result[:concurrency] = new_resource.concurrency if new_resource.concurrency
|
135
|
-
result
|
136
|
-
end
|
137
|
-
|
138
|
-
def load_current_resource
|
139
|
-
end
|
140
|
-
|
141
|
-
class CopyListener
|
142
|
-
def initialize(mirror)
|
143
|
-
@mirror = mirror
|
144
|
-
@errors = []
|
145
|
-
end
|
146
|
-
|
147
|
-
attr_reader :mirror
|
148
|
-
attr_reader :errors
|
149
|
-
|
150
|
-
# TODO output is not *always* indicative of a change. We may want to give
|
151
|
-
# ChefFS the ability to tell us that info. For now though, assuming any output
|
152
|
-
# means change is pretty damn close to the truth.
|
153
|
-
def output(str)
|
154
|
-
mirror.converge_by str do
|
155
|
-
end
|
156
|
-
end
|
157
|
-
def warn(str)
|
158
|
-
mirror.converge_by "WARNING: #{str}" do
|
159
|
-
end
|
160
|
-
end
|
161
|
-
def error(str)
|
162
|
-
mirror.converge_by "ERROR: #{str}" do
|
163
|
-
end
|
164
|
-
@errors << str
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
1
|
+
require 'chef/provider/lwrp_base'
|
2
|
+
require 'chef/chef_fs/file_pattern'
|
3
|
+
require 'chef/chef_fs/file_system'
|
4
|
+
require 'chef/chef_fs/parallelizer'
|
5
|
+
require 'chef/chef_fs/file_system/chef_server_root_dir'
|
6
|
+
require 'chef/chef_fs/file_system/chef_repository_file_system_root_dir'
|
7
|
+
|
8
|
+
class Chef
|
9
|
+
class Provider
|
10
|
+
class ChefMirror < Chef::Provider::LWRPBase
|
11
|
+
provides :chef_mirror
|
12
|
+
|
13
|
+
def whyrun_supported?
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
action :upload do
|
18
|
+
with_modified_config do
|
19
|
+
copy_to(local_fs, remote_fs)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
action :download do
|
24
|
+
with_modified_config do
|
25
|
+
copy_to(remote_fs, local_fs)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def with_modified_config
|
30
|
+
# pre-Chef-12 ChefFS reads versioned_cookbooks out of Chef::Config instead of
|
31
|
+
# taking it as an input, so we need to modify it for the duration of copy_to
|
32
|
+
@old_versioned_cookbooks = Chef::Config.versioned_cookbooks
|
33
|
+
# If versioned_cookbooks is explicitly set, set it.
|
34
|
+
if !new_resource.versioned_cookbooks.nil?
|
35
|
+
Chef::Config.versioned_cookbooks = new_resource.versioned_cookbooks
|
36
|
+
|
37
|
+
# If new_resource.chef_repo_path is set, versioned_cookbooks defaults to true.
|
38
|
+
# Otherwise, it stays at its current Chef::Config value.
|
39
|
+
elsif new_resource.chef_repo_path
|
40
|
+
Chef::Config.versioned_cookbooks = true
|
41
|
+
end
|
42
|
+
|
43
|
+
begin
|
44
|
+
yield
|
45
|
+
ensure
|
46
|
+
Chef::Config.versioned_cookbooks = @old_versioned_cookbooks
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def copy_to(src_root, dest_root)
|
51
|
+
if new_resource.concurrency && new_resource.concurrency <= 0
|
52
|
+
raise "chef_mirror.concurrency must be above 0! Was set to #{new_resource.concurrency}"
|
53
|
+
end
|
54
|
+
# Honor concurrency
|
55
|
+
Chef::ChefFS::Parallelizer.threads = (new_resource.concurrency || 10) - 1
|
56
|
+
|
57
|
+
# We don't let the user pass absolute paths; we want to reserve those for
|
58
|
+
# multi-org support (/organizations/foo).
|
59
|
+
if new_resource.path[0] == '/'
|
60
|
+
raise "Absolute paths in chef_mirror not yet supported."
|
61
|
+
end
|
62
|
+
# Copy!
|
63
|
+
path = Chef::ChefFS::FilePattern.new("/#{new_resource.path}")
|
64
|
+
ui = CopyListener.new(self)
|
65
|
+
error = Chef::ChefFS::FileSystem.copy_to(path, src_root, dest_root, nil, options, ui, proc { |p| p.path })
|
66
|
+
|
67
|
+
if error
|
68
|
+
raise "Errors while copying:#{ui.errors.map { |e| "#{e}\n" }.join('')}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def local_fs
|
73
|
+
# If chef_repo_path is set to a string, put it in the form it usually is in
|
74
|
+
# chef config (:chef_repo_path, :node_path, etc.)
|
75
|
+
path_config = new_resource.chef_repo_path
|
76
|
+
if path_config.is_a?(Hash)
|
77
|
+
chef_repo_path = path_config.delete(:chef_repo_path)
|
78
|
+
elsif path_config
|
79
|
+
chef_repo_path = path_config
|
80
|
+
path_config = {}
|
81
|
+
else
|
82
|
+
chef_repo_path = Chef::Config.chef_repo_path
|
83
|
+
path_config = Chef::Config
|
84
|
+
end
|
85
|
+
chef_repo_path = Array(chef_repo_path).flatten
|
86
|
+
|
87
|
+
# Go through the expected object paths and figure out the local paths for each.
|
88
|
+
case repo_mode
|
89
|
+
when 'hosted_everything'
|
90
|
+
object_names = %w(acls clients cookbooks containers data_bags environments groups nodes roles)
|
91
|
+
else
|
92
|
+
object_names = %w(clients cookbooks data_bags environments nodes roles users)
|
93
|
+
end
|
94
|
+
|
95
|
+
object_paths = {}
|
96
|
+
object_names.each do |object_name|
|
97
|
+
variable_name = "#{object_name[0..-2]}_path" # cookbooks -> cookbook_path
|
98
|
+
if path_config[variable_name.to_sym]
|
99
|
+
paths = Array(path_config[variable_name.to_sym]).flatten
|
100
|
+
else
|
101
|
+
paths = chef_repo_path.map { |path| ::File.join(path, object_name) }
|
102
|
+
end
|
103
|
+
object_paths[object_name] = paths.map { |path| ::File.expand_path(path) }
|
104
|
+
end
|
105
|
+
|
106
|
+
# Set up the root dir
|
107
|
+
Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir.new(object_paths)
|
108
|
+
end
|
109
|
+
|
110
|
+
def remote_fs
|
111
|
+
config = {
|
112
|
+
:chef_server_url => new_resource.chef_server[:chef_server_url],
|
113
|
+
:node_name => new_resource.chef_server[:options][:client_name],
|
114
|
+
:client_key => new_resource.chef_server[:options][:signing_key_filename],
|
115
|
+
:repo_mode => repo_mode,
|
116
|
+
:versioned_cookbooks => Chef::Config.versioned_cookbooks
|
117
|
+
}
|
118
|
+
Chef::ChefFS::FileSystem::ChefServerRootDir.new("remote", config)
|
119
|
+
end
|
120
|
+
|
121
|
+
def repo_mode
|
122
|
+
new_resource.chef_server[:chef_server_url] =~ /\/organizations\// ? 'hosted_everything' : 'everything'
|
123
|
+
end
|
124
|
+
|
125
|
+
def options
|
126
|
+
result = {
|
127
|
+
:purge => new_resource.purge,
|
128
|
+
:freeze => new_resource.freeze,
|
129
|
+
:diff => new_resource.no_diff,
|
130
|
+
:dry_run => whyrun_mode?
|
131
|
+
}
|
132
|
+
result[:diff] = !result[:diff]
|
133
|
+
result[:repo_mode] = repo_mode
|
134
|
+
result[:concurrency] = new_resource.concurrency if new_resource.concurrency
|
135
|
+
result
|
136
|
+
end
|
137
|
+
|
138
|
+
def load_current_resource
|
139
|
+
end
|
140
|
+
|
141
|
+
class CopyListener
|
142
|
+
def initialize(mirror)
|
143
|
+
@mirror = mirror
|
144
|
+
@errors = []
|
145
|
+
end
|
146
|
+
|
147
|
+
attr_reader :mirror
|
148
|
+
attr_reader :errors
|
149
|
+
|
150
|
+
# TODO output is not *always* indicative of a change. We may want to give
|
151
|
+
# ChefFS the ability to tell us that info. For now though, assuming any output
|
152
|
+
# means change is pretty damn close to the truth.
|
153
|
+
def output(str)
|
154
|
+
mirror.converge_by str do
|
155
|
+
end
|
156
|
+
end
|
157
|
+
def warn(str)
|
158
|
+
mirror.converge_by "WARNING: #{str}" do
|
159
|
+
end
|
160
|
+
end
|
161
|
+
def error(str)
|
162
|
+
mirror.converge_by "ERROR: #{str}" do
|
163
|
+
end
|
164
|
+
@errors << str
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|