cheffish 1.3.1 → 1.4.0

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 -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