fog 1.30.0 → 1.31.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 (252) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -0
  3. data/CONTRIBUTORS.md +73 -1
  4. data/LICENSE.md +1 -1
  5. data/Rakefile +10 -8
  6. data/fog.gemspec +6 -3
  7. data/lib/fog/cloudstack/models/compute/server.rb +2 -0
  8. data/lib/fog/openstack.rb +1 -1
  9. data/lib/fog/openstack/baremetal.rb +5 -5
  10. data/lib/fog/openstack/compute.rb +20 -9
  11. data/lib/fog/openstack/core.rb +53 -14
  12. data/lib/fog/openstack/examples/compute/basics.rb +3 -1
  13. data/lib/fog/openstack/identity.rb +29 -254
  14. data/lib/fog/openstack/identity_v2.rb +264 -0
  15. data/lib/fog/openstack/identity_v3.rb +249 -0
  16. data/lib/fog/openstack/image.rb +1 -1
  17. data/lib/fog/openstack/metering.rb +1 -1
  18. data/lib/fog/openstack/models/baremetal/node.rb +22 -0
  19. data/lib/fog/openstack/models/compute/flavor.rb +13 -0
  20. data/lib/fog/openstack/models/compute/service.rb +48 -0
  21. data/lib/fog/openstack/models/compute/services.rb +20 -0
  22. data/lib/fog/openstack/models/identity_v2/ec2_credential.rb +45 -0
  23. data/lib/fog/openstack/models/identity_v2/ec2_credentials.rb +55 -0
  24. data/lib/fog/openstack/models/identity_v2/role.rb +52 -0
  25. data/lib/fog/openstack/models/identity_v2/roles.rb +22 -0
  26. data/lib/fog/openstack/models/identity_v2/tenant.rb +64 -0
  27. data/lib/fog/openstack/models/identity_v2/tenants.rb +31 -0
  28. data/lib/fog/openstack/models/identity_v2/user.rb +71 -0
  29. data/lib/fog/openstack/models/identity_v2/users.rb +43 -0
  30. data/lib/fog/openstack/models/identity_v3/domain.rb +47 -0
  31. data/lib/fog/openstack/models/identity_v3/domains.rb +36 -0
  32. data/lib/fog/openstack/models/identity_v3/endpoint.rb +50 -0
  33. data/lib/fog/openstack/models/identity_v3/endpoints.rb +27 -0
  34. data/lib/fog/openstack/models/identity_v3/group.rb +96 -0
  35. data/lib/fog/openstack/models/identity_v3/groups.rb +31 -0
  36. data/lib/fog/openstack/models/identity_v3/os_credential.rb +73 -0
  37. data/lib/fog/openstack/models/identity_v3/os_credentials.rb +31 -0
  38. data/lib/fog/openstack/models/identity_v3/policies.rb +31 -0
  39. data/lib/fog/openstack/models/identity_v3/policy.rb +46 -0
  40. data/lib/fog/openstack/models/identity_v3/project.rb +98 -0
  41. data/lib/fog/openstack/models/identity_v3/projects.rb +31 -0
  42. data/lib/fog/openstack/models/identity_v3/role.rb +45 -0
  43. data/lib/fog/openstack/models/identity_v3/role_assignment.rb +22 -0
  44. data/lib/fog/openstack/models/identity_v3/role_assignments.rb +22 -0
  45. data/lib/fog/openstack/models/identity_v3/roles.rb +35 -0
  46. data/lib/fog/openstack/models/identity_v3/service.rb +47 -0
  47. data/lib/fog/openstack/models/identity_v3/services.rb +31 -0
  48. data/lib/fog/openstack/models/identity_v3/token.rb +26 -0
  49. data/lib/fog/openstack/models/identity_v3/tokens.rb +40 -0
  50. data/lib/fog/openstack/models/identity_v3/user.rb +87 -0
  51. data/lib/fog/openstack/models/identity_v3/users.rb +35 -0
  52. data/lib/fog/openstack/network.rb +2 -9
  53. data/lib/fog/openstack/orchestration.rb +1 -6
  54. data/lib/fog/openstack/planning.rb +1 -1
  55. data/lib/fog/openstack/requests/baremetal/set_node_maintenance.rb +36 -0
  56. data/lib/fog/openstack/requests/baremetal/set_node_power_state.rb +35 -0
  57. data/lib/fog/openstack/requests/baremetal/set_node_provision_state.rb +38 -0
  58. data/lib/fog/openstack/requests/baremetal/unset_node_maintenance.rb +36 -0
  59. data/lib/fog/openstack/requests/compute/create_flavor_metadata.rb +38 -0
  60. data/lib/fog/openstack/requests/compute/create_security_group.rb +1 -1
  61. data/lib/fog/openstack/requests/compute/delete_service.rb +32 -0
  62. data/lib/fog/openstack/requests/compute/disable_service.rb +37 -0
  63. data/lib/fog/openstack/requests/compute/disable_service_log_reason.rb +38 -0
  64. data/lib/fog/openstack/requests/compute/enable_service.rb +38 -0
  65. data/lib/fog/openstack/requests/compute/get_flavor_metadata.rb +27 -0
  66. data/lib/fog/openstack/requests/compute/list_services.rb +72 -0
  67. data/lib/fog/openstack/requests/compute/list_tenants_with_flavor_access.rb +1 -1
  68. data/lib/fog/openstack/requests/compute/list_zones.rb +32 -0
  69. data/lib/fog/openstack/requests/identity_v2/add_user_to_tenant.rb +36 -0
  70. data/lib/fog/openstack/requests/identity_v2/check_token.rb +22 -0
  71. data/lib/fog/openstack/requests/identity_v2/create_ec2_credential.rb +59 -0
  72. data/lib/fog/openstack/requests/identity_v2/create_role.rb +38 -0
  73. data/lib/fog/openstack/requests/identity_v2/create_tenant.rb +34 -0
  74. data/lib/fog/openstack/requests/identity_v2/create_user.rb +45 -0
  75. data/lib/fog/openstack/requests/identity_v2/create_user_role.rb +26 -0
  76. data/lib/fog/openstack/requests/identity_v2/delete_ec2_credential.rb +43 -0
  77. data/lib/fog/openstack/requests/identity_v2/delete_role.rb +30 -0
  78. data/lib/fog/openstack/requests/identity_v2/delete_tenant.rb +33 -0
  79. data/lib/fog/openstack/requests/identity_v2/delete_user.rb +30 -0
  80. data/lib/fog/openstack/requests/identity_v2/delete_user_role.rb +25 -0
  81. data/lib/fog/openstack/requests/identity_v2/get_ec2_credential.rb +50 -0
  82. data/lib/fog/openstack/requests/identity_v2/get_role.rb +30 -0
  83. data/lib/fog/openstack/requests/identity_v2/get_tenant.rb +33 -0
  84. data/lib/fog/openstack/requests/identity_v2/get_tenants_by_id.rb +20 -0
  85. data/lib/fog/openstack/requests/identity_v2/get_tenants_by_name.rb +20 -0
  86. data/lib/fog/openstack/requests/identity_v2/get_user_by_id.rb +34 -0
  87. data/lib/fog/openstack/requests/identity_v2/get_user_by_name.rb +29 -0
  88. data/lib/fog/openstack/requests/identity_v2/list_ec2_credentials.rb +45 -0
  89. data/lib/fog/openstack/requests/identity_v2/list_endpoints_for_token.rb +20 -0
  90. data/lib/fog/openstack/requests/identity_v2/list_roles.rb +33 -0
  91. data/lib/fog/openstack/requests/identity_v2/list_roles_for_user_on_tenant.rb +32 -0
  92. data/lib/fog/openstack/requests/identity_v2/list_tenants.rb +47 -0
  93. data/lib/fog/openstack/requests/identity_v2/list_user_global_roles.rb +20 -0
  94. data/lib/fog/openstack/requests/identity_v2/list_users.rb +35 -0
  95. data/lib/fog/openstack/requests/identity_v2/remove_user_from_tenant.rb +22 -0
  96. data/lib/fog/openstack/requests/identity_v2/set_tenant.rb +21 -0
  97. data/lib/fog/openstack/requests/identity_v2/update_tenant.rb +30 -0
  98. data/lib/fog/openstack/requests/identity_v2/update_user.rb +34 -0
  99. data/lib/fog/openstack/requests/identity_v2/validate_token.rb +22 -0
  100. data/lib/fog/openstack/requests/identity_v3/add_user_to_group.rb +20 -0
  101. data/lib/fog/openstack/requests/identity_v3/auth_domains.rb +29 -0
  102. data/lib/fog/openstack/requests/identity_v3/auth_projects.rb +29 -0
  103. data/lib/fog/openstack/requests/identity_v3/check_domain_group_role.rb +20 -0
  104. data/lib/fog/openstack/requests/identity_v3/check_domain_user_role.rb +20 -0
  105. data/lib/fog/openstack/requests/identity_v3/check_project_group_role.rb +20 -0
  106. data/lib/fog/openstack/requests/identity_v3/check_project_user_role.rb +20 -0
  107. data/lib/fog/openstack/requests/identity_v3/create_domain.rb +21 -0
  108. data/lib/fog/openstack/requests/identity_v3/create_endpoint.rb +21 -0
  109. data/lib/fog/openstack/requests/identity_v3/create_group.rb +21 -0
  110. data/lib/fog/openstack/requests/identity_v3/create_os_credential.rb +21 -0
  111. data/lib/fog/openstack/requests/identity_v3/create_policy.rb +21 -0
  112. data/lib/fog/openstack/requests/identity_v3/create_project.rb +21 -0
  113. data/lib/fog/openstack/requests/identity_v3/create_role.rb +21 -0
  114. data/lib/fog/openstack/requests/identity_v3/create_service.rb +21 -0
  115. data/lib/fog/openstack/requests/identity_v3/create_user.rb +21 -0
  116. data/lib/fog/openstack/requests/identity_v3/delete_domain.rb +20 -0
  117. data/lib/fog/openstack/requests/identity_v3/delete_endpoint.rb +20 -0
  118. data/lib/fog/openstack/requests/identity_v3/delete_group.rb +20 -0
  119. data/lib/fog/openstack/requests/identity_v3/delete_os_credential.rb +20 -0
  120. data/lib/fog/openstack/requests/identity_v3/delete_policy.rb +20 -0
  121. data/lib/fog/openstack/requests/identity_v3/delete_project.rb +20 -0
  122. data/lib/fog/openstack/requests/identity_v3/delete_role.rb +20 -0
  123. data/lib/fog/openstack/requests/identity_v3/delete_service.rb +20 -0
  124. data/lib/fog/openstack/requests/identity_v3/delete_user.rb +20 -0
  125. data/lib/fog/openstack/requests/identity_v3/get_domain.rb +23 -0
  126. data/lib/fog/openstack/requests/identity_v3/get_endpoint.rb +23 -0
  127. data/lib/fog/openstack/requests/identity_v3/get_group.rb +23 -0
  128. data/lib/fog/openstack/requests/identity_v3/get_os_credential.rb +23 -0
  129. data/lib/fog/openstack/requests/identity_v3/get_policy.rb +23 -0
  130. data/lib/fog/openstack/requests/identity_v3/get_project.rb +23 -0
  131. data/lib/fog/openstack/requests/identity_v3/get_role.rb +23 -0
  132. data/lib/fog/openstack/requests/identity_v3/get_service.rb +23 -0
  133. data/lib/fog/openstack/requests/identity_v3/get_user.rb +23 -0
  134. data/lib/fog/openstack/requests/identity_v3/grant_domain_group_role.rb +20 -0
  135. data/lib/fog/openstack/requests/identity_v3/grant_domain_user_role.rb +20 -0
  136. data/lib/fog/openstack/requests/identity_v3/grant_project_group_role.rb +20 -0
  137. data/lib/fog/openstack/requests/identity_v3/grant_project_user_role.rb +20 -0
  138. data/lib/fog/openstack/requests/identity_v3/group_user_check.rb +20 -0
  139. data/lib/fog/openstack/requests/identity_v3/list_domain_group_roles.rb +23 -0
  140. data/lib/fog/openstack/requests/identity_v3/list_domain_user_roles.rb +23 -0
  141. data/lib/fog/openstack/requests/identity_v3/list_domains.rb +31 -0
  142. data/lib/fog/openstack/requests/identity_v3/list_endpoints.rb +31 -0
  143. data/lib/fog/openstack/requests/identity_v3/list_group_users.rb +32 -0
  144. data/lib/fog/openstack/requests/identity_v3/list_groups.rb +42 -0
  145. data/lib/fog/openstack/requests/identity_v3/list_os_credentials.rb +29 -0
  146. data/lib/fog/openstack/requests/identity_v3/list_policies.rb +28 -0
  147. data/lib/fog/openstack/requests/identity_v3/list_project_group_roles.rb +23 -0
  148. data/lib/fog/openstack/requests/identity_v3/list_project_user_roles.rb +23 -0
  149. data/lib/fog/openstack/requests/identity_v3/list_projects.rb +42 -0
  150. data/lib/fog/openstack/requests/identity_v3/list_role_assignments.rb +35 -0
  151. data/lib/fog/openstack/requests/identity_v3/list_roles.rb +42 -0
  152. data/lib/fog/openstack/requests/identity_v3/list_services.rb +30 -0
  153. data/lib/fog/openstack/requests/identity_v3/list_user_groups.rb +23 -0
  154. data/lib/fog/openstack/requests/identity_v3/list_user_projects.rb +23 -0
  155. data/lib/fog/openstack/requests/identity_v3/list_users.rb +32 -0
  156. data/lib/fog/openstack/requests/identity_v3/remove_user_from_group.rb +20 -0
  157. data/lib/fog/openstack/requests/identity_v3/revoke_domain_group_role.rb +20 -0
  158. data/lib/fog/openstack/requests/identity_v3/revoke_domain_user_role.rb +20 -0
  159. data/lib/fog/openstack/requests/identity_v3/revoke_project_group_role.rb +20 -0
  160. data/lib/fog/openstack/requests/identity_v3/revoke_project_user_role.rb +20 -0
  161. data/lib/fog/openstack/requests/identity_v3/token_authenticate.rb +21 -0
  162. data/lib/fog/openstack/requests/identity_v3/token_check.rb +21 -0
  163. data/lib/fog/openstack/requests/identity_v3/token_revoke.rb +21 -0
  164. data/lib/fog/openstack/requests/identity_v3/token_validate.rb +22 -0
  165. data/lib/fog/openstack/requests/identity_v3/update_domain.rb +21 -0
  166. data/lib/fog/openstack/requests/identity_v3/update_endpoint.rb +21 -0
  167. data/lib/fog/openstack/requests/identity_v3/update_group.rb +21 -0
  168. data/lib/fog/openstack/requests/identity_v3/update_os_credential.rb +21 -0
  169. data/lib/fog/openstack/requests/identity_v3/update_policy.rb +21 -0
  170. data/lib/fog/openstack/requests/identity_v3/update_project.rb +21 -0
  171. data/lib/fog/openstack/requests/identity_v3/update_role.rb +21 -0
  172. data/lib/fog/openstack/requests/identity_v3/update_service.rb +21 -0
  173. data/lib/fog/openstack/requests/identity_v3/update_user.rb +21 -0
  174. data/lib/fog/openstack/requests/image/list_public_images_detailed.rb +1 -1
  175. data/lib/fog/openstack/volume.rb +1 -1
  176. data/lib/fog/version.rb +1 -1
  177. data/lib/fog/vsphere/requests/compute/cloudinit_to_customspec.rb +27 -8
  178. data/lib/fog/vsphere/requests/compute/vm_clone.rb +376 -37
  179. data/lib/tasks/changelog_task.rb +1 -1
  180. data/spec/fog/openstack/identity_v3/authv3_a.yml +61 -0
  181. data/spec/fog/openstack/identity_v3/authv3_b.yml +61 -0
  182. data/spec/fog/openstack/identity_v3/authv3_c.yml +61 -0
  183. data/spec/fog/openstack/identity_v3/authv3_project.yml +61 -0
  184. data/spec/fog/openstack/identity_v3/authv3_token.yml +151 -0
  185. data/spec/fog/openstack/identity_v3/authv3_unscoped.yml +334 -0
  186. data/spec/fog/openstack/identity_v3/idv2_unscoped_token_v3.yml +467 -0
  187. data/spec/fog/openstack/identity_v3/idv3.yml +61 -0
  188. data/spec/fog/openstack/identity_v3/idv3_credential.yml +111 -0
  189. data/spec/fog/openstack/identity_v3/idv3_credential_crud.yml +528 -0
  190. data/spec/fog/openstack/identity_v3/idv3_domain.yml +195 -0
  191. data/spec/fog/openstack/identity_v3/idv3_domain_crud.yml +686 -0
  192. data/spec/fog/openstack/identity_v3/idv3_domain_group_roles_mutation.yml +906 -0
  193. data/spec/fog/openstack/identity_v3/idv3_domain_roles_mutation.yml +505 -0
  194. data/spec/fog/openstack/identity_v3/idv3_endpoint.yml +303 -0
  195. data/spec/fog/openstack/identity_v3/idv3_endpoints_crud.yml +718 -0
  196. data/spec/fog/openstack/identity_v3/idv3_group_crud_mutation.yml +975 -0
  197. data/spec/fog/openstack/identity_v3/idv3_policy.yml +147 -0
  198. data/spec/fog/openstack/identity_v3/idv3_policy_crud.yml +368 -0
  199. data/spec/fog/openstack/identity_v3/idv3_project.yml +211 -0
  200. data/spec/fog/openstack/identity_v3/idv3_project_crud.yml +663 -0
  201. data/spec/fog/openstack/identity_v3/idv3_project_group_user_roles_mutation.yml +1378 -0
  202. data/spec/fog/openstack/identity_v3/idv3_role.yml +199 -0
  203. data/spec/fog/openstack/identity_v3/idv3_role_crud.yml +616 -0
  204. data/spec/fog/openstack/identity_v3/idv3_service.yml +223 -0
  205. data/spec/fog/openstack/identity_v3/idv3_services_crud.yml +562 -0
  206. data/spec/fog/openstack/identity_v3/idv3_token.yml +240 -0
  207. data/spec/fog/openstack/identity_v3/idv3_user_crud.yml +572 -0
  208. data/spec/fog/openstack/identity_v3/idv3_users.yml +393 -0
  209. data/spec/fog/openstack/identity_v3_spec.rb +929 -0
  210. data/tests/openstack/requests/baremetal/node_tests.rb +18 -0
  211. data/tests/openstack/requests/compute/flavor_tests.rb +18 -0
  212. data/tests/openstack/requests/compute/service_tests.rb +33 -0
  213. metadata +259 -49
  214. data/lib/fog/openstack/models/identity/ec2_credential.rb +0 -44
  215. data/lib/fog/openstack/models/identity/ec2_credentials.rb +0 -53
  216. data/lib/fog/openstack/models/identity/role.rb +0 -50
  217. data/lib/fog/openstack/models/identity/roles.rb +0 -20
  218. data/lib/fog/openstack/models/identity/tenant.rb +0 -62
  219. data/lib/fog/openstack/models/identity/tenants.rb +0 -29
  220. data/lib/fog/openstack/models/identity/user.rb +0 -69
  221. data/lib/fog/openstack/models/identity/users.rb +0 -41
  222. data/lib/fog/openstack/requests/identity/add_user_to_tenant.rb +0 -34
  223. data/lib/fog/openstack/requests/identity/check_token.rb +0 -20
  224. data/lib/fog/openstack/requests/identity/create_ec2_credential.rb +0 -57
  225. data/lib/fog/openstack/requests/identity/create_role.rb +0 -36
  226. data/lib/fog/openstack/requests/identity/create_tenant.rb +0 -32
  227. data/lib/fog/openstack/requests/identity/create_user.rb +0 -43
  228. data/lib/fog/openstack/requests/identity/create_user_role.rb +0 -24
  229. data/lib/fog/openstack/requests/identity/delete_ec2_credential.rb +0 -42
  230. data/lib/fog/openstack/requests/identity/delete_role.rb +0 -28
  231. data/lib/fog/openstack/requests/identity/delete_tenant.rb +0 -31
  232. data/lib/fog/openstack/requests/identity/delete_user.rb +0 -28
  233. data/lib/fog/openstack/requests/identity/delete_user_role.rb +0 -23
  234. data/lib/fog/openstack/requests/identity/get_ec2_credential.rb +0 -48
  235. data/lib/fog/openstack/requests/identity/get_role.rb +0 -28
  236. data/lib/fog/openstack/requests/identity/get_tenant.rb +0 -31
  237. data/lib/fog/openstack/requests/identity/get_tenants_by_id.rb +0 -18
  238. data/lib/fog/openstack/requests/identity/get_tenants_by_name.rb +0 -18
  239. data/lib/fog/openstack/requests/identity/get_user_by_id.rb +0 -32
  240. data/lib/fog/openstack/requests/identity/get_user_by_name.rb +0 -27
  241. data/lib/fog/openstack/requests/identity/list_ec2_credentials.rb +0 -43
  242. data/lib/fog/openstack/requests/identity/list_endpoints_for_token.rb +0 -18
  243. data/lib/fog/openstack/requests/identity/list_roles.rb +0 -31
  244. data/lib/fog/openstack/requests/identity/list_roles_for_user_on_tenant.rb +0 -30
  245. data/lib/fog/openstack/requests/identity/list_tenants.rb +0 -45
  246. data/lib/fog/openstack/requests/identity/list_user_global_roles.rb +0 -18
  247. data/lib/fog/openstack/requests/identity/list_users.rb +0 -33
  248. data/lib/fog/openstack/requests/identity/remove_user_from_tenant.rb +0 -20
  249. data/lib/fog/openstack/requests/identity/set_tenant.rb +0 -19
  250. data/lib/fog/openstack/requests/identity/update_tenant.rb +0 -28
  251. data/lib/fog/openstack/requests/identity/update_user.rb +0 -32
  252. data/lib/fog/openstack/requests/identity/validate_token.rb +0 -20
