fog 1.30.0 → 1.31.0

Sign up to get free protection for your applications and to get access to all the features.
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