SLING-7683 Support run modes in separate files
When the following variable is defined in a feature model:
"provisioning.runmode": "comma,separated,list"
Then all the bundles, configurations and extensions in this model have
the specified runmode(s) when converted into the provisioning model.
diff --git a/src/main/java/org/apache/sling/feature/modelconverter/FeatureToProvisioning.java b/src/main/java/org/apache/sling/feature/modelconverter/FeatureToProvisioning.java
index 6754456..afaa2e2 100644
--- a/src/main/java/org/apache/sling/feature/modelconverter/FeatureToProvisioning.java
+++ b/src/main/java/org/apache/sling/feature/modelconverter/FeatureToProvisioning.java
@@ -59,6 +59,7 @@
public class FeatureToProvisioning {
private static final Logger LOGGER = LoggerFactory.getLogger(FeatureToProvisioning.class);
static final String PROVISIONING_MODEL_NAME_VARIABLE = "provisioning.model.name";
+ static final String PROVISIONING_RUNMODE = "provisioning.runmode";
public static void convert(File inputFile, File outputFile, ArtifactManager am) throws IOException {
if (outputFile.exists()) {
@@ -78,9 +79,15 @@
featureName = feature.getId().getArtifactId();
}
+ String runMode = (String) feature.getVariables().remove(PROVISIONING_RUNMODE);
+ String[] runModes = null;
+ if (runMode != null) {
+ runModes = runMode.split(",");
+ }
+
Feature newFeature = new Feature(featureName);
convert(newFeature, feature.getVariables(), feature.getBundles(), feature.getConfigurations(),
- feature.getFrameworkProperties(), feature.getExtensions(), outputFile.getAbsolutePath());
+ feature.getFrameworkProperties(), feature.getExtensions(), outputFile.getAbsolutePath(), runModes);
}
/*
@@ -117,11 +124,15 @@
}
final Feature feature = new Feature(featureName);
- convert(feature, app.getVariables(), app.getBundles(), app.getConfigurations(), app.getFrameworkProperties(), app.getExtensions(), outputFile);
+ convert(feature, app.getVariables(), app.getBundles(), app.getConfigurations(),
+ app.getFrameworkProperties(), app.getExtensions(), outputFile, null);
}
private static void convert(Feature f, KeyValueMap variables, Bundles bundles, Configurations configurations, KeyValueMap frameworkProps,
- Extensions extensions, String outputFile) {
+ Extensions extensions, String outputFile, String [] runModes) {
+ if (runModes != null && runModes.length == 0) {
+ runModes = null;
+ }
org.apache.sling.provisioning.model.KeyValueMap<String> vars = f.getVariables();
for (Map.Entry<String, String> entry : variables) {
vars.put(entry.getKey(), entry.getValue());
@@ -162,8 +173,11 @@
startLevel = 20;
}
- String[] runModes = getRunModes(bundle);
- f.getOrCreateRunMode(runModes).getOrCreateArtifactGroup(startLevel).add(newBundle);
+ String[] bundleRunModes = runModes;
+ if (bundleRunModes == null) {
+ bundleRunModes = getRunModes(bundle);
+ }
+ f.getOrCreateRunMode(bundleRunModes).getOrCreateArtifactGroup(startLevel).add(newBundle);
}
// configurations
@@ -188,11 +202,13 @@
}
c.getProperties().put(key, val);
}
-
- String[] runModes = runModeList.toArray(new String[] {});
- if (runModes.length == 0)
- runModes = null;
- f.getOrCreateRunMode(runModes).getConfigurations().add(c);
+ String[] cfgRunModes = runModes;
+ if (cfgRunModes == null) {
+ cfgRunModes = runModeList.toArray(new String[] {});
+ if (cfgRunModes.length == 0)
+ cfgRunModes = null;
+ }
+ f.getOrCreateRunMode(cfgRunModes).getConfigurations().add(c);
}
// framework properties
@@ -214,17 +230,19 @@
for(final Extension ext : extensions) {
if ( FeatureConstants.EXTENSION_NAME_CONTENT_PACKAGES.equals(ext.getName()) ) {
for(final org.apache.sling.feature.Artifact cp : ext.getArtifacts() ) {
- String[] runmodes = null;
+ String[] extRunModes = runModes;
final ArtifactId id = cp.getId();
final Artifact newCP = new Artifact(id.getGroupId(), id.getArtifactId(), id.getVersion(), id.getClassifier(), id.getType());
for(final Map.Entry<String, String> prop : cp.getMetadata()) {
if (prop.getKey().equals("runmodes")) {
- runmodes = prop.getValue().split(",");
+ if (extRunModes == null) {
+ extRunModes = prop.getValue().split(",");
+ }
} else {
newCP.getMetadata().put(prop.getKey(), prop.getValue());
}
}
- f.getOrCreateRunMode(runmodes).getOrCreateArtifactGroup(20).add(newCP);
+ f.getOrCreateRunMode(extRunModes).getOrCreateArtifactGroup(20).add(newCP);
}
} else if ( FeatureConstants.EXTENSION_NAME_REPOINIT.equals(ext.getName()) ) {
diff --git a/src/test/java/org/apache/sling/feature/modelconverter/ModelConverterTest.java b/src/test/java/org/apache/sling/feature/modelconverter/ModelConverterTest.java
index ccdcd59..0e9fd87 100644
--- a/src/test/java/org/apache/sling/feature/modelconverter/ModelConverterTest.java
+++ b/src/test/java/org/apache/sling/feature/modelconverter/ModelConverterTest.java
@@ -113,6 +113,16 @@
}
@Test
+ public void testSeparateRunmodeFiles() throws Exception {
+ testConvertToProvisioningModel(
+ new String[] {
+ "/runmodeseparation/oak_no_runmode.json",
+ "/runmodeseparation/oak_mongo.json",
+ "/runmodeseparation/oak_tar.json"},
+ "/oak.txt");
+ }
+
+ @Test
public void testOakToFeature() throws Exception {
testConvertToFeature("/oak.txt", "/oak.json");
}
@@ -298,6 +308,22 @@
assertModelsEqual(expected, actual);
}
+ public void testConvertToProvisioningModel(String [] jsonFiles, String expectedProvModel) throws URISyntaxException, IOException {
+ List<File> generatedFiles = new ArrayList<>();
+ for (String jsonFile : jsonFiles) {
+ File inFile = new File(getClass().getResource(jsonFile).toURI());
+ File outFile = new File(tempDir.toFile(), inFile.getName() + ".txt.generated");
+
+ FeatureToProvisioning.convert(inFile, outFile, artifactManager);
+ generatedFiles.add(outFile);
+ }
+
+ File expectedFile = new File(getClass().getResource(expectedProvModel).toURI());
+ Model expected = readProvisioningModel(expectedFile);
+ Model actual = readProvisioningModel(generatedFiles);
+ assertModelsEqual(expected, actual);
+ }
+
private static Model readProvisioningModel(File modelFile) throws IOException {
return readProvisioningModel(Collections.singletonList(modelFile));
}
diff --git a/src/test/resources/runmodeseparation/oak_mongo.json b/src/test/resources/runmodeseparation/oak_mongo.json
new file mode 100644
index 0000000..9ed9a8e
--- /dev/null
+++ b/src/test/resources/runmodeseparation/oak_mongo.json
@@ -0,0 +1,29 @@
+{
+ "id": "generated/oak_mongo/1.0.0",
+
+ "variables": {
+ "oak.version": "1.6.8",
+ "provisioning.model.name": "oak",
+ "provisioning.runmode": "oak_mongo"
+ },
+
+ "bundles": [
+ {
+ "id": "org.mongodb/mongo-java-driver/3.4.1",
+ "start-level": 15,
+ "run-modes": "oak_mongo"
+ },
+ {
+ "id": "com.h2database/h2-mvstore/1.4.196",
+ "start-level": 15,
+ "run-modes": "oak_mongo"
+ }
+ ],
+
+ "configurations": {
+ "org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService": {
+ "mongouri": "mongodb://localhost:27017",
+ "db": "sling"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/runmodeseparation/oak_no_runmode.json b/src/test/resources/runmodeseparation/oak_no_runmode.json
new file mode 100644
index 0000000..abef0fc
--- /dev/null
+++ b/src/test/resources/runmodeseparation/oak_no_runmode.json
@@ -0,0 +1,76 @@
+{
+ "id": "generated/oak_no_runmode/1.0.0",
+
+ "variables": {
+ "oak.version": "1.6.8",
+ "provisioning.model.name": "oak"
+ },
+
+ "bundles": [
+ {
+ "id": "org.apache.felix/org.apache.felix.jaas/1.0.2",
+ "start-level": 10
+ },
+ {
+ "id": "org.apache.jackrabbit/oak-core/${oak.version}",
+ "start-level": 15
+ },
+ {
+ "id": "org.apache.jackrabbit/oak-commons/${oak.version}",
+ "start-level": 15
+ },
+ {
+ "id": "org.apache.jackrabbit/oak-lucene/${oak.version}",
+ "start-level": 15
+ },
+ {
+ "id": "org.apache.jackrabbit/oak-blob/${oak.version}",
+ "start-level": 15
+ },
+ {
+ "id": "org.apache.jackrabbit/oak-jcr/${oak.version}",
+ "start-level": 15
+ },
+ {
+ "id": "org.apache.sling/org.apache.sling.jcr.oak.server/1.1.4",
+ "start-level": 16
+ }
+ ],
+ "configurations": {
+ "org.apache.felix.jaas.Configuration.factory~GuestLoginModule": {
+ "jaas.controlFlag": "optional",
+ "jaas.classname": "org.apache.jackrabbit.oak.spi.security.authentication.GuestLoginModule",
+ "jaas.ranking:Integer": 300
+ },
+ "org.apache.felix.jaas.Configuration.factory~LoginModuleImpl" : {
+ "jaas.controlFlag": "required",
+ "jaas.classname": "org.apache.jackrabbit.oak.security.authentication.user.LoginModuleImpl"
+ },
+ "org.apache.felix.jaas.Configuration.factory~TokenLoginModule" : {
+ "jaas.controlFlag": "sufficient",
+ "jaas.classname": "org.apache.jackrabbit.oak.security.authentication.token.TokenLoginModule",
+ "jaas.ranking:Integer": 200
+ },
+ "org.apache.felix.jaas.ConfigurationSpi": {
+ "jaas.defaultRealmName": "jackrabbit.oak",
+ "jaas.configProviderName": "FelixJaasProvider"
+ },
+ "org.apache.jackrabbit.oak.security.authentication.AuthenticationConfigurationImpl" : {
+ "org.apache.jackrabbit.oak.authentication.configSpiName": "FelixJaasProvider"
+ },
+ "org.apache.jackrabbit.oak.security.user.UserConfigurationImpl": {
+ "groupsPath": "/home/groups",
+ "usersPath": "/home/users",
+ "defaultDepth": "1",
+ "importBehavior": "besteffort"
+ },
+ "org.apache.jackrabbit.oak.security.user.RandomAuthorizableNodeName": {
+ "length:Integer": 21
+ },
+ "org.apache.jackrabbit.oak.spi.security.user.action.DefaultAuthorizableActionProvider": {
+ "enabledActions": ["org.apache.jackrabbit.oak.spi.security.user.action.AccessControlAction"],
+ "userPrivilegeNames": ["jcr:all"],
+ "groupPrivilegeNames": ["jcr:read"]
+ }
+ }
+}
diff --git a/src/test/resources/runmodeseparation/oak_tar.json b/src/test/resources/runmodeseparation/oak_tar.json
new file mode 100644
index 0000000..71ade48
--- /dev/null
+++ b/src/test/resources/runmodeseparation/oak_tar.json
@@ -0,0 +1,23 @@
+{
+ "id": "generated/oak_tar/1.0.0",
+
+ "variables": {
+ "oak.version": "1.6.8",
+ "provisioning.model.name": "oak",
+ "provisioning.runmode": "oak_tar"
+ },
+
+ "bundles": [
+ {
+ "id": "org.apache.jackrabbit/oak-segment-tar/${oak.version}",
+ "start-level": 15,
+ "run-modes": "oak_tar"
+ }
+ ],
+
+ "configurations": {
+ "org.apache.jackrabbit.oak.segment.SegmentNodeStoreService.runmodes.oak_tar": {
+ "name": "Default NodeStore"
+ }
+ }
+}
\ No newline at end of file