Skip to content

Commit a113d08

Browse files
committed
fix: clean up deployment artifacts
1 parent 8461ad2 commit a113d08

File tree

16 files changed

+577
-26
lines changed

16 files changed

+577
-26
lines changed

src/integrationtests/java/com/aws/greengrass/integrationtests/deployment/DeploymentTaskIntegrationTest.java

Lines changed: 168 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,15 @@
120120
import static org.hamcrest.Matchers.nullValue;
121121
import static org.hamcrest.io.FileMatchers.anExistingDirectory;
122122
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.*;
128124

129125
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
130126
@SuppressWarnings("PMD.ExcessiveClassLength")
131127
// This test is essential and verified many details. Could be breakdown.
132128
class DeploymentTaskIntegrationTest extends BaseITCase {
133129

134130
public static final String SIMPLE_APP_NAME = "SimpleApp";
131+
public static final String BREAKING_APP_NAME = "BreakingApp";
135132
private static final String TEST_CUSTOMER_APP_STRING = "Hello Greengrass. This is a test";
136133
private static final String MOCK_GROUP_NAME = "thinggroup/group1";
137134
// 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_
12951292
assertThat(services, containsInAnyOrder("main", DEFAULT_NUCLEUS_COMPONENT_NAME));
12961293
}
12971294

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+
12981461
@SuppressWarnings("PMD.AvoidCatchingGenericException")
12991462
private Future<DeploymentResult> submitSampleJobDocument(URI uri, Long timestamp) throws Exception {
13001463
kernel.getContext().get(DeploymentDirectoryManager.class)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"DeploymentId": "f7fe5b16-574a-11ea-82b4-0242ac130004",
3+
"Packages": [
4+
{
5+
"Name": "BreakingApp",
6+
"ResolvedVersion": "1.0.0",
7+
"RootComponent": true
8+
}
9+
],
10+
"Timestamp": 1592574829000,
11+
"FailureHandlingPolicy": "ROLLBACK",
12+
"ComponentUpdatePolicy": {
13+
"Timeout": 60,
14+
"ComponentUpdatePolicyAction": "NOTIFY_COMPONENTS"
15+
}
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"DeploymentId": "f7fe5b16-574a-11ea-82b4-0242ac130004",
3+
"Packages": [
4+
{
5+
"Name": "BreakingApp",
6+
"ResolvedVersion": "2.0.0",
7+
"RootComponent": true
8+
}
9+
],
10+
"Timestamp": 1592574829000,
11+
"FailureHandlingPolicy": "ROLLBACK",
12+
"ComponentUpdatePolicy": {
13+
"Timeout": 60,
14+
"ComponentUpdatePolicyAction": "NOTIFY_COMPONENTS"
15+
}
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"DeploymentId": "f7fe5b16-574a-11ea-82b4-0242ac130004",
3+
"Packages": [
4+
{
5+
"Name": "BreakingApp",
6+
"ResolvedVersion": "3.0.0",
7+
"RootComponent": true
8+
}
9+
],
10+
"Timestamp": 1592574829000,
11+
"FailureHandlingPolicy": "ROLLBACK",
12+
"ComponentUpdatePolicy": {
13+
"Timeout": 60,
14+
"ComponentUpdatePolicyAction": "NOTIFY_COMPONENTS"
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore
2+
et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
3+
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
4+
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
5+
culpa qui officia deserunt mollit anim id est laborum.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore
2+
et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
3+
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
4+
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
5+
culpa qui officia deserunt mollit anim id est laborum.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore
2+
et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
3+
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
4+
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
5+
culpa qui officia deserunt mollit anim id est laborum.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
RecipeFormatVersion: '2020-01-25'
3+
ComponentName: BreakingApp
4+
ComponentDescription: A simple test app that breaks
5+
ComponentPublisher: Me
6+
ComponentVersion: '1.0.0'
7+
ComponentConfiguration:
8+
DefaultConfiguration:
9+
sampleText: This is a test
10+
Manifests:
11+
- Platform:
12+
os: all
13+
Lifecycle:
14+
install: echo Broken install. && sleep 5 && exit /b 1
15+
run:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
RecipeFormatVersion: '2020-01-25'
3+
ComponentName: BreakingApp
4+
ComponentDescription: A simple test app that breaks
5+
ComponentPublisher: Me
6+
ComponentVersion: '2.0.0'
7+
ComponentConfiguration:
8+
DefaultConfiguration:
9+
sampleText: This is a test
10+
Manifests:
11+
- Platform:
12+
os: all
13+
Lifecycle:
14+
install: echo Broken install. && sleep 5 && exit /b 1
15+
run:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
RecipeFormatVersion: '2020-01-25'
3+
ComponentName: BreakingApp
4+
ComponentDescription: A simple test app that breaks
5+
ComponentPublisher: Me
6+
ComponentVersion: '3.0.0'
7+
ComponentConfiguration:
8+
DefaultConfiguration:
9+
sampleText: This is a test
10+
Manifests:
11+
- Platform:
12+
os: all
13+
Lifecycle:
14+
install: echo Broken install. && sleep 5 && exit /b 1
15+
run:

0 commit comments

Comments
 (0)