|
120 | 120 | import static org.hamcrest.Matchers.nullValue; |
121 | 121 | import static org.hamcrest.io.FileMatchers.anExistingDirectory; |
122 | 122 | import static org.hamcrest.io.FileMatchers.anExistingFile; |
123 | | -import static org.junit.jupiter.api.Assertions.assertEquals; |
124 | | -import static org.junit.jupiter.api.Assertions.assertFalse; |
125 | | -import static org.junit.jupiter.api.Assertions.assertThrows; |
126 | | -import static org.junit.jupiter.api.Assertions.assertTrue; |
127 | | -import static org.junit.jupiter.api.Assertions.fail; |
| 123 | +import static org.junit.jupiter.api.Assertions.*; |
128 | 124 |
|
129 | 125 | @TestMethodOrder(MethodOrderer.OrderAnnotation.class) |
130 | 126 | @SuppressWarnings("PMD.ExcessiveClassLength") |
131 | 127 | // This test is essential and verified many details. Could be breakdown. |
132 | 128 | class DeploymentTaskIntegrationTest extends BaseITCase { |
133 | 129 |
|
134 | 130 | public static final String SIMPLE_APP_NAME = "SimpleApp"; |
| 131 | + public static final String BREAKING_APP_NAME = "BreakingApp"; |
135 | 132 | private static final String TEST_CUSTOMER_APP_STRING = "Hello Greengrass. This is a test"; |
136 | 133 | private static final String MOCK_GROUP_NAME = "thinggroup/group1"; |
137 | 134 | // Based on the recipe files of the packages in sample job document |
@@ -1295,6 +1292,172 @@ void GIVEN_services_with_dependency_broken_WHEN_new_deployment_failure_handling_ |
1295 | 1292 | assertThat(services, containsInAnyOrder("main", DEFAULT_NUCLEUS_COMPONENT_NAME)); |
1296 | 1293 | } |
1297 | 1294 |
|
| 1295 | + /** |
| 1296 | + * The following 4 test cases(102-105) aims to test artifact clean up for deployments |
| 1297 | + * we always keep 2 successful versions |
| 1298 | + * and if the latest deployment fails we keep that failed one on top of the 2 successful ones. |
| 1299 | + * @throws Exception |
| 1300 | + */ |
| 1301 | + |
| 1302 | + @Test |
| 1303 | + @Order(102) |
| 1304 | + void GIVEN_two_successful_deployments_WHEN_completed_THEN_both_artifacts_exist() throws Exception { |
| 1305 | + ComponentIdentifier comp1 = new ComponentIdentifier(SIMPLE_APP_NAME, new Semver("1.0.0")); |
| 1306 | + ComponentIdentifier comp2 = new ComponentIdentifier(SIMPLE_APP_NAME, new Semver("2.0.0")); |
| 1307 | + |
| 1308 | + preloadLocalStoreContent(SIMPLE_APP_NAME, "1.0.0"); |
| 1309 | + Future<DeploymentResult> result1 = submitSampleJobDocument( |
| 1310 | + DeploymentTaskIntegrationTest.class.getResource("SimpleAppJobDoc1.json").toURI(), |
| 1311 | + System.currentTimeMillis()); |
| 1312 | + assertEquals(DeploymentResult.DeploymentStatus.SUCCESSFUL, result1.get(DEPLOYMENT_TIMEOUT, TimeUnit.SECONDS).getDeploymentStatus()); |
| 1313 | + |
| 1314 | + preloadLocalStoreContent(SIMPLE_APP_NAME, "2.0.0"); |
| 1315 | + Future<DeploymentResult> result2 = submitSampleJobDocument( |
| 1316 | + DeploymentTaskIntegrationTest.class.getResource("SimpleAppJobDoc2.json").toURI(), |
| 1317 | + System.currentTimeMillis()); |
| 1318 | + assertEquals(DeploymentResult.DeploymentStatus.SUCCESSFUL, result2.get(DEPLOYMENT_TIMEOUT, TimeUnit.SECONDS).getDeploymentStatus()); |
| 1319 | + |
| 1320 | + assertRecipeArtifactExists(comp1); |
| 1321 | + assertRecipeArtifactExists(comp2); |
| 1322 | + } |
| 1323 | + |
| 1324 | + @Test |
| 1325 | + @Order(103) |
| 1326 | + void GIVEN_two_successful_and_two_failed_deployments_WHEN_completed_THEN_successful_and_latest_failed_artifacts_exist(ExtensionContext context) throws Exception { |
| 1327 | + ignoreExceptionUltimateCauseOfType(context, ServiceUpdateException.class); |
| 1328 | + ComponentIdentifier comp1 = new ComponentIdentifier(SIMPLE_APP_NAME, new Semver("1.0.0")); |
| 1329 | + ComponentIdentifier comp2 = new ComponentIdentifier(SIMPLE_APP_NAME, new Semver("2.0.0")); |
| 1330 | + ComponentIdentifier comp3 = new ComponentIdentifier(BREAKING_APP_NAME, new Semver("1.0.0")); |
| 1331 | + ComponentIdentifier comp4 = new ComponentIdentifier(BREAKING_APP_NAME, new Semver("2.0.0")); |
| 1332 | + |
| 1333 | + //deploy 1 good component |
| 1334 | + preloadLocalStoreContent(SIMPLE_APP_NAME, "1.0.0"); |
| 1335 | + Future<DeploymentResult> result1 = submitSampleJobDocument( |
| 1336 | + DeploymentTaskIntegrationTest.class.getResource("SimpleAppJobDoc1.json").toURI(), |
| 1337 | + System.currentTimeMillis()); |
| 1338 | + assertEquals(DeploymentResult.DeploymentStatus.SUCCESSFUL, result1.get(DEPLOYMENT_TIMEOUT, TimeUnit.SECONDS).getDeploymentStatus()); |
| 1339 | + |
| 1340 | + //deploy second good component |
| 1341 | + preloadLocalStoreContent(SIMPLE_APP_NAME, "2.0.0"); |
| 1342 | + Future<DeploymentResult> result2 = submitSampleJobDocument( |
| 1343 | + DeploymentTaskIntegrationTest.class.getResource("SimpleAppJobDoc2.json").toURI(), |
| 1344 | + System.currentTimeMillis()); |
| 1345 | + assertEquals(DeploymentResult.DeploymentStatus.SUCCESSFUL, result2.get(DEPLOYMENT_TIMEOUT, TimeUnit.SECONDS).getDeploymentStatus()); |
| 1346 | + |
| 1347 | + |
| 1348 | + //deploy first bad component |
| 1349 | + preloadLocalStoreContent(BREAKING_APP_NAME, "1.0.0"); |
| 1350 | + Future<DeploymentResult> result3 = submitSampleJobDocument( |
| 1351 | + DeploymentTaskIntegrationTest.class.getResource("BreakingAppJobDoc1.json").toURI(), |
| 1352 | + System.currentTimeMillis()); |
| 1353 | + assertThrows(ServiceLoadException.class, () -> kernel.locate(BREAKING_APP_NAME)); |
| 1354 | + assertEquals(DeploymentResult.DeploymentStatus.FAILED_ROLLBACK_COMPLETE, result3.get(DEPLOYMENT_TIMEOUT, TimeUnit.SECONDS).getDeploymentStatus()); |
| 1355 | + assertRecipeArtifactExists(comp3); |
| 1356 | + |
| 1357 | + //deploy third good component |
| 1358 | + preloadLocalStoreContent(BREAKING_APP_NAME, "2.0.0"); |
| 1359 | + Future<DeploymentResult> result4 = submitSampleJobDocument( |
| 1360 | + DeploymentTaskIntegrationTest.class.getResource("BreakingAppJobDoc2.json").toURI(), |
| 1361 | + System.currentTimeMillis()); |
| 1362 | + assertNotSame(result4.get(DEPLOYMENT_TIMEOUT, TimeUnit.SECONDS).getDeploymentStatus(), DeploymentResult.DeploymentStatus.SUCCESSFUL); |
| 1363 | + |
| 1364 | + |
| 1365 | + assertRecipeArtifactExists(comp1); |
| 1366 | + assertRecipeArtifactExists(comp2); |
| 1367 | + assertRecipeArtifactNotExists(comp3); |
| 1368 | + assertRecipeArtifactExists(comp4); |
| 1369 | + } |
| 1370 | + |
| 1371 | + @Test |
| 1372 | + @Order(104) |
| 1373 | + void GIVEN_multiple_failed_deployments_with_final_success_WHEN_completed_THEN_only_latest_successful_artifacts_exist(ExtensionContext context) throws Exception { |
| 1374 | + ignoreExceptionUltimateCauseOfType(context, ServiceUpdateException.class); |
| 1375 | + ComponentIdentifier comp1 = new ComponentIdentifier(BREAKING_APP_NAME, new Semver("1.0.0")); |
| 1376 | + ComponentIdentifier comp2 = new ComponentIdentifier(BREAKING_APP_NAME, new Semver("2.0.0")); |
| 1377 | + ComponentIdentifier comp3 = new ComponentIdentifier(SIMPLE_APP_NAME, new Semver("1.0.0")); |
| 1378 | + |
| 1379 | + //first bad component |
| 1380 | + preloadLocalStoreContent(BREAKING_APP_NAME, "1.0.0"); |
| 1381 | + Future<DeploymentResult> result1 = submitSampleJobDocument( |
| 1382 | + DeploymentTaskIntegrationTest.class.getResource("BreakingAppJobDoc1.json").toURI(), |
| 1383 | + System.currentTimeMillis()); |
| 1384 | + assertThrows(ServiceLoadException.class, () -> kernel.locate(BREAKING_APP_NAME)); |
| 1385 | + assertEquals(DeploymentResult.DeploymentStatus.FAILED_ROLLBACK_COMPLETE, result1.get(DEPLOYMENT_TIMEOUT, TimeUnit.SECONDS).getDeploymentStatus()); |
| 1386 | + assertRecipeArtifactExists(comp1); |
| 1387 | + |
| 1388 | + //second bad component |
| 1389 | + preloadLocalStoreContent(BREAKING_APP_NAME, "2.0.0"); |
| 1390 | + Future<DeploymentResult> result2 = submitSampleJobDocument( |
| 1391 | + DeploymentTaskIntegrationTest.class.getResource("BreakingAppJobDoc2.json").toURI(), |
| 1392 | + System.currentTimeMillis()); |
| 1393 | + assertThrows(ServiceLoadException.class, () -> kernel.locate(BREAKING_APP_NAME)); |
| 1394 | + assertEquals(DeploymentResult.DeploymentStatus.FAILED_ROLLBACK_COMPLETE, result2.get(DEPLOYMENT_TIMEOUT, TimeUnit.SECONDS).getDeploymentStatus()); |
| 1395 | + assertRecipeArtifactNotExists(comp1); |
| 1396 | + assertRecipeArtifactExists(comp2); |
| 1397 | + |
| 1398 | + // last good component |
| 1399 | + preloadLocalStoreContent(SIMPLE_APP_NAME, "1.0.0"); |
| 1400 | + Future<DeploymentResult> result3 = submitSampleJobDocument( |
| 1401 | + DeploymentTaskIntegrationTest.class.getResource("SimpleAppJobDoc1.json").toURI(), |
| 1402 | + System.currentTimeMillis()); |
| 1403 | + assertEquals(DeploymentResult.DeploymentStatus.SUCCESSFUL, result3.get(DEPLOYMENT_TIMEOUT, TimeUnit.SECONDS).getDeploymentStatus()); |
| 1404 | + |
| 1405 | + assertRecipeArtifactNotExists(comp1); |
| 1406 | + assertRecipeArtifactNotExists(comp2); |
| 1407 | + assertRecipeArtifactExists(comp3); |
| 1408 | + } |
| 1409 | + |
| 1410 | + @Test |
| 1411 | + @Order(105) |
| 1412 | + void GIVEN_successful_deployment_with_multiple_failed_deployments_with_final_success_WHEN_completed_THEN_last_two_successful_artifacts_exist(ExtensionContext context) throws Exception { |
| 1413 | + ignoreExceptionUltimateCauseOfType(context, ServiceUpdateException.class); |
| 1414 | + ComponentIdentifier comp1 = new ComponentIdentifier(SIMPLE_APP_NAME, new Semver("1.0.0")); |
| 1415 | + ComponentIdentifier comp2 = new ComponentIdentifier(BREAKING_APP_NAME, new Semver("1.0.0")); |
| 1416 | + ComponentIdentifier comp3 = new ComponentIdentifier(BREAKING_APP_NAME, new Semver("2.0.0")); |
| 1417 | + ComponentIdentifier comp4 = new ComponentIdentifier(SIMPLE_APP_NAME, new Semver("2.0.0")); |
| 1418 | + |
| 1419 | + //first good component |
| 1420 | + preloadLocalStoreContent(SIMPLE_APP_NAME, "1.0.0"); |
| 1421 | + Future<DeploymentResult> result1 = submitSampleJobDocument( |
| 1422 | + DeploymentTaskIntegrationTest.class.getResource("SimpleAppJobDoc1.json").toURI(), |
| 1423 | + System.currentTimeMillis()); |
| 1424 | + assertEquals(DeploymentResult.DeploymentStatus.SUCCESSFUL, result1.get(DEPLOYMENT_TIMEOUT, TimeUnit.SECONDS).getDeploymentStatus()); |
| 1425 | + |
| 1426 | + //first bad component |
| 1427 | + preloadLocalStoreContent(BREAKING_APP_NAME, "1.0.0"); |
| 1428 | + Future<DeploymentResult> result2 = submitSampleJobDocument( |
| 1429 | + DeploymentTaskIntegrationTest.class.getResource("BreakingAppJobDoc1.json").toURI(), |
| 1430 | + System.currentTimeMillis()); |
| 1431 | + assertThrows(ServiceLoadException.class, () -> kernel.locate(BREAKING_APP_NAME)); |
| 1432 | + assertEquals(DeploymentResult.DeploymentStatus.FAILED_ROLLBACK_COMPLETE, result2.get(DEPLOYMENT_TIMEOUT, TimeUnit.SECONDS).getDeploymentStatus()); |
| 1433 | + assertRecipeArtifactExists(comp1); |
| 1434 | + assertRecipeArtifactExists(comp2); |
| 1435 | + |
| 1436 | + // second bad component |
| 1437 | + preloadLocalStoreContent(BREAKING_APP_NAME, "2.0.0"); |
| 1438 | + Future<DeploymentResult> result3 = submitSampleJobDocument( |
| 1439 | + DeploymentTaskIntegrationTest.class.getResource("BreakingAppJobDoc2.json").toURI(), |
| 1440 | + System.currentTimeMillis()); |
| 1441 | + assertThrows(ServiceLoadException.class, () -> kernel.locate(BREAKING_APP_NAME)); |
| 1442 | + assertEquals(DeploymentResult.DeploymentStatus.FAILED_ROLLBACK_COMPLETE, result3.get(DEPLOYMENT_TIMEOUT, TimeUnit.SECONDS).getDeploymentStatus()); |
| 1443 | + assertRecipeArtifactExists(comp1); |
| 1444 | + assertRecipeArtifactNotExists(comp2); |
| 1445 | + assertRecipeArtifactExists(comp3); |
| 1446 | + |
| 1447 | + //last good component |
| 1448 | + preloadLocalStoreContent(SIMPLE_APP_NAME, "2.0.0"); |
| 1449 | + Future<DeploymentResult> result4 = submitSampleJobDocument( |
| 1450 | + DeploymentTaskIntegrationTest.class.getResource("SimpleAppJobDoc2.json").toURI(), |
| 1451 | + System.currentTimeMillis()); |
| 1452 | + assertEquals(DeploymentResult.DeploymentStatus.SUCCESSFUL, result4.get(DEPLOYMENT_TIMEOUT, TimeUnit.SECONDS).getDeploymentStatus()); |
| 1453 | + |
| 1454 | + assertRecipeArtifactExists(comp1); |
| 1455 | + assertRecipeArtifactNotExists(comp2); |
| 1456 | + assertRecipeArtifactNotExists(comp3); |
| 1457 | + assertRecipeArtifactExists(comp4); |
| 1458 | + |
| 1459 | + } |
| 1460 | + |
1298 | 1461 | @SuppressWarnings("PMD.AvoidCatchingGenericException") |
1299 | 1462 | private Future<DeploymentResult> submitSampleJobDocument(URI uri, Long timestamp) throws Exception { |
1300 | 1463 | kernel.getContext().get(DeploymentDirectoryManager.class) |
|
0 commit comments