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,3 +1,3 @@
1
- module Cheffish
2
- VERSION = '1.5.0'
3
- end
1
+ module Cheffish
2
+ VERSION = '1.6.0'
3
+ end
@@ -1,21 +1,21 @@
1
- module Cheffish
2
- module WithPattern
3
- def with(symbol)
4
- class_eval <<EOM
5
- attr_accessor :current_#{symbol}
6
-
7
- def with_#{symbol}(value)
8
- old_value = self.current_#{symbol}
9
- self.current_#{symbol} = value
10
- if block_given?
11
- begin
12
- yield
13
- ensure
14
- self.current_#{symbol} = old_value
15
- end
16
- end
17
- end
18
- EOM
19
- end
20
- end
21
- end
1
+ module Cheffish
2
+ module WithPattern
3
+ def with(symbol)
4
+ class_eval <<EOM
5
+ attr_accessor :current_#{symbol}
6
+
7
+ def with_#{symbol}(value)
8
+ old_value = self.current_#{symbol}
9
+ self.current_#{symbol} = value
10
+ if block_given?
11
+ begin
12
+ yield
13
+ ensure
14
+ self.current_#{symbol} = old_value
15
+ end
16
+ end
17
+ end
18
+ EOM
19
+ end
20
+ end
21
+ end
@@ -1,64 +1,64 @@
1
- require 'cheffish/key_formatter'
2
- require 'support/key_support'
3
-
4
- describe 'Cheffish fingerprint key formatter' do
5
-
6
- # Sample key: 0x9a6fa4c43b328c3d04c1fbc0498539218b6728e41cd35f6d27d491ef705f0b2083dc1ac977da19f54ba82b044773f20667e9627c543abb3b41b6eb9e4318ca3c68f487bbd0f1c9eea9a3101b7d1d180983c5440ac4183e78e9e256fa687d8aac63b21617a4b02b35bf5e307a3b76961a16cd8493e923536b34cc2b2da8d45220d57ef2243b081b555b84f1da0ade0e896c2aa96911b41430b59eaf75dbffb7eaa7c5b3a686f2d47a24e3b7f1acb0844f84a2fedc63660ae366b800cd9448093d6b1d96503ebb7807b48257e16c3d8a7c9a8cc5dd63116aa673bd9e09754de09358486e743e34c6a3642eeb64b2208efc96df39151572557a75638bd059c21a55 = 0xd6e92677d4e1d2aa6d14f87b5f49ee6916c6b92411536254fae4a21e82eebb0a40600247c701c1c938b21ca9f25b7b330c35fded57b4de3a951e83329a80bdbf2ba138fe2f190bffce43967b5fa93b179367bcd15cb1db7f9e3ab62caca95dc9489b62bc0a10b53841b932455a43409f96eed90dc80abc8cce5593ead8f0a26d * 0xb7f68cd427045788d5e315375f71d3a416784ec2597776a60ed77c821294d9bd66e96658bdcb43072cee0c849d297bd9f94991738f1a0df313ceb51b093a9372f12a61987f40e7a03d773911deb270916a574962ae8ff4f2d8bfcedee1c885e9c3e54212471636a6330b05b78c3a7ddf96b013be389a08ab7971db2f68fb2689
7
-
8
- sample_private_key = <<EOF
9
- -----BEGIN RSA PRIVATE KEY-----
10
- MIIEowIBAAKCAQEAmm+kxDsyjD0EwfvASYU5IYtnKOQc019tJ9SR73BfCyCD3BrJd9oZ9UuoKwRH
11
- c/IGZ+lifFQ6uztBtuueQxjKPGj0h7vQ8cnuqaMQG30dGAmDxUQKxBg+eOniVvpofYqsY7IWF6Sw
12
- KzW/XjB6O3aWGhbNhJPpI1NrNMwrLajUUiDVfvIkOwgbVVuE8doK3g6JbCqpaRG0FDC1nq912/+3
13
- 6qfFs6aG8tR6JOO38aywhE+Eov7cY2YK42a4AM2USAk9ax2WUD67eAe0glfhbD2KfJqMxd1jEWqm
14
- c72eCXVN4JNYSG50PjTGo2Qu62SyII78lt85FRVyVXp1Y4vQWcIaVQIDAQABAoIBABY+JC37FLGs
15
- DCZgOvab0HmrWUVDbX9oDBGjhQ1GUvoISdWGqiOv7vMsXWEssZnabt/CdmPPwdG7nCBbWSTyyhXf
16
- S/DMtTBN1CjsimJbJ7iRjj/4J9DMaRsDHI1IbYo/UcreGF55YsImcJSBSOmNj9rcE+eXYgmrdxJY
17
- oZNm8IWPaZ1/8KdPHSq6/HfTzRxXhcGOMGnf3lGfzkzIbV9Ee88Lv9sSV3bYrOsWMNabOe2TeTpC
18
- UTfFkC++0RkFjEDINSCnoCi+ybzHLUDnurANCwnRWLTVEAeffwNVmiDfgimuqFtzCInW5/5bOTPz
19
- rBmcC6QAFbyk2WKAlY8Zd4SBYqECgYEA1ukmd9Th0qptFPh7X0nuaRbGuSQRU2JU+uSiHoLuuwpA
20
- YAJHxwHByTiyHKnyW3szDDX97Ve03jqVHoMymoC9vyuhOP4vGQv/zkOWe1+pOxeTZ7zRXLHbf546
21
- tiysqV3JSJtivAoQtThBuTJFWkNAn5bu2Q3ICryMzlWT6tjwom0CgYEAt/aM1CcEV4jV4xU3X3HT
22
- pBZ4TsJZd3amDtd8ghKU2b1m6WZYvctDByzuDISdKXvZ+UmRc48aDfMTzrUbCTqTcvEqYZh/QOeg
23
- PXc5Ed6ycJFqV0liro/08ti/zt7hyIXpw+VCEkcWNqYzCwW3jDp935awE744mgireXHbL2j7JokC
24
- gYAOHErRTWHyYgw9dz8qd4E21y7/EvYsQmWP/5kBZdlk4HxvkVbDI0NlAdr39NSb2w/z+kuM3Nhc
25
- Sv5lfXnCGTfcKHIyesX+4AHQujFUMmi7H4YnJoecjXT7ARmbwn0ntae0o7cs34BPVb1C+qEBFy9U
26
- CyXtjHEY+15HYekPX2UVVQKBgBT8Nwxsdv5VSbDh1rM4lN//ADJb0UDjdAX1ZuqfnANKq9asKitc
27
- aIUFBxK+ff8hdbgOQF1iUaKNvBC0cCUZXYCbKi5/6uRIh+r7ErOLJ+fXbr4OTQeEvHiHaTn8Ct2J
28
- CSWjnWngWhRZ2TDEsi947Kr40ZUu+d34ZzcvWcWKwDuhAoGBAJzCRoGOu6YGy+rBPxaIg0vB+Grx
29
- rxs0NeNqGdrzmyAPN35OHXYclPwfp+DbtbJHgGMRc/9VFPqW9PeTKjIByeEsXyrcdreR35AR/fwR
30
- AUcSSKTvw+PobCpXhdkiw4TgJhFNuZnoC63FOjNqA5mu1ICZYBb4ZVlgUAgSmDQxSIgK
31
- -----END RSA PRIVATE KEY-----
32
- EOF
33
- sample_public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCab6TEOzKMPQTB+8BJhTkhi2co5BzTX20n1JHvcF8LIIPcGsl32hn1S6grBEdz8gZn6WJ8VDq7O0G2655DGMo8aPSHu9Dxye6poxAbfR0YCYPFRArEGD546eJW+mh9iqxjshYXpLArNb9eMHo7dpYaFs2Ek+kjU2s0zCstqNRSINV+8iQ7CBtVW4Tx2greDolsKqlpEbQUMLWer3Xb/7fqp8Wzpoby1Hok47fxrLCET4Si/txjZgrjZrgAzZRICT1rHZZQPrt4B7SCV+FsPYp8mozF3WMRaqZzvZ4JdU3gk1hIbnQ+NMajZC7rZLIgjvyW3zkVFXJVenVji9BZwhpV"
34
-
35
- def key_to_format(key, format)
36
- keyobj, f = Cheffish::KeyFormatter.decode(key)
37
- Cheffish::KeyFormatter.encode(keyobj, {:format => format})
38
- end
39
-
40
- context 'when computing key fingperprints' do
41
-
42
- it 'computes the PKCS#8 SHA1 private key fingerprint correctly', :pending => (RUBY_VERSION.to_f >= 2.0) do
43
- expect(key_to_format(sample_private_key, :pkcs8sha1fingerprint)).to eq(
44
- '88:7e:3a:bd:26:9f:b5:c5:d8:ae:52:f9:df:0b:64:a4:5c:17:0a:87')
45
- end
46
-
47
- it 'computes the PKCS#1 MD5 public key fingerprint correctly' do
48
- expect(key_to_format(sample_public_key, :pkcs1md5fingerprint)).to eq(
49
- '1f:e8:da:c1:16:c3:72:7d:90:e2:b7:64:c4:b4:55:20')
50
- end
51
-
52
- it 'computes the RFC4716 MD5 public key fingerprint correctly' do
53
- expect(key_to_format(sample_public_key, :rfc4716md5fingerprint)).to eq(
54
- 'b0:13:4f:da:cf:8c:dc:a7:4a:1f:d2:3a:51:92:cf:6b')
55
- end
56
-
57
- it 'defaults to the PKCS#1 MD5 public key fingerprint' do
58
- expect(key_to_format(sample_public_key, :fingerprint)).to eq(
59
- key_to_format(sample_public_key, :pkcs1md5fingerprint))
60
- end
61
-
62
- end
63
-
64
- end
1
+ require 'cheffish/key_formatter'
2
+ require 'support/key_support'
3
+
4
+ describe 'Cheffish fingerprint key formatter' do
5
+
6
+ # Sample key: 0x9a6fa4c43b328c3d04c1fbc0498539218b6728e41cd35f6d27d491ef705f0b2083dc1ac977da19f54ba82b044773f20667e9627c543abb3b41b6eb9e4318ca3c68f487bbd0f1c9eea9a3101b7d1d180983c5440ac4183e78e9e256fa687d8aac63b21617a4b02b35bf5e307a3b76961a16cd8493e923536b34cc2b2da8d45220d57ef2243b081b555b84f1da0ade0e896c2aa96911b41430b59eaf75dbffb7eaa7c5b3a686f2d47a24e3b7f1acb0844f84a2fedc63660ae366b800cd9448093d6b1d96503ebb7807b48257e16c3d8a7c9a8cc5dd63116aa673bd9e09754de09358486e743e34c6a3642eeb64b2208efc96df39151572557a75638bd059c21a55 = 0xd6e92677d4e1d2aa6d14f87b5f49ee6916c6b92411536254fae4a21e82eebb0a40600247c701c1c938b21ca9f25b7b330c35fded57b4de3a951e83329a80bdbf2ba138fe2f190bffce43967b5fa93b179367bcd15cb1db7f9e3ab62caca95dc9489b62bc0a10b53841b932455a43409f96eed90dc80abc8cce5593ead8f0a26d * 0xb7f68cd427045788d5e315375f71d3a416784ec2597776a60ed77c821294d9bd66e96658bdcb43072cee0c849d297bd9f94991738f1a0df313ceb51b093a9372f12a61987f40e7a03d773911deb270916a574962ae8ff4f2d8bfcedee1c885e9c3e54212471636a6330b05b78c3a7ddf96b013be389a08ab7971db2f68fb2689
7
+
8
+ sample_private_key = <<EOF
9
+ -----BEGIN RSA PRIVATE KEY-----
10
+ MIIEowIBAAKCAQEAmm+kxDsyjD0EwfvASYU5IYtnKOQc019tJ9SR73BfCyCD3BrJd9oZ9UuoKwRH
11
+ c/IGZ+lifFQ6uztBtuueQxjKPGj0h7vQ8cnuqaMQG30dGAmDxUQKxBg+eOniVvpofYqsY7IWF6Sw
12
+ KzW/XjB6O3aWGhbNhJPpI1NrNMwrLajUUiDVfvIkOwgbVVuE8doK3g6JbCqpaRG0FDC1nq912/+3
13
+ 6qfFs6aG8tR6JOO38aywhE+Eov7cY2YK42a4AM2USAk9ax2WUD67eAe0glfhbD2KfJqMxd1jEWqm
14
+ c72eCXVN4JNYSG50PjTGo2Qu62SyII78lt85FRVyVXp1Y4vQWcIaVQIDAQABAoIBABY+JC37FLGs
15
+ DCZgOvab0HmrWUVDbX9oDBGjhQ1GUvoISdWGqiOv7vMsXWEssZnabt/CdmPPwdG7nCBbWSTyyhXf
16
+ S/DMtTBN1CjsimJbJ7iRjj/4J9DMaRsDHI1IbYo/UcreGF55YsImcJSBSOmNj9rcE+eXYgmrdxJY
17
+ oZNm8IWPaZ1/8KdPHSq6/HfTzRxXhcGOMGnf3lGfzkzIbV9Ee88Lv9sSV3bYrOsWMNabOe2TeTpC
18
+ UTfFkC++0RkFjEDINSCnoCi+ybzHLUDnurANCwnRWLTVEAeffwNVmiDfgimuqFtzCInW5/5bOTPz
19
+ rBmcC6QAFbyk2WKAlY8Zd4SBYqECgYEA1ukmd9Th0qptFPh7X0nuaRbGuSQRU2JU+uSiHoLuuwpA
20
+ YAJHxwHByTiyHKnyW3szDDX97Ve03jqVHoMymoC9vyuhOP4vGQv/zkOWe1+pOxeTZ7zRXLHbf546
21
+ tiysqV3JSJtivAoQtThBuTJFWkNAn5bu2Q3ICryMzlWT6tjwom0CgYEAt/aM1CcEV4jV4xU3X3HT
22
+ pBZ4TsJZd3amDtd8ghKU2b1m6WZYvctDByzuDISdKXvZ+UmRc48aDfMTzrUbCTqTcvEqYZh/QOeg
23
+ PXc5Ed6ycJFqV0liro/08ti/zt7hyIXpw+VCEkcWNqYzCwW3jDp935awE744mgireXHbL2j7JokC
24
+ gYAOHErRTWHyYgw9dz8qd4E21y7/EvYsQmWP/5kBZdlk4HxvkVbDI0NlAdr39NSb2w/z+kuM3Nhc
25
+ Sv5lfXnCGTfcKHIyesX+4AHQujFUMmi7H4YnJoecjXT7ARmbwn0ntae0o7cs34BPVb1C+qEBFy9U
26
+ CyXtjHEY+15HYekPX2UVVQKBgBT8Nwxsdv5VSbDh1rM4lN//ADJb0UDjdAX1ZuqfnANKq9asKitc
27
+ aIUFBxK+ff8hdbgOQF1iUaKNvBC0cCUZXYCbKi5/6uRIh+r7ErOLJ+fXbr4OTQeEvHiHaTn8Ct2J
28
+ CSWjnWngWhRZ2TDEsi947Kr40ZUu+d34ZzcvWcWKwDuhAoGBAJzCRoGOu6YGy+rBPxaIg0vB+Grx
29
+ rxs0NeNqGdrzmyAPN35OHXYclPwfp+DbtbJHgGMRc/9VFPqW9PeTKjIByeEsXyrcdreR35AR/fwR
30
+ AUcSSKTvw+PobCpXhdkiw4TgJhFNuZnoC63FOjNqA5mu1ICZYBb4ZVlgUAgSmDQxSIgK
31
+ -----END RSA PRIVATE KEY-----
32
+ EOF
33
+ sample_public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCab6TEOzKMPQTB+8BJhTkhi2co5BzTX20n1JHvcF8LIIPcGsl32hn1S6grBEdz8gZn6WJ8VDq7O0G2655DGMo8aPSHu9Dxye6poxAbfR0YCYPFRArEGD546eJW+mh9iqxjshYXpLArNb9eMHo7dpYaFs2Ek+kjU2s0zCstqNRSINV+8iQ7CBtVW4Tx2greDolsKqlpEbQUMLWer3Xb/7fqp8Wzpoby1Hok47fxrLCET4Si/txjZgrjZrgAzZRICT1rHZZQPrt4B7SCV+FsPYp8mozF3WMRaqZzvZ4JdU3gk1hIbnQ+NMajZC7rZLIgjvyW3zkVFXJVenVji9BZwhpV"
34
+
35
+ def key_to_format(key, format)
36
+ keyobj, f = Cheffish::KeyFormatter.decode(key)
37
+ Cheffish::KeyFormatter.encode(keyobj, {:format => format})
38
+ end
39
+
40
+ context 'when computing key fingperprints' do
41
+
42
+ it 'computes the PKCS#8 SHA1 private key fingerprint correctly', :pending => (RUBY_VERSION.to_f >= 2.0) do
43
+ expect(key_to_format(sample_private_key, :pkcs8sha1fingerprint)).to eq(
44
+ '88:7e:3a:bd:26:9f:b5:c5:d8:ae:52:f9:df:0b:64:a4:5c:17:0a:87')
45
+ end
46
+
47
+ it 'computes the PKCS#1 MD5 public key fingerprint correctly' do
48
+ expect(key_to_format(sample_public_key, :pkcs1md5fingerprint)).to eq(
49
+ '1f:e8:da:c1:16:c3:72:7d:90:e2:b7:64:c4:b4:55:20')
50
+ end
51
+
52
+ it 'computes the RFC4716 MD5 public key fingerprint correctly' do
53
+ expect(key_to_format(sample_public_key, :rfc4716md5fingerprint)).to eq(
54
+ 'b0:13:4f:da:cf:8c:dc:a7:4a:1f:d2:3a:51:92:cf:6b')
55
+ end
56
+
57
+ it 'defaults to the PKCS#1 MD5 public key fingerprint' do
58
+ expect(key_to_format(sample_public_key, :fingerprint)).to eq(
59
+ key_to_format(sample_public_key, :pkcs1md5fingerprint))
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -1,20 +1,20 @@
1
- require 'cheffish/merged_config'
2
-
3
- describe "merged_config" do
4
-
5
- let(:config) do
6
- Cheffish::MergedConfig.new({:test=>'val'})
7
- end
8
-
9
- it "returns value in config" do
10
- expect(config.test).to eq('val')
11
- end
12
-
13
- it "raises a NoMethodError if calling an unknown method with arguments" do
14
- expect{config.merge({:some => 'hash'})}.to raise_error(NoMethodError)
15
- end
16
-
17
- it "has an informative string representation" do
18
- expect("#{config}").to eq("{:test=>\"val\"}")
19
- end
1
+ require 'cheffish/merged_config'
2
+
3
+ describe "merged_config" do
4
+
5
+ let(:config) do
6
+ Cheffish::MergedConfig.new({:test=>'val'})
7
+ end
8
+
9
+ it "returns value in config" do
10
+ expect(config.test).to eq('val')
11
+ end
12
+
13
+ it "raises a NoMethodError if calling an unknown method with arguments" do
14
+ expect{config.merge({:some => 'hash'})}.to raise_error(NoMethodError)
15
+ end
16
+
17
+ it "has an informative string representation" do
18
+ expect("#{config}").to eq("{:test=>\"val\"}")
19
+ end
20
20
  end
