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