yao 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +15 -0
  3. data/.github/workflows/ubuntu-rvm.yml +29 -0
  4. data/.github/workflows/ubuntu.yml +22 -0
  5. data/Gemfile +10 -2
  6. data/README.md +3 -3
  7. data/lib/yao/resources.rb +5 -0
  8. data/lib/yao/resources/action.rb +1 -1
  9. data/lib/yao/resources/compute_services.rb +46 -0
  10. data/lib/yao/resources/flavor.rb +1 -10
  11. data/lib/yao/resources/floating_ip.rb +6 -6
  12. data/lib/yao/resources/hypervisor.rb +6 -12
  13. data/lib/yao/resources/keypair.rb +22 -3
  14. data/lib/yao/resources/meter.rb +6 -7
  15. data/lib/yao/resources/network.rb +3 -1
  16. data/lib/yao/resources/network_associationable.rb +14 -0
  17. data/lib/yao/resources/old_sample.rb +5 -7
  18. data/lib/yao/resources/port.rb +6 -6
  19. data/lib/yao/resources/port_associationable.rb +14 -0
  20. data/lib/yao/resources/project.rb +16 -0
  21. data/lib/yao/resources/resource.rb +12 -7
  22. data/lib/yao/resources/restfully_accessible.rb +72 -35
  23. data/lib/yao/resources/role.rb +73 -18
  24. data/lib/yao/resources/router.rb +3 -1
  25. data/lib/yao/resources/sample.rb +1 -5
  26. data/lib/yao/resources/security_group.rb +3 -1
  27. data/lib/yao/resources/server.rb +4 -9
  28. data/lib/yao/resources/subnet.rb +5 -5
  29. data/lib/yao/resources/tenant.rb +1 -1
  30. data/lib/yao/resources/tenant_associationable.rb +17 -0
  31. data/lib/yao/resources/user.rb +15 -4
  32. data/lib/yao/resources/volume.rb +1 -10
  33. data/lib/yao/version.rb +1 -1
  34. data/test/config.rb +1 -0
  35. data/test/support/auth_stub.rb +1 -0
  36. data/test/support/test_yao_resource.rb +49 -0
  37. data/test/yao/resources/test_aggregates.rb +1 -4
  38. data/test/yao/resources/test_base.rb +1 -1
  39. data/test/yao/resources/test_compute_services.rb +118 -0
  40. data/test/yao/resources/test_flavor.rb +15 -9
  41. data/test/yao/resources/test_floating_ip.rb +24 -19
  42. data/test/yao/resources/test_host.rb +1 -1
  43. data/test/yao/resources/test_hypervisor.rb +17 -10
  44. data/test/yao/resources/test_image.rb +1 -1
  45. data/test/yao/resources/test_keypair.rb +3 -6
  46. data/test/yao/resources/test_loadbalancer.rb +1 -3
  47. data/test/yao/resources/test_loadbalancer_healthmonitor.rb +1 -3
  48. data/test/yao/resources/test_loadbalancer_listener.rb +1 -5
  49. data/test/yao/resources/test_loadbalancer_pool.rb +1 -3
  50. data/test/yao/resources/test_loadbalancer_pool_member.rb +1 -3
  51. data/test/yao/resources/test_meter.rb +13 -14
  52. data/test/yao/resources/test_network.rb +28 -1
  53. data/test/yao/resources/test_old_sample.rb +86 -0
  54. data/test/yao/resources/test_port.rb +29 -7
  55. data/test/yao/resources/test_project.rb +32 -0
  56. data/test/yao/resources/test_resource.rb +56 -0
  57. data/test/yao/resources/test_role.rb +255 -1
  58. data/test/yao/resources/test_role_assignment.rb +4 -6
  59. data/test/yao/resources/test_router.rb +26 -6
  60. data/test/yao/resources/test_sample.rb +61 -0
  61. data/test/yao/resources/test_security_group.rb +23 -1
  62. data/test/yao/resources/test_security_group_rule.rb +1 -1
  63. data/test/yao/resources/test_server.rb +34 -8
  64. data/test/yao/resources/test_subnet.rb +25 -6
  65. data/test/yao/resources/test_user.rb +73 -1
  66. data/test/yao/resources/test_volume.rb +31 -1
  67. data/test/yao/resources/test_volume_type.rb +1 -1
  68. data/test/yao/test_config.rb +21 -8
  69. data/test/yao/test_read_only.rb +3 -3
  70. data/yao.gemspec +0 -8
  71. metadata +22 -101
  72. data/.travis.yml +0 -28
