cheffish 1.3.1 → 1.4.0

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