@@ -0,0 +1,393 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://devstack.openstack.stack:35357/v3/users?page=1&per_page=30
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - fog/1.28.0 fog-core/1.29.0
12
+ Content-Type:
13
+ - application/json
14
+ Accept:
15
+ - application/json
16
+ X-Auth-Token:
17
+ - d8291e2a2a2046259316f7c2d4253e92
18
+ response:
19
+ status:
20
+ code: 401
21
+ message: ''
22
+ headers:
23
+ Www-Authenticate:
24
+ - Keystone uri="http://devstack.openstack.stack:35357"
25
+ Vary:
26
+ - X-Auth-Token
27
+ X-Distribution:
28
+ - Ubuntu
29
+ Content-Type:
30
+ - application/json
31
+ Content-Length:
32
+ - '114'
33
+ Date:
34
+ - Mon, 23 Mar 2015 09:25:21 GMT
35
+ body:
36
+ encoding: US-ASCII
37
+ string: ! '{"error": {"message": "The request you have made requires authentication.",
38
+ "code": 401, "title": "Unauthorized"}}'
39
+ http_version:
40
+ recorded_at: Mon, 23 Mar 2015 09:25:21 GMT
41
+ - request:
42
+ method: post
43
+ uri: http://devstack.openstack.stack:5000/v3/auth/tokens
44
+ body:
45
+ encoding: UTF-8
46
+ string: ! '{"auth":{"identity":{"methods":["password"],"password":{"user":{"password":"openstack","id":"8d5732a0ebd9485396351d74e24c9647"}}},"scope":{"project":{"name":"admin","domain":{"id":"default"}}}}}'
47
+ headers:
48
+ User-Agent:
49
+ - fog/1.28.0 fog-core/1.29.0
50
+ Content-Type:
51
+ - application/json
52
+ response:
53
+ status:
54
+ code: 201
55
+ message: ''
56
+ headers:
57
+ X-Subject-Token:
58
+ - d448367868f7446696b876c5fb251fa4
59
+ Vary:
60
+ - X-Auth-Token
61
+ X-Distribution:
62
+ - Ubuntu
63
+ Content-Type:
64
+ - application/json
65
+ Content-Length:
66
+ - '2254'
67
+ Date:
68
+ - Mon, 23 Mar 2015 09:25:21 GMT
69
+ body:
70
+ encoding: US-ASCII
71
+ string: ! '{"token": {"methods": ["password"], "roles": [{"id": "7ebef8a2837246eda8f83f96ffb82b2f",
72
+ "name": "admin"}], "expires_at": "2015-03-23T10:25:21.353957Z", "project":
73
+ {"domain": {"id": "default", "name": "Default"}, "id": "c7767afa57b74f33863a420daba5f57f",
74
+ "name": "admin"}, "catalog": [{"endpoints": [{"url": "http://devstack.openstack.stack:35357/v2.0",
75
+ "region": "europe", "interface": "public", "id": "0b4b1e907e184880a1c3f32f00cd676f"},
76
+ {"url": "http://devstack.openstack.stack:35357/v2.0", "region": "europe",
77
+ "interface": "admin", "id": "53d872f1c5d04f35ac69509e41600c0b"}, {"url": "http://devstack.openstack.stack:35357/v2.0",
78
+ "region": "europe", "interface": "internal", "id": "67aa3eedc510444faadb9ef3c7e8b2e4"}],
79
+ "type": "identity", "id": "8e53f1d389df4059aeab1acfece2fc66", "name": "keystone"},
80
+ {"endpoints": [{"url": "http://devstack.openstack.stack:35357/v3", "region":
81
+ "europe", "interface": "internal", "id": "7002cfd6dbe74512b0b817d3b7380abb"},
82
+ {"url": "http://devstack.openstack.stack:35357/v3", "region": "europe", "interface":
83
+ "public", "id": "a7c634aa7f034284b62ddf974ddc04eb"}, {"url": "http://devstack.openstack.stack:35357/v3",
84
+ "region": "europe", "interface": "admin", "id": "cba56e3e7a9c4ddfb39e1e4053bd04ab"}],
85
+ "type": "identity_v3", "id": "a47e0f0014fa409993cef0bd984a5ac6", "name": "identity_v3"},
86
+ {"endpoints": [{"url": "http://localhost/testurl/c7767afa57b74f33863a420daba5f57f",
87
+ "region": "europe", "interface": "public", "id": "3387dfbf7bc440728e7aa1488f6ca96e"}],
88
+ "type": "test_stefan", "id": "d36a1f72832b428688b7dae7d0ab8a39", "name": "test_stefan"},
89
+ {"endpoints": [{"url": "http://devstack.openstack.stack:9292", "region": "europe",
90
+ "interface": "public", "id": "0dabc688a031422381d3c92b7dfdfe4c"}, {"url":
91
+ "http://devstack.openstack.stack:9292", "region": "europe", "interface": "admin",
92
+ "id": "768f3eb8b29d49a19c4d50a85541d42e"}, {"url": "http://devstack.openstack.stack:9292",
93
+ "region": "europe", "interface": "internal", "id": "a0c5556c80e448aca907a3ee785bd602"}],
94
+ "type": "image", "id": "ee073ec39e804cca96d2440d8f109932", "name": "glance"}],
95
+ "extras": {}, "user": {"domain": {"id": "default", "name": "Default"}, "id":
96
+ "8d5732a0ebd9485396351d74e24c9647", "name": "admin"}, "issued_at": "2015-03-23T09:25:21.354000Z"}}'
97
+ http_version:
98
+ recorded_at: Mon, 23 Mar 2015 09:25:21 GMT
99
+ - request:
100
+ method: get
101
+ uri: http://devstack.openstack.stack:35357/v3/users?page=1&per_page=30
102
+ body:
103
+ encoding: US-ASCII
104
+ string: ''
105
+ headers:
106
+ User-Agent:
107
+ - fog/1.28.0 fog-core/1.29.0
108
+ Content-Type:
109
+ - application/json
110
+ Accept:
111
+ - application/json
112
+ X-Auth-Token:
113
+ - d448367868f7446696b876c5fb251fa4
114
+ response:
115
+ status:
116
+ code: 200
117
+ message: ''
118
+ headers:
119
+ Vary:
120
+ - X-Auth-Token
121
+ X-Distribution:
122
+ - Ubuntu
123
+ Content-Type:
124
+ - application/json
125
+ Content-Length:
126
+ - '1094'
127
+ Date:
128
+ - Mon, 23 Mar 2015 09:25:21 GMT
129
+ body:
130
+ encoding: US-ASCII
131
+ string: ! '{"users": [{"name": "glance", "links": {"self": "http://devstack.openstack.stack:35357/v3/users/3c5a9e9790614a60b5c19712d8e97c6d"},
132
+ "domain_id": "default", "enabled": true, "email": null, "id": "3c5a9e9790614a60b5c19712d8e97c6d"},
133
+ {"name": "u-foobar", "links": {"self": "http://devstack.openstack.stack:35357/v3/users/660d8086a1db41078c0d64fa568db135"},
134
+ "domain_id": "default", "enabled": true, "email": "foobar@example.com", "id":
135
+ "660d8086a1db41078c0d64fa568db135"}, {"name": "admin", "links": {"self": "http://devstack.openstack.stack:35357/v3/users/8d5732a0ebd9485396351d74e24c9647"},
136
+ "domain_id": "default", "enabled": true, "email": "andrew@batty.com", "id":
137
+ "8d5732a0ebd9485396351d74e24c9647"}, {"domain_id": "default", "name": "demo",
138
+ "links": {"self": "http://devstack.openstack.stack:35357/v3/users/ac33746004f1470b904e364d408cf42e"},
139
+ "id": "ac33746004f1470b904e364d408cf42e", "enabled": true, "email": "andrew@battye.com",
140
+ "default_project_id": "c9f75b1200f64bf09ed079206a1a1b75"}], "links": {"self":
141
+ "http://devstack.openstack.stack:35357/v3/users", "previous": null, "next":
142
+ null}}'
143
+ http_version:
144
+ recorded_at: Mon, 23 Mar 2015 09:25:21 GMT
145
+ - request:
146
+ method: get
147
+ uri: http://devstack.openstack.stack:35357/v3/users?page=1&per_page=30
148
+ body:
149
+ encoding: US-ASCII
150
+ string: ''
151
+ headers:
152
+ User-Agent:
153
+ - fog/1.28.0 fog-core/1.29.0
154
+ Content-Type:
155
+ - application/json
156
+ Accept:
157
+ - application/json
158
+ X-Auth-Token:
159
+ - d448367868f7446696b876c5fb251fa4
160
+ response:
161
+ status:
162
+ code: 200
163
+ message: ''
164
+ headers:
165
+ Vary:
166
+ - X-Auth-Token
167
+ X-Distribution:
168
+ - Ubuntu
169
+ Content-Type:
170
+ - application/json
171
+ Content-Length:
172
+ - '1094'
173
+ Date:
174
+ - Mon, 23 Mar 2015 09:25:21 GMT
175
+ body:
176
+ encoding: US-ASCII
177
+ string: ! '{"users": [{"name": "glance", "links": {"self": "http://devstack.openstack.stack:35357/v3/users/3c5a9e9790614a60b5c19712d8e97c6d"},
178
+ "domain_id": "default", "enabled": true, "email": null, "id": "3c5a9e9790614a60b5c19712d8e97c6d"},
179
+ {"name": "u-foobar", "links": {"self": "http://devstack.openstack.stack:35357/v3/users/660d8086a1db41078c0d64fa568db135"},
180
+ "domain_id": "default", "enabled": true, "email": "foobar@example.com", "id":
181
+ "660d8086a1db41078c0d64fa568db135"}, {"name": "admin", "links": {"self": "http://devstack.openstack.stack:35357/v3/users/8d5732a0ebd9485396351d74e24c9647"},
182
+ "domain_id": "default", "enabled": true, "email": "andrew@batty.com", "id":
183
+ "8d5732a0ebd9485396351d74e24c9647"}, {"domain_id": "default", "name": "demo",
184
+ "links": {"self": "http://devstack.openstack.stack:35357/v3/users/ac33746004f1470b904e364d408cf42e"},
185
+ "id": "ac33746004f1470b904e364d408cf42e", "enabled": true, "email": "andrew@battye.com",
186
+ "default_project_id": "c9f75b1200f64bf09ed079206a1a1b75"}], "links": {"self":
187
+ "http://devstack.openstack.stack:35357/v3/users", "previous": null, "next":
188
+ null}}'
189
+ http_version:
190
+ recorded_at: Mon, 23 Mar 2015 09:25:21 GMT
191
+ - request:
192
+ method: get
193
+ uri: http://devstack.openstack.stack:35357/v3/users/u-random-blah
194
+ body:
195
+ encoding: US-ASCII
196
+ string: ''
197
+ headers:
198
+ User-Agent:
199
+ - fog/1.28.0 fog-core/1.29.0
200
+ Content-Type:
201
+ - application/json
202
+ Accept:
203
+ - application/json
204
+ X-Auth-Token:
205
+ - d448367868f7446696b876c5fb251fa4
206
+ response:
207
+ status:
208
+ code: 404
209
+ message: ''
210
+ headers:
211
+ Vary:
212
+ - X-Auth-Token
213
+ X-Distribution:
214
+ - Ubuntu
215
+ Content-Type:
216
+ - application/json
217
+ Content-Length:
218
+ - '96'
219
+ Date:
220
+ - Mon, 23 Mar 2015 09:25:21 GMT
221
+ body:
222
+ encoding: US-ASCII
223
+ string: ! '{"error": {"message": "Could not find user, u-random-blah.", "code":
224
+ 404, "title": "Not Found"}}'
225
+ http_version:
226
+ recorded_at: Mon, 23 Mar 2015 09:25:21 GMT
227
+ - request:
228
+ method: get
229
+ uri: http://devstack.openstack.stack:35357/v3/users?page=1&per_page=30
230
+ body:
231
+ encoding: US-ASCII
232
+ string: ''
233
+ headers:
234
+ User-Agent:
235
+ - fog/1.28.0 fog-core/1.29.0
236
+ Content-Type:
237
+ - application/json
238
+ Accept:
239
+ - application/json
240
+ X-Auth-Token:
241
+ - d448367868f7446696b876c5fb251fa4
242
+ response:
243
+ status:
244
+ code: 200
245
+ message: ''
246
+ headers:
247
+ Vary:
248
+ - X-Auth-Token
249
+ X-Distribution:
250
+ - Ubuntu
251
+ Content-Type:
252
+ - application/json
253
+ Content-Length:
254
+ - '1094'
255
+ Date:
256
+ - Mon, 23 Mar 2015 09:25:22 GMT
257
+ body:
258
+ encoding: US-ASCII
259
+ string: ! '{"users": [{"name": "glance", "links": {"self": "http://devstack.openstack.stack:35357/v3/users/3c5a9e9790614a60b5c19712d8e97c6d"},
260
+ "domain_id": "default", "enabled": true, "email": null, "id": "3c5a9e9790614a60b5c19712d8e97c6d"},
261
+ {"name": "u-foobar", "links": {"self": "http://devstack.openstack.stack:35357/v3/users/660d8086a1db41078c0d64fa568db135"},
262
+ "domain_id": "default", "enabled": true, "email": "foobar@example.com", "id":
263
+ "660d8086a1db41078c0d64fa568db135"}, {"name": "admin", "links": {"self": "http://devstack.openstack.stack:35357/v3/users/8d5732a0ebd9485396351d74e24c9647"},
264
+ "domain_id": "default", "enabled": true, "email": "andrew@batty.com", "id":
265
+ "8d5732a0ebd9485396351d74e24c9647"}, {"domain_id": "default", "name": "demo",
266
+ "links": {"self": "http://devstack.openstack.stack:35357/v3/users/ac33746004f1470b904e364d408cf42e"},
267
+ "id": "ac33746004f1470b904e364d408cf42e", "enabled": true, "email": "andrew@battye.com",
268
+ "default_project_id": "c9f75b1200f64bf09ed079206a1a1b75"}], "links": {"self":
269
+ "http://devstack.openstack.stack:35357/v3/users", "previous": null, "next":
270
+ null}}'
271
+ http_version:
272
+ recorded_at: Mon, 23 Mar 2015 09:25:22 GMT
273
+ - request:
274
+ method: get
275
+ uri: http://devstack.openstack.stack:35357/v3/users?page=1&per_page=30
276
+ body:
277
+ encoding: US-ASCII
278
+ string: ''
279
+ headers:
280
+ User-Agent:
281
+ - fog/1.28.0 fog-core/1.29.0
282
+ Content-Type:
283
+ - application/json
284
+ Accept:
285
+ - application/json
286
+ X-Auth-Token:
287
+ - d448367868f7446696b876c5fb251fa4
288
+ response:
289
+ status:
290
+ code: 200
291
+ message: ''
292
+ headers:
293
+ Vary:
294
+ - X-Auth-Token
295
+ X-Distribution:
296
+ - Ubuntu
297
+ Content-Type:
298
+ - application/json
299
+ Content-Length:
300
+ - '1094'
301
+ Date:
302
+ - Mon, 23 Mar 2015 09:25:22 GMT
303
+ body:
304
+ encoding: US-ASCII
305
+ string: ! '{"users": [{"name": "glance", "links": {"self": "http://devstack.openstack.stack:35357/v3/users/3c5a9e9790614a60b5c19712d8e97c6d"},
306
+ "domain_id": "default", "enabled": true, "email": null, "id": "3c5a9e9790614a60b5c19712d8e97c6d"},
307
+ {"name": "u-foobar", "links": {"self": "http://devstack.openstack.stack:35357/v3/users/660d8086a1db41078c0d64fa568db135"},
308
+ "domain_id": "default", "enabled": true, "email": "foobar@example.com", "id":
309
+ "660d8086a1db41078c0d64fa568db135"}, {"name": "admin", "links": {"self": "http://devstack.openstack.stack:35357/v3/users/8d5732a0ebd9485396351d74e24c9647"},
310
+ "domain_id": "default", "enabled": true, "email": "andrew@batty.com", "id":
311
+ "8d5732a0ebd9485396351d74e24c9647"}, {"domain_id": "default", "name": "demo",
312
+ "links": {"self": "http://devstack.openstack.stack:35357/v3/users/ac33746004f1470b904e364d408cf42e"},
313
+ "id": "ac33746004f1470b904e364d408cf42e", "enabled": true, "email": "andrew@battye.com",
314
+ "default_project_id": "c9f75b1200f64bf09ed079206a1a1b75"}], "links": {"self":
315
+ "http://devstack.openstack.stack:35357/v3/users", "previous": null, "next":
316
+ null}}'
317
+ http_version:
318
+ recorded_at: Mon, 23 Mar 2015 09:25:22 GMT
319
+ - request:
320
+ method: get
321
+ uri: http://devstack.openstack.stack:35357/v3/users?name=admin&page=1&per_page=30
322
+ body:
323
+ encoding: US-ASCII
324
+ string: ''
325
+ headers:
326
+ User-Agent:
327
+ - fog/1.28.0 fog-core/1.29.0
328
+ Content-Type:
329
+ - application/json
330
+ Accept:
331
+ - application/json
332
+ X-Auth-Token:
333
+ - d448367868f7446696b876c5fb251fa4
334
+ response:
335
+ status:
336
+ code: 200
337
+ message: ''
338
+ headers:
339
+ Vary:
340
+ - X-Auth-Token
341
+ X-Distribution:
342
+ - Ubuntu
343
+ Content-Type:
344
+ - application/json
345
+ Content-Length:
346
+ - '345'
347
+ Date:
348
+ - Mon, 23 Mar 2015 09:25:22 GMT
349
+ body:
350
+ encoding: US-ASCII
351
+ string: ! '{"users": [{"name": "admin", "links": {"self": "http://devstack.openstack.stack:35357/v3/users/8d5732a0ebd9485396351d74e24c9647"},
352
+ "domain_id": "default", "enabled": true, "email": "andrew@batty.com", "id":
353
+ "8d5732a0ebd9485396351d74e24c9647"}], "links": {"self": "http://devstack.openstack.stack:35357/v3/users",
354
+ "previous": null, "next": null}}'
355
+ http_version:
356
+ recorded_at: Mon, 23 Mar 2015 09:25:22 GMT
357
+ - request:
358
+ method: get
359
+ uri: http://devstack.openstack.stack:35357/v3/users?name=pimpernel&page=1&per_page=30
360
+ body:
361
+ encoding: US-ASCII
362
+ string: ''
363
+ headers:
364
+ User-Agent:
365
+ - fog/1.28.0 fog-core/1.29.0
366
+ Content-Type:
367
+ - application/json
368
+ Accept:
369
+ - application/json
370
+ X-Auth-Token:
371
+ - d448367868f7446696b876c5fb251fa4
372
+ response:
373
+ status:
374
+ code: 200
375
+ message: ''
376
+ headers:
377
+ Vary:
378
+ - X-Auth-Token
379
+ X-Distribution:
380
+ - Ubuntu
381
+ Content-Type:
382
+ - application/json
383
+ Content-Length:
384
+ - '114'
385
+ Date:
386
+ - Mon, 23 Mar 2015 09:25:22 GMT
387
+ body:
388
+ encoding: US-ASCII
389
+ string: ! '{"users": [], "links": {"self": "http://devstack.openstack.stack:35357/v3/users",
390
+ "previous": null, "next": null}}'
391
+ http_version:
392
+ recorded_at: Mon, 23 Mar 2015 09:25:22 GMT
393
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,929 @@
1
+ require 'fog/openstack/identity'
2
+ require 'fog/openstack/identity_v3'
3
+ require 'rspec/core'
4
+ require 'vcr'
5
+
6
+ RSpec.describe Fog::Identity::OpenStack::V3 do
7
+
8
+ before :each do |example|
9
+ @os_auth_url = ENV['OS_AUTH_URL']
10
+
11
+ # if OS_AUTH_URL is set but FOG_MOCK is not, don't record anything and just pass through the requests
12
+ VCR.configure do |c|
13
+ c.ignore_request do |request|
14
+ ENV['FOG_MOCK']!='true' && !ENV['OS_AUTH_URL'].nil?
15
+ end
16
+ end if @os_auth_url
17
+
18
+ # Fail-safe URL which matches the VCR recordings
19
+ @os_auth_url ||= 'http://devstack.openstack.stack:5000/v3'
20
+
21
+ VCR.configure do |config|
22
+ config.allow_http_connections_when_no_cassette = true
23
+ config.hook_into :webmock
24
+ config.cassette_library_dir = "spec/fog/openstack/identity_v3"
25
+ config.default_cassette_options = {:record => :none}
26
+ end
27
+
28
+ unless example.metadata[:skip_preauthentication]
29
+ VCR.use_cassette('idv3') do
30
+ @id_v3 = Fog::Identity::OpenStack::V3.new(
31
+ :openstack_project_name => ENV['OS_TENANT_NAME'] || 'admin',
32
+ :openstack_domain_name => 'Default',
33
+ :openstack_api_key => ENV['OS_PASSWORD'] || 'openstack',
34
+ :openstack_username => ENV['OS_USERNAME'] || 'admin',
35
+ :openstack_auth_url => "#{@os_auth_url}/auth/tokens") unless @id_v3
36
+ end
37
+ end
38
+ end
39
+
40
+ it 'authenticates with password, userid and domain_id', :skip_preauthentication do
41
+ VCR.use_cassette('authv3_a') do
42
+ Fog::Identity::OpenStack::V3.new(
43
+ :openstack_project_name => ENV['OS_TENANT_NAME'] || 'admin',
44
+ :openstack_domain_name => 'Default',
45
+ :openstack_api_key => ENV['OS_PASSWORD'] || 'openstack',
46
+ :openstack_username => ENV['OS_USERNAME'] || 'admin',
47
+ :openstack_auth_url => "#{@os_auth_url}/auth/tokens")
48
+ end
49
+ end
50
+
51
+ it 'authenticates with password, username and domain_id', :skip_preauthentication do
52
+ VCR.use_cassette('authv3_b') do
53
+ Fog::Identity::OpenStack::V3.new(
54
+ :openstack_project_name => ENV['OS_TENANT_NAME'] || 'admin',
55
+ :openstack_domain_name => 'Default',
56
+ :openstack_api_key => ENV['OS_PASSWORD'] || 'openstack',
57
+ :openstack_username => ENV['OS_USERNAME'] || 'admin',
58
+ :openstack_auth_url => "#{@os_auth_url}/auth/tokens")
59
+ end
60
+ end
61
+
62
+ it 'authenticates with password, username and domain_name', :skip_preauthentication do
63
+ VCR.use_cassette('authv3_c') do
64
+ Fog::Identity::OpenStack::V3.new(
65
+ :openstack_project_name => ENV['OS_TENANT_NAME'] || 'admin',
66
+ :openstack_domain_name => 'Default',
67
+ :openstack_api_key => ENV['OS_PASSWORD'] || 'openstack',
68
+ :openstack_username => ENV['OS_USERNAME'] || 'admin',
69
+ :openstack_auth_url => "#{@os_auth_url}/auth/tokens")
70
+ end
71
+ end
72
+
73
+ it 'authenticates with project scope', :skip_preauthentication do
74
+ VCR.use_cassette('authv3_project') do
75
+ Fog::Identity::OpenStack::V3.new(
76
+ :openstack_project_name => ENV['OS_TENANT_NAME'] || 'admin',
77
+ :openstack_domain_name => 'Default',
78
+ :openstack_api_key => ENV['OS_PASSWORD'] || 'openstack',
79
+ :openstack_username => ENV['OS_USERNAME'] || 'admin',
80
+ :openstack_auth_url => "#{@os_auth_url}/auth/tokens")
81
+ end
82
+ end
83
+
84
+ it "get an unscoped token using v2, then use it to get a scoped token in v3", :skip_preauthentication do
85
+ VCR.use_cassette('idv2_unscoped_token_v3') do
86
+
87
+ # Juno Keystone
88
+ # Get an initial unscoped token by authenticating with username & password
89
+ openstack_auth_url = @os_auth_url.gsub(/v3/, 'v2.0')
90
+ @id_v2 = Fog::Identity::OpenStack.new(
91
+ :openstack_api_key => ENV['OS_PASSWORD'] || 'openstack',
92
+ :openstack_username => ENV['OS_USERNAME'] || 'admin',
93
+ :openstack_auth_url => "#{openstack_auth_url}/tokens")
94
+
95
+ # Exchange it for a project-scoped token
96
+ auth = Fog::Identity::OpenStack::V3.new(
97
+ :openstack_project_name => ENV['OS_USERNAME'] || 'admin',
98
+ :openstack_domain_name => 'Default',
99
+ :openstack_tenant => ENV['OS_USERNAME'] || 'admin',
100
+ :openstack_auth_token => @id_v2.credentials[:openstack_auth_token],
101
+ :openstack_auth_url => "#{@os_auth_url}/auth/tokens")
102
+
103
+ token = auth.credentials[:openstack_auth_token]
104
+
105
+ # We can use the scoped token to validate the scoped token
106
+ validated_token = @id_v2.validate_token(token)
107
+ expect(validated_token).to_not be_nil
108
+
109
+ @id_v2.check_token(token)
110
+ expect { @id_v2.check_token(token, 'random-tenant-id') }.to raise_error(Excon::Errors::Unauthorized)
111
+ end
112
+ end
113
+
114
+ it 'get an unscoped token, then use it to get a scoped token', :skip_preauthentication do
115
+ VCR.use_cassette('authv3_unscoped') do
116
+
117
+ # Juno Keystone
118
+ @id_v3 = Fog::Identity::OpenStack::V3.new(
119
+ :openstack_api_key => ENV['OS_PASSWORD'] || 'openstack',
120
+ :openstack_userid => '8d5732a0ebd9485396351d74e24c9647',
121
+ :openstack_auth_url => "#{@os_auth_url}/auth/tokens")
122
+
123
+ # Exchange it for a project-scoped token
124
+ auth = Fog::Identity::OpenStack::V3.new(
125
+ :openstack_project_name => ENV['OS_USERNAME'] || 'admin',
126
+ :openstack_domain_name => 'Default',
127
+ :openstack_tenant => ENV['OS_USERNAME'] || 'admin',
128
+ :openstack_auth_token => @id_v3.credentials[:openstack_auth_token],
129
+ :openstack_auth_url => "#{@os_auth_url}/auth/tokens")
130
+
131
+ token = auth.credentials[:openstack_auth_token]
132
+
133
+ # We can use the unscoped token to validate the scoped token
134
+ validated_token = @id_v3.tokens.validate(token)
135
+ expect(validated_token).to_not be_nil
136
+
137
+ @id_v3.tokens.check(token)
138
+ expect { @id_v3.tokens.check('random-token') }.to raise_error(Fog::Identity::OpenStack::NotFound)
139
+ end
140
+ end
141
+
142
+ it "find specific user, lists users" do
143
+ VCR.use_cassette('idv3_users') do
144
+
145
+ other_user = @id_v3.users.find_by_id '8d5732a0ebd9485396351d74e24c9647'
146
+
147
+ expect(other_user).to_not be_nil
148
+ expect { nonexistent_user = @id_v3.users.find_by_id 'u-random-blah' }.to raise_error(Fog::Identity::OpenStack::NotFound)
149
+
150
+ users = @id_v3.users
151
+ expect(users).to_not be_nil
152
+ expect(users.length).to_not be 0
153
+
154
+ users_all = @id_v3.users.all
155
+ expect(users_all).to_not be_nil
156
+ expect(users_all.length).to_not be 0
157
+
158
+ admin_user = @id_v3.users.find_by_name 'admin'
159
+ expect(admin_user.length).to be 1
160
+
161
+ expect(@id_v3.users.find_by_name('pimpernel').length).to be 0
162
+ end
163
+ end
164
+
165
+ it 'CRUD users' do
166
+ VCR.use_cassette('idv3_user_crud') do
167
+
168
+ # Make sure there are no existing users called foobar or baz
169
+ ['foobar', 'baz'].each do |username|
170
+ user = @id_v3.users.find_by_name(username).first
171
+ user.update(:enabled => false) if user
172
+ user.destroy if user
173
+ end
174
+ expect(@id_v3.users.find_by_name('foobar').length).to be 0
175
+ expect(@id_v3.users.find_by_name('baz').length).to be 0
176
+
177
+ # Create a user called foobar
178
+ foobar_user = @id_v3.users.create(:name => 'foobar',
179
+ :email => 'foobar@example.com',
180
+ :password => 's3cret!')
181
+ foobar_id = foobar_user.id
182
+ expect(@id_v3.users.find_by_name('foobar').length).to be 1
183
+
184
+ # Rename it to baz and disable it (required so we can delete it)
185
+ foobar_user.update(:name => 'baz', :enabled => false)
186
+ expect(foobar_user.name).to eq 'baz'
187
+
188
+ # Read the user freshly and check the name & enabled state
189
+ expect(@id_v3.users.find_by_name('baz').length).to be 1
190
+ baz_user = @id_v3.users.find_by_id foobar_id
191
+ expect(baz_user).to_not be_nil
192
+ expect(baz_user.name).to eq 'baz'
193
+ expect(baz_user.email).to eq 'foobar@example.com'
194
+ expect(baz_user.enabled).to be false
195
+
196
+ # Delete the user
197
+ baz_user.destroy
198
+ # Check that the deletion worked
199
+ expect { @id_v3.users.find_by_id foobar_id }.to raise_error(Fog::Identity::OpenStack::NotFound)
200
+ expect(@id_v3.users.all.select { |user| ['foobar', 'baz'].include? user.name }.length).to be 0
201
+ expect(@id_v3.users.find_by_name('foobar').length).to be 0
202
+ expect(@id_v3.users.find_by_name('baz').length).to be 0
203
+ end
204
+ end
205
+
206
+ it "CRUD & manipulate groups" do
207
+ VCR.use_cassette('idv3_group_crud_mutation') do
208
+
209
+ # Make sure there are no existing groups called foobar or baz
210
+ @id_v3.groups.all.select { |group| ['foobar', 'baz'].include? group.name }.each do |group|
211
+ group.destroy
212
+ end
213
+ expect(@id_v3.groups.all.select { |group| ['foobar', 'baz'].include? group.name }.length).to be 0
214
+
215
+ # Create a group called foobar
216
+ foobar_group = @id_v3.groups.create(:name => 'foobar', :description => "Group of Foobar users")
217
+ foobar_id = foobar_group.id
218
+ expect(@id_v3.groups.all.select { |group| group.name == 'foobar' }.length).to be 1
219
+
220
+ # Rename it to baz
221
+ foobar_group.update(:name => 'baz', :description => "Group of Baz users")
222
+ expect(foobar_group.name).to eq 'baz'
223
+
224
+ # Read the group freshly and check the name
225
+ expect(@id_v3.groups.all.select { |group| group.name == 'baz' }.length).to be 1
226
+ baz_group = @id_v3.groups.find_by_id foobar_id
227
+ expect(baz_group).to_not be_nil
228
+ expect(baz_group.name).to eq 'baz'
229
+
230
+ # Add users to the group
231
+ foobar_user1 = @id_v3.users.create(:name => 'foobar1',
232
+ :email => 'foobar1@example.com',
233
+ :password => 's3cret!1')
234
+ foobar_user2 = @id_v3.users.create(:name => 'foobar2',
235
+ :email => 'foobar2@example.com',
236
+ :password => 's3cret!2')
237
+
238
+ expect(foobar_user1.groups.length).to be 0
239
+ expect(baz_group.users.length).to be 0
240
+
241
+ baz_group.add_user(foobar_user1.id)
242
+
243
+ # Check that a user is in the group
244
+ expect(foobar_user1.groups.length).to be 1
245
+ expect(baz_group.contains_user? foobar_user1.id).to be true
246
+
247
+ baz_group.add_user(foobar_user2.id)
248
+
249
+ # List users in the group
250
+ expect(baz_group.users.length).to be 2
251
+
252
+
253
+ # Remove a user from the group
254
+ baz_group.remove_user(foobar_user1.id)
255
+ expect(baz_group.contains_user? foobar_user1.id).to be false
256
+ expect(baz_group.users.length).to be 1
257
+
258
+ # Delete the users and make sure they are no longer in the group
259
+ foobar_user1.destroy
260
+ foobar_user2.destroy
261
+ expect(baz_group.contains_user? foobar_user2.id).to be false
262
+ expect(baz_group.users.length).to be 0
263
+
264
+ # Delete the group
265
+ baz_group.destroy
266
+ expect { @id_v3.groups.find_by_id foobar_id }.to raise_error(Fog::Identity::OpenStack::NotFound)
267
+ expect(@id_v3.groups.all.select { |group| ['foobar', 'baz'].include? group.name }.length).to be 0
268
+ end
269
+ end
270
+
271
+ it "gets a token, checks it and then revokes it" do
272
+ VCR.use_cassette('idv3_token') do
273
+ auth = {:auth => {:identity => {:methods => %w{password},
274
+ :password => {:user => {:id => '8d5732a0ebd9485396351d74e24c9647', :password => 'openstack'}}},
275
+ :scope => {:project => {:domain => {:id => 'default'}, :name => 'admin'}}}}
276
+
277
+ token = @id_v3.tokens.authenticate(auth)
278
+ expect(token).to_not be_nil
279
+
280
+ validated_token = @id_v3.tokens.validate token.value
281
+ expect(validated_token).to_not be_nil
282
+
283
+ @id_v3.tokens.check(token.value)
284
+ @id_v3.tokens.revoke(token.value)
285
+
286
+ expect { @id_v3.tokens.check(token.value) }.to raise_error(Fog::Identity::OpenStack::NotFound)
287
+ end
288
+ end
289
+
290
+ it 'authenticates with a token' do
291
+ VCR.use_cassette('authv3_token') do
292
+ # Setup - get a non-admin token to check by using username/password authentication to start with
293
+ auth_url = "#{@os_auth_url}/auth/tokens"
294
+ nonadmin_v3 = Fog::Identity::OpenStack::V3.new(
295
+ :openstack_project_name => 'demo',
296
+ :openstack_domain_id => 'default',
297
+ :openstack_api_key => 'openstack',
298
+ :openstack_username => 'demo',
299
+ :openstack_region => 'europe',
300
+ :openstack_auth_url => auth_url)
301
+
302
+ # Test - check the token validity by using it to create a new Fog::Identity::OpenStack::V3 instance
303
+ token_check = Fog::Identity::OpenStack::V3.new(
304
+ :openstack_auth_token => nonadmin_v3.auth_token,
305
+ :openstack_region => 'europe',
306
+ :openstack_auth_url => auth_url)
307
+
308
+ expect(token_check).to_not be_nil
309
+
310
+ expect { Fog::Identity::OpenStack::V3.new(
311
+ :openstack_auth_token => 'blahblahblah',
312
+ :openstack_region => 'europe',
313
+ :openstack_auth_url => auth_url) }.to raise_error(Excon::Errors::NotFound)
314
+ end
315
+ end
316
+
317
+ it "lists domains" do
318
+ VCR.use_cassette('idv3_domain') do
319
+
320
+ domains = @id_v3.domains
321
+ expect(domains).to_not be_nil
322
+ expect(domains.length).to_not be 0
323
+
324
+ domains_all = @id_v3.domains.all
325
+ expect(domains_all).to_not be_nil
326
+ expect(domains_all.length).to_not be 0
327
+
328
+ default_domain = @id_v3.domains.find_by_id 'default'
329
+ expect(default_domain).to_not be_nil
330
+
331
+ expect { @id_v3.domains.find_by_id 'atlantis' }.to raise_error(Fog::Identity::OpenStack::NotFound)
332
+ end
333
+ end
334
+
335
+ it "CRUD domains" do
336
+ VCR.use_cassette('idv3_domain_crud') do
337
+
338
+ # Make sure there are no existing domains called foobar or baz
339
+ ['foobar', 'baz'].each do |domain_name|
340
+ @id_v3.domains.all(:name => domain_name).each do |domain|
341
+ domain.update(:enabled => false) if domain
342
+ domain.destroy if domain
343
+ end
344
+ expect(@id_v3.domains.all(:name => domain_name).length).to be 0
345
+ end
346
+
347
+ # Create a domain called foobar
348
+ foobar_domain = @id_v3.domains.create(:name => 'foobar')
349
+ foobar_id = foobar_domain.id
350
+ expect(@id_v3.domains.all(:name => 'foobar').length).to be 1
351
+
352
+ # Rename it to baz and disable it (required so we can delete it)
353
+ foobar_domain.update(:name => 'baz', :enabled => false)
354
+ expect(foobar_domain.name).to eq 'baz'
355
+
356
+ # Read the domain freshly and check the name & enabled state
357
+ expect(@id_v3.domains.all(:name => 'baz').length).to be 1
358
+ baz_domain = @id_v3.domains.find_by_id foobar_id
359
+ expect(baz_domain).to_not be_nil
360
+ expect(baz_domain.name).to eq 'baz'
361
+ expect(baz_domain.enabled).to be false
362
+
363
+ # Delete the domain
364
+ baz_domain.destroy
365
+ # Check that the deletion worked
366
+ expect { @id_v3.domains.find_by_id foobar_id }.to raise_error(Fog::Identity::OpenStack::NotFound)
367
+ ['foobar', 'baz'].each do |domain_name|
368
+ expect(@id_v3.domains.all(:name => domain_name).length).to be 0
369
+ end
370
+ end
371
+ end
372
+
373
+ it "Manipulates roles on domains" do
374
+ # Note that the domain is implicit in the user operations here
375
+
376
+ VCR.use_cassette('idv3_domain_roles_mutation') do
377
+
378
+ foobar_user = @id_v3.users.find_by_name('foobar').first
379
+ foobar_user.destroy if foobar_user
380
+ foobar_user = @id_v3.users.create(:name => 'foobar',
381
+ :email => 'foobar@example.com',
382
+ :password => 's3cret!')
383
+
384
+ # User has no roles initially
385
+ expect(foobar_user.roles.length).to be 0
386
+
387
+ # Create a role and add it to the user in the user's domain
388
+ foobar_role = @id_v3.roles.all.select { |role| role.name == 'foobar_role' }.first
389
+ foobar_role.destroy if foobar_role
390
+ foobar_role = @id_v3.roles.create(:name => 'foobar_role')
391
+ foobar_user.grant_role(foobar_role.id)
392
+ expect(foobar_user.roles.length).to be 1
393
+ assignments = @id_v3.role_assignments.filter_by(:user_id => foobar_user.id)
394
+ expect(assignments.length).to be 1
395
+ expect(assignments.first.role['id']).to eq foobar_role.id
396
+ expect(assignments.first.user['id']).to eq foobar_user.id
397
+ expect(assignments.first.scope['domain']['id']).to eq foobar_user.domain_id
398
+ expect(assignments.first.links['assignment'].end_with? "/v3/domains/#{foobar_user.domain_id}/users/#{foobar_user.id}/roles/#{foobar_role.id}").to be true
399
+
400
+ # Quick test of @id_v3.role_assignments.all while we're at it
401
+ all_assignments = @id_v3.role_assignments.all
402
+ expect(assignments.length).to be >= 1
403
+
404
+ # Check that the user has the role
405
+ expect(foobar_user.check_role(foobar_role.id)).to be true
406
+
407
+ # Revoke the role from the user
408
+ foobar_user.revoke_role(foobar_role.id)
409
+ expect(foobar_user.check_role(foobar_role.id)).to be false
410
+
411
+ foobar_user.destroy
412
+ foobar_role.destroy
413
+ end
414
+ end
415
+
416
+ it "Manipulates roles on domain groups" do
417
+ VCR.use_cassette('idv3_domain_group_roles_mutation') do
418
+
419
+ # Make sure there is no existing domain called foobar
420
+ @id_v3.domains.all.select { |domain| ['d-foobar'].include? domain.name }.each do |domain|
421
+ domain.update(:enabled => false)
422
+ domain.destroy
423
+ end
424
+ expect(@id_v3.domains.all.select { |domain| domain.name == 'd-foobar' }.length).to be 0
425
+
426
+ # Create a domain called foobar
427
+ foobar_domain = @id_v3.domains.create(:name => 'd-foobar')
428
+
429
+ # Create a group in this domain
430
+ @id_v3.groups.all.select { |group| ['g-foobar'].include? group.name }.each do |group|
431
+ group.destroy
432
+ end
433
+ foobar_group = @id_v3.groups.create(:name => 'g-foobar',
434
+ :description => "Group of Foobar users",
435
+ :domain_id => foobar_domain.id)
436
+
437
+ # Create a user in the domain
438
+ foobar_user = @id_v3.users.find_by_name('u-foobar').first
439
+ foobar_user.destroy if foobar_user
440
+ foobar_user = @id_v3.users.create(:name => 'u-foobar',
441
+ :email => 'foobar@example.com',
442
+ :password => 's3cret!',
443
+ :domain_id => foobar_domain.id)
444
+
445
+ # User has no roles initially
446
+ expect(foobar_user.roles.length).to be 0
447
+
448
+ # Create a role and add it to the domain group
449
+ foobar_role = @id_v3.roles.all.select { |role| role.name == 'foobar_role' }.first
450
+ foobar_role.destroy if foobar_role
451
+ foobar_role = @id_v3.roles.create(:name => 'foobar_role')
452
+
453
+ foobar_group.grant_role foobar_role.id
454
+ expect(foobar_group.roles.length).to be 1
455
+
456
+ # Add user to the group and check that it inherits the role
457
+ expect(foobar_user.check_role foobar_role.id).to be false
458
+ expect(@id_v3.role_assignments.filter_by(:user_id => foobar_user.id, :effective => true).length).to be 0
459
+ foobar_group.add_user foobar_user.id
460
+ expect(foobar_user.check_role foobar_role.id).to be false # Still false in absolute assignment terms
461
+ assignments = @id_v3.role_assignments.filter_by(:user_id => foobar_user.id, :effective => true)
462
+ expect(assignments.length).to be 1
463
+ expect(assignments.first.role['id']).to eq foobar_role.id
464
+ expect(assignments.first.user['id']).to eq foobar_user.id
465
+ expect(assignments.first.scope['domain']['id']).to eq foobar_user.domain_id
466
+ expect(assignments.first.links['assignment'].end_with? "/v3/domains/#{foobar_domain.id}/groups/#{foobar_group.id}/roles/#{foobar_role.id}").to be true
467
+ expect(assignments.first.links['membership'].end_with? "/v3/groups/#{foobar_group.id}/users/#{foobar_user.id}").to be true
468
+
469
+ group_assignments = @id_v3.role_assignments.filter_by(:group_id => foobar_group.id)
470
+ expect(group_assignments.length).to be 1
471
+ expect(group_assignments.first.role['id']).to eq foobar_role.id
472
+ expect(group_assignments.first.group['id']).to eq foobar_group.id
473
+ expect(group_assignments.first.scope['domain']['id']).to eq foobar_user.domain_id
474
+ expect(group_assignments.first.links['assignment'].end_with? "/v3/domains/#{foobar_domain.id}/groups/#{foobar_group.id}/roles/#{foobar_role.id}").to be true
475
+
476
+ # Revoke the role from the group and check the user no longer has it
477
+ foobar_group.revoke_role foobar_role.id
478
+ expect(@id_v3.role_assignments.filter_by(:user_id => foobar_user.id, :effective => true).length).to be 0
479
+
480
+ # Clean up
481
+ foobar_user.destroy
482
+ foobar_group.destroy
483
+ foobar_role.destroy
484
+ foobar_domain.update(:enabled => false)
485
+ foobar_domain.destroy
486
+ end
487
+ end
488
+
489
+ it "lists roles and assignments" do
490
+ VCR.use_cassette('idv3_role') do
491
+
492
+ roles = @id_v3.roles
493
+ expect(roles).to_not be_nil
494
+ expect(roles.length).to_not be 0
495
+
496
+ roles_all = @id_v3.roles.all
497
+ expect(roles_all).to_not be_nil
498
+ expect(roles_all.length).to_not be 0
499
+
500
+ default_role = @id_v3.roles.find_by_id '9fe2ff9ee4384b1894a90878d3e92bab'
501
+ expect(default_role).to_not be_nil
502
+
503
+ expect { @id_v3.roles.find_by_id 'atlantis' }.to raise_error(Fog::Identity::OpenStack::NotFound)
504
+ end
505
+ end
506
+
507
+ it "CRUD roles" do
508
+ VCR.use_cassette('idv3_role_crud') do
509
+
510
+ # Make sure there are no existing roles called foobar or baz
511
+ ['foobar', 'baz'].each do |role_name|
512
+ @id_v3.roles.all(:name => role_name).each do |role|
513
+ role.update(:enabled => false)
514
+ role.destroy
515
+ end
516
+ expect(@id_v3.roles.all(:name => role_name).length).to be 0
517
+ end
518
+
519
+ # Create a role called foobar
520
+ foobar_role = @id_v3.roles.create(:name => 'foobar')
521
+ foobar_id = foobar_role.id
522
+ expect(@id_v3.roles.all(:name => 'foobar').length).to be 1
523
+
524
+ # Rename it to baz
525
+ foobar_role.update(:name => 'baz')
526
+ expect(foobar_role.name).to eq 'baz'
527
+
528
+ # Read the role freshly and check the name & enabled state
529
+ expect(@id_v3.roles.all(:name => 'baz').length).to be 1
530
+ baz_role = @id_v3.roles.find_by_id foobar_id
531
+ expect(baz_role).to_not be_nil
532
+ expect(baz_role.name).to eq 'baz'
533
+
534
+ # Delete the role
535
+ baz_role.destroy
536
+ # Check that the deletion worked
537
+ expect { @id_v3.roles.find_by_id foobar_id }.to raise_error(Fog::Identity::OpenStack::NotFound)
538
+ ['foobar', 'baz'].each do |role_name|
539
+ expect(@id_v3.roles.all(:name => role_name).length).to be 0
540
+ end
541
+ end
542
+ end
543
+
544
+ it "lists projects" do
545
+ VCR.use_cassette('idv3_project') do
546
+
547
+ projects = @id_v3.projects
548
+ expect(projects).to_not be_nil
549
+ expect(projects.length).to_not be 0
550
+
551
+ projects_all = @id_v3.projects.all
552
+ expect(projects_all).to_not be_nil
553
+ expect(projects_all.length).to_not be 0
554
+
555
+ default_project = @id_v3.projects.find_by_id 'c9f75b1200f64bf09ed079206a1a1b75'
556
+ expect(default_project).to_not be_nil
557
+
558
+ expect { @id_v3.projects.find_by_id 'atlantis' }.to raise_error(Fog::Identity::OpenStack::NotFound)
559
+ end
560
+ end
561
+
562
+ it "CRUD projects" do
563
+ VCR.use_cassette('idv3_project_crud') do
564
+
565
+ default_domain = @id_v3.domains.find_by_id 'default'
566
+
567
+ # Make sure there are no existing projects called foobar or baz
568
+ ['p-foobar', 'p-baz'].each do |project_name|
569
+ @id_v3.projects.all(:name => project_name).each do |project|
570
+ project.update(:enabled => false) if project
571
+ project.destroy if project
572
+ end
573
+ expect(@id_v3.projects.all(:name => project_name).length).to be 0
574
+ end
575
+
576
+ # Create a project called foobar - should not work without domain id?
577
+ foobar_project = @id_v3.projects.create(:name => 'p-foobar')
578
+ foobar_id = foobar_project.id
579
+ expect(@id_v3.projects.all(:name => 'p-foobar').length).to be 1
580
+ expect(foobar_project.domain_id).to eq default_domain.id
581
+
582
+ # Rename it to baz and disable it (required so we can delete it)
583
+ foobar_project.update(:name => 'p-baz', :enabled => false)
584
+ expect(foobar_project.name).to eq 'p-baz'
585
+
586
+ # Read the project freshly and check the name & enabled state
587
+ expect(@id_v3.projects.all(:name => 'p-baz').length).to be 1
588
+ baz_project = @id_v3.projects.find_by_id foobar_id
589
+ expect(baz_project).to_not be_nil
590
+ expect(baz_project.name).to eq 'p-baz'
591
+ expect(baz_project.enabled).to be false
592
+
593
+ # Delete the project
594
+ baz_project.destroy
595
+
596
+ # Check that the deletion worked
597
+ expect { @id_v3.projects.find_by_id foobar_id }.to raise_error(Fog::Identity::OpenStack::NotFound)
598
+ ['p-foobar', 'p-baz'].each do |project_name|
599
+ expect(@id_v3.projects.all(:name => project_name).length).to be 0
600
+ end
601
+ end
602
+ end
603
+
604
+ it "Manipulates projects - add/remove users/groups via role assignment/revocation" do
605
+ VCR.use_cassette('idv3_project_group_user_roles_mutation') do
606
+
607
+ # Make sure there is no existing project called foobar
608
+ @id_v3.projects.all(:name => 'p-foobar').each do |project|
609
+ project.update(:enabled => false)
610
+ project.destroy
611
+ end
612
+ expect(@id_v3.projects.all(:name => 'p-foobar').length).to be 0
613
+
614
+ # Create a project called foobar
615
+ foobar_project = @id_v3.projects.create(:name => 'p-foobar')
616
+
617
+ # Create a role called baz
618
+ @id_v3.roles.all(:name => 'baz').each do |role|
619
+ role.update(:enabled => false)
620
+ role.destroy
621
+ end
622
+ baz_role = @id_v3.roles.create(:name => 'baz')
623
+
624
+ # Create a user
625
+ foobar_user = @id_v3.users.find_by_name('u-foobar').first
626
+ foobar_user.destroy if foobar_user
627
+ foobar_user = @id_v3.users.create(:name => 'u-foobar',
628
+ :email => 'foobar@example.com',
629
+ :password => 's3cret!')
630
+
631
+ # Create a group and add the user to it
632
+ @id_v3.groups.all.select { |group| ['g-foobar'].include? group.name }.each do |group|
633
+ group.destroy
634
+ end
635
+ foobar_group = @id_v3.groups.create(:name => 'g-foobar',
636
+ :description => "Group of Foobar users")
637
+ foobar_group.add_user foobar_user.id
638
+
639
+ # User has no projects initially
640
+ expect(foobar_user.projects.length).to be 0
641
+ expect(@id_v3.role_assignments.filter_by(:user_id => foobar_user.id,
642
+ :project_id => foobar_project.id,
643
+ :effective => true).length).to be 0
644
+ expect(foobar_project.user_roles(foobar_user.id).length).to be 0
645
+
646
+ # Grant role to the user in the new project - this assigns the project to the user
647
+ foobar_project.grant_role_to_user(baz_role.id, foobar_user.id)
648
+ expect(foobar_user.projects.length).to be 1
649
+ expect(foobar_project.check_user_role(foobar_user.id, baz_role.id)).to be true
650
+ expect(foobar_project.user_roles(foobar_user.id).length).to be 1
651
+
652
+ # Revoke role from the user in the new project - this removes the user from the project
653
+ foobar_project.revoke_role_from_user(baz_role.id, foobar_user.id)
654
+ expect(foobar_user.projects.length).to be 0
655
+ expect(foobar_project.check_user_role(foobar_user.id, baz_role.id)).to be false
656
+
657
+ # Group initially has no roles in project
658
+ expect(foobar_project.group_roles(foobar_group.id).length).to be 0
659
+
660
+ expect(@id_v3.role_assignments.filter_by(:user_id => foobar_user.id,
661
+ :project_id => foobar_project.id,
662
+ :effective => true).length).to be 0
663
+
664
+ # Grant role to the group in the new project - this assigns the project to the group
665
+ foobar_project.grant_role_to_group(baz_role.id, foobar_group.id)
666
+ expect(foobar_project.check_group_role(foobar_group.id, baz_role.id)).to be true
667
+ expect(foobar_project.group_roles(foobar_group.id).length).to be 1
668
+
669
+ # Now we check that a user has the role in that project
670
+ assignments = @id_v3.role_assignments.filter_by(:user_id => foobar_user.id,
671
+ :project_id => foobar_project.id,
672
+ :effective => true)
673
+ expect(assignments.length).to be 1
674
+ expect(assignments.first.role['id']).to eq baz_role.id
675
+ expect(assignments.first.user['id']).to eq foobar_user.id
676
+ expect(assignments.first.scope['project']['id']).to eq foobar_project.id
677
+ expect(assignments.first.links['assignment'].end_with? "/v3/projects/#{foobar_project.id}/groups/#{foobar_group.id}/roles/#{baz_role.id}").to be true
678
+ expect(assignments.first.links['membership'].end_with? "/v3/groups/#{foobar_group.id}/users/#{foobar_user.id}").to be true
679
+
680
+ # and we check that the user is in the project because of group membership
681
+ expect(foobar_user.projects.length).to be 1
682
+
683
+ # Revoke role from the group in the new project - this removes the group from the project
684
+ foobar_project.revoke_role_from_group(baz_role.id, foobar_group.id)
685
+ expect(foobar_user.projects.length).to be 0
686
+ expect(foobar_project.check_group_role(foobar_group.id, baz_role.id)).to be false
687
+
688
+ # Clean up
689
+ foobar_user.destroy
690
+ foobar_group.destroy
691
+ baz_role.destroy
692
+ foobar_project.update(:enabled => false)
693
+ foobar_project.destroy
694
+ end
695
+ end
696
+
697
+ it "lists services" do
698
+ VCR.use_cassette('idv3_service') do
699
+
700
+ services = @id_v3.services
701
+ expect(services).to_not be_nil
702
+ expect(services.length).to_not be 0
703
+
704
+ services_all = @id_v3.services.all
705
+ expect(services_all).to_not be_nil
706
+ expect(services_all.length).to_not be 0
707
+
708
+ some_service = @id_v3.services.find_by_id services_all.first.id
709
+ expect(some_service).to_not be_nil
710
+
711
+ expect { @id_v3.services.find_by_id 'atlantis' }.to raise_error(Fog::Identity::OpenStack::NotFound)
712
+ end
713
+ end
714
+
715
+ it "CRUD services" do
716
+ VCR.use_cassette('idv3_services_crud') do
717
+
718
+ all_services = @id_v3.services.all
719
+
720
+ # Make sure there are no existing services called foobar or baz
721
+ @id_v3.services.all.select { |service| ['foobar', 'baz'].include? service.name }.each do |service|
722
+ service.destroy
723
+ end
724
+ expect(all_services.select { |service| ['foobar', 'baz'].include? service.name }.length).to be 0
725
+
726
+ # Create a service called foobar
727
+ foobar_service = @id_v3.services.create(:type => 'volume', :name => 'foobar')
728
+ foobar_id = foobar_service.id
729
+ expect(@id_v3.services.all(:type => 'volume').select { |service| service.name == 'foobar' }.length).to be 1
730
+
731
+ # Rename it to baz
732
+ foobar_service.update(:name => 'baz')
733
+ expect(foobar_service.name).to eq 'baz'
734
+
735
+ # Read the service freshly and check the name
736
+ expect(@id_v3.services.all.select { |service| service.name == 'baz' }.length).to be 1
737
+ baz_service = @id_v3.services.find_by_id foobar_id
738
+ expect(baz_service).to_not be_nil
739
+ expect(baz_service.name).to eq 'baz'
740
+ expect(baz_service.type).to eq 'volume'
741
+
742
+ # Delete the service
743
+ baz_service.destroy
744
+
745
+ # Check that the deletion worked
746
+ expect { @id_v3.services.find_by_id foobar_id }.to raise_error(Fog::Identity::OpenStack::NotFound)
747
+ expect(@id_v3.services.all.select { |service| ['foobar', 'baz'].include? service.name }.length).to be 0
748
+ end
749
+ end
750
+
751
+ it "lists endpoints" do
752
+ VCR.use_cassette('idv3_endpoint') do
753
+
754
+ endpoints = @id_v3.endpoints
755
+ expect(endpoints).to_not be_nil
756
+ expect(endpoints.length).to_not be 0
757
+
758
+ endpoints_all = @id_v3.endpoints.all
759
+ expect(endpoints_all).to_not be_nil
760
+ expect(endpoints_all.length).to_not be 0
761
+
762
+ some_endpoint = @id_v3.endpoints.find_by_id endpoints_all.first.id
763
+ expect(some_endpoint).to_not be_nil
764
+
765
+ expect { @id_v3.endpoints.find_by_id 'atlantis' }.to raise_error(Fog::Identity::OpenStack::NotFound)
766
+ end
767
+ end
768
+
769
+ it "CRUD endpoints" do
770
+ VCR.use_cassette('idv3_endpoints_crud') do
771
+
772
+ service = @id_v3.services.all.first
773
+ all_endpoints = @id_v3.endpoints.all
774
+
775
+ # Make sure there are no existing endpoints called foobar or baz
776
+ @id_v3.endpoints.all.select { |endpoint| ['foobar', 'baz'].include? endpoint.name }.each do |endpoint|
777
+ endpoint.destroy
778
+ end
779
+ expect(all_endpoints.select { |endpoint| ['foobar', 'baz'].include? endpoint.name }.length).to be 0
780
+
781
+ # Create a endpoint called foobar
782
+ foobar_endpoint = @id_v3.endpoints.create(:service_id => service.id,
783
+ :interface => 'internal',
784
+ :name => 'foobar',
785
+ :url => 'http://example.com/foobar',
786
+ :enabled => false)
787
+ foobar_id = foobar_endpoint.id
788
+ expect(@id_v3.endpoints.all(:interface => 'internal').select { |endpoint| endpoint.name == 'foobar' }.length).to be 1
789
+
790
+ # Rename it to baz
791
+ foobar_endpoint.update(:name => 'baz', :url => 'http://example.com/baz')
792
+ expect(foobar_endpoint.name).to eq 'baz'
793
+ expect(foobar_endpoint.url).to eq 'http://example.com/baz'
794
+
795
+ # Read the endpoint freshly and check the name
796
+ expect(@id_v3.endpoints.all(:interface => 'internal').select { |endpoint| endpoint.name == 'baz' }.length).to be 1
797
+ baz_endpoint = @id_v3.endpoints.find_by_id foobar_id
798
+ expect(baz_endpoint).to_not be_nil
799
+ expect(baz_endpoint.name).to eq 'baz'
800
+ expect(baz_endpoint.url).to eq 'http://example.com/baz'
801
+ expect(baz_endpoint.interface).to eq 'internal'
802
+
803
+ # Delete the endpoint
804
+ baz_endpoint.destroy
805
+
806
+ # Check that the deletion worked
807
+ expect { @id_v3.endpoints.find_by_id foobar_id }.to raise_error(Fog::Identity::OpenStack::NotFound)
808
+ expect(@id_v3.endpoints.all.select { |endpoint| ['foobar', 'baz'].include? endpoint.name }.length).to be 0
809
+ end
810
+ end
811
+
812
+ it "lists OS credentials" do
813
+ VCR.use_cassette('idv3_credential') do
814
+ credentials = @id_v3.os_credentials
815
+ expect(credentials).to_not be_nil
816
+
817
+ credentials_all = @id_v3.os_credentials.all
818
+ expect(credentials_all).to_not be_nil
819
+
820
+ expect { @id_v3.os_credentials.find_by_id 'atlantis' }.to raise_error(Fog::Identity::OpenStack::NotFound)
821
+ end
822
+ end
823
+
824
+ it "CRUD OS credentials" do
825
+ VCR.use_cassette('idv3_credential_crud') do
826
+
827
+ # Create a user
828
+ foobar_user = @id_v3.users.find_by_name('u-foobar').first
829
+ foobar_user.destroy if foobar_user
830
+ foobar_user = @id_v3.users.create(:name => 'u-foobar',
831
+ :email => 'foobar@example.com',
832
+ :password => 's3cret!')
833
+
834
+ project = @id_v3.projects.all.first
835
+
836
+ access_key = '9c4e774a-f644-498f-90c4-970b3f817fc5'
837
+ secret_key = '7e084117-b13d-4656-9eca-85376b690897'
838
+
839
+ # OpenStack Keystone requires the blob to be a JSON string - i.e. not JSON, but a string containing JSON :-/
840
+ blob_json = {:access => access_key,
841
+ :secret => secret_key}.to_json
842
+
843
+ # Make sure there are no existing ec2 credentials
844
+ @id_v3.os_credentials.all.select { |credential| credential.type == 'foo' || credential.type == 'ec2' }.each do |credential|
845
+ credential.destroy
846
+ end
847
+ expect(@id_v3.os_credentials.all.select { |credential| credential.type == 'ec2' }.length).to be 0
848
+
849
+ # Create a credential
850
+ foo_credential = @id_v3.os_credentials.create(:type => 'ec2',
851
+ :project_id => project.id,
852
+ :user_id => foobar_user.id,
853
+ :blob => blob_json)
854
+ credential_id = foo_credential.id
855
+ expect(@id_v3.os_credentials.all.select { |credential| credential.type == 'ec2' }.length).to be 1
856
+
857
+ # Update secret key
858
+ new_secret_key = '62307bcd-ca3c-47ae-a114-27a6cadb5bc9'
859
+ new_blob_json = {:access => access_key,
860
+ :secret => new_secret_key}.to_json
861
+ foo_credential.update(:blob => new_blob_json)
862
+ expect(JSON.parse(foo_credential.blob)['secret']).to eq new_secret_key
863
+
864
+ # Read the credential freshly and check the secret key
865
+ expect(@id_v3.os_credentials.all.select { |credential| credential.type == 'ec2' }.length).to be 1
866
+ updated_credential = @id_v3.os_credentials.find_by_id credential_id
867
+ expect(updated_credential).to_not be_nil
868
+ expect(updated_credential.type).to eq 'ec2'
869
+ expect(JSON.parse(updated_credential.blob)['secret']).to eq new_secret_key
870
+
871
+ # Delete the credential
872
+ updated_credential.destroy
873
+
874
+ # Check that the deletion worked
875
+ expect { @id_v3.os_credentials.find_by_id credential_id }.to raise_error(Fog::Identity::OpenStack::NotFound)
876
+ expect(@id_v3.os_credentials.all.select { |credential| credential.type == 'ec2' }.length).to be 0
877
+ end
878
+ end
879
+
880
+ it "lists policies" do
881
+ VCR.use_cassette('idv3_policy') do
882
+ policies = @id_v3.policies
883
+ expect(policies).to_not be_nil
884
+ expect(policies.length).to be 0
885
+
886
+ policies_all = @id_v3.policies.all
887
+ expect(policies_all).to_not be_nil
888
+ expect(policies_all.length).to be 0
889
+
890
+ expect { @id_v3.policies.find_by_id 'atlantis' }.to raise_error(Fog::Identity::OpenStack::NotFound)
891
+ end
892
+ end
893
+
894
+ it "CRUD policies" do
895
+ VCR.use_cassette('idv3_policy_crud') do
896
+
897
+ blob = {'foobar_user' => ['role:compute-user']}.to_json
898
+
899
+ # Make sure there are no existing policies
900
+ expect(@id_v3.policies.all.select { |policy| policy.type == 'application/json' }.length).to be 0
901
+
902
+ # Create a policy
903
+ foo_policy = @id_v3.policies.create(:type => 'application/json',
904
+ :blob => blob)
905
+ policy_id = foo_policy.id
906
+ expect(@id_v3.policies.all.select { |policy| policy.type == 'application/json' }.length).to be 1
907
+
908
+ # Update policy blob
909
+ new_blob = {'baz_user' => ['role:compute-user']}.to_json
910
+ foo_policy.update(:blob => new_blob)
911
+ expect(foo_policy.blob).to eq new_blob
912
+
913
+ # Read the policy freshly and check the secret key
914
+ expect(@id_v3.policies.all.select { |policy| policy.type == 'application/json' }.length).to be 1
915
+ updated_policy = @id_v3.policies.find_by_id policy_id
916
+ expect(updated_policy).to_not be_nil
917
+ expect(updated_policy.type).to eq 'application/json'
918
+ expect(updated_policy.blob).to eq new_blob
919
+
920
+ # Delete the policy
921
+ updated_policy.destroy
922
+
923
+ # Check that the deletion worked
924
+ expect { @id_v3.policies.find_by_id policy_id }.to raise_error(Fog::Identity::OpenStack::NotFound)
925
+ expect(@id_v3.policies.all.select { |policy| policy.type == 'application/json' }.length).to be 0
926
+ end
927
+ end
928
+
929
+ end