@@ -1,4 +1,4 @@
1
- class TestRole < Test::Unit::TestCase
1
+ class TestRole < TestYaoResource
2
2
  def test_role_attributes
3
3
  params = {
4
4
  "name" => "test_role",
@@ -9,4 +9,258 @@ class TestRole < Test::Unit::TestCase
9
9
  assert_equal(role.name, "test_role")
10
10
  assert_equal(role.description, "test_description_1")
11
11
  end
12
+
13
+ sub_test_case 'with keystone v2.0' do
14
+
15
+ def setup
16
+ super
17
+ Yao.default_client.admin_pool["identity"] = Yao::Client.gen_client("https://example.com:12345/v2.0")
18
+ end
19
+
20
+ def test_find_by_name
21
+ stub = stub_request(:get, "https://example.com:12345/v2.0/OS-KSADM/roles").
22
+ to_return(
23
+ status: 200,
24
+ body: <<-JSON,
25
+ {
26
+ "roles": [{
27
+ "id": "0123456789abcdef0123456789abcdef",
28
+ "name": "admin"
29
+ }]
30
+ }
31
+ JSON
32
+ headers: {'Content-Type' => 'application/json'}
33
+ )
34
+
35
+ roles = Yao::Role.find_by_name("admin")
36
+
37
+ assert_instance_of(Yao::Role, roles.first)
38
+ assert_equal(roles.first.id, "0123456789abcdef0123456789abcdef")
39
+ assert_requested(stub)
40
+ end
41
+
42
+ def test_resource_path
43
+ stub = stub_request(:get, "https://example.com:12345/v2.0/OS-KSADM/roles").
44
+ to_return(
45
+ status: 200,
46
+ body: <<-JSON,
47
+ {
48
+ "roles": [{
49
+ "id": "0123456789abcdef0123456789abcdef",
50
+ "name": "admin"
51
+ }]
52
+ }
53
+ JSON
54
+ headers: {'Content-Type' => 'application/json'}
55
+ )
56
+
57
+ roles = Yao::Role.list
58
+
59
+ assert_instance_of(Yao::Role, roles.first)
60
+ assert_equal(roles.first.id, "0123456789abcdef0123456789abcdef")
61
+ assert_requested(stub)
62
+ end
63
+
64
+ def test_list_for_user
65
+ stub_user
66
+ stub_tenant
67
+ stub = stub_request(:get, "https://example.com:12345/v2.0/tenants/0123456789abcdef0123456789abcdef/users/2844b2a08be147a08ef58317d6471f1f/roles").
68
+ to_return(
69
+ status: 200,
70
+ body: <<-JSON,
71
+ {
72
+ "roles": [{
73
+ "id": "0123456789abcdef0123456789abcdef",
74
+ "name": "admin"
75
+ }]
76
+ }
77
+ JSON
78
+ headers: {'Content-Type' => 'application/json'}
79
+ )
80
+
81
+ roles = Yao::Role.list_for_user("test_user", on:"admin")
82
+ assert_equal(roles.first.id, "0123456789abcdef0123456789abcdef")
83
+ assert_received(Yao::User) { |subject| subject.get("test_user") }
84
+ assert_received(Yao::Tenant) { |subject| subject.find_by_name("admin") }
85
+ assert_requested(stub)
86
+ end
87
+
88
+ def test_grant
89
+ stub_role
90
+ stub_user
91
+ stub_tenant
92
+ stub = stub_request(:put, "https://example.com:12345/v2.0/tenants/0123456789abcdef0123456789abcdef/users/2844b2a08be147a08ef58317d6471f1f/roles/OS-KSADM/5318e65d75574c17bf5339d3df33a5a3").
93
+ to_return(
94
+ status: 204,
95
+ body: "",
96
+ headers: {'Content-Type' => 'application/json'}
97
+ )
98
+
99
+ Yao::Role.grant("test_role", to:"test_user", on:"admin")
100
+ assert_received(Yao::Role) { |subject| subject.get("test_role") }
101
+ assert_received(Yao::User) { |subject| subject.get("test_user") }
102
+ assert_received(Yao::Tenant) { |subject| subject.find_by_name("admin") }
103
+ assert_requested(stub)
104
+ end
105
+
106
+ def test_revoke
107
+ stub_role
108
+ stub_user
109
+ stub_tenant
110
+ stub = stub_request(:delete, "https://example.com:12345/v2.0/tenants/0123456789abcdef0123456789abcdef/users/2844b2a08be147a08ef58317d6471f1f/roles/OS-KSADM/5318e65d75574c17bf5339d3df33a5a3").
111
+ to_return(
112
+ status: 204,
113
+ body: "",
114
+ headers: {'Content-Type' => 'application/json'}
115
+ )
116
+
117
+ Yao::Role.revoke("test_role", from:"test_user", on:"admin")
118
+ assert_received(Yao::Role) { |subject| subject.get("test_role") }
119
+ assert_received(Yao::User) { |subject| subject.get("test_user") }
120
+ assert_received(Yao::Tenant) { |subject| subject.find_by_name("admin") }
121
+ assert_requested(stub)
122
+ end
123
+ end
124
+
125
+ sub_test_case 'with keystone v3' do
126
+
127
+ def setup
128
+ super
129
+ Yao.default_client.admin_pool["identity"] = Yao::Client.gen_client("https://example.com:12345/v3")
130
+ end
131
+
132
+ def test_find_by_name
133
+ stub = stub_request(:get, "https://example.com:12345/v3/roles?name=admin").
134
+ to_return(
135
+ status: 200,
136
+ body: <<-JSON,
137
+ {
138
+ "roles": [{
139
+ "id": "0123456789abcdef0123456789abcdef",
140
+ "name": "admin"
141
+ }]
142
+ }
143
+ JSON
144
+ headers: {'Content-Type' => 'application/json'}
145
+ )
146
+
147
+ roles = Yao::Role.find_by_name("admin")
148
+
149
+ assert_instance_of(Yao::Role, roles.first)
150
+ assert_equal(roles.first.id, "0123456789abcdef0123456789abcdef")
151
+ assert_requested(stub)
152
+ end
153
+
154
+ def test_resource_path
155
+ stub = stub_request(:get, "https://example.com:12345/v3/roles").
156
+ to_return(
157
+ status: 200,
158
+ body: <<-JSON,
159
+ {
160
+ "roles": [{
161
+ "id": "0123456789abcdef0123456789abcdef",
162
+ "name": "admin"
163
+ }]
164
+ }
165
+ JSON
166
+ headers: {'Content-Type' => 'application/json'}
167
+ )
168
+
169
+ roles = Yao::Role.list
170
+
171
+ assert_instance_of(Yao::Role, roles.first)
172
+ assert_equal(roles.first.id, "0123456789abcdef0123456789abcdef")
173
+ assert_requested(stub)
174
+ end
175
+
176
+ def test_list_for_user
177
+ stub_user
178
+ stub_project
179
+ stub = stub_request(:get, "https://example.com:12345/v3/projects/0123456789abcdef0123456789abcdef/users/2844b2a08be147a08ef58317d6471f1f/roles").
180
+ to_return(
181
+ status: 200,
182
+ body: <<-JSON,
183
+ {
184
+ "roles": [{
185
+ "id": "0123456789abcdef0123456789abcdef",
186
+ "name": "admin"
187
+ }]
188
+ }
189
+ JSON
190
+ headers: {'Content-Type' => 'application/json'}
191
+ )
192
+
193
+ roles = Yao::Role.list_for_user("test_user", on:"admin")
194
+ assert_equal(roles.first.id, "0123456789abcdef0123456789abcdef")
195
+ assert_received(Yao::Resources::User) { |subject| subject.get("test_user") }
196
+ assert_received(Yao::Resources::Project) { |subject| subject.get("admin") }
197
+ assert_requested(stub)
198
+ end
199
+
200
+ def test_grant
201
+ stub_role
202
+ stub_user
203
+ stub_project
204
+ stub = stub_request(:put, "https://example.com:12345/v3/projects/0123456789abcdef0123456789abcdef/users/2844b2a08be147a08ef58317d6471f1f/roles/5318e65d75574c17bf5339d3df33a5a3").
205
+ to_return(
206
+ status: 204,
207
+ body: "",
208
+ headers: {'Content-Type' => 'application/json'}
209
+ )
210
+
211
+ Yao::Role.grant("test_role", to:"test_user", on:"admin")
212
+ assert_received(Yao::Role) { |subject| subject.get("test_role") }
213
+ assert_received(Yao::User) { |subject| subject.get("test_user") }
214
+ assert_received(Yao::Project) { |subject| subject.get("admin") }
215
+ assert_requested(stub)
216
+ end
217
+
218
+ def test_revoke
219
+ stub_role
220
+ stub_user
221
+ stub_project
222
+ stub = stub_request(:delete, "https://example.com:12345/v3/projects/0123456789abcdef0123456789abcdef/users/2844b2a08be147a08ef58317d6471f1f/roles/5318e65d75574c17bf5339d3df33a5a3").
223
+ to_return(
224
+ status: 204,
225
+ body: "",
226
+ headers: {'Content-Type' => 'application/json'}
227
+ )
228
+
229
+ Yao::Role.revoke("test_role", from:"test_user", on:"admin")
230
+ assert_received(Yao::Role) { |subject| subject.get("test_role") }
231
+ assert_received(Yao::User) { |subject| subject.get("test_user") }
232
+ assert_received(Yao::Project) { |subject| subject.get("admin") }
233
+ assert_requested(stub)
234
+ end
235
+ end
236
+
237
+ private
238
+ def stub_role
239
+ stub(Yao::Role).get { Yao::Role.new(
240
+ "id" => "5318e65d75574c17bf5339d3df33a5a3",
241
+ "name" => "test_role",
242
+ "description" => "test_description_1"
243
+ )}
244
+ end
245
+
246
+ def stub_user
247
+ stub(Yao::User).get { Yao::User.new({
248
+ "id" => "2844b2a08be147a08ef58317d6471f1f",
249
+ "name" => "test_user",
250
+ }) }
251
+ end
252
+
253
+ def stub_tenant
254
+ stub(Yao::Tenant).find_by_name { Yao::Tenant.new({
255
+ "id" => "0123456789abcdef0123456789abcdef",
256
+ "name" => "admin",
257
+ }) }
258
+ end
259
+
260
+ def stub_project
261
+ stub(Yao::Project).get { Yao::Tenant.new({
262
+ "id" => "0123456789abcdef0123456789abcdef",
263
+ "name" => "admin",
264
+ }) }
265
+ end
12
266
  end
@@ -1,8 +1,4 @@
1
- class TestRoleAssignment < Test::Unit::TestCase
2
-
3
- def setup
4
- Yao.default_client.pool["compute"] = Yao::Client.gen_client("https://example.com:12345")
5
- end
1
+ class TestRoleAssignment < TestYaoResource
6
2
 
7
3
  def test_role_assignment
8
4
 
@@ -37,7 +33,7 @@ class TestRoleAssignment < Test::Unit::TestCase
37
33
  end
38
34
 
39
35
  def test_project
40
- stub_request(:get, "http://endpoint.example.com:12345/tenants/456789").
36
+ stub = stub_request(:get, "http://example.com:12345/tenants/456789").
41
37
  to_return(
42
38
  status: 200,
43
39
  body: <<-JSON,
@@ -61,5 +57,7 @@ class TestRoleAssignment < Test::Unit::TestCase
61
57
  role_assignment = Yao::RoleAssignment.new(params)
62
58
  assert_instance_of(Yao::Resources::Tenant, role_assignment.project)
63
59
  assert_equal(role_assignment.project.id, "456789")
60
+
61
+ assert_requested(stub)
64
62
  end
65
63
  end
@@ -1,8 +1,4 @@
1
- class TestRouter < Test::Unit::TestCase
2
-
3
- def setup
4
- Yao.default_client.pool["network"] = Yao::Client.gen_client("https://example.com:12345")
5
- end
1
+ class TestRouter < TestYaoResource
6
2
 
7
3
  def test_router
8
4
 
@@ -108,7 +104,7 @@ class TestRouter < Test::Unit::TestCase
108
104
  end
109
105
 
110
106
  def test_iterfaces
111
- stub_request(:get, "https://example.com:12345/ports?device_id=00000000-0000-0000-0000-000000000000")
107
+ stub = stub_request(:get, "https://example.com:12345/ports?device_id=00000000-0000-0000-0000-000000000000")
112
108
  .to_return(
113
109
  status: 200,
114
110
  body: <<-JSON,
@@ -129,5 +125,29 @@ class TestRouter < Test::Unit::TestCase
129
125
  port = router.interfaces.first
130
126
  assert_instance_of(Yao::Port, port)
131
127
  assert_equal(port.id, "00000000-0000-0000-0000-000000000000")
128
+
129
+ assert_requested(stub)
130
+ end
131
+
132
+ def test_tenant
133
+
134
+ stub = stub_request(:get, "https://example.com:12345/tenants/0123456789abcdef0123456789abcdef")
135
+ .to_return(
136
+ status: 200,
137
+ body: <<-JSON,
138
+ {
139
+ "tenant": {
140
+ "id": "0123456789abcdef0123456789abcdef"
141
+ }
142
+ }
143
+ JSON
144
+ headers: {'Content-Type' => 'application/json'}
145
+ )
146
+
147
+ router = Yao::Router.new('tenant_id' => '0123456789abcdef0123456789abcdef')
148
+ assert_instance_of(Yao::Tenant, router.tenant)
149
+ assert_equal(router.tenant.id, '0123456789abcdef0123456789abcdef')
150
+
151
+ assert_requested(stub)
132
152
  end
133
153
  end
@@ -0,0 +1,61 @@
1
+ class TestSample < TestYaoResource
2
+
3
+ def test_sample
4
+
5
+ # https://docs.openstack.org/ceilometer/pike/webapi/v2.html#Sample
6
+ params = {
7
+ "id" => "2e589cbc-738f-11e9-a9b2-bc764e200515",
8
+ "metadata" => {
9
+ "name1" => "value1",
10
+ "name2" => "value2"
11
+ },
12
+ "meter" => "instance",
13
+ "project_id" => "35b17138-b364-4e6a-a131-8f3099c5be68",
14
+ "recorded_at" => "2015-01-01T12:00:00",
15
+ "resource_id" => "bd9431c1-8d69-4ad3-803a-8d4a6b89fd36",
16
+ "source" => "openstack",
17
+ "timestamp" => "2015-01-01T12:00:00",
18
+ "type" => "gauge",
19
+ "unit" => "instance",
20
+ "user_id" => "efd87807-12d2-4b38-9c70-5f5c2ac427ff",
21
+ "volume" => 1.0
22
+ }
23
+
24
+ sample = Yao::Resources::Sample.new(params)
25
+ assert_equal(sample.id, "2e589cbc-738f-11e9-a9b2-bc764e200515")
26
+ assert_equal(sample.metadata, {
27
+ "name1" => "value1",
28
+ "name2" => "value2"
29
+ })
30
+ assert_equal(sample.meter, "instance")
31
+ assert_equal(sample.source, "openstack")
32
+ assert_equal(sample.type, "gauge")
33
+ assert_equal(sample.unit, "instance")
34
+ assert_equal(sample.volume, 1.0)
35
+ assert_equal(sample.resource_id, "bd9431c1-8d69-4ad3-803a-8d4a6b89fd36")
36
+ assert_equal(sample.user_id, "efd87807-12d2-4b38-9c70-5f5c2ac427ff")
37
+ assert_equal(sample.recorded_at, Time.parse("2015-01-01T12:00:00"))
38
+ assert_equal(sample.timestamp, Time.parse("2015-01-01T12:00:00"))
39
+ end
40
+
41
+ def test_resource
42
+ # https://docs.openstack.org/ceilometer/pike/webapi/v2.html
43
+ stub = stub_request(:get, "https://example.com:12345/v2/resources/00000000-0000-0000-0000-000000000000")
44
+ .to_return(
45
+ status: 200,
46
+ body: <<-JSON,
47
+ {
48
+ "resource_id": "00000000-0000-0000-0000-000000000000"
49
+ }
50
+ JSON
51
+ headers: {'Content-Type' => 'application/json'}
52
+ )
53
+
54
+ sample = Yao::Resources::Sample.new( 'resource_id' => '00000000-0000-0000-0000-000000000000' )
55
+
56
+ assert_instance_of(Yao::Resources::Resource, sample.resource)
57
+ assert_equal(sample.resource.id, "00000000-0000-0000-0000-000000000000")
58
+
59
+ assert_requested(stub)
60
+ end
61
+ end
@@ -1,4 +1,4 @@
1
- class TestSecurityGroup < Test::Unit::TestCase
1
+ class TestSecurityGroup < TestYaoResource
2
2
  def test_sg_attributes
3
3
  params = {
4
4
  "id" => "test_group_id_1",
@@ -22,4 +22,26 @@ class TestSecurityGroup < Test::Unit::TestCase
22
22
  assert_equal(sg.description, "test_description_1")
23
23
  assert(sg.rules[0].instance_of?(Yao::SecurityGroupRule))
24
24
  end
25
+
26
+ def test_sg_to_tenant
27
+
28
+ stub = stub_request(:get, "https://example.com:12345/tenants/0123456789abcdef0123456789abcdef")
29
+ .to_return(
30
+ status: 200,
31
+ body: <<-JSON,
32
+ {
33
+ "tenant": {
34
+ "id": "0123456789abcdef0123456789abcdef"
35
+ }
36
+ }
37
+ JSON
38
+ headers: {'Content-Type' => 'application/json'}
39
+ )
40
+
41
+ sg = Yao::SecurityGroup.new('tenant_id' => '0123456789abcdef0123456789abcdef')
42
+ assert_instance_of(Yao::Tenant, sg.tenant)
43
+ assert_equal(sg.tenant.id, '0123456789abcdef0123456789abcdef')
44
+
45
+ assert_requested(stub)
46
+ end
25
47
  end
@@ -1,4 +1,4 @@
1
- class TestSecurityGroup < Test::Unit::TestCase
1
+ class TestSecurityGroup < TestYaoResource
2
2
  def test_rule_attributes
3
3
  params = {
4
4
  "id" => "test_rule_id_1",
@@ -1,8 +1,4 @@
1
- class TestServer < Test::Unit::TestCase
2
-
3
- def setup
4
- Yao.default_client.pool["compute"] = Yao::Client.gen_client("https://example.com:12345")
5
- end
1
+ class TestServer < TestYaoResource
6
2
 
7
3
  def test_server
8
4
 
@@ -142,8 +138,8 @@ class TestServer < Test::Unit::TestCase
142
138
  assert_equal(server.ext_sts_vm_state, "active")
143
139
  end
144
140
 
145
- def test_list_detail
146
- stub_request(:get, "https://example.com:12345/servers/detail")
141
+ def test_list
142
+ stub = stub_request(:get, "https://example.com:12345/servers/detail")
147
143
  .to_return(
148
144
  status: 200,
149
145
  body: <<-JSON,
@@ -156,9 +152,39 @@ class TestServer < Test::Unit::TestCase
156
152
  headers: {'Content-Type' => 'application/json'}
157
153
  )
158
154
 
159
- servers = Yao::Server.list_detail
155
+ assert(Yao::Server.resources_detail_available)
156
+
157
+ servers = Yao::Server.list
160
158
  assert_instance_of(Array, servers)
161
159
  assert_instance_of(Yao::Server, servers.first)
162
160
  assert_equal(servers.first.id, 'dummy')
161
+
162
+ assert_requested(stub)
163
+ end
164
+
165
+ def test_list_detail
166
+ assert_equal(Yao::Server.method(:list_detail), Yao::Server.method(:list))
167
+ end
168
+
169
+ def test_tenant
170
+
171
+ stub = stub_request(:get, "https://example.com:12345/tenants/0123456789abcdef0123456789abcdef")
172
+ .to_return(
173
+ status: 200,
174
+ body: <<-JSON,
175
+ {
176
+ "tenant": {
177
+ "id": "0123456789abcdef0123456789abcdef"
178
+ }
179
+ }
180
+ JSON
181
+ headers: {'Content-Type' => 'application/json'}
182
+ )
183
+
184
+ server = Yao::Server.new('tenant_id' => '0123456789abcdef0123456789abcdef')
185
+ assert_instance_of(Yao::Tenant, server.tenant)
186
+ assert_equal(server.tenant.id, '0123456789abcdef0123456789abcdef')
187
+
188
+ assert_requested(stub)
163
189
  end
164
190
  end