github.com/cloudfoundry-attic/cli-with-i18n@v6.32.1-0.20171002233121-7401370d3b85+incompatible/integration/assets/service_broker/spec/service_broker_spec.rb (about) 1 require 'spec_helper' 2 require 'json' 3 4 describe ServiceBroker do 5 before do 6 post '/config/reset' 7 end 8 9 describe 'GET /v2/catalog' do 10 it 'returns a non-empty catalog' do 11 get '/v2/catalog' 12 response = last_response 13 expect(response.body).to be 14 expect(JSON.parse(response.body)).to be 15 end 16 end 17 18 describe 'POST /v2/catalog' do 19 it 'changes the catalog' do 20 get '/v2/catalog' 21 first_response = last_response 22 expect(first_response.body).to be 23 24 post '/v2/catalog' 25 26 get '/v2/catalog' 27 second_response = last_response 28 expect(second_response.body).to eq(first_response.body) 29 end 30 end 31 32 describe 'PUT /v2/service_instances/:id' do 33 it 'returns 200 with an empty JSON body' do 34 put '/v2/service_instances/fakeIDThough', {}.to_json 35 expect(last_response.status).to eq(200) 36 expect(JSON.parse(last_response.body)).to be_empty 37 end 38 39 context 'when the plan is configured as async_only' do 40 before do 41 config = { 42 max_fetch_service_instance_requests: 1, 43 behaviors: { 44 provision: { 45 'fake-async-plan-guid' => { 46 sleep_seconds: 0, 47 async_only: true, 48 status: 202, 49 body: {} 50 }, 51 default: { 52 sleep_seconds: 0, 53 status: 202, 54 body: {} 55 } 56 } 57 } 58 }.to_json 59 60 post '/config', config 61 end 62 63 64 context 'request is for an async plan' do 65 it 'returns as usual if it does include accepts_incomplete' do 66 put '/v2/service_instances/fake-guid?accepts_incomplete=true', {plan_id: 'fake-async-plan-guid'}.to_json 67 68 expect(last_response.status).to eq(202) 69 end 70 71 it 'rejects request if it does not include accepts_incomplete' do 72 put '/v2/service_instances/fake-guid', {plan_id: 'fake-async-plan-guid'}.to_json 73 74 expect(last_response.status).to eq(422) 75 expect(last_response.body).to eq( 76 { 77 'error' => 'AsyncRequired', 78 'description' => 'This service plan requires client support for asynchronous service operations.' 79 }.to_json 80 ) 81 end 82 end 83 84 end 85 end 86 87 describe 'PATCH /v2/service_instance/:id' do 88 context 'when updating to an async plan' do 89 it 'returns a 202' do 90 patch '/v2/service_instances/fake-guid?accepts_incomplete=true', {plan_id: 'fake-async-plan-guid'}.to_json 91 expect(last_response.status).to eq(202) 92 end 93 end 94 95 context 'when updating to a sync plan' do 96 it 'returns a 200' do 97 patch '/v2/service_instances/fake-guid?accepts_incomplete=true', {plan_id: 'fake-plan-guid'}.to_json 98 expect(last_response.status).to eq(200) 99 end 100 end 101 102 context 'when the plan is configured as async_only' do 103 before do 104 config = { 105 max_fetch_service_instance_requests: 1, 106 behaviors: { 107 update: { 108 'fake-async-plan-guid' => { 109 sleep_seconds: 0, 110 async_only: true, 111 status: 202, 112 body: {} 113 }, 114 default: { 115 sleep_seconds: 0, 116 status: 202, 117 body: {} 118 } 119 } 120 } 121 }.to_json 122 123 post '/config', config 124 end 125 126 127 context 'request is for an async plan' do 128 it 'returns as usual if it does include accepts_incomplete' do 129 patch '/v2/service_instances/fake-guid?accepts_incomplete=true', {plan_id: 'fake-async-plan-guid'}.to_json 130 131 expect(last_response.status).to eq(202) 132 end 133 134 it 'rejects request if it does not include accepts_incomplete' do 135 patch '/v2/service_instances/fake-guid', {plan_id: 'fake-async-plan-guid'}.to_json 136 137 expect(last_response.status).to eq(422) 138 expect(last_response.body).to eq( 139 { 140 'error' => 'AsyncRequired', 141 'description' => 'This service plan requires client support for asynchronous service operations.' 142 }.to_json 143 ) 144 end 145 end 146 147 end 148 end 149 150 describe 'DELETE /v2/service_instances/:id' do 151 before do 152 put '/v2/service_instances/fake-guid?accepts_incomplete=true', {plan_id: 'fake-async-plan-guid'}.to_json 153 expect(last_response.status).to eq(202) 154 end 155 156 context 'when the plan is configured as async_only' do 157 before do 158 config = { 159 max_fetch_service_instance_requests: 1, 160 behaviors: { 161 deprovision: { 162 'fake-async-plan-guid' => { 163 sleep_seconds: 0, 164 async_only: true, 165 status: 202, 166 body: {} 167 }, 168 default: { 169 sleep_seconds: 0, 170 status: 202, 171 body: {} 172 } 173 } 174 } 175 }.to_json 176 177 post '/config', config 178 end 179 180 181 context 'request is for an async plan' do 182 it 'returns as usual if it does include accepts_incomplete' do 183 delete '/v2/service_instances/fake-guid?accepts_incomplete=true' 184 185 expect(last_response.status).to eq(202) 186 end 187 188 it 'rejects request if it does not include accepts_incomplete' do 189 delete '/v2/service_instances/fake-guid' 190 191 expect(last_response.status).to eq(422) 192 expect(last_response.body).to eq( 193 { 194 'error' => 'AsyncRequired', 195 'description' => 'This service plan requires client support for asynchronous service operations.' 196 }.to_json 197 ) 198 end 199 end 200 end 201 end 202 203 describe 'configuration management' do 204 before do 205 post '/config/reset' 206 end 207 208 def provision 209 put '/v2/service_instances/fake-guid', {plan_id: 'fake-plan-guid'}.to_json 210 end 211 212 def deprovision 213 delete '/v2/service_instances/fake-guid?plan_id=fake-plan-guid', {}.to_json 214 end 215 216 def update 217 patch '/v2/service_instances/fake-guid', {plan_id: 'fake-plan-guid'}.to_json 218 end 219 220 def bind 221 put '/v2/service_instances/fake-guid/service_bindings/binding-gui', {plan_id: 'fake-plan-guid'}.to_json 222 end 223 224 def unbind 225 delete '/v2/service_instances/fake-guid/service_bindings/binding-gui?plan_id=fake-plan-guid', {}.to_json 226 end 227 228 [:provision, :deprovision, :update, :bind, :unbind].each do |action| 229 context "for a #{action} operation" do 230 before do 231 put '/v2/service_instances/fake-guid', {plan_id: 'fake-plan-guid'}.to_json unless action == :provision 232 put '/v2/service_instances/fake-guid/service_bindings/binding-gui', {plan_id: 'fake-plan-guid'}.to_json if action == :unbind 233 end 234 235 it 'should change the response using a json body' do 236 config = { 237 behaviors: { 238 action => { 239 default: { 240 status: 400, 241 sleep_seconds: 0, 242 body: {} 243 } 244 } 245 } 246 }.to_json 247 248 post '/config', config 249 250 send(action) 251 expect(last_response.status).to eq(400) 252 expect(last_response.body).to eq('{}') 253 end 254 255 it 'should change the response using an invalid json body' do 256 config = { 257 behaviors: { 258 action => { 259 default: { 260 status: 201, 261 sleep_seconds: 0, 262 raw_body: 'foo' 263 } 264 } 265 } 266 }.to_json 267 268 post '/config', config 269 270 send(action) 271 expect(last_response.status).to eq(201) 272 expect(last_response.body).to eq 'foo' 273 end 274 275 it 'should cause the action to sleep' do 276 config = { 277 behaviors: { 278 action => { 279 default: { 280 status: 200, 281 sleep_seconds: 1.1, 282 body: {} 283 } 284 } 285 } 286 }.to_json 287 288 post '/config', config 289 290 291 expect do 292 Timeout::timeout(1) do 293 send(action) 294 end 295 end.to raise_error(TimeoutError) 296 end 297 298 it 'can be customized on a per-plan basis' do 299 config = { 300 behaviors: { 301 action => { 302 'fake-plan-guid' => { 303 status: 200, 304 sleep_seconds: 0, 305 raw_body: 'fake-plan body' 306 }, 307 default: { 308 status: 400, 309 sleep_seconds: 0, 310 body: {} 311 } 312 } 313 } 314 }.to_json 315 316 post '/config', config 317 318 send(action) 319 expect(last_response.status).to eq(200) 320 expect(last_response.body).to eq('fake-plan body') 321 end 322 end 323 end 324 325 context 'for a fetch operation' do 326 before do 327 put '/v2/service_instances/fake-guid', {plan_id: 'fake-plan-guid'}.to_json 328 end 329 330 it 'should change the response using a json body' do 331 config = { 332 max_fetch_service_instance_requests: 1, 333 behaviors: { 334 fetch: { 335 default: { 336 in_progress: { 337 status: 200, 338 sleep_seconds: 0, 339 body: {} 340 }, 341 finished: { 342 status: 400, 343 sleep_seconds: 0, 344 body: { foo: :bar } 345 } 346 } 347 } 348 } 349 }.to_json 350 351 post '/config', config 352 353 get '/v2/service_instances/fake-guid/last_operation' 354 expect(last_response.status).to eq(200) 355 expect(last_response.body).to eq('{}') 356 357 get '/v2/service_instances/fake-guid/last_operation' 358 expect(last_response.status).to eq(400) 359 expect(last_response.body).to eq({ foo: :bar }.to_json) 360 end 361 362 it 'should change the response using an invalid json body' do 363 config = { 364 max_fetch_service_instance_requests: 1, 365 behaviors: { 366 fetch: { 367 default: { 368 in_progress: { 369 status: 200, 370 sleep_seconds: 0, 371 raw_body: 'cheese' 372 }, 373 finished: { 374 status: 400, 375 sleep_seconds: 0, 376 raw_body: 'cake' 377 } 378 } 379 } 380 } 381 }.to_json 382 383 post '/config', config 384 385 get '/v2/service_instances/fake-guid/last_operation' 386 expect(last_response.status).to eq(200) 387 expect(last_response.body).to eq 'cheese' 388 389 get '/v2/service_instances/fake-guid/last_operation' 390 expect(last_response.status).to eq(400) 391 expect(last_response.body).to eq 'cake' 392 end 393 394 it 'should cause the action to sleep' do 395 config = { 396 max_fetch_service_instance_requests: 1, 397 behaviors: { 398 fetch: { 399 default: { 400 in_progress: { 401 status: 200, 402 sleep_seconds: 1.1, 403 body: {} 404 }, 405 finished: { 406 status: 200, 407 sleep_seconds: 0.6, 408 body: { } 409 } 410 } 411 } 412 } 413 }.to_json 414 415 post '/config', config 416 417 expect do 418 Timeout::timeout(1) do 419 get '/v2/service_instances/fake-guid/last_operation' 420 end 421 end.to raise_error(TimeoutError) 422 423 expect do 424 Timeout::timeout(0.5) do 425 get '/v2/service_instances/fake-guid/last_operation' 426 end 427 end.to raise_error(TimeoutError) 428 end 429 430 it 'honors max_fetch_service_instance_request' do 431 config = { 432 max_fetch_service_instance_requests: 2, 433 behaviors: { 434 fetch: { 435 default: { 436 in_progress: { 437 status: 200, 438 sleep_seconds: 0, 439 body: {} 440 }, 441 finished: { 442 status: 400, 443 sleep_seconds: 0, 444 body: { foo: :bar } 445 } 446 } 447 } 448 } 449 }.to_json 450 451 post '/config', config 452 453 get '/v2/service_instances/fake-guid/last_operation' 454 expect(last_response.status).to eq(200) 455 expect(last_response.body).to eq('{}') 456 457 get '/v2/service_instances/fake-guid/last_operation' 458 expect(last_response.status).to eq(200) 459 expect(last_response.body).to eq('{}') 460 461 get '/v2/service_instances/fake-guid/last_operation' 462 expect(last_response.status).to eq(400) 463 expect(last_response.body).to eq({ foo: :bar }.to_json) 464 end 465 466 it 'can be customized on a per-plan basis' do 467 config = { 468 max_fetch_service_instance_requests: 1, 469 behaviors: { 470 fetch: { 471 'fake-plan-guid' => { 472 in_progress: { 473 status: 200, 474 sleep_seconds: 0, 475 body: { foo: 'bar' } 476 }, 477 finished: { 478 status: 201, 479 sleep_seconds: 0, 480 body: { foo: 'baz' } 481 } 482 }, 483 default: { 484 in_progress: { 485 status: 200, 486 sleep_seconds: 0, 487 body: {} 488 }, 489 finished: { 490 status: 400, 491 sleep_seconds: 0, 492 body: { foo: :bar } 493 } 494 } 495 } 496 } 497 }.to_json 498 499 post '/config', config 500 501 get '/v2/service_instances/fake-guid/last_operation' 502 expect(last_response.status).to eq(200) 503 expect(last_response.body).to eq({ foo: 'bar' }.to_json) 504 505 get '/v2/service_instances/fake-guid/last_operation' 506 expect(last_response.status).to eq(201) 507 expect(last_response.body).to eq({ foo: 'baz' }.to_json) 508 end 509 end 510 511 it 'should allow resetting the configuration to its defaults' do 512 get '/config' 513 data = last_response.body 514 515 config = { 516 behaviors: { 517 provision: { 518 default: { 519 status: 400, 520 sleep_seconds: 0, 521 body: {} 522 } 523 } 524 } 525 }.to_json 526 post '/config', config 527 528 post '/config/reset' 529 expect(last_response.status).to eq(200) 530 531 get '/config' 532 expect(last_response.body).to eq(data) 533 end 534 535 it 'should be able to restore a previously saved configuration' do 536 get '/config' 537 data = last_response.body 538 539 post '/config', data 540 expect(last_response.status).to eq(200) 541 expect(last_response.body).to eq(data) 542 end 543 end 544 end