@@ -1502,12 +1502,13 @@ def check_filtered_instances(*instances)
15021502 )
15031503 end
15041504 let ( :new_service_plan ) { VCAP ::CloudController ::ServicePlan . make ( service : service_offering ) }
1505+ let ( :original_maintenance_info ) { { version : '1.1.0' } }
15051506 let! ( :service_instance ) do
15061507 si = VCAP ::CloudController ::ManagedServiceInstance . make (
15071508 tags : %w( foo bar ) ,
15081509 space : space ,
15091510 service_plan : original_service_plan ,
1510- maintenance_info : { version : '1.1.0' }
1511+ maintenance_info : original_maintenance_info
15111512 )
15121513 si . annotation_ids = [
15131514 VCAP ::CloudController ::ServiceInstanceAnnotationModel . make ( key_prefix : 'pre.fix' , key_name : 'to_delete' , value : 'value' ) . id ,
@@ -1597,11 +1598,10 @@ def check_filtered_instances(*instances)
15971598 api_call . call ( space_dev_headers )
15981599
15991600 instance = VCAP ::CloudController ::ServiceInstance . last
1601+
16001602 stub_request ( :patch , "#{ instance . service_broker . broker_url } /v2/service_instances/#{ instance . guid } " ) .
1603+ with ( query : { 'accepts_incomplete' => true } ) .
16011604 to_return ( status : broker_status_code , body : broker_response . to_json , headers : { } )
1602-
1603- # TODO: add this when doing async responses:
1604- # with(query: { 'accepts_incomplete' => true }).
16051605 end
16061606
16071607 it 'sends a UPDATE request with the right arguments to the service broker' do
@@ -1610,8 +1610,7 @@ def check_filtered_instances(*instances)
16101610 expect (
16111611 a_request ( :patch , "#{ service_instance . service_broker . broker_url } /v2/service_instances/#{ service_instance . guid } " ) .
16121612 with (
1613- # TODO: add in when async part done:
1614- # query: { accepts_incomplete: true },
1613+ query : { accepts_incomplete : true } ,
16151614 body : {
16161615 service_id : new_service_plan . service . unique_id ,
16171616 plan_id : new_service_plan . unique_id ,
@@ -1675,6 +1674,174 @@ def check_filtered_instances(*instances)
16751674 end
16761675 end
16771676
1677+ context 'when the update is asynchronous' do
1678+ let ( :broker_status_code ) { 202 }
1679+ let ( :broker_response ) { { operation : 'task12' } }
1680+ let ( :last_operation_status_code ) { 200 }
1681+ let ( :last_operation_response ) { { state : 'in progress' } }
1682+
1683+ before do
1684+ stub_request ( :get , "#{ service_instance . service_broker . broker_url } /v2/service_instances/#{ service_instance . guid } /last_operation" ) .
1685+ with (
1686+ query : {
1687+ operation : 'task12' ,
1688+ service_id : service_instance . service_plan . service . unique_id ,
1689+ plan_id : service_instance . service_plan . unique_id ,
1690+ } ) .
1691+ to_return ( status : last_operation_status_code , body : last_operation_response . to_json , headers : { } )
1692+ end
1693+
1694+ it 'marks the job state as polling' do
1695+ execute_all_jobs ( expected_successes : 1 , expected_failures : 0 )
1696+ expect ( job . state ) . to eq ( VCAP ::CloudController ::PollableJobModel ::POLLING_STATE )
1697+ end
1698+
1699+ it 'calls last operation immediately' do
1700+ execute_all_jobs ( expected_successes : 1 , expected_failures : 0 )
1701+ expect (
1702+ a_request ( :get , "#{ service_instance . service_broker . broker_url } /v2/service_instances/#{ service_instance . guid } /last_operation" ) .
1703+ with (
1704+ query : {
1705+ operation : 'task12' ,
1706+ service_id : service_instance . service_plan . service . unique_id ,
1707+ plan_id : service_instance . service_plan . unique_id ,
1708+ } )
1709+ ) . to have_been_made . once
1710+ end
1711+
1712+ it 'enqueues the next fetch last operation job' do
1713+ execute_all_jobs ( expected_successes : 1 , expected_failures : 0 )
1714+ expect ( Delayed ::Job . count ) . to eq ( 1 )
1715+ end
1716+
1717+ context 'when last operation eventually returns `update succeeded`' do
1718+ let ( :last_operation_status_code ) { 200 }
1719+ let ( :last_operation_response ) { { state : 'in progress' } }
1720+
1721+ before do
1722+ stub_request ( :get , "#{ service_instance . service_broker . broker_url } /v2/service_instances/#{ service_instance . guid } /last_operation" ) .
1723+ with (
1724+ query : {
1725+ operation : 'task12' ,
1726+ service_id : service_instance . service_plan . service . unique_id ,
1727+ plan_id : service_instance . service_plan . unique_id ,
1728+ } ) .
1729+ to_return ( status : last_operation_status_code , body : last_operation_response . to_json , headers : { } ) . times ( 1 ) . then .
1730+ to_return ( status : 200 , body : { state : 'succeeded' } . to_json , headers : { } )
1731+
1732+ execute_all_jobs ( expected_successes : 1 , expected_failures : 0 )
1733+ expect ( job . state ) . to eq ( VCAP ::CloudController ::PollableJobModel ::POLLING_STATE )
1734+
1735+ Timecop . freeze ( Time . now + 1 . hour ) do
1736+ execute_all_jobs ( expected_successes : 1 , expected_failures : 0 )
1737+ end
1738+ end
1739+
1740+ it 'completes the job' do
1741+ updated_job = VCAP ::CloudController ::PollableJobModel . find ( guid : job . guid )
1742+ expect ( updated_job . state ) . to eq ( VCAP ::CloudController ::PollableJobModel ::COMPLETE_STATE )
1743+ end
1744+
1745+ it 'sets the service instance last operation to create succeeded' do
1746+ expect ( service_instance . last_operation . type ) . to eq ( 'update' )
1747+ expect ( service_instance . last_operation . state ) . to eq ( 'succeeded' )
1748+ end
1749+ end
1750+
1751+ context 'when last operation eventually returns `update failed`' do
1752+ before do
1753+ stub_request ( :get , "#{ service_instance . service_broker . broker_url } /v2/service_instances/#{ service_instance . guid } /last_operation" ) .
1754+ with (
1755+ query : {
1756+ operation : 'task12' ,
1757+ service_id : service_instance . service_plan . service . unique_id ,
1758+ plan_id : service_instance . service_plan . unique_id ,
1759+ } ) .
1760+ to_return ( status : last_operation_status_code , body : last_operation_response . to_json , headers : { } ) . times ( 1 ) . then .
1761+ to_return ( status : 200 , body : { state : 'failed' } . to_json , headers : { } )
1762+
1763+ execute_all_jobs ( expected_successes : 1 , expected_failures : 0 )
1764+ expect ( job . state ) . to eq ( VCAP ::CloudController ::PollableJobModel ::POLLING_STATE )
1765+
1766+ Timecop . freeze ( Time . now + 1 . hour ) do
1767+ execute_all_jobs ( expected_successes : 0 , expected_failures : 1 , jobs_to_execute : 1 )
1768+ end
1769+ end
1770+
1771+ it 'completes the job' do
1772+ updated_job = VCAP ::CloudController ::PollableJobModel . find ( guid : job . guid )
1773+ expect ( updated_job . state ) . to eq ( VCAP ::CloudController ::PollableJobModel ::FAILED_STATE )
1774+ end
1775+
1776+ it 'sets the service instance last operation to update failed' do
1777+ expect ( service_instance . last_operation . type ) . to eq ( 'update' )
1778+ expect ( service_instance . last_operation . state ) . to eq ( 'failed' )
1779+ end
1780+ end
1781+
1782+ context 'when last operation eventually returns error 400' do
1783+ before do
1784+ stub_request ( :get , "#{ service_instance . service_broker . broker_url } /v2/service_instances/#{ service_instance . guid } /last_operation" ) .
1785+ with (
1786+ query : {
1787+ operation : 'task12' ,
1788+ service_id : service_instance . service_plan . service . unique_id ,
1789+ plan_id : service_instance . service_plan . unique_id ,
1790+ } ) .
1791+ to_return ( status : last_operation_status_code , body : last_operation_response . to_json , headers : { } ) . times ( 1 ) . then .
1792+ to_return ( status : 400 , body : { } . to_json , headers : { } )
1793+
1794+ execute_all_jobs ( expected_successes : 1 , expected_failures : 0 )
1795+ expect ( job . state ) . to eq ( VCAP ::CloudController ::PollableJobModel ::POLLING_STATE )
1796+
1797+ Timecop . freeze ( Time . now + 1 . hour ) do
1798+ execute_all_jobs ( expected_successes : 0 , expected_failures : 1 , jobs_to_execute : 1 )
1799+ end
1800+ end
1801+
1802+ it 'completes the job' do
1803+ updated_job = VCAP ::CloudController ::PollableJobModel . find ( guid : job . guid )
1804+ expect ( updated_job . state ) . to eq ( VCAP ::CloudController ::PollableJobModel ::FAILED_STATE )
1805+ end
1806+
1807+ it 'sets the service instance last operation to update failed' do
1808+ expect ( service_instance . last_operation . type ) . to eq ( 'update' )
1809+ expect ( service_instance . last_operation . state ) . to eq ( 'failed' )
1810+ end
1811+
1812+ it 'does not update the instance' do
1813+ # TODO maybe look in the client to add this test and make sure what it returns? so we can test at a unit level in the job as well
1814+ service_instance . reload
1815+ expect ( service_instance . reload . tags ) . to eq ( %w( foo bar ) )
1816+ expect ( service_instance . service_plan ) . to eq ( original_service_plan )
1817+ expect_metadata (
1818+ service_instance ,
1819+ annotations : [
1820+ { prefix : 'pre.fix' , key : 'to_delete' , value : 'value' } ,
1821+ { prefix : 'pre.fix' , key : 'fox' , value : 'bushy' } ,
1822+ ] ,
1823+ labels : [
1824+ { prefix : 'pre.fix' , key : 'to_delete' , value : 'value' } ,
1825+ { prefix : 'pre.fix' , key : 'tail' , value : 'fluffy' }
1826+ ]
1827+ )
1828+ end
1829+
1830+ context 'when changing maintenance_info' do
1831+ let ( :request_body ) do
1832+ {
1833+ maintenance_info : { version : '1.1.1' } ,
1834+ }
1835+ end
1836+
1837+ it 'does not update the instance' do
1838+ service_instance . reload
1839+ expect ( service_instance . maintenance_info . symbolize_keys ) . to eq ( original_maintenance_info )
1840+ end
1841+ end
1842+ end
1843+ end
1844+
16781845 context 'changing maintenance_info alongside other parameters' do
16791846 let ( :new_maintenance_info ) { { version : '1.1.1' } }
16801847 let ( :request_body ) do
0 commit comments