@@ -1,13 +1,13 @@
1
- require 'cheffish'
2
-
3
- describe "api version" do
4
-
5
- let(:server_api) do
6
- Cheffish.chef_server_api({:chef_server_url => "my.chef.server"})
7
- end
8
-
9
- it "is pinned to 0" do
10
- expect(Cheffish::ServerAPI).to receive(:new).with("my.chef.server", {api_version: "0"})
11
- server_api
12
- end
13
- end
1
+ require 'cheffish'
2
+
3
+ describe "api version" do
4
+
5
+ let(:server_api) do
6
+ Cheffish.chef_server_api({:chef_server_url => "my.chef.server"})
7
+ end
8
+
9
+ it "is pinned to 0" do
10
+ expect(Cheffish::ServerAPI).to receive(:new).with("my.chef.server", {api_version: "0"})
11
+ server_api
12
+ end
13
+ end
@@ -1,879 +1,892 @@
1
- require 'support/spec_support'
2
- require 'cheffish/rspec/chef_run_support'
3
- require 'chef/resource/chef_acl'
4
- require 'chef/provider/chef_acl'
5
- require 'chef_zero/version'
6
- require 'uri'
7
-
8
- if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new('3.1')
9
- describe Chef::Resource::ChefAcl do
10
- extend Cheffish::RSpec::ChefRunSupport
11
-
12
- # let(:chef_config) { super().merge(log_level: :debug, stdout: STDOUT, stderr: STDERR, log_location: STDOUT) }
13
-
14
- context "Rights attributes" do
15
- when_the_chef_server 'has a node named x', :osc_compat => false do
16
- node 'x', {}
17
-
18
- it 'Converging chef_acl "nodes/x" changes nothing' do
19
- expect_recipe {
20
- chef_acl 'nodes/x'
21
- }.to be_up_to_date
22
- expect(get('nodes/x/_acl')).to partially_match({})
23
- end
24
-
25
- it 'Converging chef_acl "nodes/x" with "complete true" and no rights raises an error' do
26
- expect_converge {
27
- chef_acl 'nodes/x' do
28
- complete true
29
- end
30
- }.to raise_error(RuntimeError)
31
- end
32
-
33
- it 'Removing all :grant rights from a node raises an error' do
34
- expect_converge {
35
- chef_acl 'nodes/x' do
36
- remove_rights :grant, users: %w(pivotal), groups: %w(admins users clients)
37
- end
38
- }.to raise_error(RuntimeError)
39
- end
40
-
41
- context 'and a user "blarghle"' do
42
- user 'blarghle', {}
43
-
44
- it 'Converging chef_acl "nodes/x" with user "blarghle" adds the user' do
45
- expect_recipe {
46
- chef_acl 'nodes/x' do
47
- rights :read, users: %w(blarghle)
48
- end
49
- }.to be_updated
50
- expect(get('nodes/x/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
51
- end
52
-
53
- it 'Converging chef_acl "nodes/x" with "complete true" removes all ACLs except those specified' do
54
- expect_recipe {
55
- chef_acl 'nodes/x' do
56
- rights :grant, users: %w(blarghle)
57
- complete true
58
- end
59
- }.to be_updated
60
- expect(get('nodes/x/_acl')).to eq(
61
- "create"=>{"actors"=>[], "groups"=>[]},
62
- "read" =>{"actors"=>[], "groups"=>[]},
63
- "update"=>{"actors"=>[], "groups"=>[]},
64
- "delete"=>{"actors"=>[], "groups"=>[]},
65
- "grant" =>{"actors"=>["blarghle"], "groups"=>[]}
66
- )
67
- end
68
- end
69
-
70
- it 'Converging chef_acl "nodes/x" with "complete true" removes all ACLs except those specified in :all' do
71
- expect_recipe {
72
- chef_acl 'nodes/x' do
73
- rights :all, users: %w(blarghle)
74
- complete true
75
- end
76
- }.to be_updated
77
- expect(get('nodes/x/_acl')).to eq(
78
- "create"=>{"actors"=>["blarghle"], "groups"=>[]},
79
- "read" =>{"actors"=>["blarghle"], "groups"=>[]},
80
- "update"=>{"actors"=>["blarghle"], "groups"=>[]},
81
- "delete"=>{"actors"=>["blarghle"], "groups"=>[]},
82
- "grant" =>{"actors"=>["blarghle"], "groups"=>[]}
83
- )
84
- end
85
-
86
- context 'and a client "blarghle"' do
87
- user 'blarghle', {}
88
-
89
- it 'Converging chef_acl "nodes/x" with client "blarghle" adds the client' do
90
- expect_recipe {
91
- chef_acl 'nodes/x' do
92
- rights :read, clients: %w(blarghle)
93
- end
94
- }.to be_updated
95
- expect(get('nodes/x/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
96
- end
97
- end
98
-
99
- context 'and a group "blarghle"' do
100
- group 'blarghle', {}
101
-
102
- it 'Converging chef_acl "nodes/x" with group "blarghle" adds the group' do
103
- expect_recipe {
104
- chef_acl 'nodes/x' do
105
- rights :read, groups: %w(blarghle)
106
- end
107
- }.to be_updated
108
- expect(get('nodes/x/_acl')).to partially_match('read' => { 'groups' => %w(blarghle) })
109
- end
110
- end
111
-
112
- context 'and multiple users and groups' do
113
- user 'u1', {}
114
- user 'u2', {}
115
- user 'u3', {}
116
- client 'c1', {}
117
- client 'c2', {}
118
- client 'c3', {}
119
- group 'g1', {}
120
- group 'g2', {}
121
- group 'g3', {}
122
-
123
- it 'Converging chef_acl "nodes/x" with multiple groups, users and clients in an acl makes the appropriate changes' do
124
- expect_recipe {
125
- chef_acl 'nodes/x' do
126
- rights :create, users: [ 'u1', 'u2', 'u3' ], clients: [ 'c1', 'c2', 'c3' ], groups: [ 'g1', 'g2', 'g3' ]
127
- end
128
- }.to be_updated
129
- expect(get('nodes/x/_acl')).to partially_match(
130
- 'create' => { 'groups' => %w(g1 g2 g3), 'actors' => %w(u1 u2 u3 c1 c2 c3) }
131
- )
132
- end
133
-
134
- it 'Converging chef_acl "nodes/x" with multiple groups, users and clients across multiple "rights" groups makes the appropriate changes' do
135
- expect_recipe {
136
- chef_acl 'nodes/x' do
137
- rights :create, users: %w(u1), clients: %w(c1), groups: %w(g1)
138
- rights :create, users: %w(u2 u3), clients: %w(c2 c3), groups: %w(g2)
139
- rights :read, users: %w(u1)
140
- rights :read, groups: %w(g1)
141
- end
142
- }.to be_updated
143
- expect(get('nodes/x/_acl')).to partially_match(
144
- 'create' => { 'groups' => %w(g1 g2), 'actors' => %w(u1 u2 u3 c1 c2 c3) },
145
- 'read' => { 'groups' => %w(g1), 'actors' => %w(u1) }
146
- )
147
- end
148
-
149
- it 'Converging chef_acl "nodes/x" with rights [ :read, :create, :update, :delete, :grant ] modifies all rights' do
150
- expect_recipe {
151
- chef_acl 'nodes/x' do
152
- rights [ :create, :read, :update, :delete, :grant ], users: %w(u1 u2), clients: %w(c1), groups: %w(g1)
153
- end
154
- }.to be_updated
155
- expect(get('nodes/x/_acl')).to partially_match(
156
- 'create' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
157
- 'read' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
158
- 'update' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
159
- 'delete' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
160
- 'grant' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
161
- )
162
- end
163
-
164
- it 'Converging chef_acl "nodes/x" with rights :all modifies all rights' do
165
- expect_recipe {
166
- chef_acl 'nodes/x' do
167
- rights :all, users: %w(u1 u2), clients: %w(c1), groups: %w(g1)
168
- end
169
- }.to be_updated
170
- expect(get('nodes/x/_acl')).to partially_match(
171
- 'create' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
172
- 'read' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
173
- 'update' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
174
- 'delete' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
175
- 'grant' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
176
- )
177
- end
178
- end
179
-
180
- it 'Converging chef_acl "nodes/y" throws a 404' do
181
- expect_converge {
182
- chef_acl 'nodes/y'
183
- }.to raise_error(Net::HTTPServerException)
184
- end
185
- end
186
-
187
- when_the_chef_server 'has a node named x with user blarghle in its acl', :osc_compat => false do
188
- user 'blarghle', {}
189
- node 'x', {} do
190
- acl 'read' => { 'actors' => %w(blarghle) }
191
- end
192
-
193
- it 'Converging chef_acl "nodes/x" with that user changes nothing' do
194
- expect_recipe {
195
- chef_acl 'nodes/x' do
196
- rights :read, users: %w(blarghle)
197
- end
198
- }.to be_up_to_date
199
- expect(get('nodes/x/_acl')).to partially_match({})
200
- end
201
- end
202
-
203
- when_the_chef_server 'has a node named x with users foo and bar in all its acls', :osc_compat => false do
204
- user 'foo', {}
205
- user 'bar', {}
206
- node 'x', {} do
207
- acl 'create' => { 'actors' => %w(foo bar) },
208
- 'read' => { 'actors' => %w(foo bar) },
209
- 'update' => { 'actors' => %w(foo bar) },
210
- 'delete' => { 'actors' => %w(foo bar) },
211
- 'grant' => { 'actors' => %w(foo bar) }
212
- end
213
-
214
- it 'Converging chef_acl "nodes/x" with remove_rights :all removes foo from everything' do
215
- expect_recipe {
216
- chef_acl 'nodes/x' do
217
- remove_rights :all, users: %w(foo)
218
- end
219
- }.to be_updated
220
- expect(get('nodes/x/_acl')).to partially_match(
221
- 'create' => { 'actors' => exclude('foo') },
222
- 'read' => { 'actors' => exclude('foo') },
223
- 'update' => { 'actors' => exclude('foo') },
224
- 'delete' => { 'actors' => exclude('foo') },
225
- 'grant' => { 'actors' => exclude('foo') },
226
- )
227
- end
228
- end
229
-
230
- ::RSpec::Matchers.define_negated_matcher :exclude, :include
231
-
232
- context 'recursive' do
233
- when_the_chef_server 'has a nodes container with user blarghle in its acl', :osc_compat => false do
234
- user 'blarghle', {}
235
- acl_for 'containers/nodes', 'read' => { 'actors' => %w(blarghle) }
236
- node 'x', {} do
237
- acl 'read' => { 'actors' => [] }
238
- end
239
-
240
- it 'Converging chef_acl "nodes" makes no changes' do
241
- expect {
242
- expect_recipe {
243
- chef_acl 'nodes' do
244
- rights :read, users: %w(blarghle)
245
- end
246
- }.to be_up_to_date
247
- }.to not_change { get('containers/nodes/_acl') }.
248
- and not_change { get('nodes/x/_acl') }
249
- end
250
-
251
- RSpec::Matchers.define_negated_matcher :not_change, :change
252
-
253
- it 'Converging chef_acl "nodes" with recursive :on_change makes no changes' do
254
- expect {
255
- expect_recipe {
256
- chef_acl 'nodes' do
257
- rights :read, users: %w(blarghle)
258
- recursive :on_change
259
- end
260
- }.to be_up_to_date
261
- }.to not_change { get('containers/nodes/_acl') }.
262
- and not_change { get('nodes/x/_acl') }
263
- end
264
-
265
- it 'Converging chef_acl "nodes" with recursive true changes nodes/x\'s acls' do
266
- expect_recipe {
267
- chef_acl 'nodes' do
268
- rights :read, users: %w(blarghle)
269
- recursive true
270
- end
271
- }.to be_updated
272
- expect(get('nodes/x/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
273
- end
274
-
275
- it 'Converging chef_acl "" with recursive false does not change nodes/x\'s acls' do
276
- expect_recipe {
277
- chef_acl '' do
278
- rights :read, users: %w(blarghle)
279
- recursive false
280
- end
281
- }.to be_updated
282
- expect(get('containers/nodes/_acl')).to partially_match({})
283
- expect(get('nodes/x/_acl')).to partially_match({})
284
- end
285
-
286
- it 'Converging chef_acl "" with recursive :on_change does not change nodes/x\'s acls' do
287
- expect_recipe {
288
- chef_acl '' do
289
- rights :read, users: %w(blarghle)
290
- recursive :on_change
291
- end
292
- }.to be_updated
293
- expect(get('containers/nodes/_acl')).to partially_match({})
294
- expect(get('nodes/x/_acl')).to partially_match({})
295
- end
296
-
297
- it 'Converging chef_acl "" with recursive true changes nodes/x\'s acls' do
298
- expect_recipe {
299
- chef_acl '' do
300
- rights :read, users: %w(blarghle)
301
- recursive true
302
- end
303
- }.to be_updated
304
- expect(get('/organizations/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
305
- expect(get('nodes/x/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
306
- end
307
- end
308
- end
309
- end
310
-
311
- context 'ACLs on each type of thing' do
312
- when_the_chef_server 'has an organization named foo', :osc_compat => false, :single_org => false do
313
- organization 'foo' do
314
- user 'u', {}
315
- client 'x', {}
316
- container 'x', {}
317
- cookbook 'x', '1.0.0', {}
318
- data_bag 'x', { 'y' => {} }
319
- environment 'x', {}
320
- group 'x', {}
321
- node 'x', {}
322
- role 'x', {}
323
- sandbox 'x', {}
324
- user 'x', {}
325
- end
326
-
327
- organization 'bar' do
328
- user 'u', {}
329
- node 'x', {}
330
- end
331
-
332
- context 'and the chef server URL points at /organizations/foo' do
333
- before :each do
334
- Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url, '/organizations/foo').to_s
335
- end
336
-
337
- context 'relative paths' do
338
- it "chef_acl 'nodes/x' changes the acls" do
339
- expect_recipe {
340
- chef_acl "nodes/x" do
341
- rights :read, users: %w(u)
342
- end
343
- }.to be_updated
344
- expect(get("nodes/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
345
- end
346
-
347
- it "chef_acl '*/*' changes the acls" do
348
- expect_recipe {
349
- chef_acl "*/*" do
350
- rights :read, users: %w(u)
351
- end
352
- }.to be_updated
353
- %w(clients containers cookbooks data environments groups nodes roles).each do |type|
354
- expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match(
355
- 'read' => { 'actors' => %w(u) })
356
- end
357
- end
358
- end
359
-
360
- context 'absolute paths' do
361
- %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
362
- it "chef_acl '/organizations/foo/#{type}/x' changes the acl" do
363
- expect_recipe {
364
- chef_acl "/organizations/foo/#{type}/x" do
365
- rights :read, users: %w(u)
366
- end
367
- }.to be_updated
368
- expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
369
- end
370
- end
371
-
372
- %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
373
- it "chef_acl '/organizations/foo/#{type}/x' changes the acl" do
374
- expect_recipe {
375
- chef_acl "/organizations/foo/#{type}/x" do
376
- rights :read, users: %w(u)
377
- end
378
- }.to be_updated
379
- expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
380
- end
381
- end
382
-
383
- %w(clients containers cookbooks data environments groups nodes roles).each do |type|
384
- it "chef_acl '/*/*/#{type}/*' changes the acl" do
385
- expect_recipe {
386
- chef_acl "/*/*/#{type}/*" do
387
- rights :read, users: %w(u)
388
- end
389
- }.to be_updated
390
- expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
391
- end
392
- end
393
-
394
- it "chef_acl '/*/*/*/x' changes the acls" do
395
- expect_recipe {
396
- chef_acl "/*/*/*/x" do
397
- rights :read, users: %w(u)
398
- end
399
- }.to be_updated
400
- %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
401
- expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match(
402
- 'read' => { 'actors' => %w(u) })
403
- end
404
- end
405
-
406
- it "chef_acl '/*/*/*/*' changes the acls" do
407
- expect_recipe {
408
- chef_acl "/*/*/*/*" do
409
- rights :read, users: %w(u)
410
- end
411
- }.to be_updated
412
- %w(clients containers cookbooks data environments groups nodes roles).each do |type|
413
- expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match(
414
- 'read' => { 'actors' => %w(u) })
415
- end
416
- end
417
-
418
- it 'chef_acl "/organizations/foo/data_bags/x" changes the acl' do
419
- expect_recipe {
420
- chef_acl '/organizations/foo/data_bags/x' do
421
- rights :read, users: %w(u)
422
- end
423
- }.to be_updated
424
- expect(get('/organizations/foo/data/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
425
- end
426
-
427
- it 'chef_acl "/*/*/data_bags/*" changes the acl' do
428
- expect_recipe {
429
- chef_acl '/*/*/data_bags/*' do
430
- rights :read, users: %w(u)
431
- end
432
- }.to be_updated
433
- expect(get('/organizations/foo/data/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
434
- end
435
-
436
- it "chef_acl '/organizations/foo/cookbooks/x/1.0.0' raises an error" do
437
- expect_converge {
438
- chef_acl "/organizations/foo/cookbooks/x/1.0.0" do
439
- rights :read, users: %w(u)
440
- end
441
- }.to raise_error(/ACLs cannot be set on children of \/organizations\/foo\/cookbooks\/x/)
442
- end
443
-
444
- it "chef_acl '/organizations/foo/cookbooks/*/*' raises an error" do
445
- pending
446
- expect_converge {
447
- chef_acl "/organizations/foo/cookbooks/*/*" do
448
- rights :read, users: %w(u)
449
- end
450
- }.to raise_error(/ACLs cannot be set on children of \/organizations\/foo\/cookbooks\/*/)
451
- end
452
-
453
- it 'chef_acl "/organizations/foo/data/x/y" raises an error' do
454
- expect_converge {
455
- chef_acl '/organizations/foo/data/x/y' do
456
- rights :read, users: %w(u)
457
- end
458
- }.to raise_error(/ACLs cannot be set on children of \/organizations\/foo\/data\/x/)
459
- end
460
-
461
- it 'chef_acl "/organizations/foo/data/*/*" raises an error' do
462
- pending
463
- expect_converge {
464
- chef_acl '/organizations/foo/data/*/*' do
465
- rights :read, users: %w(u)
466
- end
467
- }.to raise_error(/ACLs cannot be set on children of \/organizations\/foo\/data\/*/)
468
- end
469
-
470
- it 'chef_acl "/organizations/foo" changes the acl' do
471
- expect_recipe {
472
- chef_acl '/organizations/foo' do
473
- rights :read, users: %w(u)
474
- end
475
- }.to be_updated
476
- expect(get('/organizations/foo/organizations/_acl')).to partially_match('read' => { 'actors' => %w(u) })
477
- expect(get('/organizations/foo/nodes/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
478
- end
479
-
480
- it 'chef_acl "/organizations/*" changes the acl' do
481
- expect_recipe {
482
- chef_acl '/organizations/*' do
483
- rights :read, users: %w(u)
484
- end
485
- }.to be_updated
486
- expect(get('/organizations/foo/organizations/_acl')).to partially_match('read' => { 'actors' => %w(u) })
487
- expect(get('/organizations/foo/nodes/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
488
- end
489
-
490
- it 'chef_acl "/users/x" changes the acl' do
491
- expect_recipe {
492
- chef_acl '/users/x' do
493
- rights :read, users: %w(u)
494
- end
495
- }.to be_updated
496
- expect(get('/users/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
497
- end
498
-
499
- it 'chef_acl "/users/*" changes the acl' do
500
- expect_recipe {
501
- chef_acl '/users/*' do
502
- rights :read, users: %w(u)
503
- end
504
- }.to be_updated
505
- expect(get('/users/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
506
- end
507
-
508
- it 'chef_acl "/*/x" changes the acl' do
509
- expect_recipe {
510
- chef_acl '/*/x' do
511
- rights :read, users: %w(u)
512
- end
513
- }.to be_updated
514
- expect(get('/users/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
515
- end
516
-
517
- it 'chef_acl "/*/*" changes the acl' do
518
- expect_recipe {
519
- chef_acl '/*/*' do
520
- rights :read, users: %w(u)
521
- end
522
- }.to be_updated
523
- expect(get('/organizations/foo/organizations/_acl')).to partially_match('read' => { 'actors' => %w(u) })
524
- expect(get('/users/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
525
- end
526
- end
527
- end
528
-
529
- context 'and the chef server URL points at /organizations/bar' do
530
- before :each do
531
- Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url.to_s, '/organizations/bar').to_s
532
- end
533
-
534
- it "chef_acl '/organizations/foo/nodes/*' changes the acl" do
535
- expect_recipe {
536
- chef_acl "/organizations/foo/nodes/*" do
537
- rights :read, users: %w(u)
538
- end
539
- }.to be_updated
540
- expect(get("/organizations/foo/nodes/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
541
- end
542
- end
543
-
544
- context 'and the chef server URL points at /' do
545
- before :each do
546
- Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url.to_s, '/').to_s
547
- end
548
-
549
- it "chef_acl '/organizations/foo/nodes/*' changes the acl" do
550
- expect_recipe {
551
- chef_acl "/organizations/foo/nodes/*" do
552
- rights :read, users: %w(u)
553
- end
554
- }.to be_updated
555
- expect(get("/organizations/foo/nodes/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
556
- end
557
- end
558
- end
559
-
560
- when_the_chef_server 'has a user "u" in single org mode', :osc_compat => false do
561
- user 'u', {}
562
- client 'x', {}
563
- container 'x', {}
564
- cookbook 'x', '1.0.0', {}
565
- data_bag 'x', { 'y' => {} }
566
- environment 'x', {}
567
- group 'x', {}
568
- node 'x', {}
569
- role 'x', {}
570
- sandbox 'x', {}
571
- user 'x', {}
572
-
573
- %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
574
- it "chef_acl #{type}/x' changes the acl" do
575
- expect_recipe {
576
- chef_acl "#{type}/x" do
577
- rights :read, users: %w(u)
578
- end
579
- }.to be_updated
580
- expect(get("#{type}/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
581
- end
582
- end
583
-
584
- %w(clients containers cookbooks data environments groups nodes roles).each do |type|
585
- it "chef_acl '#{type}/*' changes the acl" do
586
- expect_recipe {
587
- chef_acl "#{type}/*" do
588
- rights :read, users: %w(u)
589
- end
590
- }.to be_updated
591
- expect(get("#{type}/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
592
- end
593
- end
594
-
595
- it "chef_acl '*/x' changes the acls" do
596
- expect_recipe {
597
- chef_acl "*/x" do
598
- rights :read, users: %w(u)
599
- end
600
- }.to be_updated
601
- %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
602
- expect(get("#{type}/x/_acl")).to partially_match(
603
- 'read' => { 'actors' => %w(u) })
604
- end
605
- end
606
-
607
- it "chef_acl '*/*' changes the acls" do
608
- expect_recipe {
609
- chef_acl "*/*" do
610
- rights :read, users: %w(u)
611
- end
612
- }.to be_updated
613
- %w(clients containers cookbooks data environments groups nodes roles).each do |type|
614
- expect(get("#{type}/x/_acl")).to partially_match(
615
- 'read' => { 'actors' => %w(u) })
616
- end
617
- end
618
-
619
- it "chef_acl 'groups/*' changes the acl" do
620
- expect_recipe {
621
- chef_acl "groups/*" do
622
- rights :read, users: %w(u)
623
- end
624
- }.to be_updated
625
- %w(admins billing-admins clients users x).each do |n|
626
- expect(get("groups/#{n}/_acl")).to partially_match(
627
- 'read' => { 'actors' => %w(u) })
628
- end
629
- end
630
-
631
- it 'chef_acl "data_bags/x" changes the acl' do
632
- expect_recipe {
633
- chef_acl 'data_bags/x' do
634
- rights :read, users: %w(u)
635
- end
636
- }.to be_updated
637
- expect(get('data/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
638
- end
639
-
640
- it 'chef_acl "data_bags/*" changes the acl' do
641
- expect_recipe {
642
- chef_acl 'data_bags/*' do
643
- rights :read, users: %w(u)
644
- end
645
- }.to be_updated
646
- expect(get('data/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
647
- end
648
-
649
- it 'chef_acl "" changes the organization acl' do
650
- expect_recipe {
651
- chef_acl '' do
652
- rights :read, users: %w(u)
653
- end
654
- }.to be_updated
655
- expect(get('/organizations/_acl')).to partially_match('read' => { 'actors' => %w(u) })
656
- expect(get('nodes/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
657
- end
658
- end
659
- end
660
-
661
- context 'ACLs on each container type' do
662
- when_the_chef_server 'has an organization named foo', :osc_compat => false, :single_org => false do
663
- organization 'foo' do
664
- user 'u', {}
665
- client 'x', {}
666
- container 'x', {}
667
- cookbook 'x', '1.0.0', {}
668
- data_bag 'x', { 'y' => {} }
669
- environment 'x', {}
670
- group 'x', {}
671
- node 'x', {}
672
- role 'x', {}
673
- sandbox 'x', {}
674
- user 'x', {}
675
- end
676
-
677
- %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
678
- it "chef_acl '/organizations/foo/#{type}' changes the acl" do
679
- expect_recipe {
680
- chef_acl "/organizations/foo/#{type}" do
681
- rights :read, users: %w(u)
682
- end
683
- }.to be_updated
684
- expect(get("/organizations/foo/containers/#{type}/_acl")).to partially_match('read' => { 'actors' => %w(u) })
685
- end
686
- end
687
-
688
- %w(clients containers cookbooks data environments groups nodes roles).each do |type|
689
- it "chef_acl '/*/*/#{type}' changes the acl" do
690
- expect_recipe {
691
- chef_acl "/*/*/#{type}" do
692
- rights :read, users: %w(u)
693
- end
694
- }.to be_updated
695
- expect(get("/organizations/foo/containers/#{type}/_acl")).to partially_match('read' => { 'actors' => %w(u) })
696
- end
697
- end
698
-
699
- it "chef_acl '/*/*/*' changes the acls" do
700
- expect_recipe {
701
- chef_acl "/*/*/*" do
702
- rights :read, users: %w(u)
703
- end
704
- }.to be_updated
705
- %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
706
- expect(get("/organizations/foo/containers/#{type}/_acl")).to partially_match(
707
- 'read' => { 'actors' => %w(u) })
708
- end
709
- end
710
-
711
- it 'chef_acl "/organizations/foo/data_bags" changes the acl' do
712
- expect_recipe {
713
- chef_acl '/organizations/foo/data_bags' do
714
- rights :read, users: %w(u)
715
- end
716
- }.to be_updated
717
- expect(get('/organizations/foo/containers/data/_acl')).to partially_match('read' => { 'actors' => %w(u) })
718
- end
719
-
720
- it 'chef_acl "/*/*/data_bags" changes the acl' do
721
- expect_recipe {
722
- chef_acl '/*/*/data_bags' do
723
- rights :read, users: %w(u)
724
- end
725
- }.to be_updated
726
- expect(get('/organizations/foo/containers/data/_acl')).to partially_match('read' => { 'actors' => %w(u) })
727
- end
728
- end
729
-
730
- when_the_chef_server 'has a user "u" in single org mode', :osc_compat => false do
731
- user 'u', {}
732
- client 'x', {}
733
- container 'x', {}
734
- cookbook 'x', '1.0.0', {}
735
- data_bag 'x', { 'y' => {} }
736
- environment 'x', {}
737
- group 'x', {}
738
- node 'x', {}
739
- role 'x', {}
740
- sandbox 'x', {}
741
- user 'x', {}
742
-
743
- %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
744
- it "chef_acl #{type}' changes the acl" do
745
- expect_recipe {
746
- chef_acl "#{type}" do
747
- rights :read, users: %w(u)
748
- end
749
- }.to be_updated
750
- expect(get("containers/#{type}/_acl")).to partially_match('read' => { 'actors' => %w(u) })
751
- end
752
- end
753
-
754
- it "chef_acl '*' changes the acls" do
755
- expect_recipe {
756
- chef_acl "*" do
757
- rights :read, users: %w(u)
758
- end
759
- }.to be_updated
760
- %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
761
- expect(get("containers/#{type}/_acl")).to partially_match(
762
- 'read' => { 'actors' => %w(u) })
763
- end
764
- end
765
- end
766
- end
767
-
768
- context 'remove_rights' do
769
- when_the_chef_server 'has a node "x" with "u", "c" and "g" in its acl', :osc_compat => false do
770
- user 'u', {}
771
- user 'u2', {}
772
- client 'c', {}
773
- client 'c2', {}
774
- group 'g', {}
775
- group 'g2', {}
776
- node 'x', {} do
777
- acl 'create' => { 'actors' => [ 'u', 'c' ], 'groups' => [ 'g' ] },
778
- 'read' => { 'actors' => [ 'u', 'c' ], 'groups' => [ 'g' ] },
779
- 'update' => { 'actors' => [ 'u', 'c' ], 'groups' => [ 'g' ] }
780
- end
781
-
782
- it 'chef_acl with remove_rights "u" removes the user\'s rights' do
783
- expect_recipe {
784
- chef_acl "nodes/x" do
785
- remove_rights :read, users: %w(u)
786
- end
787
- }.to be_updated
788
- expect(get("nodes/x/_acl")).to partially_match('read' => { 'actors' => exclude('u') })
789
- end
790
-
791
- it 'chef_acl with remove_rights "c" removes the client\'s rights' do
792
- expect_recipe {
793
- chef_acl "nodes/x" do
794
- remove_rights :read, clients: %w(c)
795
- end
796
- }.to be_updated
797
- expect(get("nodes/x/_acl")).to partially_match('read' => { 'actors' => exclude('c') })
798
- end
799
-
800
- it 'chef_acl with remove_rights "g" removes the group\'s rights' do
801
- expect_recipe {
802
- chef_acl "nodes/x" do
803
- remove_rights :read, groups: %w(g)
804
- end
805
- }.to be_updated
806
- expect(get("nodes/x/_acl")).to partially_match(
807
- 'read' => { 'groups' => exclude('g') }
808
- )
809
- end
810
-
811
- it 'chef_acl with remove_rights [ :create, :read ], "u", "c", "g" removes all three' do
812
- expect_recipe {
813
- chef_acl "nodes/x" do
814
- remove_rights [ :create, :read ], users: %w(u), clients: %w(c), groups: %w(g)
815
- end
816
- }.to be_updated
817
- expect(get("nodes/x/_acl")).to partially_match(
818
- 'create' => { 'actors' => exclude('u').and(exclude('c')), 'groups' => exclude('g') },
819
- 'read' => { 'actors' => exclude('u').and(exclude('c')), 'groups' => exclude('g') }
820
- )
821
- end
822
-
823
- it 'chef_acl with remove_rights "u2", "c2", "g2" has no effect' do
824
- expect {
825
- expect_recipe {
826
- chef_acl "nodes/x" do
827
- remove_rights :read, users: %w(u2), clients: %w(c2), groups: %w(g2)
828
- end
829
- }.to be_up_to_date
830
- }.not_to change { get("nodes/x/_acl") }
831
- end
832
- end
833
- end
834
-
835
- when_the_chef_server 'has a node named data_bags', :osc_compat => false do
836
- user 'blarghle', {}
837
- node 'data_bags', {}
838
-
839
- it 'Converging chef_acl "nodes/data_bags" with user "blarghle" adds the user' do
840
- expect_recipe {
841
- chef_acl 'nodes/data_bags' do
842
- rights :read, users: %w(blarghle)
843
- end
844
- }.to be_updated
845
- expect(get('nodes/data_bags/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
846
- end
847
- end
848
-
849
- when_the_chef_server 'has a node named data_bags in multi-org mode', :osc_compat => false, :single_org => false do
850
- user 'blarghle', {}
851
- organization 'foo' do
852
- node 'data_bags', {}
853
- end
854
-
855
- it 'Converging chef_acl "/organizations/foo/nodes/data_bags" with user "blarghle" adds the user' do
856
- expect_recipe {
857
- chef_acl '/organizations/foo/nodes/data_bags' do
858
- rights :read, users: %w(blarghle)
859
- end
860
- }.to be_updated
861
- expect(get('/organizations/foo/nodes/data_bags/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
862
- end
863
- end
864
-
865
- when_the_chef_server 'has a user named data_bags in multi-org mode', :osc_compat => false, :single_org => false do
866
- user 'data_bags', {}
867
- user 'blarghle', {}
868
-
869
- it 'Converging chef_acl "/users/data_bags" with user "blarghle" adds the user' do
870
- expect_recipe {
871
- chef_acl '/users/data_bags' do
872
- rights :read, users: %w(blarghle)
873
- end
874
- }.to be_updated
875
- expect(get('/users/data_bags/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
876
- end
877
- end
878
- end
879
- end
1
+ require 'support/spec_support'
2
+ require 'cheffish/rspec/chef_run_support'
3
+ require 'chef/resource/chef_acl'
4
+ require 'chef/provider/chef_acl'
5
+ require 'chef_zero/version'
6
+ require 'uri'
7
+
8
+ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new('3.1')
9
+ describe Chef::Resource::ChefAcl do
10
+ extend Cheffish::RSpec::ChefRunSupport
11
+
12
+ # let(:chef_config) { super().merge(log_level: :debug, stdout: STDOUT, stderr: STDERR, log_location: STDOUT) }
13
+
14
+ context "Rights attributes" do
15
+ when_the_chef_server 'has a node named x', :osc_compat => false do
16
+ node 'x', {}
17
+
18
+ it 'Converging chef_acl "nodes/x" changes nothing' do
19
+ expect_recipe {
20
+ chef_acl 'nodes/x'
21
+ }.to be_up_to_date
22
+ expect(get('nodes/x/_acl')).to partially_match({})
23
+ end
24
+
25
+ it 'Converging chef_acl "nodes/x" with "complete true" and no rights raises an error' do
26
+ expect_converge {
27
+ chef_acl 'nodes/x' do
28
+ complete true
29
+ end
30
+ }.to raise_error(RuntimeError)
31
+ end
32
+
33
+ it 'Removing all :grant rights from a node raises an error' do
34
+ expect_converge {
35
+ chef_acl 'nodes/x' do
36
+ remove_rights :grant, users: %w(pivotal), groups: %w(admins users clients)
37
+ end
38
+ }.to raise_error(RuntimeError)
39
+ end
40
+
41
+ context 'and a user "blarghle"' do
42
+ user 'blarghle', {}
43
+
44
+ it 'Converging chef_acl "nodes/x" with user "blarghle" adds the user' do
45
+ expect_recipe {
46
+ chef_acl 'nodes/x' do
47
+ rights :read, users: %w(blarghle)
48
+ end
49
+ }.to be_updated
50
+ expect(get('nodes/x/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
51
+ end
52
+
53
+ it 'Converging chef_acl "nodes/x" with "complete true" removes all ACLs except those specified' do
54
+ expect_recipe {
55
+ chef_acl 'nodes/x' do
56
+ rights :grant, users: %w(blarghle)
57
+ complete true
58
+ end
59
+ }.to be_updated
60
+ expect(get('nodes/x/_acl')).to eq(
61
+ "create"=>{"actors"=>[], "groups"=>[]},
62
+ "read" =>{"actors"=>[], "groups"=>[]},
63
+ "update"=>{"actors"=>[], "groups"=>[]},
64
+ "delete"=>{"actors"=>[], "groups"=>[]},
65
+ "grant" =>{"actors"=>["blarghle"], "groups"=>[]}
66
+ )
67
+ end
68
+ end
69
+
70
+ it 'Converging chef_acl "nodes/x" with "complete true" removes all ACLs except those specified in :all' do
71
+ expect_recipe {
72
+ chef_acl 'nodes/x' do
73
+ rights :all, users: %w(blarghle)
74
+ complete true
75
+ end
76
+ }.to be_updated
77
+ expect(get('nodes/x/_acl')).to eq(
78
+ "create"=>{"actors"=>["blarghle"], "groups"=>[]},
79
+ "read" =>{"actors"=>["blarghle"], "groups"=>[]},
80
+ "update"=>{"actors"=>["blarghle"], "groups"=>[]},
81
+ "delete"=>{"actors"=>["blarghle"], "groups"=>[]},
82
+ "grant" =>{"actors"=>["blarghle"], "groups"=>[]}
83
+ )
84
+ end
85
+
86
+ context 'and a client "blarghle"' do
87
+ user 'blarghle', {}
88
+
89
+ it 'Converging chef_acl "nodes/x" with client "blarghle" adds the client' do
90
+ expect_recipe {
91
+ chef_acl 'nodes/x' do
92
+ rights :read, clients: %w(blarghle)
93
+ end
94
+ }.to be_updated
95
+ expect(get('nodes/x/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
96
+ end
97
+ end
98
+
99
+ context 'and a group "blarghle"' do
100
+ group 'blarghle', {}
101
+
102
+ it 'Converging chef_acl "nodes/x" with group "blarghle" adds the group' do
103
+ expect_recipe {
104
+ chef_acl 'nodes/x' do
105
+ rights :read, groups: %w(blarghle)
106
+ end
107
+ }.to be_updated
108
+ expect(get('nodes/x/_acl')).to partially_match('read' => { 'groups' => %w(blarghle) })
109
+ end
110
+ end
111
+
112
+ context 'and multiple users and groups' do
113
+ user 'u1', {}
114
+ user 'u2', {}
115
+ user 'u3', {}
116
+ client 'c1', {}
117
+ client 'c2', {}
118
+ client 'c3', {}
119
+ group 'g1', {}
120
+ group 'g2', {}
121
+ group 'g3', {}
122
+
123
+ it 'Converging chef_acls should ignore order of the values in the acls' do
124
+ expect_recipe {
125
+ chef_acl 'nodes/x' do
126
+ rights :create, users: [ 'u1', 'u2', 'u3' ], clients: [ 'c1', 'c2', 'c3' ], groups: [ 'g1', 'g2', 'g3' ]
127
+ end
128
+ }.to be_updated
129
+ expect_recipe {
130
+ chef_acl 'nodes/x' do
131
+ rights :create, users: [ 'u2', 'u3', 'u1' ], clients: [ 'c3', 'c2', 'c1' ], groups: [ 'g1', 'g2', 'g3' ]
132
+ end
133
+ }.to be_up_to_date
134
+ end
135
+
136
+ it 'Converging chef_acl "nodes/x" with multiple groups, users and clients in an acl makes the appropriate changes' do
137
+ expect_recipe {
138
+ chef_acl 'nodes/x' do
139
+ rights :create, users: [ 'u1', 'u2', 'u3' ], clients: [ 'c1', 'c2', 'c3' ], groups: [ 'g1', 'g2', 'g3' ]
140
+ end
141
+ }.to be_updated
142
+ expect(get('nodes/x/_acl')).to partially_match(
143
+ 'create' => { 'groups' => %w(g1 g2 g3), 'actors' => %w(u1 u2 u3 c1 c2 c3) }
144
+ )
145
+ end
146
+
147
+ it 'Converging chef_acl "nodes/x" with multiple groups, users and clients across multiple "rights" groups makes the appropriate changes' do
148
+ expect_recipe {
149
+ chef_acl 'nodes/x' do
150
+ rights :create, users: %w(u1), clients: %w(c1), groups: %w(g1)
151
+ rights :create, users: %w(u2 u3), clients: %w(c2 c3), groups: %w(g2)
152
+ rights :read, users: %w(u1)
153
+ rights :read, groups: %w(g1)
154
+ end
155
+ }.to be_updated
156
+ expect(get('nodes/x/_acl')).to partially_match(
157
+ 'create' => { 'groups' => %w(g1 g2), 'actors' => %w(u1 u2 u3 c1 c2 c3) },
158
+ 'read' => { 'groups' => %w(g1), 'actors' => %w(u1) }
159
+ )
160
+ end
161
+
162
+ it 'Converging chef_acl "nodes/x" with rights [ :read, :create, :update, :delete, :grant ] modifies all rights' do
163
+ expect_recipe {
164
+ chef_acl 'nodes/x' do
165
+ rights [ :create, :read, :update, :delete, :grant ], users: %w(u1 u2), clients: %w(c1), groups: %w(g1)
166
+ end
167
+ }.to be_updated
168
+ expect(get('nodes/x/_acl')).to partially_match(
169
+ 'create' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
170
+ 'read' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
171
+ 'update' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
172
+ 'delete' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
173
+ 'grant' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
174
+ )
175
+ end
176
+
177
+ it 'Converging chef_acl "nodes/x" with rights :all modifies all rights' do
178
+ expect_recipe {
179
+ chef_acl 'nodes/x' do
180
+ rights :all, users: %w(u1 u2), clients: %w(c1), groups: %w(g1)
181
+ end
182
+ }.to be_updated
183
+ expect(get('nodes/x/_acl')).to partially_match(
184
+ 'create' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
185
+ 'read' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
186
+ 'update' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
187
+ 'delete' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
188
+ 'grant' => { 'groups' => %w(g1), 'actors' => %w(u1 u2 c1) },
189
+ )
190
+ end
191
+ end
192
+
193
+ it 'Converging chef_acl "nodes/y" throws a 404' do
194
+ expect_converge {
195
+ chef_acl 'nodes/y'
196
+ }.to raise_error(Net::HTTPServerException)
197
+ end
198
+ end
199
+
200
+ when_the_chef_server 'has a node named x with user blarghle in its acl', :osc_compat => false do
201
+ user 'blarghle', {}
202
+ node 'x', {} do
203
+ acl 'read' => { 'actors' => %w(blarghle) }
204
+ end
205
+
206
+ it 'Converging chef_acl "nodes/x" with that user changes nothing' do
207
+ expect_recipe {
208
+ chef_acl 'nodes/x' do
209
+ rights :read, users: %w(blarghle)
210
+ end
211
+ }.to be_up_to_date
212
+ expect(get('nodes/x/_acl')).to partially_match({})
213
+ end
214
+ end
215
+
216
+ when_the_chef_server 'has a node named x with users foo and bar in all its acls', :osc_compat => false do
217
+ user 'foo', {}
218
+ user 'bar', {}
219
+ node 'x', {} do
220
+ acl 'create' => { 'actors' => %w(foo bar) },
221
+ 'read' => { 'actors' => %w(foo bar) },
222
+ 'update' => { 'actors' => %w(foo bar) },
223
+ 'delete' => { 'actors' => %w(foo bar) },
224
+ 'grant' => { 'actors' => %w(foo bar) }
225
+ end
226
+
227
+ it 'Converging chef_acl "nodes/x" with remove_rights :all removes foo from everything' do
228
+ expect_recipe {
229
+ chef_acl 'nodes/x' do
230
+ remove_rights :all, users: %w(foo)
231
+ end
232
+ }.to be_updated
233
+ expect(get('nodes/x/_acl')).to partially_match(
234
+ 'create' => { 'actors' => exclude('foo') },
235
+ 'read' => { 'actors' => exclude('foo') },
236
+ 'update' => { 'actors' => exclude('foo') },
237
+ 'delete' => { 'actors' => exclude('foo') },
238
+ 'grant' => { 'actors' => exclude('foo') },
239
+ )
240
+ end
241
+ end
242
+
243
+ ::RSpec::Matchers.define_negated_matcher :exclude, :include
244
+
245
+ context 'recursive' do
246
+ when_the_chef_server 'has a nodes container with user blarghle in its acl', :osc_compat => false do
247
+ user 'blarghle', {}
248
+ acl_for 'containers/nodes', 'read' => { 'actors' => %w(blarghle) }
249
+ node 'x', {} do
250
+ acl 'read' => { 'actors' => [] }
251
+ end
252
+
253
+ it 'Converging chef_acl "nodes" makes no changes' do
254
+ expect {
255
+ expect_recipe {
256
+ chef_acl 'nodes' do
257
+ rights :read, users: %w(blarghle)
258
+ end
259
+ }.to be_up_to_date
260
+ }.to not_change { get('containers/nodes/_acl') }.
261
+ and not_change { get('nodes/x/_acl') }
262
+ end
263
+
264
+ RSpec::Matchers.define_negated_matcher :not_change, :change
265
+
266
+ it 'Converging chef_acl "nodes" with recursive :on_change makes no changes' do
267
+ expect {
268
+ expect_recipe {
269
+ chef_acl 'nodes' do
270
+ rights :read, users: %w(blarghle)
271
+ recursive :on_change
272
+ end
273
+ }.to be_up_to_date
274
+ }.to not_change { get('containers/nodes/_acl') }.
275
+ and not_change { get('nodes/x/_acl') }
276
+ end
277
+
278
+ it 'Converging chef_acl "nodes" with recursive true changes nodes/x\'s acls' do
279
+ expect_recipe {
280
+ chef_acl 'nodes' do
281
+ rights :read, users: %w(blarghle)
282
+ recursive true
283
+ end
284
+ }.to be_updated
285
+ expect(get('nodes/x/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
286
+ end
287
+
288
+ it 'Converging chef_acl "" with recursive false does not change nodes/x\'s acls' do
289
+ expect_recipe {
290
+ chef_acl '' do
291
+ rights :read, users: %w(blarghle)
292
+ recursive false
293
+ end
294
+ }.to be_updated
295
+ expect(get('containers/nodes/_acl')).to partially_match({})
296
+ expect(get('nodes/x/_acl')).to partially_match({})
297
+ end
298
+
299
+ it 'Converging chef_acl "" with recursive :on_change does not change nodes/x\'s acls' do
300
+ expect_recipe {
301
+ chef_acl '' do
302
+ rights :read, users: %w(blarghle)
303
+ recursive :on_change
304
+ end
305
+ }.to be_updated
306
+ expect(get('containers/nodes/_acl')).to partially_match({})
307
+ expect(get('nodes/x/_acl')).to partially_match({})
308
+ end
309
+
310
+ it 'Converging chef_acl "" with recursive true changes nodes/x\'s acls' do
311
+ expect_recipe {
312
+ chef_acl '' do
313
+ rights :read, users: %w(blarghle)
314
+ recursive true
315
+ end
316
+ }.to be_updated
317
+ expect(get('/organizations/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
318
+ expect(get('nodes/x/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
319
+ end
320
+ end
321
+ end
322
+ end
323
+
324
+ context 'ACLs on each type of thing' do
325
+ when_the_chef_server 'has an organization named foo', :osc_compat => false, :single_org => false do
326
+ organization 'foo' do
327
+ user 'u', {}
328
+ client 'x', {}
329
+ container 'x', {}
330
+ cookbook 'x', '1.0.0', {}
331
+ data_bag 'x', { 'y' => {} }
332
+ environment 'x', {}
333
+ group 'x', {}
334
+ node 'x', {}
335
+ role 'x', {}
336
+ sandbox 'x', {}
337
+ user 'x', {}
338
+ end
339
+
340
+ organization 'bar' do
341
+ user 'u', {}
342
+ node 'x', {}
343
+ end
344
+
345
+ context 'and the chef server URL points at /organizations/foo' do
346
+ before :each do
347
+ Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url, '/organizations/foo').to_s
348
+ end
349
+
350
+ context 'relative paths' do
351
+ it "chef_acl 'nodes/x' changes the acls" do
352
+ expect_recipe {
353
+ chef_acl "nodes/x" do
354
+ rights :read, users: %w(u)
355
+ end
356
+ }.to be_updated
357
+ expect(get("nodes/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
358
+ end
359
+
360
+ it "chef_acl '*/*' changes the acls" do
361
+ expect_recipe {
362
+ chef_acl "*/*" do
363
+ rights :read, users: %w(u)
364
+ end
365
+ }.to be_updated
366
+ %w(clients containers cookbooks data environments groups nodes roles).each do |type|
367
+ expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match(
368
+ 'read' => { 'actors' => %w(u) })
369
+ end
370
+ end
371
+ end
372
+
373
+ context 'absolute paths' do
374
+ %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
375
+ it "chef_acl '/organizations/foo/#{type}/x' changes the acl" do
376
+ expect_recipe {
377
+ chef_acl "/organizations/foo/#{type}/x" do
378
+ rights :read, users: %w(u)
379
+ end
380
+ }.to be_updated
381
+ expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
382
+ end
383
+ end
384
+
385
+ %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
386
+ it "chef_acl '/organizations/foo/#{type}/x' changes the acl" do
387
+ expect_recipe {
388
+ chef_acl "/organizations/foo/#{type}/x" do
389
+ rights :read, users: %w(u)
390
+ end
391
+ }.to be_updated
392
+ expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
393
+ end
394
+ end
395
+
396
+ %w(clients containers cookbooks data environments groups nodes roles).each do |type|
397
+ it "chef_acl '/*/*/#{type}/*' changes the acl" do
398
+ expect_recipe {
399
+ chef_acl "/*/*/#{type}/*" do
400
+ rights :read, users: %w(u)
401
+ end
402
+ }.to be_updated
403
+ expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
404
+ end
405
+ end
406
+
407
+ it "chef_acl '/*/*/*/x' changes the acls" do
408
+ expect_recipe {
409
+ chef_acl "/*/*/*/x" do
410
+ rights :read, users: %w(u)
411
+ end
412
+ }.to be_updated
413
+ %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
414
+ expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match(
415
+ 'read' => { 'actors' => %w(u) })
416
+ end
417
+ end
418
+
419
+ it "chef_acl '/*/*/*/*' changes the acls" do
420
+ expect_recipe {
421
+ chef_acl "/*/*/*/*" do
422
+ rights :read, users: %w(u)
423
+ end
424
+ }.to be_updated
425
+ %w(clients containers cookbooks data environments groups nodes roles).each do |type|
426
+ expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match(
427
+ 'read' => { 'actors' => %w(u) })
428
+ end
429
+ end
430
+
431
+ it 'chef_acl "/organizations/foo/data_bags/x" changes the acl' do
432
+ expect_recipe {
433
+ chef_acl '/organizations/foo/data_bags/x' do
434
+ rights :read, users: %w(u)
435
+ end
436
+ }.to be_updated
437
+ expect(get('/organizations/foo/data/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
438
+ end
439
+
440
+ it 'chef_acl "/*/*/data_bags/*" changes the acl' do
441
+ expect_recipe {
442
+ chef_acl '/*/*/data_bags/*' do
443
+ rights :read, users: %w(u)
444
+ end
445
+ }.to be_updated
446
+ expect(get('/organizations/foo/data/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
447
+ end
448
+
449
+ it "chef_acl '/organizations/foo/cookbooks/x/1.0.0' raises an error" do
450
+ expect_converge {
451
+ chef_acl "/organizations/foo/cookbooks/x/1.0.0" do
452
+ rights :read, users: %w(u)
453
+ end
454
+ }.to raise_error(/ACLs cannot be set on children of \/organizations\/foo\/cookbooks\/x/)
455
+ end
456
+
457
+ it "chef_acl '/organizations/foo/cookbooks/*/*' raises an error" do
458
+ pending
459
+ expect_converge {
460
+ chef_acl "/organizations/foo/cookbooks/*/*" do
461
+ rights :read, users: %w(u)
462
+ end
463
+ }.to raise_error(/ACLs cannot be set on children of \/organizations\/foo\/cookbooks\/*/)
464
+ end
465
+
466
+ it 'chef_acl "/organizations/foo/data/x/y" raises an error' do
467
+ expect_converge {
468
+ chef_acl '/organizations/foo/data/x/y' do
469
+ rights :read, users: %w(u)
470
+ end
471
+ }.to raise_error(/ACLs cannot be set on children of \/organizations\/foo\/data\/x/)
472
+ end
473
+
474
+ it 'chef_acl "/organizations/foo/data/*/*" raises an error' do
475
+ pending
476
+ expect_converge {
477
+ chef_acl '/organizations/foo/data/*/*' do
478
+ rights :read, users: %w(u)
479
+ end
480
+ }.to raise_error(/ACLs cannot be set on children of \/organizations\/foo\/data\/*/)
481
+ end
482
+
483
+ it 'chef_acl "/organizations/foo" changes the acl' do
484
+ expect_recipe {
485
+ chef_acl '/organizations/foo' do
486
+ rights :read, users: %w(u)
487
+ end
488
+ }.to be_updated
489
+ expect(get('/organizations/foo/organizations/_acl')).to partially_match('read' => { 'actors' => %w(u) })
490
+ expect(get('/organizations/foo/nodes/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
491
+ end
492
+
493
+ it 'chef_acl "/organizations/*" changes the acl' do
494
+ expect_recipe {
495
+ chef_acl '/organizations/*' do
496
+ rights :read, users: %w(u)
497
+ end
498
+ }.to be_updated
499
+ expect(get('/organizations/foo/organizations/_acl')).to partially_match('read' => { 'actors' => %w(u) })
500
+ expect(get('/organizations/foo/nodes/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
501
+ end
502
+
503
+ it 'chef_acl "/users/x" changes the acl' do
504
+ expect_recipe {
505
+ chef_acl '/users/x' do
506
+ rights :read, users: %w(u)
507
+ end
508
+ }.to be_updated
509
+ expect(get('/users/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
510
+ end
511
+
512
+ it 'chef_acl "/users/*" changes the acl' do
513
+ expect_recipe {
514
+ chef_acl '/users/*' do
515
+ rights :read, users: %w(u)
516
+ end
517
+ }.to be_updated
518
+ expect(get('/users/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
519
+ end
520
+
521
+ it 'chef_acl "/*/x" changes the acl' do
522
+ expect_recipe {
523
+ chef_acl '/*/x' do
524
+ rights :read, users: %w(u)
525
+ end
526
+ }.to be_updated
527
+ expect(get('/users/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
528
+ end
529
+
530
+ it 'chef_acl "/*/*" changes the acl' do
531
+ expect_recipe {
532
+ chef_acl '/*/*' do
533
+ rights :read, users: %w(u)
534
+ end
535
+ }.to be_updated
536
+ expect(get('/organizations/foo/organizations/_acl')).to partially_match('read' => { 'actors' => %w(u) })
537
+ expect(get('/users/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
538
+ end
539
+ end
540
+ end
541
+
542
+ context 'and the chef server URL points at /organizations/bar' do
543
+ before :each do
544
+ Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url.to_s, '/organizations/bar').to_s
545
+ end
546
+
547
+ it "chef_acl '/organizations/foo/nodes/*' changes the acl" do
548
+ expect_recipe {
549
+ chef_acl "/organizations/foo/nodes/*" do
550
+ rights :read, users: %w(u)
551
+ end
552
+ }.to be_updated
553
+ expect(get("/organizations/foo/nodes/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
554
+ end
555
+ end
556
+
557
+ context 'and the chef server URL points at /' do
558
+ before :each do
559
+ Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url.to_s, '/').to_s
560
+ end
561
+
562
+ it "chef_acl '/organizations/foo/nodes/*' changes the acl" do
563
+ expect_recipe {
564
+ chef_acl "/organizations/foo/nodes/*" do
565
+ rights :read, users: %w(u)
566
+ end
567
+ }.to be_updated
568
+ expect(get("/organizations/foo/nodes/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
569
+ end
570
+ end
571
+ end
572
+
573
+ when_the_chef_server 'has a user "u" in single org mode', :osc_compat => false do
574
+ user 'u', {}
575
+ client 'x', {}
576
+ container 'x', {}
577
+ cookbook 'x', '1.0.0', {}
578
+ data_bag 'x', { 'y' => {} }
579
+ environment 'x', {}
580
+ group 'x', {}
581
+ node 'x', {}
582
+ role 'x', {}
583
+ sandbox 'x', {}
584
+ user 'x', {}
585
+
586
+ %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
587
+ it "chef_acl #{type}/x' changes the acl" do
588
+ expect_recipe {
589
+ chef_acl "#{type}/x" do
590
+ rights :read, users: %w(u)
591
+ end
592
+ }.to be_updated
593
+ expect(get("#{type}/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
594
+ end
595
+ end
596
+
597
+ %w(clients containers cookbooks data environments groups nodes roles).each do |type|
598
+ it "chef_acl '#{type}/*' changes the acl" do
599
+ expect_recipe {
600
+ chef_acl "#{type}/*" do
601
+ rights :read, users: %w(u)
602
+ end
603
+ }.to be_updated
604
+ expect(get("#{type}/x/_acl")).to partially_match('read' => { 'actors' => %w(u) })
605
+ end
606
+ end
607
+
608
+ it "chef_acl '*/x' changes the acls" do
609
+ expect_recipe {
610
+ chef_acl "*/x" do
611
+ rights :read, users: %w(u)
612
+ end
613
+ }.to be_updated
614
+ %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
615
+ expect(get("#{type}/x/_acl")).to partially_match(
616
+ 'read' => { 'actors' => %w(u) })
617
+ end
618
+ end
619
+
620
+ it "chef_acl '*/*' changes the acls" do
621
+ expect_recipe {
622
+ chef_acl "*/*" do
623
+ rights :read, users: %w(u)
624
+ end
625
+ }.to be_updated
626
+ %w(clients containers cookbooks data environments groups nodes roles).each do |type|
627
+ expect(get("#{type}/x/_acl")).to partially_match(
628
+ 'read' => { 'actors' => %w(u) })
629
+ end
630
+ end
631
+
632
+ it "chef_acl 'groups/*' changes the acl" do
633
+ expect_recipe {
634
+ chef_acl "groups/*" do
635
+ rights :read, users: %w(u)
636
+ end
637
+ }.to be_updated
638
+ %w(admins billing-admins clients users x).each do |n|
639
+ expect(get("groups/#{n}/_acl")).to partially_match(
640
+ 'read' => { 'actors' => %w(u) })
641
+ end
642
+ end
643
+
644
+ it 'chef_acl "data_bags/x" changes the acl' do
645
+ expect_recipe {
646
+ chef_acl 'data_bags/x' do
647
+ rights :read, users: %w(u)
648
+ end
649
+ }.to be_updated
650
+ expect(get('data/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
651
+ end
652
+
653
+ it 'chef_acl "data_bags/*" changes the acl' do
654
+ expect_recipe {
655
+ chef_acl 'data_bags/*' do
656
+ rights :read, users: %w(u)
657
+ end
658
+ }.to be_updated
659
+ expect(get('data/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
660
+ end
661
+
662
+ it 'chef_acl "" changes the organization acl' do
663
+ expect_recipe {
664
+ chef_acl '' do
665
+ rights :read, users: %w(u)
666
+ end
667
+ }.to be_updated
668
+ expect(get('/organizations/_acl')).to partially_match('read' => { 'actors' => %w(u) })
669
+ expect(get('nodes/x/_acl')).to partially_match('read' => { 'actors' => %w(u) })
670
+ end
671
+ end
672
+ end
673
+
674
+ context 'ACLs on each container type' do
675
+ when_the_chef_server 'has an organization named foo', :osc_compat => false, :single_org => false do
676
+ organization 'foo' do
677
+ user 'u', {}
678
+ client 'x', {}
679
+ container 'x', {}
680
+ cookbook 'x', '1.0.0', {}
681
+ data_bag 'x', { 'y' => {} }
682
+ environment 'x', {}
683
+ group 'x', {}
684
+ node 'x', {}
685
+ role 'x', {}
686
+ sandbox 'x', {}
687
+ user 'x', {}
688
+ end
689
+
690
+ %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
691
+ it "chef_acl '/organizations/foo/#{type}' changes the acl" do
692
+ expect_recipe {
693
+ chef_acl "/organizations/foo/#{type}" do
694
+ rights :read, users: %w(u)
695
+ end
696
+ }.to be_updated
697
+ expect(get("/organizations/foo/containers/#{type}/_acl")).to partially_match('read' => { 'actors' => %w(u) })
698
+ end
699
+ end
700
+
701
+ %w(clients containers cookbooks data environments groups nodes roles).each do |type|
702
+ it "chef_acl '/*/*/#{type}' changes the acl" do
703
+ expect_recipe {
704
+ chef_acl "/*/*/#{type}" do
705
+ rights :read, users: %w(u)
706
+ end
707
+ }.to be_updated
708
+ expect(get("/organizations/foo/containers/#{type}/_acl")).to partially_match('read' => { 'actors' => %w(u) })
709
+ end
710
+ end
711
+
712
+ it "chef_acl '/*/*/*' changes the acls" do
713
+ expect_recipe {
714
+ chef_acl "/*/*/*" do
715
+ rights :read, users: %w(u)
716
+ end
717
+ }.to be_updated
718
+ %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
719
+ expect(get("/organizations/foo/containers/#{type}/_acl")).to partially_match(
720
+ 'read' => { 'actors' => %w(u) })
721
+ end
722
+ end
723
+
724
+ it 'chef_acl "/organizations/foo/data_bags" changes the acl' do
725
+ expect_recipe {
726
+ chef_acl '/organizations/foo/data_bags' do
727
+ rights :read, users: %w(u)
728
+ end
729
+ }.to be_updated
730
+ expect(get('/organizations/foo/containers/data/_acl')).to partially_match('read' => { 'actors' => %w(u) })
731
+ end
732
+
733
+ it 'chef_acl "/*/*/data_bags" changes the acl' do
734
+ expect_recipe {
735
+ chef_acl '/*/*/data_bags' do
736
+ rights :read, users: %w(u)
737
+ end
738
+ }.to be_updated
739
+ expect(get('/organizations/foo/containers/data/_acl')).to partially_match('read' => { 'actors' => %w(u) })
740
+ end
741
+ end
742
+
743
+ when_the_chef_server 'has a user "u" in single org mode', :osc_compat => false do
744
+ user 'u', {}
745
+ client 'x', {}
746
+ container 'x', {}
747
+ cookbook 'x', '1.0.0', {}
748
+ data_bag 'x', { 'y' => {} }
749
+ environment 'x', {}
750
+ group 'x', {}
751
+ node 'x', {}
752
+ role 'x', {}
753
+ sandbox 'x', {}
754
+ user 'x', {}
755
+
756
+ %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
757
+ it "chef_acl #{type}' changes the acl" do
758
+ expect_recipe {
759
+ chef_acl "#{type}" do
760
+ rights :read, users: %w(u)
761
+ end
762
+ }.to be_updated
763
+ expect(get("containers/#{type}/_acl")).to partially_match('read' => { 'actors' => %w(u) })
764
+ end
765
+ end
766
+
767
+ it "chef_acl '*' changes the acls" do
768
+ expect_recipe {
769
+ chef_acl "*" do
770
+ rights :read, users: %w(u)
771
+ end
772
+ }.to be_updated
773
+ %w(clients containers cookbooks data environments groups nodes roles sandboxes).each do |type|
774
+ expect(get("containers/#{type}/_acl")).to partially_match(
775
+ 'read' => { 'actors' => %w(u) })
776
+ end
777
+ end
778
+ end
779
+ end
780
+
781
+ context 'remove_rights' do
782
+ when_the_chef_server 'has a node "x" with "u", "c" and "g" in its acl', :osc_compat => false do
783
+ user 'u', {}
784
+ user 'u2', {}
785
+ client 'c', {}
786
+ client 'c2', {}
787
+ group 'g', {}
788
+ group 'g2', {}
789
+ node 'x', {} do
790
+ acl 'create' => { 'actors' => [ 'u', 'c' ], 'groups' => [ 'g' ] },
791
+ 'read' => { 'actors' => [ 'u', 'c' ], 'groups' => [ 'g' ] },
792
+ 'update' => { 'actors' => [ 'u', 'c' ], 'groups' => [ 'g' ] }
793
+ end
794
+
795
+ it 'chef_acl with remove_rights "u" removes the user\'s rights' do
796
+ expect_recipe {
797
+ chef_acl "nodes/x" do
798
+ remove_rights :read, users: %w(u)
799
+ end
800
+ }.to be_updated
801
+ expect(get("nodes/x/_acl")).to partially_match('read' => { 'actors' => exclude('u') })
802
+ end
803
+
804
+ it 'chef_acl with remove_rights "c" removes the client\'s rights' do
805
+ expect_recipe {
806
+ chef_acl "nodes/x" do
807
+ remove_rights :read, clients: %w(c)
808
+ end
809
+ }.to be_updated
810
+ expect(get("nodes/x/_acl")).to partially_match('read' => { 'actors' => exclude('c') })
811
+ end
812
+
813
+ it 'chef_acl with remove_rights "g" removes the group\'s rights' do
814
+ expect_recipe {
815
+ chef_acl "nodes/x" do
816
+ remove_rights :read, groups: %w(g)
817
+ end
818
+ }.to be_updated
819
+ expect(get("nodes/x/_acl")).to partially_match(
820
+ 'read' => { 'groups' => exclude('g') }
821
+ )
822
+ end
823
+
824
+ it 'chef_acl with remove_rights [ :create, :read ], "u", "c", "g" removes all three' do
825
+ expect_recipe {
826
+ chef_acl "nodes/x" do
827
+ remove_rights [ :create, :read ], users: %w(u), clients: %w(c), groups: %w(g)
828
+ end
829
+ }.to be_updated
830
+ expect(get("nodes/x/_acl")).to partially_match(
831
+ 'create' => { 'actors' => exclude('u').and(exclude('c')), 'groups' => exclude('g') },
832
+ 'read' => { 'actors' => exclude('u').and(exclude('c')), 'groups' => exclude('g') }
833
+ )
834
+ end
835
+
836
+ it 'chef_acl with remove_rights "u2", "c2", "g2" has no effect' do
837
+ expect {
838
+ expect_recipe {
839
+ chef_acl "nodes/x" do
840
+ remove_rights :read, users: %w(u2), clients: %w(c2), groups: %w(g2)
841
+ end
842
+ }.to be_up_to_date
843
+ }.not_to change { get("nodes/x/_acl") }
844
+ end
845
+ end
846
+ end
847
+
848
+ when_the_chef_server 'has a node named data_bags', :osc_compat => false do
849
+ user 'blarghle', {}
850
+ node 'data_bags', {}
851
+
852
+ it 'Converging chef_acl "nodes/data_bags" with user "blarghle" adds the user' do
853
+ expect_recipe {
854
+ chef_acl 'nodes/data_bags' do
855
+ rights :read, users: %w(blarghle)
856
+ end
857
+ }.to be_updated
858
+ expect(get('nodes/data_bags/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
859
+ end
860
+ end
861
+
862
+ when_the_chef_server 'has a node named data_bags in multi-org mode', :osc_compat => false, :single_org => false do
863
+ user 'blarghle', {}
864
+ organization 'foo' do
865
+ node 'data_bags', {}
866
+ end
867
+
868
+ it 'Converging chef_acl "/organizations/foo/nodes/data_bags" with user "blarghle" adds the user' do
869
+ expect_recipe {
870
+ chef_acl '/organizations/foo/nodes/data_bags' do
871
+ rights :read, users: %w(blarghle)
872
+ end
873
+ }.to be_updated
874
+ expect(get('/organizations/foo/nodes/data_bags/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
875
+ end
876
+ end
877
+
878
+ when_the_chef_server 'has a user named data_bags in multi-org mode', :osc_compat => false, :single_org => false do
879
+ user 'data_bags', {}
880
+ user 'blarghle', {}
881
+
882
+ it 'Converging chef_acl "/users/data_bags" with user "blarghle" adds the user' do
883
+ expect_recipe {
884
+ chef_acl '/users/data_bags' do
885
+ rights :read, users: %w(blarghle)
886
+ end
887
+ }.to be_updated
888
+ expect(get('/users/data_bags/_acl')).to partially_match('read' => { 'actors' => %w(blarghle) })
889
+ end
890
+ end
891
+ end
892
+ end