diff --git a/pom.xml b/pom.xml
index 4da898d8a4..b6a06f7fde 100644
--- a/pom.xml
+++ b/pom.xml
@@ -47,7 +47,7 @@
2025.6.25
2.4.0
- 2025.7.25-6883709e548a1a5b33c7202e
+ 2025.7.29-6888d7ba4e318f3fad1d864c
3.0.23
diff --git a/step-automation-packages/step-automation-packages-controller/src/main/java/step/automation/packages/AutomationPackageServices.java b/step-automation-packages/step-automation-packages-controller/src/main/java/step/automation/packages/AutomationPackageServices.java
index 30c289918f..fd0e6f86f5 100644
--- a/step-automation-packages/step-automation-packages-controller/src/main/java/step/automation/packages/AutomationPackageServices.java
+++ b/step-automation-packages/step-automation-packages-controller/src/main/java/step/automation/packages/AutomationPackageServices.java
@@ -116,7 +116,7 @@ public String createAutomationPackage(@QueryParam("version") String apVersion,
ObjectId id = automationPackageManager.createAutomationPackage(
automationPackageInputStream, fileDetail.getFileName(),
apVersion, activationExpression,
- getObjectEnricher(), getObjectPredicate()
+ getObjectEnricher(), getObjectPredicate(), getObjectValidator()
);
return id == null ? null : id.toString();
} catch (AutomationPackageManagerException e) {
@@ -146,7 +146,7 @@ public String createAutomationPackageFromMaven(@QueryParam("version") String apV
try {
MavenArtifactIdentifier mavenArtifactIdentifier = getMavenArtifactIdentifierFromXml(mavenArtifactXml);
return automationPackageManager.createAutomationPackageFromMaven(
- mavenArtifactIdentifier, apVersion, activationExpression, getObjectEnricher(), getObjectPredicate()
+ mavenArtifactIdentifier, apVersion, activationExpression, getObjectEnricher(), getObjectPredicate(), getObjectValidator()
).toString();
} catch (AutomationPackageManagerException e) {
throw new ControllerServiceException(e.getMessage());
@@ -192,7 +192,8 @@ public List executeAutomationPackage(@FormDataParam("file") InputStream
fileDetail == null ? null : fileDetail.getFileName(),
executionParameters,
getObjectEnricher(),
- getObjectPredicate()
+ getObjectPredicate(),
+ getObjectValidator()
);
} catch (AutomationPackageManagerException e) {
throw new ControllerServiceException(e.getMessage());
@@ -259,7 +260,7 @@ public AutomationPackageUpdateResult updateAutomationPackage(@PathParam("id") St
return automationPackageManager.createOrUpdateAutomationPackage(
true, false, new ObjectId(id),
uploadedInputStream, fileDetail.getFileName(), apVersion, activationExpression,
- getObjectEnricher(), getObjectPredicate(), async != null && async
+ getObjectEnricher(), getObjectPredicate(), getObjectValidator(), async != null && async
);
} catch (AutomationPackageManagerException e) {
throw new ControllerServiceException(e.getMessage());
@@ -290,7 +291,7 @@ public Response createOrUpdateAutomationPackage(@QueryParam("async") Boolean asy
try {
AutomationPackageUpdateResult result = automationPackageManager.createOrUpdateAutomationPackage(
true, true, null, uploadedInputStream, fileDetail.getFileName(), apVersion, activationExpression,
- getObjectEnricher(), getObjectPredicate(), async != null && async
+ getObjectEnricher(), getObjectPredicate(), getObjectValidator(), async != null && async
);
Response.ResponseBuilder responseBuilder;
if (result.getStatus() == AutomationPackageUpdateStatus.CREATED) {
@@ -326,7 +327,7 @@ public AutomationPackageUpdateResult createOrUpdateAutomationPackageFromMaven(@Q
try {
MavenArtifactIdentifier mvnIdentifier = getMavenArtifactIdentifierFromXml(mavenArtifactXml);
return automationPackageManager.createOrUpdateAutomationPackageFromMaven(
- mvnIdentifier, true, true, null, apVersion, activationExpression, getObjectEnricher(), getObjectPredicate(), async == null ? false : async
+ mvnIdentifier, true, true, null, apVersion, activationExpression, getObjectEnricher(), getObjectPredicate(), getObjectValidator(), async == null ? false : async
);
} catch (AutomationPackageManagerException e) {
throw new ControllerServiceException(e.getMessage());
@@ -358,7 +359,7 @@ public AutomationPackageUpdateResult updateAutomationPackageFromMaven(@PathParam
MavenArtifactIdentifier mvnIdentifier = getMavenArtifactIdentifierFromXml(mavenArtifactXml);
return automationPackageManager.createOrUpdateAutomationPackageFromMaven(
mvnIdentifier, true, false, new ObjectId(id), apVersion,
- activationExpression, getObjectEnricher(), getObjectPredicate(), async == null ? false : async
+ activationExpression, getObjectEnricher(), getObjectPredicate(), getObjectValidator(), async == null ? false : async
);
} catch (AutomationPackageManagerException e) {
throw new ControllerServiceException(e.getMessage());
diff --git a/step-automation-packages/step-automation-packages-controller/src/test/java/step/automation/packages/AutomationPackageManagerOSTest.java b/step-automation-packages/step-automation-packages-controller/src/test/java/step/automation/packages/AutomationPackageManagerOSTest.java
index 534f749867..de699a350d 100644
--- a/step-automation-packages/step-automation-packages-controller/src/test/java/step/automation/packages/AutomationPackageManagerOSTest.java
+++ b/step-automation-packages/step-automation-packages-controller/src/test/java/step/automation/packages/AutomationPackageManagerOSTest.java
@@ -165,7 +165,7 @@ public void testCrud() throws IOException {
String fileName = "step-automation-packages-sample1-extended.jar";
File automationPackageJar = new File("src/test/resources/samples/" + fileName);
try (InputStream is = new FileInputStream(automationPackageJar)) {
- AutomationPackageUpdateResult result = manager.createOrUpdateAutomationPackage(true, true, null, is, fileName, null, null, null, null, false);
+ AutomationPackageUpdateResult result = manager.createOrUpdateAutomationPackage(true, true, null, is, fileName, null, null, null, null, null, false);
Assert.assertEquals(AutomationPackageUpdateStatus.UPDATED, result.getStatus());
ObjectId resultId = result.getId();
@@ -310,7 +310,7 @@ public void testResourcesInKeywordsAndPlans() throws IOException {
try (InputStream is = new FileInputStream(automationPackageJar)) {
ObjectId result;
- result = manager.createAutomationPackage(is, fileName, null, null, null, null);
+ result = manager.createAutomationPackage(is, fileName, null, null, null, null, null);
AutomationPackage storedPackage = automationPackageAccessor.get(result);
List storedPlans = planAccessor.findManyByCriteria(getAutomationPackageIdCriteria(result)).collect(Collectors.toList());
@@ -332,7 +332,7 @@ public void testResourcesInKeywordsAndPlans() throws IOException {
@Test
public void testInvalidFile() throws IOException {
try (InputStream is = new FileInputStream("src/test/resources/step/automation/packages/picture.png")) {
- manager.createAutomationPackage(is, "picture.png", null, null, null, null);
+ manager.createAutomationPackage(is, "picture.png", null, null, null, null, null);
Assert.fail("The exception should be thrown in case of invalid automation package file");
} catch (AutomationPackageManagerException ex) {
// ok - invalid file should cause the exception
@@ -343,7 +343,7 @@ public void testInvalidFile() throws IOException {
public void testZipArchive() throws IOException {
try (InputStream is = new FileInputStream("src/test/resources/step/automation/packages/step-automation-packages.zip")) {
ObjectId result;
- result = manager.createAutomationPackage(is, "step-automation-packages.zip", null, null, null, null);
+ result = manager.createAutomationPackage(is, "step-automation-packages.zip", null, null, null, null, null);
AutomationPackage storedPackage = automationPackageAccessor.get(result);
List storedPlans = planAccessor.findManyByCriteria(getAutomationPackageIdCriteria(result)).collect(Collectors.toList());
@@ -420,9 +420,9 @@ private SampleUploadingResult uploadSample1WithAsserts(boolean createNew, boolea
try (InputStream is = new FileInputStream(automationPackageJar)) {
ObjectId result;
if (createNew) {
- result = manager.createAutomationPackage(is, fileName, null, null, null, null);
+ result = manager.createAutomationPackage(is, fileName, null, null, null, null,null);
} else {
- AutomationPackageUpdateResult updateResult = manager.createOrUpdateAutomationPackage(true, true, null, is, fileName, null, null, null, null, async);
+ AutomationPackageUpdateResult updateResult = manager.createOrUpdateAutomationPackage(true, true, null, is, fileName, null, null, null, null, null, async);
if (async && expectedDelay) {
Assert.assertEquals(AutomationPackageUpdateStatus.UPDATE_DELAYED, updateResult.getStatus());
} else {
diff --git a/step-automation-packages/step-automation-packages-junit-core/src/main/java/step/automation/packages/junit/JUnitPlansProvider.java b/step-automation-packages/step-automation-packages-junit-core/src/main/java/step/automation/packages/junit/JUnitPlansProvider.java
index 490e80e99f..ffa81d9574 100644
--- a/step-automation-packages/step-automation-packages-junit-core/src/main/java/step/automation/packages/junit/JUnitPlansProvider.java
+++ b/step-automation-packages/step-automation-packages-junit-core/src/main/java/step/automation/packages/junit/JUnitPlansProvider.java
@@ -47,7 +47,7 @@ public List getTestPlans(ExecutionEngine executionEngine)
AutomationPackageFromClassLoaderProvider automationPackageProvider = new AutomationPackageFromClassLoaderProvider(testClass.getClassLoader());
ObjectId automationPackageId = automationPackageManager.createOrUpdateAutomationPackage(
false, true, null, automationPackageProvider, null, null,
- true, null, null, false
+ true, null, null, null, false
).getId();
List planFilterList = new ArrayList<>();
diff --git a/step-automation-packages/step-automation-packages-junit5/src/test/java/step/junit5/runner/StepRunnerWithPlansAnnotationTest.java b/step-automation-packages/step-automation-packages-junit5/src/test/java/step/junit5/runner/StepRunnerWithPlansAnnotationTest.java
index a318baa90f..6ec5123c29 100644
--- a/step-automation-packages/step-automation-packages-junit5/src/test/java/step/junit5/runner/StepRunnerWithPlansAnnotationTest.java
+++ b/step-automation-packages/step-automation-packages-junit5/src/test/java/step/junit5/runner/StepRunnerWithPlansAnnotationTest.java
@@ -22,6 +22,10 @@
import step.junit.runners.annotations.ExecutionParameters;
import step.junit.runners.annotations.Plans;
+/**
+ * This test covers some plans from annotation package. Plans with JMeter keywords are excluded to support local
+ * launch without installed JMeter. All plans including JMeter are covered by {@link StepAutomationPackageRunAllTest}
+ */
@ExcludePlans({"JMeter Plan", "testAutomation.plan"})
@Plans({"plans/plan2.plan", "plans/plan3.plan", "plans/assertsTest.plan"})
@ExecutionParameters({"PARAM_EXEC","Value","PARAM_EXEC2","Value","PARAM_EXEC3","Value"})
diff --git a/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/AutomationPackageManager.java b/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/AutomationPackageManager.java
index 1aa5422a7c..92f3dcaa07 100644
--- a/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/AutomationPackageManager.java
+++ b/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/AutomationPackageManager.java
@@ -30,10 +30,7 @@
import step.core.collections.IndexField;
import step.core.entities.Entity;
import step.core.maven.MavenArtifactIdentifier;
-import step.core.objectenricher.EnricheableObject;
-import step.core.objectenricher.ObjectEnricher;
-import step.core.objectenricher.ObjectEnricherComposer;
-import step.core.objectenricher.ObjectPredicate;
+import step.core.objectenricher.*;
import step.core.plans.InMemoryPlanAccessor;
import step.core.plans.Plan;
import step.core.plans.PlanAccessor;
@@ -291,14 +288,15 @@ protected void deleteAutomationPackageEntities(AutomationPackage automationPacka
deletePlans(automationPackage);
// schedules will be deleted in deleteAdditionalData via hooks
deleteResources(automationPackage);
- deleteAdditionalData(automationPackage, new AutomationPackageContext(operationMode, resourceManager, null, null,null, extensions));
+ // TODO: archive, packageContent, enricher and validator are only used in AutomationPackageContext for save/update - maybe it is better to create separate class AutomationPackageContextForSave rather then use nulls here
+ deleteAdditionalData(automationPackage, new AutomationPackageContext(operationMode, resourceManager, null, null,null, null, extensions));
}
- public ObjectId createAutomationPackageFromMaven(MavenArtifactIdentifier mavenArtifactIdentifier, String apVersion, String activationExpr, ObjectEnricher enricher, ObjectPredicate objectPredicate) {
+ public ObjectId createAutomationPackageFromMaven(MavenArtifactIdentifier mavenArtifactIdentifier, String apVersion, String activationExpr, ObjectEnricher enricher, ObjectPredicate objectPredicate, ObjectValidator objectValidator) {
validateMavenConfigAndArtifactClassifier(mavenArtifactIdentifier);
try {
try (AutomationPackageFromMavenProvider provider = new AutomationPackageFromMavenProvider(mavenConfigProvider.getConfig(objectPredicate), mavenArtifactIdentifier)) {
- return createOrUpdateAutomationPackage(false, true, null, provider, apVersion, activationExpr, false, enricher, objectPredicate, false).getId();
+ return createOrUpdateAutomationPackage(false, true, null, provider, apVersion, activationExpr, false, enricher, objectPredicate, objectValidator, false).getId();
}
} catch (IOException ex) {
throw new AutomationPackageManagerException("Automation package cannot be created. Caused by: " + ex.getMessage(), ex);
@@ -332,8 +330,9 @@ protected void validateMavenConfigAndArtifactClassifier(MavenArtifactIdentifier
* @return the id of created package
* @throws AutomationPackageManagerException
*/
- public ObjectId createAutomationPackage(InputStream packageStream, String fileName, String apVersion, String activationExpr, ObjectEnricher enricher, ObjectPredicate objectPredicate) throws AutomationPackageManagerException {
- return createOrUpdateAutomationPackage(false, true, null, packageStream, fileName, apVersion, activationExpr, enricher, objectPredicate, false).getId();
+ public ObjectId createAutomationPackage(InputStream packageStream, String fileName, String apVersion, String activationExpr,
+ ObjectEnricher enricher, ObjectPredicate objectPredicate, ObjectValidator validator) throws AutomationPackageManagerException {
+ return createOrUpdateAutomationPackage(false, true, null, packageStream, fileName, apVersion, activationExpr, enricher, objectPredicate, validator, false).getId();
}
/**
@@ -349,10 +348,11 @@ public ObjectId createAutomationPackage(InputStream packageStream, String fileNa
*/
public AutomationPackageUpdateResult createOrUpdateAutomationPackage(boolean allowUpdate, boolean allowCreate, ObjectId explicitOldId,
InputStream inputStream, String fileName, String apVersion, String activationExpr,
- ObjectEnricher enricher, ObjectPredicate objectPredicate, boolean async) throws AutomationPackageManagerException {
+ ObjectEnricher enricher, ObjectPredicate objectPredicate, ObjectValidator validator,
+ boolean async) throws AutomationPackageManagerException {
try {
try (AutomationPackageArchiveProvider provider = new AutomationPackageFromInputStreamProvider(inputStream, fileName)) {
- return createOrUpdateAutomationPackage(allowUpdate, allowCreate, explicitOldId, provider, apVersion, activationExpr, false, enricher, objectPredicate, async);
+ return createOrUpdateAutomationPackage(allowUpdate, allowCreate, explicitOldId, provider, apVersion, activationExpr, false, enricher, objectPredicate, validator, async);
}
} catch (IOException | AutomationPackageReadingException ex) {
throw new AutomationPackageManagerException("Automation package cannot be created. Caused by: " + ex.getMessage(), ex);
@@ -372,11 +372,12 @@ public AutomationPackageUpdateResult createOrUpdateAutomationPackage(boolean all
public AutomationPackageUpdateResult createOrUpdateAutomationPackageFromMaven(MavenArtifactIdentifier mavenArtifactIdentifier,
boolean allowUpdate, boolean allowCreate, ObjectId explicitOldId,
String apVersion, String activationExpr,
- ObjectEnricher enricher, ObjectPredicate objectPredicate, boolean async) throws AutomationPackageManagerException {
+ ObjectEnricher enricher, ObjectPredicate objectPredicate, ObjectValidator objectValidator,
+ boolean async) throws AutomationPackageManagerException {
try {
validateMavenConfigAndArtifactClassifier(mavenArtifactIdentifier);
try (AutomationPackageFromMavenProvider provider = new AutomationPackageFromMavenProvider(mavenConfigProvider.getConfig(objectPredicate), mavenArtifactIdentifier)) {
- return createOrUpdateAutomationPackage(allowUpdate, allowCreate, explicitOldId, provider, apVersion, activationExpr, false, enricher, objectPredicate, async);
+ return createOrUpdateAutomationPackage(allowUpdate, allowCreate, explicitOldId, provider, apVersion, activationExpr, false, enricher, objectPredicate, objectValidator, async);
}
} catch (IOException ex) {
throw new AutomationPackageManagerException("Automation package cannot be created. Caused by: " + ex.getMessage(), ex);
@@ -432,7 +433,8 @@ public void updateAutomationPackageMetadata(ObjectId id, String apVersion, Strin
*/
public AutomationPackageUpdateResult createOrUpdateAutomationPackage(boolean allowUpdate, boolean allowCreate, ObjectId explicitOldId,
AutomationPackageArchiveProvider automationPackageProvider, String apVersion, String activationExpr,
- boolean isLocalPackage, ObjectEnricher enricher, ObjectPredicate objectPredicate, boolean async) {
+ boolean isLocalPackage, ObjectEnricher enricher,
+ ObjectPredicate objectPredicate, ObjectValidator validator, boolean async) {
AutomationPackageArchive automationPackageArchive;
AutomationPackageContent packageContent;
@@ -483,7 +485,7 @@ public AutomationPackageUpdateResult createOrUpdateAutomationPackage(boolean all
enrichers.add(new AutomationPackageLinkEnricher(newPackage.getId().toString()));
ObjectEnricher enricherForIncludedEntities = ObjectEnricherComposer.compose(enrichers);
- fillStaging(staging, packageContent, oldPackage, enricherForIncludedEntities, automationPackageArchive, activationExpr, objectPredicate);
+ fillStaging(staging, packageContent, oldPackage, enricherForIncludedEntities, validator, automationPackageArchive, activationExpr, objectPredicate);
// persist and activate automation package
log.debug("Updating automation package, old package is " + ((oldPackage == null) ? "null" : "not null" + ", async: " + async));
@@ -492,7 +494,7 @@ public AutomationPackageUpdateResult createOrUpdateAutomationPackage(boolean all
if (oldPackage == null || !async || immediateWriteLock) {
//If not async or if it's a new package, we synchronously wait on a write lock and update
log.info("Updating the automation package " + newPackage.getId().toString() + " synchronously, any running executions on this package will delay the update.");
- ObjectId result = updateAutomationPackage(oldPackage, newPackage, packageContent, staging, enricherForIncludedEntities, immediateWriteLock, automationPackageArchive);
+ ObjectId result = updateAutomationPackage(oldPackage, newPackage, packageContent, staging, enricherForIncludedEntities, validator, immediateWriteLock, automationPackageArchive);
return new AutomationPackageUpdateResult(oldPackage == null ? AutomationPackageUpdateStatus.CREATED : AutomationPackageUpdateStatus.UPDATED, result);
} else {
// async update
@@ -502,7 +504,7 @@ public AutomationPackageUpdateResult createOrUpdateAutomationPackage(boolean all
AutomationPackage finalNewPackage = newPackage;
delayedUpdateExecutor.submit(() -> {
try {
- updateAutomationPackage(oldPackage, finalNewPackage, packageContent, staging, enricherForIncludedEntities, false, automationPackageArchive);
+ updateAutomationPackage(oldPackage, finalNewPackage, packageContent, staging, enricherForIncludedEntities, validator, false, automationPackageArchive);
} catch (Exception e) {
log.error("Exception on delayed AP update", e);
}
@@ -533,7 +535,7 @@ public Map> getAllEntities(Obj
AutomationPackageHook> hook = automationPackageHookRegistry.getHook(hookName);
result.putAll(hook.getEntitiesForAutomationPackage(
automationPackageId,
- new AutomationPackageContext(operationMode, resourceManager, null, null, null, extensions)
+ new AutomationPackageContext(operationMode, resourceManager, null, null, null, null, extensions)
)
);
}
@@ -541,7 +543,8 @@ public Map> getAllEntities(Obj
}
private ObjectId updateAutomationPackage(AutomationPackage oldPackage, AutomationPackage newPackage,
- AutomationPackageContent packageContent, AutomationPackageStaging staging, ObjectEnricher enricherForIncludedEntities,
+ AutomationPackageContent packageContent, AutomationPackageStaging staging,
+ ObjectEnricher enricherForIncludedEntities, ObjectValidator validator,
boolean alreadyLocked, AutomationPackageArchive automationPackageArchive) {
try {
//If not already locked (i.e. was not able to acquire an immediate write lock)
@@ -555,7 +558,7 @@ private ObjectId updateAutomationPackage(AutomationPackage oldPackage, Automatio
deleteAutomationPackageEntities(oldPackage);
}
// persist all staged entities
- persistStagedEntities(staging, enricherForIncludedEntities, automationPackageArchive, packageContent);
+ persistStagedEntities(staging, enricherForIncludedEntities, validator, automationPackageArchive, packageContent);
ObjectId result = automationPackageAccessor.save(newPackage).getId();
logAfterSave(staging, oldPackage, newPackage);
return result;
@@ -603,10 +606,11 @@ protected AutomationPackageStaging createStaging(){
return new AutomationPackageStaging();
}
- protected void fillStaging(AutomationPackageStaging staging, AutomationPackageContent packageContent, AutomationPackage oldPackage, ObjectEnricher enricherForIncludedEntities,
+ protected void fillStaging(AutomationPackageStaging staging, AutomationPackageContent packageContent, AutomationPackage oldPackage,
+ ObjectEnricher enricherForIncludedEntities, ObjectValidator validatorForIncludedEntities,
AutomationPackageArchive automationPackageArchive, String evaluationExpression, ObjectPredicate objectPredicate) {
- staging.getPlans().addAll(preparePlansStaging(packageContent, automationPackageArchive, oldPackage, enricherForIncludedEntities, staging.getResourceManager(), evaluationExpression));
- staging.getFunctions().addAll(prepareFunctionsStaging(automationPackageArchive, packageContent, enricherForIncludedEntities, oldPackage, staging.getResourceManager(), evaluationExpression));
+ staging.getPlans().addAll(preparePlansStaging(packageContent, automationPackageArchive, oldPackage, enricherForIncludedEntities, validatorForIncludedEntities, staging.getResourceManager(), evaluationExpression));
+ staging.getFunctions().addAll(prepareFunctionsStaging(automationPackageArchive, packageContent, enricherForIncludedEntities, validatorForIncludedEntities, oldPackage, staging.getResourceManager(), evaluationExpression));
List hookEntries = new ArrayList<>();
for (String additionalField : packageContent.getAdditionalFields()) {
@@ -621,7 +625,7 @@ protected void fillStaging(AutomationPackageStaging staging, AutomationPackageCo
try {
boolean hooked = automationPackageHookRegistry.onPrepareStaging(
hookEntry.fieldName,
- new AutomationPackageContext(operationMode, staging.getResourceManager(), automationPackageArchive, packageContent, enricherForIncludedEntities, extensions),
+ new AutomationPackageContext(operationMode, staging.getResourceManager(), automationPackageArchive, packageContent, enricherForIncludedEntities, validatorForIncludedEntities, extensions),
packageContent,
hookEntry.values,
oldPackage, staging, objectPredicate);
@@ -639,6 +643,7 @@ protected void fillStaging(AutomationPackageStaging staging, AutomationPackageCo
protected void persistStagedEntities(AutomationPackageStaging staging,
ObjectEnricher objectEnricher,
+ ObjectValidator objectValidator,
AutomationPackageArchive automationPackageArchive,
AutomationPackageContent packageContent) {
List stagingResources = staging.getResourceManager().findManyByCriteria(null);
@@ -673,7 +678,7 @@ protected void persistStagedEntities(AutomationPackageStaging staging,
try {
boolean hooked = automationPackageHookRegistry.onCreate(
hookEntry.fieldName, hookEntry.values,
- new AutomationPackageContext(operationMode, resourceManager, automationPackageArchive, packageContent, objectEnricher, extensions)
+ new AutomationPackageContext(operationMode, resourceManager, automationPackageArchive, packageContent, objectEnricher, objectValidator, extensions)
);
if (!hooked) {
log.warn("Additional field in automation package has been ignored and skipped: " + hookEntry.fieldName);
@@ -702,11 +707,11 @@ public void runExtensionsBeforeIsolatedExecution(AutomationPackage automationPac
}
protected List preparePlansStaging(AutomationPackageContent packageContent, AutomationPackageArchive automationPackageArchive,
- AutomationPackage oldPackage, ObjectEnricher enricher, ResourceManager stagingResourceManager,
+ AutomationPackage oldPackage, ObjectEnricher enricher, ObjectValidator validator, ResourceManager stagingResourceManager,
String evaluationExpression) {
List plans = packageContent.getPlans();
AutomationPackagePlansAttributesApplier specialAttributesApplier = new AutomationPackagePlansAttributesApplier(stagingResourceManager);
- specialAttributesApplier.applySpecialAttributesToPlans(plans, automationPackageArchive, packageContent, enricher, extensions, operationMode);
+ specialAttributesApplier.applySpecialAttributesToPlans(plans, automationPackageArchive, packageContent, enricher, validator, extensions, operationMode);
fillEntities(plans, oldPackage != null ? getPackagePlans(oldPackage.getId()) : new ArrayList<>(), enricher);
if (evaluationExpression != null && !evaluationExpression.isEmpty()){
@@ -717,9 +722,10 @@ protected List preparePlansStaging(AutomationPackageContent packageContent
return plans;
}
- protected List prepareFunctionsStaging(AutomationPackageArchive automationPackageArchive, AutomationPackageContent packageContent, ObjectEnricher enricher,
+ protected List prepareFunctionsStaging(AutomationPackageArchive automationPackageArchive, AutomationPackageContent packageContent,
+ ObjectEnricher enricher, ObjectValidator validator,
AutomationPackage oldPackage, ResourceManager stagingResourceManager, String evaluationExpression) {
- AutomationPackageContext apContext = new AutomationPackageContext(operationMode, stagingResourceManager, automationPackageArchive, packageContent, enricher, extensions);
+ AutomationPackageContext apContext = new AutomationPackageContext(operationMode, stagingResourceManager, automationPackageArchive, packageContent, enricher, validator, extensions);
List completeFunctions = packageContent.getKeywords().stream().map(keyword -> keyword.prepareKeyword(apContext)).collect(Collectors.toList());
// get old functions with same name and reuse their ids
diff --git a/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/AutomationPackagePlansAttributesApplier.java b/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/AutomationPackagePlansAttributesApplier.java
index fb0c841069..ff70879ac1 100644
--- a/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/AutomationPackagePlansAttributesApplier.java
+++ b/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/AutomationPackagePlansAttributesApplier.java
@@ -24,6 +24,7 @@
import step.core.entities.EntityManager;
import step.core.entities.EntityReference;
import step.core.objectenricher.ObjectEnricher;
+import step.core.objectenricher.ObjectValidator;
import step.core.plans.Plan;
import step.resources.Resource;
import step.resources.ResourceManager;
@@ -55,15 +56,18 @@ public AutomationPackagePlansAttributesApplier(ResourceManager resourceManager)
public void applySpecialAttributesToPlans(List plans,
AutomationPackageArchive automationPackageArchive,
AutomationPackageContent packageContent,
- ObjectEnricher objectEnricher, Map extensions, AutomationPackageOperationMode operationMode) {
- AutomationPackageContext apContext = prepareContext(operationMode, automationPackageArchive, packageContent, objectEnricher, extensions);
+ ObjectEnricher objectEnricher, ObjectValidator validator,
+ Map extensions,
+ AutomationPackageOperationMode operationMode) {
+ AutomationPackageContext apContext = prepareContext(operationMode, automationPackageArchive, packageContent, objectEnricher, validator, extensions);
for (Plan plan : plans) {
applySpecialValuesForArtifact(plan.getRoot(), apContext);
}
}
- protected AutomationPackageContext prepareContext(AutomationPackageOperationMode operationMode, AutomationPackageArchive automationPackageArchive, AutomationPackageContent packageContent, ObjectEnricher enricher, Map extensions) {
- return new AutomationPackageContext(operationMode, resourceManager, automationPackageArchive, packageContent, enricher, extensions);
+ protected AutomationPackageContext prepareContext(AutomationPackageOperationMode operationMode, AutomationPackageArchive automationPackageArchive, AutomationPackageContent packageContent,
+ ObjectEnricher enricher, ObjectValidator validator, Map extensions) {
+ return new AutomationPackageContext(operationMode, resourceManager, automationPackageArchive, packageContent, enricher, validator, extensions);
}
private void applySpecialValuesForArtifact(AbstractArtefact artifact, AutomationPackageContext apContext) {
diff --git a/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/execution/AutomationPackageExecutor.java b/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/execution/AutomationPackageExecutor.java
index dc0c117e12..bae3c3b017 100644
--- a/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/execution/AutomationPackageExecutor.java
+++ b/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/execution/AutomationPackageExecutor.java
@@ -30,6 +30,7 @@
import step.core.execution.model.*;
import step.core.objectenricher.ObjectEnricher;
import step.core.objectenricher.ObjectPredicate;
+import step.core.objectenricher.ObjectValidator;
import step.core.plans.Plan;
import step.core.plans.PlanFilter;
import step.core.repositories.RepositoryObjectManager;
@@ -89,7 +90,7 @@ public List runDeployedAutomationPackage(ObjectId automationPackageId,
}
public List runInIsolation(InputStream apInputStream, String inputStreamFileName, IsolatedAutomationPackageExecutionParameters parameters,
- ObjectEnricher objectEnricher, ObjectPredicate objectPredicate) {
+ ObjectEnricher objectEnricher, ObjectPredicate objectPredicate, ObjectValidator validator) {
ObjectId contextId = new ObjectId();
List executions = new ArrayList<>();
diff --git a/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/execution/RepositoryWithAutomationPackageSupport.java b/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/execution/RepositoryWithAutomationPackageSupport.java
index 66866a3eaa..87d9f99a1d 100644
--- a/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/execution/RepositoryWithAutomationPackageSupport.java
+++ b/step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/execution/RepositoryWithAutomationPackageSupport.java
@@ -92,6 +92,8 @@ public TestSetStatusOverview getTestSetStatusOverview(Map reposi
PackageExecutionContext ctx = null;
try {
File artifact = getArtifact(repositoryParameters, objectPredicate);
+
+ // we don't pass the ObjectValidator here, because it is only required to validate the entity before persist into DB
ctx = createIsolatedPackageExecutionContext(null, objectPredicate, new ObjectId().toString(), new AutomationPackageFile(artifact, null), false);
TestSetStatusOverview overview = new TestSetStatusOverview();
List runs = getFilteredPackagePlans(ctx.getAutomationPackage(), repositoryParameters, ctx.getAutomationPackageManager())
@@ -301,7 +303,7 @@ public PackageExecutionContext createIsolatedPackageExecutionContext(ObjectEnric
// create single automation package in isolated manager
try (FileInputStream fis = new FileInputStream(apFile.getFile())) {
// the apVersion is null (we always use the actual version), because we only create the isolated in-memory AP here
- inMemoryPackageManager.createAutomationPackage(fis, apFile.getFile().getName(), null, null, enricher, predicate);
+ inMemoryPackageManager.createAutomationPackage(fis, apFile.getFile().getName(), null, null, enricher, predicate, null);
} catch (IOException e) {
throw new AutomationPackageManagerException("Cannot read the AP file: " + apFile.getFile().getName());
}
diff --git a/step-cli/step-cli-launcher/src/main/java/step/cli/ApLocalExecuteCommandHandler.java b/step-cli/step-cli-launcher/src/main/java/step/cli/ApLocalExecuteCommandHandler.java
index 37bee80614..6ca7c12519 100644
--- a/step-cli/step-cli-launcher/src/main/java/step/cli/ApLocalExecuteCommandHandler.java
+++ b/step-cli/step-cli-launcher/src/main/java/step/cli/ApLocalExecuteCommandHandler.java
@@ -62,7 +62,7 @@ public void afterExecutionEnd(ExecutionContext context) {
AutomationPackageFromInputStreamProvider automationPackageProvider = new AutomationPackageFromInputStreamProvider(is, apFile.getName());
ObjectId automationPackageId = automationPackageManager.createOrUpdateAutomationPackage(
false, true, null, automationPackageProvider, null, null,
- true, null, null, false
+ true, null, null, null, false
).getId();
PlanFilter planFilters = getPlanFilters(includePlans, excludePlans, includeCategories, excludeCategories);
diff --git a/step-controller/step-controller-backend/src/test/java/step/core/export/ExportManagerTest.java b/step-controller/step-controller-backend/src/test/java/step/core/export/ExportManagerTest.java
index 1c2aa9a971..5171216712 100644
--- a/step-controller/step-controller-backend/src/test/java/step/core/export/ExportManagerTest.java
+++ b/step-controller/step-controller-backend/src/test/java/step/core/export/ExportManagerTest.java
@@ -57,6 +57,7 @@
import step.core.plans.PlanEntity;
import step.core.plans.builder.PlanBuilder;
import step.datapool.excel.ExcelDataPool;
+import step.encryption.AbstractEncryptedValuesManager;
import step.expressions.ExpressionHandler;
import step.functions.Function;
import step.functions.accessor.FunctionAccessor;
@@ -72,7 +73,8 @@
import step.planbuilder.FunctionArtefacts;
import step.plugins.functions.types.CompositeFunction;
import step.plugins.functions.types.CompositeFunctionType;
-import step.plugins.parametermanager.ParameterManagerControllerPlugin;
+import step.plugins.encryption.EncryptedEntityImportBiConsumer;
+import step.plugins.encryption.EncryptedEntityExportBiConsumer;
import step.resources.*;
import java.io.File;
@@ -88,6 +90,13 @@
public class ExportManagerTest {
+ private static String EXPORT_ENCRYPT_WARN = "The parameter list contains encrypted parameters. The values of these parameters will be reset if you import them on an other installation of step.";
+ private static String EXPORT_PROTECT_WARN = "The parameter list contains protected parameter. The values of these parameters won't be exported and will have to be reset at import.";
+
+ private static String IMPORT_DECRYPT_FAIL_WARN = "The export file contains encrypted parameter which could not be decrypted. The values of these parameters will be reset.";
+ private static String IMPORT_DECRYPT_NO_EM_WARN = "The export file contains encrypted parameters. The values of these parameters will be reset.";
+ private static String IMPORT_RESET_WARN = "The export file contains protected parameters. Their values must be reset.";
+
private PlanAccessor planAccessor;
private EntityManager entityManager;
private MigrationManager migrationManager;
@@ -150,8 +159,28 @@ private void newContext(EncryptionManager encryptionManager) {
.register(new ResourceEntity(resourceAccessor, resourceManager, fileResolver, entityManager))
.register(new Entity<>(EntityManager.resourceRevisions, resourceRevisionAccessor, ResourceRevision.class));
- entityManager.registerExportHook(new ParameterManagerControllerPlugin.ParameterExportBiConsumer());
- entityManager.registerImportHook(new ParameterManagerControllerPlugin.ParameterImportBiConsumer(encryptionManager));
+ entityManager.registerExportHook(new EncryptedEntityExportBiConsumer(Parameter.class, "parameter") {
+ @Override
+ protected Object getValue(Parameter obj) {
+ return obj.getValue();
+ }
+
+ @Override
+ protected void setResetValue(Parameter obj) {
+ obj.setValue(new DynamicValue<>(AbstractEncryptedValuesManager.RESET_VALUE));
+ }
+ });
+ entityManager.registerImportHook(new EncryptedEntityImportBiConsumer(encryptionManager, Parameter.class, "parameter") {
+ @Override
+ protected Object getValue(Parameter obj) {
+ return obj.getValue();
+ }
+
+ @Override
+ protected void setResetValue(Parameter obj) {
+ obj.setValue(new DynamicValue<>(AbstractEncryptedValuesManager.RESET_VALUE));
+ }
+ });
entityManager.registerImportHook(new ResourceImporter(resourceManager));
migrationManager = new MigrationManager();
@@ -300,8 +329,8 @@ public void testExportAllPlansWithParameters() throws Exception {
ExportResult exportResult = exportManager.exportAll(exportConfig);
assertEquals(2,exportResult.getMessages().size());
- assertEquals(ParameterManagerControllerPlugin.EXPORT_PROTECT_PARAM_WARN,exportResult.getMessages().toArray()[1]);
- assertEquals(ParameterManagerControllerPlugin.EXPORT_ENCRYPT_PARAM_WARN,exportResult.getMessages().toArray()[0]);
+ assertEquals(EXPORT_PROTECT_WARN,exportResult.getMessages().toArray()[1]);
+ assertEquals(EXPORT_ENCRYPT_WARN,exportResult.getMessages().toArray()[0]);
EncryptionManager encryptionManager = new EncryptionManager() {
@Override
@@ -329,7 +358,7 @@ public boolean isFirstStart() {
ImportConfiguration importConfiguration = new ImportConfiguration(testExportFile, dummyObjectEnricher(), null, true);
ImportResult importResult = importManager.importAll(importConfiguration);
assertEquals(1,importResult.getMessages().size());
- assertEquals(ParameterManagerControllerPlugin.IMPORT_RESET_WARN,importResult.getMessages().toArray()[0]);
+ assertEquals(IMPORT_RESET_WARN,importResult.getMessages().toArray()[0]);
Plan actualPlan = planAccessor.get(plan.getId());
Plan actualPlan2 = planAccessor.get(plan2.getId());
@@ -372,7 +401,7 @@ public void testImportNewEncryptionManager() throws Exception {
ExportResult exportResult = exportManager.exportAll(exportConfig);
assertEquals(1,exportResult.getMessages().size());
- assertEquals(ParameterManagerControllerPlugin.EXPORT_ENCRYPT_PARAM_WARN,exportResult.getMessages().toArray()[0]);
+ assertEquals(EXPORT_ENCRYPT_WARN,exportResult.getMessages().toArray()[0]);
//Override previous encryption manager to simulate new instance
EncryptionManager encryptionManagerNewInstance = new EncryptionManager() {
@@ -398,7 +427,7 @@ public boolean isFirstStart() {
ImportConfiguration importConfiguration = new ImportConfiguration(testExportFile, dummyObjectEnricher(), null, true);
ImportResult importResult = importManager.importAll(importConfiguration);
assertEquals(1,importResult.getMessages().size());
- assertEquals(ParameterManagerControllerPlugin.IMPORT_DECRYPT_FAIL_WARN,importResult.getMessages().toArray()[0]);
+ assertEquals(IMPORT_DECRYPT_FAIL_WARN,importResult.getMessages().toArray()[0]);
Parameter actualParamProtectedEncrypted = parameterAccessor.get(savedParamProtectedEncrypted.getId());
assertEquals(savedParamProtectedEncrypted.getId(), actualParamProtectedEncrypted.getId());
@@ -429,7 +458,7 @@ public void testImportNoEncryptionManager() throws Exception {
ExportResult exportResult = exportManager.exportAll(exportConfig);
assertEquals(1,exportResult.getMessages().size());
- assertEquals(ParameterManagerControllerPlugin.EXPORT_ENCRYPT_PARAM_WARN,exportResult.getMessages().toArray()[0]);
+ assertEquals(EXPORT_ENCRYPT_WARN,exportResult.getMessages().toArray()[0]);
// Create a new context without encryption manager
newContext(null);
@@ -437,7 +466,7 @@ public void testImportNoEncryptionManager() throws Exception {
ImportConfiguration importConfiguration = new ImportConfiguration(testExportFile, dummyObjectEnricher(), null, true);
ImportResult importResult = importManager.importAll(importConfiguration);
assertEquals(1,importResult.getMessages().size());
- assertEquals(ParameterManagerControllerPlugin.IMPORT_DECRYPT_NO_EM_WARN,importResult.getMessages().toArray()[0]);
+ assertEquals(IMPORT_DECRYPT_NO_EM_WARN,importResult.getMessages().toArray()[0]);
Parameter actualParamProtectedEncrypted = parameterAccessor.get(savedParamProtectedEncrypted.getId());
assertEquals(savedParamProtectedEncrypted.getId(), actualParamProtectedEncrypted.getId());
@@ -466,13 +495,13 @@ public void testImportProtectedToEncrypted() throws Exception {
ExportResult exportResult = exportManager.exportAll(exportConfig);
assertEquals(1,exportResult.getMessages().size());
- assertEquals(ParameterManagerControllerPlugin.EXPORT_PROTECT_PARAM_WARN,exportResult.getMessages().toArray()[0]);
+ assertEquals(EXPORT_PROTECT_WARN,exportResult.getMessages().toArray()[0]);
ImportManager importManager = createNewContextAndGetImportManager();
ImportConfiguration importConfiguration = new ImportConfiguration(testExportFile, dummyObjectEnricher(), null, true);
ImportResult importResult = importManager.importAll(importConfiguration);
assertEquals(1,importResult.getMessages().size());
- assertEquals(ParameterManagerControllerPlugin.IMPORT_RESET_WARN,importResult.getMessages().toArray()[0]);
+ assertEquals(IMPORT_RESET_WARN,importResult.getMessages().toArray()[0]);
Parameter actualParamProtectedEncrypted = parameterAccessor.get(savedParamProtected.getId());
assertEquals(savedParamProtected.getId(), actualParamProtectedEncrypted.getId());
diff --git a/step-controller/step-controller-base-plugins/src/main/java/step/plugins/encryption/EncryptedEntityExportBiConsumer.java b/step-controller/step-controller-base-plugins/src/main/java/step/plugins/encryption/EncryptedEntityExportBiConsumer.java
new file mode 100644
index 0000000000..a8dd871169
--- /dev/null
+++ b/step-controller/step-controller-base-plugins/src/main/java/step/plugins/encryption/EncryptedEntityExportBiConsumer.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (C) 2020, exense GmbH
+ *
+ * This file is part of STEP
+ *
+ * STEP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * STEP is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with STEP. If not, see .
+ ******************************************************************************/
+package step.plugins.encryption;
+
+import step.core.EncryptedTrackedObject;
+import step.core.dynamicbeans.DynamicValue;
+import step.core.export.ExportContext;
+import step.encryption.AbstractEncryptedValuesManager;
+
+import java.util.function.BiConsumer;
+
+public abstract class EncryptedEntityExportBiConsumer implements BiConsumer