1818
1919import static com .google .common .truth .Truth .assertThat ;
2020import static com .google .common .truth .Truth .assertWithMessage ;
21+ import static org .mockito .Mockito .mock ;
22+ import static org .mockito .Mockito .times ;
23+ import static org .mockito .Mockito .verify ;
24+ import static org .mockito .Mockito .when ;
2125
26+ import com .google .api .gax .longrunning .OperationFuture ;
2227import com .google .api .gax .rpc .NotFoundException ;
28+ import com .google .cloud .compute .v1 .AllocationSpecificSKUReservation ;
29+ import com .google .cloud .compute .v1 .Operation ;
2330import com .google .cloud .compute .v1 .Reservation ;
2431import com .google .cloud .compute .v1 .ReservationsClient ;
32+ import com .google .cloud .compute .v1 .ShareSettings ;
33+ import com .google .cloud .compute .v1 .ShareSettingsProjectConfig ;
2534import compute .CreateInstanceTemplate ;
2635import compute .CreateRegionalInstanceTemplate ;
2736import compute .DeleteInstanceTemplate ;
3645import java .util .concurrent .TimeoutException ;
3746import org .junit .Assert ;
3847import org .junit .jupiter .api .AfterAll ;
48+ import org .junit .jupiter .api .AfterEach ;
3949import org .junit .jupiter .api .Assertions ;
4050import org .junit .jupiter .api .BeforeAll ;
51+ import org .junit .jupiter .api .BeforeEach ;
4152import org .junit .jupiter .api .MethodOrderer ;
4253import org .junit .jupiter .api .Order ;
4354import org .junit .jupiter .api .Test ;
@@ -69,7 +80,16 @@ public class ReservationIT {
6980 private static final String REGIONAL_INSTANCE_TEMPLATE_URI =
7081 String .format ("projects/%s/regions/%s/instanceTemplates/%s" ,
7182 PROJECT_ID , REGION , REGIONAL_INSTANCE_TEMPLATE_NAME );
83+ private static final String SPECIFIC_SHARED_INSTANCE_TEMPLATE_NAME =
84+ "test-shared-inst-temp-" + javaVersion + "-"
85+ + UUID .randomUUID ().toString ().substring (0 , 8 );
86+ private static final String INSTANCE_TEMPLATE_SHARED_RESERV_URI =
87+ String .format ("projects/%s/global/instanceTemplates/%s" ,
88+ PROJECT_ID , SPECIFIC_SHARED_INSTANCE_TEMPLATE_NAME );
89+ private static final String RESERVATION_NAME_SHARED = "test-reservation-shared-" + javaVersion
90+ + "-" + UUID .randomUUID ().toString ().substring (0 , 8 );
7291 private static final int NUMBER_OF_VMS = 3 ;
92+ private ByteArrayOutputStream stdOut ;
7393
7494 // Check if the required environment variables are set.
7595 public static void requireEnvVar (String envVarName ) {
@@ -93,6 +113,7 @@ public static void setUp()
93113 Util .cleanUpExistingReservations (
94114 "test-reservation-global-" + javaVersion , PROJECT_ID , ZONE );
95115 Util .cleanUpExistingReservations ("test-reservation-regional-" + javaVersion , PROJECT_ID , ZONE );
116+ Util .cleanUpExistingInstanceTemplates ("test-shared-inst-temp-" + javaVersion , PROJECT_ID );
96117
97118 // Initialize the client once for all tests
98119 reservationsClient = ReservationsClient .create ();
@@ -105,6 +126,9 @@ public static void setUp()
105126 CreateRegionalInstanceTemplate .createRegionalInstanceTemplate (
106127 PROJECT_ID , REGION , REGIONAL_INSTANCE_TEMPLATE_NAME );
107128 assertThat (stdOut .toString ()).contains ("Instance Template Operation Status: DONE" );
129+ // Create instance template for shares reservation.
130+ CreateInstanceTemplate .createInstanceTemplate (
131+ PROJECT_ID , SPECIFIC_SHARED_INSTANCE_TEMPLATE_NAME );
108132
109133 stdOut .close ();
110134 System .setOut (out );
@@ -130,6 +154,13 @@ public static void cleanup()
130154 .contains ("Instance template deletion operation status for "
131155 + REGIONAL_INSTANCE_TEMPLATE_NAME );
132156
157+ // Delete instance template for shared reservation
158+ DeleteInstanceTemplate .deleteInstanceTemplate (
159+ PROJECT_ID , SPECIFIC_SHARED_INSTANCE_TEMPLATE_NAME );
160+ assertThat (stdOut .toString ())
161+ .contains ("Instance template deletion operation status for "
162+ + SPECIFIC_SHARED_INSTANCE_TEMPLATE_NAME );
163+
133164 // Delete all reservations created for testing.
134165 DeleteReservation .deleteReservation (PROJECT_ID , ZONE , RESERVATION_NAME_GLOBAL );
135166 DeleteReservation .deleteReservation (PROJECT_ID , ZONE , RESERVATION_NAME_REGIONAL );
@@ -149,6 +180,18 @@ public static void cleanup()
149180 System .setOut (out );
150181 }
151182
183+ @ BeforeEach
184+ public void beforeEach () {
185+ stdOut = new ByteArrayOutputStream ();
186+ System .setOut (new PrintStream (stdOut ));
187+ }
188+
189+ @ AfterEach
190+ public void afterEach () {
191+ stdOut = null ;
192+ System .setOut (null );
193+ }
194+
152195 @ Test
153196 @ Order (1 )
154197 public void testCreateReservationWithGlobalInstanceTemplate ()
@@ -189,4 +232,53 @@ public void testUpdateVmsForReservation()
189232
190233 Assert .assertEquals (newNumberOfVms , reservation .getSpecificReservation ().getCount ());
191234 }
235+
236+ @ Test
237+ public void testCreateSharedReservation ()
238+ throws ExecutionException , InterruptedException , TimeoutException {
239+ // Mock the ReservationsClient
240+ ReservationsClient mockReservationsClient = mock (ReservationsClient .class );
241+
242+ // This test require projects in the test environment to share reservation with,
243+ // therefore the operation should be mocked. If you want to make a real test,
244+ // please set the CONSUMER_PROJECT_ID_1 and CONSUMER_PROJECT_ID_2 accordingly.
245+ // Make sure that base project has proper permissions to share reservations.
246+ // See: https://cloud.google.com/compute/docs/instances/reservations-shared#shared_reservation_constraint
247+ ShareSettings shareSettings = ShareSettings .newBuilder ()
248+ .setShareType (String .valueOf (ShareSettings .ShareType .SPECIFIC_PROJECTS ))
249+ .putProjectMap ("CONSUMER_PROJECT_ID_1" , ShareSettingsProjectConfig .newBuilder ().build ())
250+ .putProjectMap ("CONSUMER_PROJECT_ID_2" , ShareSettingsProjectConfig .newBuilder ().build ())
251+ .build ();
252+
253+ Reservation reservation =
254+ Reservation .newBuilder ()
255+ .setName (RESERVATION_NAME_SHARED )
256+ .setZone (ZONE )
257+ .setSpecificReservationRequired (true )
258+ .setShareSettings (shareSettings )
259+ .setSpecificReservation (
260+ AllocationSpecificSKUReservation .newBuilder ()
261+ .setCount (NUMBER_OF_VMS )
262+ .setSourceInstanceTemplate (INSTANCE_TEMPLATE_SHARED_RESERV_URI )
263+ .build ())
264+ .build ();
265+
266+ OperationFuture mockFuture = mock (OperationFuture .class );
267+ when (mockReservationsClient .insertAsync (PROJECT_ID , ZONE , reservation ))
268+ .thenReturn (mockFuture );
269+ Operation mockOperation = mock (Operation .class );
270+ when (mockFuture .get (3 , TimeUnit .MINUTES )).thenReturn (mockOperation );
271+ when (mockOperation .hasError ()).thenReturn (false );
272+ when (mockOperation .getStatus ()).thenReturn (Operation .Status .DONE );
273+
274+ // Create an instance, passing in the mock client
275+ CreateSharedReservation creator = new CreateSharedReservation (mockReservationsClient );
276+
277+ creator .createSharedReservation (PROJECT_ID , ZONE ,
278+ RESERVATION_NAME_SHARED , INSTANCE_TEMPLATE_SHARED_RESERV_URI , NUMBER_OF_VMS );
279+
280+ verify (mockReservationsClient , times (1 ))
281+ .insertAsync (PROJECT_ID , ZONE , reservation );
282+ assertThat (stdOut .toString ()).contains ("Reservation created. Operation Status: DONE" );
283+ }
192284}
0 commit comments