Add fix for Download-Only deployment type on DDI-API (#848)
Signed-off-by: Jeroen Laverman <jeroen.laverman@bosch-si.com>
This commit is contained in:
@@ -142,6 +142,13 @@ public interface Action extends TenantAwareBaseEntity {
|
||||
return ActionType.FORCED == getActionType();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true when action is downloadonly, false otherwise
|
||||
*/
|
||||
default boolean isDownloadOnly() {
|
||||
return ActionType.DOWNLOAD_ONLY == getActionType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Action status as reported by the controller.
|
||||
*
|
||||
|
||||
@@ -294,7 +294,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
final DdiActionHistory actionHistory = actionHistoryMsgs.isEmpty() ? null
|
||||
: new DdiActionHistory(action.getStatus().name(), actionHistoryMsgs);
|
||||
|
||||
final HandlingType downloadType = action.isForce() ? HandlingType.FORCED : HandlingType.ATTEMPT;
|
||||
final HandlingType downloadType = calculateDownloadType(action);
|
||||
final HandlingType updateType = calculateUpdateType(action, downloadType);
|
||||
|
||||
final DdiMaintenanceWindowStatus maintenanceWindow = calculateMaintenanceWindow(action);
|
||||
@@ -302,7 +302,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
final DdiDeploymentBase base = new DdiDeploymentBase(Long.toString(action.getId()),
|
||||
new DdiDeployment(downloadType, updateType, chunks, maintenanceWindow), actionHistory);
|
||||
|
||||
LOG.debug("Found an active UpdateAction for target {}. returning deyploment: {}", controllerId, base);
|
||||
LOG.debug("Found an active UpdateAction for target {}. returning deployment: {}", controllerId, base);
|
||||
|
||||
controllerManagement.registerRetrieved(action.getId(), RepositoryConstants.SERVER_MESSAGE_PREFIX
|
||||
+ "Target retrieved update action and should start now the download.");
|
||||
@@ -313,6 +313,13 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
private static HandlingType calculateDownloadType(final Action action) {
|
||||
if (action.isDownloadOnly() || action.isForce()) {
|
||||
return HandlingType.FORCED;
|
||||
}
|
||||
return HandlingType.ATTEMPT;
|
||||
}
|
||||
|
||||
private static DdiMaintenanceWindowStatus calculateMaintenanceWindow(final Action action) {
|
||||
if (action.hasMaintenanceSchedule()) {
|
||||
return action.isMaintenanceWindowAvailable() ? DdiMaintenanceWindowStatus.AVAILABLE
|
||||
@@ -322,7 +329,9 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
private static HandlingType calculateUpdateType(final Action action, final HandlingType downloadType) {
|
||||
if (action.hasMaintenanceSchedule()) {
|
||||
if (action.isDownloadOnly()) {
|
||||
return HandlingType.SKIP;
|
||||
} else if (action.hasMaintenanceSchedule()) {
|
||||
return action.isMaintenanceWindowAvailable() ? downloadType : HandlingType.SKIP;
|
||||
}
|
||||
return downloadType;
|
||||
|
||||
@@ -24,6 +24,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -107,7 +108,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that artifacts are not found, when softare module does not exists.")
|
||||
@Description("Ensures that artifacts are not found, when software module does not exists.")
|
||||
public void artifactsNotFound() throws Exception {
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final Long softwareModuleIdNotExist = 1l;
|
||||
@@ -141,8 +142,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Forced deployment to a controller. Checks if the resource reponse payload for a given deployment is as expected.")
|
||||
public void deplomentForceAction() throws Exception {
|
||||
@Description("Forced deployment to a controller. Checks if the resource response payload for a given deployment is as expected.")
|
||||
public void deploymentForceAction() throws Exception {
|
||||
// Prepare test data
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
@@ -260,7 +261,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Checks that the deployementBase URL changes when the action is switched from soft to forced in TIMEFORCED case.")
|
||||
@Description("Checks that the deploymentBase URL changes when the action is switched from soft to forced in TIMEFORCED case.")
|
||||
public void changeEtagIfActionSwitchesFromSoftToForced() throws Exception {
|
||||
// Prepare test data
|
||||
final Target target = testdataFactory.createTarget("4712");
|
||||
@@ -297,8 +298,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Attempt/soft deployment to a controller. Checks if the resource reponse payload for a given deployment is as expected.")
|
||||
public void deplomentAttemptAction() throws Exception {
|
||||
@Description("Attempt/soft deployment to a controller. Checks if the resource response payload for a given deployment is as expected.")
|
||||
public void deploymentAttemptAction() throws Exception {
|
||||
// Prepare test data
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
@@ -306,7 +307,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final String visibleMetadataOsValue = "withValue";
|
||||
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomUtils.nextBytes(artifactSize);
|
||||
final byte[] random = RandomUtils.nextBytes(artifactSize);
|
||||
final Artifact artifact = artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(random), getOsModule(ds), "test1", false, artifactSize));
|
||||
final Artifact artifactSignature = artifactManagement.create(new ArtifactUpload(
|
||||
@@ -423,14 +424,14 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Attempt/soft deployment to a controller including automated switch to hard. Checks if the resource reponse payload for a given deployment is as expected.")
|
||||
public void deplomentAutoForceAction() throws Exception {
|
||||
@Description("Attempt/soft deployment to a controller including automated switch to hard. Checks if the resource response payload for a given deployment is as expected.")
|
||||
public void deploymentAutoForceAction() throws Exception {
|
||||
// Prepare test data
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomUtils.nextBytes(artifactSize);
|
||||
final byte[] random = RandomUtils.nextBytes(artifactSize);
|
||||
final Artifact artifact = artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(random), getOsModule(ds), "test1", false, artifactSize));
|
||||
final Artifact artifactSignature = artifactManagement.create(new ArtifactUpload(
|
||||
@@ -539,6 +540,133 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(actionStatusMessage.getStatus()).isEqualTo(Status.RETRIEVED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test download-only (forced + skip) deployment to a controller. Checks if the resource response payload for a given deployment is as expected.")
|
||||
public void deploymentDownloadOnlyAction () throws Exception {
|
||||
// Prepare test data
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
final String visibleMetadataOsKey = "metaDataVisible";
|
||||
final String visibleMetadataOsValue = "withValue";
|
||||
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte[] random = RandomUtils.nextBytes(artifactSize);
|
||||
final Artifact artifact = artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(random), getOsModule(ds), "test1", false, artifactSize));
|
||||
final Artifact artifactSignature = artifactManagement.create(new ArtifactUpload(
|
||||
new ByteArrayInputStream(random), getOsModule(ds), "test1.signature", false, artifactSize));
|
||||
|
||||
softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds))
|
||||
.key(visibleMetadataOsKey).value(visibleMetadataOsValue).targetVisible(true));
|
||||
softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds))
|
||||
.key("metaDataNotVisible").value("withValue").targetVisible(false));
|
||||
|
||||
final Target savedTarget = testdataFactory.createTarget("4712");
|
||||
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty();
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(0);
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(0);
|
||||
|
||||
List<Target> saved = deploymentManagement.assignDistributionSet(ds.getId(), ActionType.DOWNLOAD_ONLY,
|
||||
RepositoryModelConstants.NO_FORCE_TIME, Collections.singletonList(savedTarget.getControllerId()))
|
||||
.getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(1);
|
||||
assignDistributionSet(ds2, saved).getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(2);
|
||||
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
assertThat(uaction.getDistributionSet()).isEqualTo(ds);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
|
||||
// Run test
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href", startsWith("http://localhost/"
|
||||
+ tenantAware.getCurrentTenant() + "/controller/v1/4712/deploymentBase/" + uaction.getId())));
|
||||
assertThat(targetManagement.getByControllerID("4712").get().getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
assertThat(targetManagement.getByControllerID("4712").get().getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(2);
|
||||
|
||||
final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get();
|
||||
|
||||
mvc.perform(
|
||||
get("/{tenant}/controller/v1/4712/deploymentBase/" + uaction.getId(), tenantAware.getCurrentTenant())
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(action.getId()))))
|
||||
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.update", equalTo("skip")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='jvm')].name",
|
||||
contains(ds.findFirstModuleByType(runtimeType).get().getName())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='jvm')].version",
|
||||
contains(ds.findFirstModuleByType(runtimeType).get().getVersion())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].name",
|
||||
contains(ds.findFirstModuleByType(osType).get().getName())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].version",
|
||||
contains(ds.findFirstModuleByType(osType).get().getVersion())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].metadata[0].key").value(visibleMetadataOsKey))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].metadata[0].value")
|
||||
.value(visibleMetadataOsValue))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[0].size", contains(5 * 1024)))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[0].filename", contains("test1")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[0].hashes.md5",
|
||||
contains(artifact.getMd5Hash())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[0].hashes.sha1",
|
||||
contains(artifact.getSha1Hash())))
|
||||
.andExpect(
|
||||
jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[0]._links.download-http.href",
|
||||
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant()
|
||||
+ "/controller/v1/4712/softwaremodules/"
|
||||
+ getOsModule(findDistributionSetByAction) + "/artifacts/test1")))
|
||||
.andExpect(
|
||||
jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[0]._links.md5sum-http.href",
|
||||
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant()
|
||||
+ "/controller/v1/4712/softwaremodules/"
|
||||
+ getOsModule(findDistributionSetByAction) + "/artifacts/test1.MD5SUM")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[1].size", contains(5 * 1024)))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[1].filename",
|
||||
contains("test1.signature")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[1].hashes.md5",
|
||||
contains(artifactSignature.getMd5Hash())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[1].hashes.sha1",
|
||||
contains(artifactSignature.getSha1Hash())))
|
||||
.andExpect(
|
||||
jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[1]._links.download-http.href",
|
||||
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant()
|
||||
+ "/controller/v1/4712/softwaremodules/"
|
||||
+ getOsModule(findDistributionSetByAction) + "/artifacts/test1.signature")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[1]._links.md5sum-http.href",
|
||||
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant()
|
||||
+ "/controller/v1/4712/softwaremodules/" + getOsModule(findDistributionSetByAction)
|
||||
+ "/artifacts/test1.signature.MD5SUM")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='bApp')].version",
|
||||
contains(ds.findFirstModuleByType(appType).get().getVersion())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='bApp')].metadata").doesNotExist())
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='bApp')].name")
|
||||
.value(ds.findFirstModuleByType(appType).get().getName()));
|
||||
|
||||
// Retrieved is reported
|
||||
final List<ActionStatus> actionStatusMessages = deploymentManagement
|
||||
.findActionStatusByAction(PageRequest.of(0, 100, Direction.DESC, "id"), uaction.getId()).getContent();
|
||||
assertThat(actionStatusMessages).hasSize(2);
|
||||
final ActionStatus actionStatusMessage = actionStatusMessages.iterator().next();
|
||||
assertThat(actionStatusMessage.getStatus()).isEqualTo(Status.RETRIEVED);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test various invalid access attempts to the deployment resource und the expected behaviour of the server.")
|
||||
public void badDeploymentAction() throws Exception {
|
||||
@@ -563,7 +691,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
|
||||
// wrong media type
|
||||
final List<Target> toAssign = Arrays.asList(target);
|
||||
final List<Target> toAssign = Collections.singletonList(target);
|
||||
final DistributionSet savedSet = testdataFactory.createDistributionSet("");
|
||||
|
||||
final Long actionId = assignDistributionSet(savedSet, toAssign).getActionIds().get(0);
|
||||
@@ -575,9 +703,9 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("The server protects itself against to many feedback upload attempts. The test verfies that "
|
||||
+ "it is not possible to exceed the configured maximum number of feedback uplods.")
|
||||
public void tooMuchDeplomentActionFeedback() throws Exception {
|
||||
@Description("The server protects itself against to many feedback upload attempts. The test verifies that "
|
||||
+ "it is not possible to exceed the configured maximum number of feedback uploads.")
|
||||
public void tooMuchDeploymentActionFeedback() throws Exception {
|
||||
final Target target = testdataFactory.createTarget("4712");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
@@ -627,7 +755,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Multiple uploads of deployment status feedback to the server.")
|
||||
public void multipleDeplomentActionFeedback() throws Exception {
|
||||
public void multipleDeploymentActionFeedback() throws Exception {
|
||||
final Target savedTarget1 = testdataFactory.createTarget("4712");
|
||||
testdataFactory.createTarget("4713");
|
||||
testdataFactory.createTarget("4714");
|
||||
@@ -704,8 +832,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that an update action is correctly set to error if the controller provides error feedback.")
|
||||
public void rootRsSingleDeplomentActionWithErrorFeedback() throws Exception {
|
||||
@Description("Verifies that an update action is correctly set to error if the controller provides error feedback.")
|
||||
public void rootRsSingleDeploymentActionWithErrorFeedback() throws Exception {
|
||||
DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
final Target savedTarget = testdataFactory.createTarget("4712");
|
||||
|
||||
@@ -764,13 +892,13 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the controller can provided as much feedback entries as necessry as long as it is in the configured limites.")
|
||||
public void rootRsSingleDeplomentActionFeedback() throws Exception {
|
||||
@Description("Verifies that the controller can provided as much feedback entries as necessary as long as it is in the configured limits.")
|
||||
public void rootRsSingleDeploymentActionFeedback() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
final Target savedTarget = testdataFactory.createTarget("4712");
|
||||
|
||||
final List<Target> toAssign = Arrays.asList(savedTarget);
|
||||
final List<Target> toAssign = Collections.singletonList(savedTarget);
|
||||
|
||||
Target myT = targetManagement.getByControllerID("4712").get();
|
||||
assertThat(myT.getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN);
|
||||
@@ -891,8 +1019,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Various forbidden request appempts on the feedback resource. Ensures correct answering behaviour as expected to these kind of errors.")
|
||||
public void badDeplomentActionFeedback() throws Exception {
|
||||
@Description("Various forbidden request attempts on the feedback resource. Ensures correct answering behaviour as expected to these kind of errors.")
|
||||
public void badDeploymentActionFeedback() throws Exception {
|
||||
final DistributionSet savedSet = testdataFactory.createDistributionSet("");
|
||||
final DistributionSet savedSet2 = testdataFactory.createDistributionSet("1");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user