cheffish 1.5.0 → 1.6.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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +10 -0
  3. data/LICENSE +201 -201
  4. data/README.md +120 -120
  5. data/Rakefile +23 -23
  6. data/cheffish.gemspec +26 -0
  7. data/lib/chef/provider/chef_acl.rb +446 -439
  8. data/lib/chef/provider/chef_client.rb +53 -53
  9. data/lib/chef/provider/chef_container.rb +55 -55
  10. data/lib/chef/provider/chef_data_bag.rb +55 -55
  11. data/lib/chef/provider/chef_data_bag_item.rb +278 -278
  12. data/lib/chef/provider/chef_environment.rb +83 -83
  13. data/lib/chef/provider/chef_group.rb +83 -83
  14. data/lib/chef/provider/chef_mirror.rb +169 -169
  15. data/lib/chef/provider/chef_node.rb +87 -87
  16. data/lib/chef/provider/chef_organization.rb +155 -155
  17. data/lib/chef/provider/chef_resolved_cookbooks.rb +46 -46
  18. data/lib/chef/provider/chef_role.rb +84 -84
  19. data/lib/chef/provider/chef_user.rb +59 -59
  20. data/lib/chef/provider/private_key.rb +225 -225
  21. data/lib/chef/provider/public_key.rb +88 -88
  22. data/lib/chef/resource/chef_acl.rb +69 -69
  23. data/lib/chef/resource/chef_client.rb +48 -48
  24. data/lib/chef/resource/chef_container.rb +22 -22
  25. data/lib/chef/resource/chef_data_bag.rb +22 -22
  26. data/lib/chef/resource/chef_data_bag_item.rb +121 -121
  27. data/lib/chef/resource/chef_environment.rb +77 -77
  28. data/lib/chef/resource/chef_group.rb +53 -53
  29. data/lib/chef/resource/chef_mirror.rb +52 -52
  30. data/lib/chef/resource/chef_node.rb +22 -22
  31. data/lib/chef/resource/chef_organization.rb +69 -69
  32. data/lib/chef/resource/chef_resolved_cookbooks.rb +35 -35
  33. data/lib/chef/resource/chef_role.rb +110 -110
  34. data/lib/chef/resource/chef_user.rb +56 -56
  35. data/lib/chef/resource/private_key.rb +48 -48
  36. data/lib/chef/resource/public_key.rb +25 -25
  37. data/lib/cheffish.rb +235 -235
  38. data/lib/cheffish/actor_provider_base.rb +131 -131
  39. data/lib/cheffish/basic_chef_client.rb +184 -184
  40. data/lib/cheffish/chef_provider_base.rb +246 -246
  41. data/lib/cheffish/chef_run.rb +162 -162
  42. data/lib/cheffish/chef_run_data.rb +19 -19
  43. data/lib/cheffish/chef_run_listener.rb +30 -30
  44. data/lib/cheffish/key_formatter.rb +113 -113
  45. data/lib/cheffish/merged_config.rb +98 -94
  46. data/lib/cheffish/recipe_dsl.rb +157 -157
  47. data/lib/cheffish/rspec.rb +8 -8
  48. data/lib/cheffish/rspec/chef_run_support.rb +83 -83
  49. data/lib/cheffish/rspec/matchers.rb +4 -4
  50. data/lib/cheffish/rspec/matchers/be_idempotent.rb +16 -16
  51. data/lib/cheffish/rspec/matchers/emit_no_warnings_or_errors.rb +15 -15
  52. data/lib/cheffish/rspec/matchers/have_updated.rb +37 -37
  53. data/lib/cheffish/rspec/matchers/partially_match.rb +63 -63
  54. data/lib/cheffish/rspec/recipe_run_wrapper.rb +78 -78
  55. data/lib/cheffish/rspec/repository_support.rb +108 -108
  56. data/lib/cheffish/server_api.rb +52 -52
  57. data/lib/cheffish/version.rb +3 -3
  58. data/lib/cheffish/with_pattern.rb +21 -21
  59. data/spec/functional/fingerprint_spec.rb +64 -64
  60. data/spec/functional/merged_config_spec.rb +19 -19
  61. data/spec/functional/server_api_spec.rb +13 -13
  62. data/spec/integration/chef_acl_spec.rb +892 -879
  63. data/spec/integration/chef_client_spec.rb +105 -105
  64. data/spec/integration/chef_container_spec.rb +33 -33
  65. data/spec/integration/chef_group_spec.rb +309 -309
  66. data/spec/integration/chef_mirror_spec.rb +491 -491
  67. data/spec/integration/chef_node_spec.rb +786 -786
  68. data/spec/integration/chef_organization_spec.rb +226 -226
  69. data/spec/integration/chef_role_spec.rb +78 -78
  70. data/spec/integration/chef_user_spec.rb +85 -85
  71. data/spec/integration/private_key_spec.rb +399 -399
  72. data/spec/integration/recipe_dsl_spec.rb +28 -28
  73. data/spec/integration/rspec/converge_spec.rb +183 -183
  74. data/spec/support/key_support.rb +29 -29
  75. data/spec/support/spec_support.rb +15 -15
  76. data/spec/unit/get_private_key_spec.rb +131 -131
  77. data/spec/unit/recipe_run_wrapper_spec.rb +37 -37
  78. metadata +7 -5
@@ -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