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,87 +1,87 @@
1
- require 'cheffish/chef_provider_base'
2
- require 'chef/resource/chef_node'
3
- require 'chef/chef_fs/data_handler/node_data_handler'
4
-
5
- class Chef
6
- class Provider
7
- class ChefNode < Cheffish::ChefProviderBase
8
- provides :chef_node
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 node #{new_resource.name} at #{rest.url}" ] + differences
20
- converge_by description do
21
- rest.put("nodes/#{new_resource.name}", normalize_for_put(new_json))
22
- end
23
- end
24
- else
25
- description = [ "create node #{new_resource.name} at #{rest.url}" ] + differences
26
- converge_by description do
27
- rest.post("nodes", 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 node #{new_resource.name} at #{rest.url}" do
35
- rest.delete("nodes/#{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("nodes/#{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
- # Preserve tags even if "attributes" was overwritten directly
54
- json['normal']['tags'] = current_json['normal']['tags'] unless json['normal']['tags']
55
- # Apply modifiers
56
- json['run_list'] = apply_run_list_modifiers(new_resource.run_list_modifiers, new_resource.run_list_removers, json['run_list'])
57
- json['normal'] = apply_modifiers(new_resource.attribute_modifiers, json['normal'])
58
- # Preserve default/override/automatic even when "complete true"
59
- json['default'] = current_json['default']
60
- json['override'] = current_json['override']
61
- json['automatic'] = current_json['automatic']
62
- json
63
- end
64
-
65
- #
66
- # Helpers
67
- #
68
-
69
- def resource_class
70
- Chef::Resource::ChefNode
71
- end
72
-
73
- def data_handler
74
- Chef::ChefFS::DataHandler::NodeDataHandler.new
75
- end
76
-
77
- def keys
78
- {
79
- 'name' => :name,
80
- 'chef_environment' => :chef_environment,
81
- 'run_list' => :run_list,
82
- 'normal' => :attributes
83
- }
84
- end
85
- end
86
- end
87
- end
1
+ require 'cheffish/chef_provider_base'
2
+ require 'chef/resource/chef_node'
3
+ require 'chef/chef_fs/data_handler/node_data_handler'
4
+
5
+ class Chef
6
+ class Provider
7
+ class ChefNode < Cheffish::ChefProviderBase
8
+ provides :chef_node
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 node #{new_resource.name} at #{rest.url}" ] + differences
20
+ converge_by description do
21
+ rest.put("nodes/#{new_resource.name}", normalize_for_put(new_json))
22
+ end
23
+ end
24
+ else
25
+ description = [ "create node #{new_resource.name} at #{rest.url}" ] + differences
26
+ converge_by description do
27
+ rest.post("nodes", 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 node #{new_resource.name} at #{rest.url}" do
35
+ rest.delete("nodes/#{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("nodes/#{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
+ # Preserve tags even if "attributes" was overwritten directly
54
+ json['normal']['tags'] = current_json['normal']['tags'] unless json['normal']['tags']
55
+ # Apply modifiers
56
+ json['run_list'] = apply_run_list_modifiers(new_resource.run_list_modifiers, new_resource.run_list_removers, json['run_list'])
57
+ json['normal'] = apply_modifiers(new_resource.attribute_modifiers, json['normal'])
58
+ # Preserve default/override/automatic even when "complete true"
59
+ json['default'] = current_json['default']
60
+ json['override'] = current_json['override']
61
+ json['automatic'] = current_json['automatic']
62
+ json
63
+ end
64
+
65
+ #
66
+ # Helpers
67
+ #
68
+
69
+ def resource_class
70
+ Chef::Resource::ChefNode
71
+ end
72
+
73
+ def data_handler
74
+ Chef::ChefFS::DataHandler::NodeDataHandler.new
75
+ end
76
+
77
+ def keys
78
+ {
79
+ 'name' => :name,
80
+ 'chef_environment' => :chef_environment,
81
+ 'run_list' => :run_list,
82
+ 'normal' => :attributes
83
+ }
84
+ end
85
+ end
86
+ end
87
+ end
@@ -1,155 +1,155 @@
1
- require 'cheffish/chef_provider_base'
2
- require 'chef/resource/chef_organization'
3
- require 'chef/chef_fs/data_handler/data_handler_base'
4
-
5
- class Chef
6
- class Provider
7
- class ChefOrganization < Cheffish::ChefProviderBase
8
- provides :chef_organization
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 organization #{new_resource.name} at #{rest.url}" ] + differences
20
- converge_by description do
21
- rest.put("#{rest.root_url}/organizations/#{new_resource.name}", normalize_for_put(new_json))
22
- end
23
- end
24
- else
25
- description = [ "create organization #{new_resource.name} at #{rest.url}" ] + differences
26
- converge_by description do
27
- rest.post("#{rest.root_url}/organizations", normalize_for_post(new_json))
28
- end
29
- end
30
-
31
- # Revoke invites and memberships when asked
32
- invites_to_remove.each do |user|
33
- if outstanding_invites.has_key?(user)
34
- converge_by "revoke #{user}'s invitation to organization #{new_resource.name}" do
35
- rest.delete("#{rest.root_url}/organizations/#{new_resource.name}/association_requests/#{outstanding_invites[user]}")
36
- end
37
- end
38
- end
39
- members_to_remove.each do |user|
40
- if existing_members.include?(user)
41
- converge_by "remove #{user} from organization #{new_resource.name}" do
42
- rest.delete("#{rest.root_url}/organizations/#{new_resource.name}/users/#{user}")
43
- end
44
- end
45
- end
46
-
47
- # Invite and add members when asked
48
- new_resource.invites.each do |user|
49
- if !existing_members.include?(user) && !outstanding_invites.has_key?(user)
50
- converge_by "invite #{user} to organization #{new_resource.name}" do
51
- rest.post("#{rest.root_url}/organizations/#{new_resource.name}/association_requests", { 'user' => user })
52
- end
53
- end
54
- end
55
- new_resource.members.each do |user|
56
- if !existing_members.include?(user)
57
- converge_by "Add #{user} to organization #{new_resource.name}" do
58
- rest.post("#{rest.root_url}/organizations/#{new_resource.name}/users/", { 'username' => user })
59
- end
60
- end
61
- end
62
- end
63
-
64
- def existing_members
65
- @existing_members ||= rest.get("#{rest.root_url}/organizations/#{new_resource.name}/users").map { |u| u['user']['username'] }
66
- end
67
-
68
- def outstanding_invites
69
- @outstanding_invites ||= begin
70
- invites = {}
71
- rest.get("#{rest.root_url}/organizations/#{new_resource.name}/association_requests").each do |r|
72
- invites[r['username']] = r['id']
73
- end
74
- invites
75
- end
76
- end
77
-
78
- def invites_to_remove
79
- if new_resource.complete
80
- if new_resource.invites_specified? || new_resource.members_specified?
81
- outstanding_invites.keys - (new_resource.invites | new_resource.members)
82
- else
83
- []
84
- end
85
- else
86
- new_resource.remove_members
87
- end
88
- end
89
-
90
- def members_to_remove
91
- if new_resource.complete
92
- if new_resource.members_specified?
93
- existing_members - (new_resource.invites | new_resource.members)
94
- else
95
- []
96
- end
97
- else
98
- new_resource.remove_members
99
- end
100
- end
101
-
102
- action :delete do
103
- if current_resource_exists?
104
- converge_by "delete organization #{new_resource.name} at #{rest.url}" do
105
- rest.delete("#{rest.root_url}/organizations/#{new_resource.name}")
106
- end
107
- end
108
- end
109
-
110
- def load_current_resource
111
- begin
112
- @current_resource = json_to_resource(rest.get("#{rest.root_url}/organizations/#{new_resource.name}"))
113
- rescue Net::HTTPServerException => e
114
- if e.response.code == "404"
115
- @current_resource = not_found_resource
116
- else
117
- raise
118
- end
119
- end
120
- end
121
-
122
- #
123
- # Helpers
124
- #
125
-
126
- def resource_class
127
- Chef::Resource::ChefOrganization
128
- end
129
-
130
- def data_handler
131
- OrganizationDataHandler.new
132
- end
133
-
134
- def keys
135
- {
136
- 'name' => :name,
137
- 'full_name' => :full_name
138
- }
139
- end
140
-
141
- class OrganizationDataHandler < Chef::ChefFS::DataHandler::DataHandlerBase
142
- def normalize(organization, entry)
143
- # Normalize the order of the keys for easier reading
144
- normalize_hash(organization, {
145
- 'name' => remove_dot_json(entry.name),
146
- 'full_name' => remove_dot_json(entry.name),
147
- 'org_type' => 'Business',
148
- 'clientname' => "#{remove_dot_json(entry.name)}-validator",
149
- 'billing_plan' => 'platform-free'
150
- })
151
- end
152
- end
153
- end
154
- end
155
- end
1
+ require 'cheffish/chef_provider_base'
2
+ require 'chef/resource/chef_organization'
3
+ require 'chef/chef_fs/data_handler/data_handler_base'
4
+
5
+ class Chef
6
+ class Provider
7
+ class ChefOrganization < Cheffish::ChefProviderBase
8
+ provides :chef_organization
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 organization #{new_resource.name} at #{rest.url}" ] + differences
20
+ converge_by description do
21
+ rest.put("#{rest.root_url}/organizations/#{new_resource.name}", normalize_for_put(new_json))
22
+ end
23
+ end
24
+ else
25
+ description = [ "create organization #{new_resource.name} at #{rest.url}" ] + differences
26
+ converge_by description do
27
+ rest.post("#{rest.root_url}/organizations", normalize_for_post(new_json))
28
+ end
29
+ end
30
+
31
+ # Revoke invites and memberships when asked
32
+ invites_to_remove.each do |user|
33
+ if outstanding_invites.has_key?(user)
34
+ converge_by "revoke #{user}'s invitation to organization #{new_resource.name}" do
35
+ rest.delete("#{rest.root_url}/organizations/#{new_resource.name}/association_requests/#{outstanding_invites[user]}")
36
+ end
37
+ end
38
+ end
39
+ members_to_remove.each do |user|
40
+ if existing_members.include?(user)
41
+ converge_by "remove #{user} from organization #{new_resource.name}" do
42
+ rest.delete("#{rest.root_url}/organizations/#{new_resource.name}/users/#{user}")
43
+ end
44
+ end
45
+ end
46
+
47
+ # Invite and add members when asked
48
+ new_resource.invites.each do |user|
49
+ if !existing_members.include?(user) && !outstanding_invites.has_key?(user)
50
+ converge_by "invite #{user} to organization #{new_resource.name}" do
51
+ rest.post("#{rest.root_url}/organizations/#{new_resource.name}/association_requests", { 'user' => user })
52
+ end
53
+ end
54
+ end
55
+ new_resource.members.each do |user|
56
+ if !existing_members.include?(user)
57
+ converge_by "Add #{user} to organization #{new_resource.name}" do
58
+ rest.post("#{rest.root_url}/organizations/#{new_resource.name}/users/", { 'username' => user })
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ def existing_members
65
+ @existing_members ||= rest.get("#{rest.root_url}/organizations/#{new_resource.name}/users").map { |u| u['user']['username'] }
66
+ end
67
+
68
+ def outstanding_invites
69
+ @outstanding_invites ||= begin
70
+ invites = {}
71
+ rest.get("#{rest.root_url}/organizations/#{new_resource.name}/association_requests").each do |r|
72
+ invites[r['username']] = r['id']
73
+ end
74
+ invites
75
+ end
76
+ end
77
+
78
+ def invites_to_remove
79
+ if new_resource.complete
80
+ if new_resource.invites_specified? || new_resource.members_specified?
81
+ outstanding_invites.keys - (new_resource.invites | new_resource.members)
82
+ else
83
+ []
84
+ end
85
+ else
86
+ new_resource.remove_members
87
+ end
88
+ end
89
+
90
+ def members_to_remove
91
+ if new_resource.complete
92
+ if new_resource.members_specified?
93
+ existing_members - (new_resource.invites | new_resource.members)
94
+ else
95
+ []
96
+ end
97
+ else
98
+ new_resource.remove_members
99
+ end
100
+ end
101
+
102
+ action :delete do
103
+ if current_resource_exists?
104
+ converge_by "delete organization #{new_resource.name} at #{rest.url}" do
105
+ rest.delete("#{rest.root_url}/organizations/#{new_resource.name}")
106
+ end
107
+ end
108
+ end
109
+
110
+ def load_current_resource
111
+ begin
112
+ @current_resource = json_to_resource(rest.get("#{rest.root_url}/organizations/#{new_resource.name}"))
113
+ rescue Net::HTTPServerException => e
114
+ if e.response.code == "404"
115
+ @current_resource = not_found_resource
116
+ else
117
+ raise
118
+ end
119
+ end
120
+ end
121
+
122
+ #
123
+ # Helpers
124
+ #
125
+
126
+ def resource_class
127
+ Chef::Resource::ChefOrganization
128
+ end
129
+
130
+ def data_handler
131
+ OrganizationDataHandler.new
132
+ end
133
+
134
+ def keys
135
+ {
136
+ 'name' => :name,
137
+ 'full_name' => :full_name
138
+ }
139
+ end
140
+
141
+ class OrganizationDataHandler < Chef::ChefFS::DataHandler::DataHandlerBase
142
+ def normalize(organization, entry)
143
+ # Normalize the order of the keys for easier reading
144
+ normalize_hash(organization, {
145
+ 'name' => remove_dot_json(entry.name),
146
+ 'full_name' => remove_dot_json(entry.name),
147
+ 'org_type' => 'Business',
148
+ 'clientname' => "#{remove_dot_json(entry.name)}-validator",
149
+ 'billing_plan' => 'platform-free'
150
+ })
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -1,46 +1,46 @@
1
- require 'chef/provider/lwrp_base'
2
- require 'chef_zero'
3
-
4
- class Chef
5
- class Provider
6
- class ChefResolvedCookbooks < Chef::Provider::LWRPBase
7
- provides :chef_resolved_cookbooks
8
-
9
- action :resolve do
10
- new_resource.cookbooks_from.each do |path|
11
- ::Dir.entries(path).each do |name|
12
- if ::File.directory?(::File.join(path, name)) && name != '.' && name != '..'
13
- new_resource.berksfile.cookbook name, :path => ::File.join(path, name)
14
- end
15
- end
16
- end
17
-
18
- new_resource.berksfile.install
19
-
20
- # Ridley really really wants a key :/
21
- if new_resource.chef_server[:options][:signing_key_filename]
22
- new_resource.berksfile.upload(
23
- :server_url => new_resource.chef_server[:chef_server_url],
24
- :client_name => new_resource.chef_server[:options][:client_name],
25
- :client_key => new_resource.chef_server[:options][:signing_key_filename])
26
- else
27
- file = Tempfile.new('privatekey')
28
- begin
29
- file.write(ChefZero::PRIVATE_KEY)
30
- file.close
31
-
32
- new_resource.berksfile.upload(
33
- :server_url => new_resource.chef_server[:chef_server_url],
34
- :client_name => new_resource.chef_server[:options][:client_name] || 'me',
35
- :client_key => file.path)
36
-
37
- ensure
38
- file.close
39
- file.unlink
40
- end
41
- end
42
- end
43
-
44
- end
45
- end
46
- end
1
+ require 'chef/provider/lwrp_base'
2
+ require 'chef_zero'
3
+
4
+ class Chef
5
+ class Provider
6
+ class ChefResolvedCookbooks < Chef::Provider::LWRPBase
7
+ provides :chef_resolved_cookbooks
8
+
9
+ action :resolve do
10
+ new_resource.cookbooks_from.each do |path|
11
+ ::Dir.entries(path).each do |name|
12
+ if ::File.directory?(::File.join(path, name)) && name != '.' && name != '..'
13
+ new_resource.berksfile.cookbook name, :path => ::File.join(path, name)
14
+ end
15
+ end
16
+ end
17
+
18
+ new_resource.berksfile.install
19
+
20
+ # Ridley really really wants a key :/
21
+ if new_resource.chef_server[:options][:signing_key_filename]
22
+ new_resource.berksfile.upload(
23
+ :server_url => new_resource.chef_server[:chef_server_url],
24
+ :client_name => new_resource.chef_server[:options][:client_name],
25
+ :client_key => new_resource.chef_server[:options][:signing_key_filename])
26
+ else
27
+ file = Tempfile.new('privatekey')
28
+ begin
29
+ file.write(ChefZero::PRIVATE_KEY)
30
+ file.close
31
+
32
+ new_resource.berksfile.upload(
33
+ :server_url => new_resource.chef_server[:chef_server_url],
34
+ :client_name => new_resource.chef_server[:options][:client_name] || 'me',
35
+ :client_key => file.path)
36
+
37
+ ensure
38
+ file.close
39
+ file.unlink
40
+ end
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+ end