cheffish 1.4.1 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +201 -201
  3. data/README.md +120 -120
  4. data/Rakefile +23 -23
  5. data/lib/chef/provider/chef_acl.rb +439 -439
  6. data/lib/chef/provider/chef_client.rb +53 -53
  7. data/lib/chef/provider/chef_container.rb +55 -55
  8. data/lib/chef/provider/chef_data_bag.rb +55 -55
  9. data/lib/chef/provider/chef_data_bag_item.rb +278 -278
  10. data/lib/chef/provider/chef_environment.rb +83 -83
  11. data/lib/chef/provider/chef_group.rb +83 -83
  12. data/lib/chef/provider/chef_mirror.rb +169 -169
  13. data/lib/chef/provider/chef_node.rb +87 -87
  14. data/lib/chef/provider/chef_organization.rb +155 -155
  15. data/lib/chef/provider/chef_resolved_cookbooks.rb +46 -46
  16. data/lib/chef/provider/chef_role.rb +84 -84
  17. data/lib/chef/provider/chef_user.rb +59 -59
  18. data/lib/chef/provider/private_key.rb +225 -225
  19. data/lib/chef/provider/public_key.rb +88 -88
  20. data/lib/chef/resource/chef_acl.rb +69 -69
  21. data/lib/chef/resource/chef_client.rb +48 -48
  22. data/lib/chef/resource/chef_container.rb +22 -22
  23. data/lib/chef/resource/chef_data_bag.rb +22 -22
  24. data/lib/chef/resource/chef_data_bag_item.rb +121 -121
  25. data/lib/chef/resource/chef_environment.rb +77 -77
  26. data/lib/chef/resource/chef_group.rb +53 -53
  27. data/lib/chef/resource/chef_mirror.rb +52 -52
  28. data/lib/chef/resource/chef_node.rb +22 -22
  29. data/lib/chef/resource/chef_organization.rb +69 -69
  30. data/lib/chef/resource/chef_resolved_cookbooks.rb +35 -35
  31. data/lib/chef/resource/chef_role.rb +110 -110
  32. data/lib/chef/resource/chef_user.rb +56 -56
  33. data/lib/chef/resource/private_key.rb +48 -48
  34. data/lib/chef/resource/public_key.rb +25 -25
  35. data/lib/cheffish/actor_provider_base.rb +131 -131
  36. data/lib/cheffish/basic_chef_client.rb +184 -184
  37. data/lib/cheffish/chef_provider_base.rb +246 -246
  38. data/lib/cheffish/chef_run.rb +162 -162
  39. data/lib/cheffish/chef_run_data.rb +19 -19
  40. data/lib/cheffish/chef_run_listener.rb +30 -30
  41. data/lib/cheffish/key_formatter.rb +113 -113
  42. data/lib/cheffish/merged_config.rb +94 -94
  43. data/lib/cheffish/recipe_dsl.rb +157 -157
  44. data/lib/cheffish/rspec/chef_run_support.rb +83 -83
  45. data/lib/cheffish/rspec/matchers/be_idempotent.rb +16 -16
  46. data/lib/cheffish/rspec/matchers/emit_no_warnings_or_errors.rb +15 -15
  47. data/lib/cheffish/rspec/matchers/have_updated.rb +37 -37
  48. data/lib/cheffish/rspec/matchers/partially_match.rb +63 -63
  49. data/lib/cheffish/rspec/matchers.rb +4 -4
  50. data/lib/cheffish/rspec/recipe_run_wrapper.rb +78 -59
  51. data/lib/cheffish/rspec/repository_support.rb +108 -108
  52. data/lib/cheffish/rspec.rb +8 -8
  53. data/lib/cheffish/server_api.rb +52 -52
  54. data/lib/cheffish/version.rb +3 -3
  55. data/lib/cheffish/with_pattern.rb +21 -21
  56. data/lib/cheffish.rb +235 -235
  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 -78
  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 -37
  76. 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