From 1c5cb3bd31d7ede255d719059d6753bf6e31384c Mon Sep 17 00:00:00 2001 From: Andrei Savu Date: Sun, 27 Jan 2013 23:33:19 +0200 Subject: [PATCH] Add the ability to register templates as xml files No need to recompile the code or install new bundles. You can even edit / add new templates while the application server is running or during bundle / feature installation. Changes: * replaced Java pool templates with xml file (still part of core) * implemented file system watcher based on Felix fileinstall for pool templates * downgraded osgi framework from 4.3.2 (1.6) to 4.2.0 (1.5) * removed Activiti process engine test code (used just for learning) * disabled kar deployer * improved listing for provisionr:templates * the final distribution no longer installs by default axemblr-provisionr-console and axemblr-provisionr-cloudstack --- core/pom.xml | 42 ++- .../core/templates/ClouderaCDH3Template.java | 101 ------- .../core/templates/JenkinsTemplate.java | 73 ----- .../core/templates/PoolTemplateInstaller.java | 109 ++++++++ .../core/templates/xml/FileEntry.java | 91 +++++++ .../core/templates/xml/RepositoryEntry.java | 114 ++++++++ .../core/templates/xml/XmlTemplate.java | 257 ++++++++++++++++++ .../resources/OSGI-INF/blueprint/context.xml | 21 +- .../provisionr/core/templates/cdh3.xml | 108 ++++++++ .../provisionr/core/templates/cloudera.key | 29 -- .../core/templates/jenkins-ci.org.key | 112 -------- .../provisionr/core/templates/jenkins.xml | 132 +++++++++ core/src/main/resources/features.xml | 12 + ...org.apache.felix.fileinstall-templates.cfg | 12 + .../axemblr/provisionr/core/BaseJaxbTest.java | 41 +++ .../SpawnProcessForEachMachineTest.java | 6 +- .../templates/PoolTemplateInstallerTest.java | 61 +++++ .../core/templates/xml/XmlTemplateTest.java | 106 ++++++++ .../sample/SampleProvisioningProcessTest.java | 73 ----- .../MultiInstanceIdempotentTask.java | 40 --- .../MultiInstanceProcessTest.java | 121 --------- .../sample/multiinstance/SpawnProcesses.java | 42 --- .../sample/suspend/FailingTask.java | 41 --- .../sample/suspend/JobFailAndResumeTest.java | 87 ------ .../sample/tasks/CheckCredentialsTask.java | 30 -- .../sample/tasks/CheckParametersTask.java | 29 -- .../tasks/ProvisionMachinesInBatches.java | 36 --- .../sample/tasks/SetupAdminAccessTask.java | 28 -- .../sample/tasks/SetupNetworkContextTask.java | 29 -- .../test/resources/diagrams/empty.bpmn20.xml | 26 ++ .../resources/diagrams/helloDude.bpmn20.xml | 31 --- .../diagrams/multiInstance.bpmn20.xml | 31 --- .../test/resources/diagrams/sample.bpmn20.xml | 234 ---------------- core/src/test/resources/templates/test.xml | 24 ++ karaf/assembly-tests/pom.xml | 6 + .../karaf/CustomKarafDistributionTest.java | 45 ++- karaf/assembly/src/main/assembly/unix.xml | 14 +- .../{jre.properties => jre.properties.cxf} | 0 .../filtered-resources/etc/startup.properties | 2 +- .../main/filtered-resources/templates/README | 4 + .../templates/cdh3.xml.sample | 106 ++++++++ .../commands/ListTemplatesCommand.java | 2 +- .../commands/CreatePoolCommandTest.java | 22 +- .../commands/ListTemplatesCommandTest.java | 22 +- karaf/features/pom.xml | 6 +- .../features/src/main/resources/features.xml | 7 +- parent/pom.xml | 27 +- .../amazon/AmazonProvisionrLiveTest.java | 11 +- test-support/pom.xml | 6 +- .../test/ProvisionrLiveTestSupport.java | 6 +- 50 files changed, 1389 insertions(+), 1226 deletions(-) delete mode 100644 core/src/main/java/com/axemblr/provisionr/core/templates/ClouderaCDH3Template.java delete mode 100644 core/src/main/java/com/axemblr/provisionr/core/templates/JenkinsTemplate.java create mode 100644 core/src/main/java/com/axemblr/provisionr/core/templates/PoolTemplateInstaller.java create mode 100644 core/src/main/java/com/axemblr/provisionr/core/templates/xml/FileEntry.java create mode 100644 core/src/main/java/com/axemblr/provisionr/core/templates/xml/RepositoryEntry.java create mode 100644 core/src/main/java/com/axemblr/provisionr/core/templates/xml/XmlTemplate.java create mode 100644 core/src/main/resources/com/axemblr/provisionr/core/templates/cdh3.xml delete mode 100644 core/src/main/resources/com/axemblr/provisionr/core/templates/cloudera.key delete mode 100644 core/src/main/resources/com/axemblr/provisionr/core/templates/jenkins-ci.org.key create mode 100644 core/src/main/resources/com/axemblr/provisionr/core/templates/jenkins.xml create mode 100644 core/src/main/resources/org.apache.felix.fileinstall-templates.cfg create mode 100644 core/src/test/java/com/axemblr/provisionr/core/BaseJaxbTest.java create mode 100644 core/src/test/java/com/axemblr/provisionr/core/templates/PoolTemplateInstallerTest.java create mode 100644 core/src/test/java/com/axemblr/provisionr/core/templates/xml/XmlTemplateTest.java delete mode 100644 core/src/test/java/com/axemblr/provisionr/sample/SampleProvisioningProcessTest.java delete mode 100644 core/src/test/java/com/axemblr/provisionr/sample/multiinstance/MultiInstanceIdempotentTask.java delete mode 100644 core/src/test/java/com/axemblr/provisionr/sample/multiinstance/MultiInstanceProcessTest.java delete mode 100644 core/src/test/java/com/axemblr/provisionr/sample/multiinstance/SpawnProcesses.java delete mode 100644 core/src/test/java/com/axemblr/provisionr/sample/suspend/FailingTask.java delete mode 100644 core/src/test/java/com/axemblr/provisionr/sample/suspend/JobFailAndResumeTest.java delete mode 100644 core/src/test/java/com/axemblr/provisionr/sample/tasks/CheckCredentialsTask.java delete mode 100644 core/src/test/java/com/axemblr/provisionr/sample/tasks/CheckParametersTask.java delete mode 100644 core/src/test/java/com/axemblr/provisionr/sample/tasks/ProvisionMachinesInBatches.java delete mode 100644 core/src/test/java/com/axemblr/provisionr/sample/tasks/SetupAdminAccessTask.java delete mode 100644 core/src/test/java/com/axemblr/provisionr/sample/tasks/SetupNetworkContextTask.java create mode 100644 core/src/test/resources/diagrams/empty.bpmn20.xml delete mode 100644 core/src/test/resources/diagrams/helloDude.bpmn20.xml delete mode 100644 core/src/test/resources/diagrams/multiInstance.bpmn20.xml delete mode 100644 core/src/test/resources/diagrams/sample.bpmn20.xml create mode 100644 core/src/test/resources/templates/test.xml rename karaf/assembly/src/main/filtered-resources/etc/{jre.properties => jre.properties.cxf} (100%) create mode 100644 karaf/assembly/src/main/filtered-resources/templates/README create mode 100644 karaf/assembly/src/main/filtered-resources/templates/cdh3.xml.sample diff --git a/core/pom.xml b/core/pom.xml index 116397a..69fb528 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -30,7 +30,16 @@ provisionr-core bundle + + * + com.axemblr.provisionr.core* + + + + org.osgi + org.osgi.core + org.slf4j slf4j-api @@ -55,6 +64,10 @@ com.github.spullara.mustache.java compiler + + org.apache.felix + org.apache.felix.fileinstall + com.axemblr.provisionr provisionr-test-support @@ -107,6 +120,11 @@ mockito-all test + + xmlunit + xmlunit + test + @@ -125,7 +143,8 @@ maven-bundle-plugin - com.axemblr.provisionr.core, * + ${osgi.import} + ${osgi.export} @@ -151,6 +170,27 @@ cfg defaults + + + ${project.build.directory}/classes/org.apache.felix.fileinstall-templates.cfg + + cfg + fileinstall + + + + ${project.build.directory}/classes/com/axemblr/provisionr/core/templates/cdh3.xml + + template + cdh3 + + + + ${project.build.directory}/classes/com/axemblr/provisionr/core/templates/jenkins.xml + + template + jenkins + diff --git a/core/src/main/java/com/axemblr/provisionr/core/templates/ClouderaCDH3Template.java b/core/src/main/java/com/axemblr/provisionr/core/templates/ClouderaCDH3Template.java deleted file mode 100644 index 86c21ad..0000000 --- a/core/src/main/java/com/axemblr/provisionr/core/templates/ClouderaCDH3Template.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2012 S.C. Axemblr Software Solutions S.R.L - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.axemblr.provisionr.core.templates; - -import com.axemblr.provisionr.api.network.Network; -import com.axemblr.provisionr.api.network.Rule; -import com.axemblr.provisionr.api.pool.Pool; -import com.axemblr.provisionr.api.provider.Provider; -import com.axemblr.provisionr.api.software.Repository; -import com.axemblr.provisionr.api.software.Software; -import com.google.common.base.Charsets; -import com.google.common.base.Throwables; -import com.google.common.io.Resources; -import java.io.IOException; - -/** - * Cloudera CDH3 template for Ubuntu lucid - */ -public class ClouderaCDH3Template implements PoolTemplate { - - public static final String CLOUDERA_MANAGER_URL = - "http://archive.cloudera.com/cm4/installer/latest/cloudera-manager-installer.bin"; - - public static final String CLOUDERA_MANAGER_REMOTE_PATH = "/opt/cloudera-manager-installer.bin"; - - public static final String UBUNTU_VERSION = "10.04 LTS"; - - @Override - public String getId() { - return "cloudera-cdh3"; - } - - @Override - public String getDescription() { - return "Cloudera CDH3 template for Ubuntu 10.04 LTS (lucid) including Cloudera Manager"; - } - - @Override - public Pool apply(Pool pool) { - String key; - try { - key = Resources.toString(Resources.getResource(ClouderaCDH3Template.class, - "/com/axemblr/provisionr/core/templates/cloudera.key"), Charsets.UTF_8); - - } catch (IOException e) { - throw Throwables.propagate(e); - } - - Repository cdh3Repository = Repository.builder() - .name("cloudera-cdh3").key(key) - .addEntry("deb http://archive.cloudera.com/debian lucid-cdh3 contrib") - .createRepository(); - - Repository clouderaManagerRepository = Repository.builder() - .name("cloudera-cm4").key(key) - .addEntry("deb http://archive.cloudera.com/cm4/ubuntu/lucid/amd64/cm lucid-cm4 contrib") - .addEntry("deb-src http://archive.cloudera.com/cm4/ubuntu/lucid/amd64/cm lucid-cm4 contrib") - .createRepository(); - - Software software = pool.getSoftware().toBuilder() - .repository(cdh3Repository) - .repository(clouderaManagerRepository) - .file(CLOUDERA_MANAGER_URL, CLOUDERA_MANAGER_REMOTE_PATH) - .addPackage("cloudera-manager-agent").addPackage("cloudera-manager-daemons") - .addPackage("oracle-j2sdk1.6").addPackage("hadoop-0.20").addPackage("hadoop-0.20-native") - .addPackage("hadoop-hive").addPackage("hadoop-pig").addPackage("oozie-client") - .addPackage("oozie").addPackage("hue-plugins").addPackage("hue-common") - .addPackage("hue-proxy").addPackage("hue-about").addPackage("hue-help") - .addPackage("hue-filebrowser").addPackage("hue-jobsub").addPackage("hue-beeswax") - .addPackage("hue-useradmin").addPackage("hue-shell").addPackage("hue") - .createSoftware(); - - /* CDH3 has binaries only for lucid not for precise */ - Provider provider = pool.getProvider().toBuilder() - .option("version", UBUNTU_VERSION).createProvider(); - - Network network = pool.getNetwork().toBuilder() - .addRules( - Rule.builder().anySource().tcp().port(7180).createRule(), // Cloudera Manager - Rule.builder().anySource().tcp().port(8888).createRule(), // Hue - Rule.builder().anySource().tcp().port(8080).createRule() // Hue - ).createNetwork(); - - return pool.toBuilder().provider(provider).network(network) - .software(software).createPool(); - } -} diff --git a/core/src/main/java/com/axemblr/provisionr/core/templates/JenkinsTemplate.java b/core/src/main/java/com/axemblr/provisionr/core/templates/JenkinsTemplate.java deleted file mode 100644 index c582ea5..0000000 --- a/core/src/main/java/com/axemblr/provisionr/core/templates/JenkinsTemplate.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2012 S.C. Axemblr Software Solutions S.R.L - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.axemblr.provisionr.core.templates; - -import com.axemblr.provisionr.api.network.Network; -import com.axemblr.provisionr.api.network.Rule; -import com.axemblr.provisionr.api.pool.Pool; -import com.axemblr.provisionr.api.software.Repository; -import com.axemblr.provisionr.api.software.Software; -import com.google.common.base.Charsets; -import com.google.common.base.Throwables; -import com.google.common.io.Resources; -import java.io.IOException; - -/** - * Jenkins template for debian based operating systems - */ -public class JenkinsTemplate implements PoolTemplate { - - public static final String JENKINS_KEY = "/com/axemblr/provisionr/core/templates/jenkins-ci.org.key"; - - public static final int JENKINS_PORT = 8080; - - @Override - public String getId() { - return "jenkins"; - } - - @Override - public String getDescription() { - return "A short template that installs the latest jenkins with git"; - } - - @Override - public Pool apply(Pool pool) { - try { - final String key = Resources.toString(Resources.getResource( - JenkinsTemplate.class, JENKINS_KEY), Charsets.UTF_8); - - final Repository repository = Repository.builder() - .name("jenkins") - .addEntry("deb http://pkg.jenkins-ci.org/debian binary/") - .key(key).createRepository(); - - final Software software = pool.getSoftware().toBuilder() - .addPackage("jenkins").addPackage("git-core") - .repository(repository).createSoftware(); - - final Network network = pool.getNetwork().toBuilder() - .addRules(Rule.builder().anySource().tcp().port(JENKINS_PORT).createRule()) - .createNetwork(); - - return pool.toBuilder().network(network).software(software).createPool(); - - } catch (IOException e) { - throw Throwables.propagate(e); - } - } -} diff --git a/core/src/main/java/com/axemblr/provisionr/core/templates/PoolTemplateInstaller.java b/core/src/main/java/com/axemblr/provisionr/core/templates/PoolTemplateInstaller.java new file mode 100644 index 0000000..3147e9e --- /dev/null +++ b/core/src/main/java/com/axemblr/provisionr/core/templates/PoolTemplateInstaller.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2012 S.C. Axemblr Software Solutions S.R.L + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.axemblr.provisionr.core.templates; + +import com.axemblr.provisionr.core.templates.xml.XmlTemplate; +import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.collect.Maps; +import java.io.File; +import java.util.concurrent.ConcurrentMap; +import org.apache.felix.fileinstall.ArtifactInstaller; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Listener for pool template files + *

+ * When a new xml file is places under templates this class is + * notified and a new pool template is registered as a service + */ +public class PoolTemplateInstaller implements ArtifactInstaller { + + private static final Logger LOG = LoggerFactory.getLogger(PoolTemplateInstaller.class); + + public static final String TEMPLATES_FOLDER = "templates"; + public static final String TEMPLATES_EXTENSION = ".xml"; + + /** + * A bundle context provided by the OSGi framework + */ + private final BundleContext bundleContext; + + /** + * A map with all the pool templates registered by this listener + */ + private final ConcurrentMap templates; + + public PoolTemplateInstaller(BundleContext bundleContext) { + this.bundleContext = checkNotNull(bundleContext, "bundleContext is null"); + this.templates = Maps.newConcurrentMap(); + } + + @Override + public boolean canHandle(File file) { + return TEMPLATES_FOLDER.equals(file.getParentFile().getName()) + && file.getName().endsWith(TEMPLATES_EXTENSION); + } + + /** + * Install a new pool template as a service using the file content + *

+ * The absolute file path is the unique identifier + */ + @Override + public void install(File file) throws Exception { + final String absolutePath = file.getAbsolutePath(); + LOG.info("Installing Pool template from " + absolutePath); + + if (!templates.containsKey(absolutePath)) { + PoolTemplate template = XmlTemplate.newXmlTemplate(file); + ServiceRegistration registration = bundleContext + .registerService(PoolTemplate.class.getName(), template, null); + + templates.put(absolutePath, registration); + LOG.info("Registered new template with ID: " + template.getId()); + } + } + + /** + * Uninstall a pool description identified by the absolute file path + */ + @Override + public void uninstall(File file) throws Exception { + final String absolutePath = file.getAbsolutePath(); + LOG.info("Uninstalling Pool template for path " + absolutePath); + + if (templates.containsKey(absolutePath)) { + templates.remove(absolutePath).unregister(); + } + } + + /** + * Update a pool template + *

+ * This method performs no actions if there is no pool registered for this file + */ + @Override + public void update(File file) throws Exception { + if (templates.containsKey(file.getAbsolutePath())) { + uninstall(file); + install(file); + } + } +} diff --git a/core/src/main/java/com/axemblr/provisionr/core/templates/xml/FileEntry.java b/core/src/main/java/com/axemblr/provisionr/core/templates/xml/FileEntry.java new file mode 100644 index 0000000..edaba76 --- /dev/null +++ b/core/src/main/java/com/axemblr/provisionr/core/templates/xml/FileEntry.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2013 S.C. Axemblr Software Solutions S.R.L + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.axemblr.provisionr.core.templates.xml; + +import com.google.common.annotations.VisibleForTesting; +import static com.google.common.base.Preconditions.checkNotNull; +import javax.xml.bind.annotation.XmlAttribute; + +/** + * Represents a file entry from a pool template + *

+ * Designed to be consumed only by JAXB. It looks like this in xml: + *

+ * + */ +public class FileEntry { + + private String source; + private String destination; + + public FileEntry() { + } + + @VisibleForTesting + FileEntry(String source, String destination) { + this.source = checkNotNull(source, "source is null"); + this.destination = checkNotNull(destination, "destination is null"); + } + + @XmlAttribute(name = "source") + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = checkNotNull(source, "source is null"); + } + + @XmlAttribute(name = "destination") + public String getDestination() { + return destination; + } + + public void setDestination(String destination) { + this.destination = checkNotNull(destination, "destination is null"); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FileEntry fileEntry = (FileEntry) o; + + if (destination != null ? !destination.equals(fileEntry.destination) : fileEntry.destination != null) + return false; + if (source != null ? !source.equals(fileEntry.source) : fileEntry.source != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = source != null ? source.hashCode() : 0; + result = 31 * result + (destination != null ? destination.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "FileEntry{" + + "source='" + source + '\'' + + ", destination='" + destination + '\'' + + '}'; + } +} diff --git a/core/src/main/java/com/axemblr/provisionr/core/templates/xml/RepositoryEntry.java b/core/src/main/java/com/axemblr/provisionr/core/templates/xml/RepositoryEntry.java new file mode 100644 index 0000000..b991c4c --- /dev/null +++ b/core/src/main/java/com/axemblr/provisionr/core/templates/xml/RepositoryEntry.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2013 S.C. Axemblr Software Solutions S.R.L + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.axemblr.provisionr.core.templates.xml; + +import com.google.common.annotations.VisibleForTesting; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Lists.newArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; + +/** + * Represents a custom repository entry from a pool template + *

+ * Designed to be consumed only by JAXB. It looks like this in xml: + *

+ * + * + * deb http://archive.cloudera.com/debian lucid-cdh3 contrib + * + * + * + */ +public class RepositoryEntry { + + private String id; + + private List entries = newArrayList(); + + private String key; + + public RepositoryEntry() { + } + + @VisibleForTesting + RepositoryEntry(String id, List entries, String key) { + this.id = checkNotNull(id, "id is null"); + this.entries = checkNotNull(entries, "entries is null"); + this.key = checkNotNull(key, "key is null"); + } + + @XmlAttribute(name = "id") + public String getId() { + return id; + } + + public void setId(String id) { + this.id = checkNotNull(id, "id is null"); + } + + @XmlElementWrapper(name = "entries") + @XmlElement(name = "entry") + public List getEntries() { + return entries; + } + + public void setEntries(List entries) { + this.entries = checkNotNull(entries, "entries is null"); + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = checkNotNull(key, "key is null"); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + RepositoryEntry that = (RepositoryEntry) o; + + if (entries != null ? !entries.equals(that.entries) : that.entries != null) return false; + if (id != null ? !id.equals(that.id) : that.id != null) return false; + if (key != null ? !key.equals(that.key) : that.key != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = id != null ? id.hashCode() : 0; + result = 31 * result + (entries != null ? entries.hashCode() : 0); + result = 31 * result + (key != null ? key.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "RepositoryEntry{" + + "id='" + id + '\'' + + ", entries=" + entries + + ", key='" + key + '\'' + + '}'; + } +} diff --git a/core/src/main/java/com/axemblr/provisionr/core/templates/xml/XmlTemplate.java b/core/src/main/java/com/axemblr/provisionr/core/templates/xml/XmlTemplate.java new file mode 100644 index 0000000..e6f132e --- /dev/null +++ b/core/src/main/java/com/axemblr/provisionr/core/templates/xml/XmlTemplate.java @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2013 S.C. Axemblr Software Solutions S.R.L + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.axemblr.provisionr.core.templates.xml; + +import com.axemblr.provisionr.api.network.Network; +import com.axemblr.provisionr.api.network.NetworkBuilder; +import com.axemblr.provisionr.api.network.Rule; +import com.axemblr.provisionr.api.pool.Pool; +import com.axemblr.provisionr.api.pool.PoolBuilder; +import com.axemblr.provisionr.api.software.Repository; +import com.axemblr.provisionr.api.software.Software; +import com.axemblr.provisionr.api.software.SoftwareBuilder; +import com.axemblr.provisionr.core.templates.PoolTemplate; +import com.google.common.annotations.VisibleForTesting; +import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.base.Throwables; +import static com.google.common.collect.Lists.newArrayList; +import com.google.common.io.CharStreams; +import com.google.common.io.Closeables; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.List; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Basic representation of a pool template + *

+ * Designed to be consumed *only* by JAXB + *

+ * If you need to implement a pool template see {@code PoolTemplate} + */ +@XmlRootElement(name = "template") +public class XmlTemplate implements PoolTemplate { + + /** + * @return an XmlTemplate instance resulted from parsing the content + */ + public static XmlTemplate newXmlTemplate(String content) { + try { + JAXBContext context = JAXBContext.newInstance(XmlTemplate.class); + return (XmlTemplate) context.createUnmarshaller() + .unmarshal(new ByteArrayInputStream(content.getBytes())); + + } catch (JAXBException e) { + throw Throwables.propagate(e); + } + } + + /** + * @return an XmlTemplate instance resulted from parsing a file + */ + public static XmlTemplate newXmlTemplate(File file) { + FileReader reader = null; + try { + reader = new FileReader(file); + return newXmlTemplate(CharStreams.toString(reader)); + + } catch (IOException e) { + throw Throwables.propagate(e); + } finally { + Closeables.closeQuietly(reader); + } + } + + private String id; + private String description; + private String osVersion; + + private List packages = newArrayList(); + private List ports = newArrayList(); + + private List files = newArrayList(); + + private List repositories = newArrayList(); + + public XmlTemplate() { + } + + @Override + public Pool apply(Pool pool) { + PoolBuilder result = pool.toBuilder(); + + result.software(apply(pool.getSoftware())); + result.network(apply(pool.getNetwork())); + + if (osVersion != null) { + result.provider(pool.getProvider().toBuilder() + .option("version", osVersion).createProvider()); + } + + return result.createPool(); + } + + @VisibleForTesting + Software apply(Software software) { + SoftwareBuilder result = software.toBuilder(); + + // Add all the new packages + for (String pkg : packages) { + result.addPackage(pkg); + } + + // Add all the new files + for (FileEntry entry : files) { + result.file(entry.getSource(), entry.getDestination()); + } + + // Add all the new custom repositories + for (RepositoryEntry entry : repositories) { + result.repository(Repository.builder().name(entry.getId()).key(entry.getKey()) + .entries(entry.getEntries()).createRepository()); + } + + return result.createSoftware(); + } + + @VisibleForTesting + Network apply(Network network) { + NetworkBuilder result = network.toBuilder(); + for (int port : ports) { + result.addRules(Rule.builder().anySource().tcp().port(port).createRule()); + } + return result.createNetwork(); + } + + @XmlAttribute(name = "id") + @Override + public String getId() { + return id; + } + + public void setId(String id) { + this.id = checkNotNull(id, "id is null"); + } + + @Override + public String getDescription() { + return description.trim(); + } + + public void setDescription(String description) { + this.description = checkNotNull(description, "description is null"); + } + + @XmlAttribute(name = "os-version") + public String getOsVersion() { + return osVersion; + } + + public void setOsVersion(String osVersion) { + this.osVersion = checkNotNull(osVersion, "osVersion is null"); + } + + @XmlElementWrapper(name = "packages") + @XmlElement(name = "package") + public List getPackages() { + return packages; + } + + public void setPackages(List packages) { + this.packages = checkNotNull(packages, "packages is null"); + } + + @XmlElementWrapper(name = "ports") + @XmlElement(name = "port") + public List getPorts() { + return ports; + } + + public void setPorts(List ports) { + this.ports = checkNotNull(ports, "ports is null"); + } + + @XmlElementWrapper(name = "files") + @XmlElement(name = "file") + public List getFiles() { + return files; + } + + public void setFiles(List files) { + this.files = checkNotNull(files, "files is null"); + } + + @XmlElementWrapper(name = "repositories") + @XmlElement(name = "repository") + public List getRepositories() { + return repositories; + } + + public void setRepositories(List repositories) { + this.repositories = checkNotNull(repositories, "repositories is null"); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + XmlTemplate that = (XmlTemplate) o; + + if (description != null ? !description.equals(that.description) : that.description != null) return false; + if (files != null ? !files.equals(that.files) : that.files != null) return false; + if (id != null ? !id.equals(that.id) : that.id != null) return false; + if (osVersion != null ? !osVersion.equals(that.osVersion) : that.osVersion != null) return false; + if (packages != null ? !packages.equals(that.packages) : that.packages != null) return false; + if (ports != null ? !ports.equals(that.ports) : that.ports != null) return false; + if (repositories != null ? !repositories.equals(that.repositories) : that.repositories != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = id != null ? id.hashCode() : 0; + result = 31 * result + (description != null ? description.hashCode() : 0); + result = 31 * result + (osVersion != null ? osVersion.hashCode() : 0); + result = 31 * result + (packages != null ? packages.hashCode() : 0); + result = 31 * result + (ports != null ? ports.hashCode() : 0); + result = 31 * result + (files != null ? files.hashCode() : 0); + result = 31 * result + (repositories != null ? repositories.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "XmlTemplate{" + + "id='" + id + '\'' + + ", description='" + description + '\'' + + ", osVersion='" + osVersion + '\'' + + ", packages=" + packages + + ", ports=" + ports + + ", files=" + files + + ", repositories=" + repositories + + '}'; + } +} diff --git a/core/src/main/resources/OSGI-INF/blueprint/context.xml b/core/src/main/resources/OSGI-INF/blueprint/context.xml index 2b01236..7d07c57 100644 --- a/core/src/main/resources/OSGI-INF/blueprint/context.xml +++ b/core/src/main/resources/OSGI-INF/blueprint/context.xml @@ -96,6 +96,15 @@ + + + + + + + + @@ -113,17 +122,5 @@ - - - - - - - - - - - diff --git a/core/src/main/resources/com/axemblr/provisionr/core/templates/cdh3.xml b/core/src/main/resources/com/axemblr/provisionr/core/templates/cdh3.xml new file mode 100644 index 0000000..a289182 --- /dev/null +++ b/core/src/main/resources/com/axemblr/provisionr/core/templates/cdh3.xml @@ -0,0 +1,108 @@ + + \ No newline at end of file diff --git a/core/src/main/resources/com/axemblr/provisionr/core/templates/cloudera.key b/core/src/main/resources/com/axemblr/provisionr/core/templates/cloudera.key deleted file mode 100644 index 876c25b..0000000 --- a/core/src/main/resources/com/axemblr/provisionr/core/templates/cloudera.key +++ /dev/null @@ -1,29 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.9 (GNU/Linux) - -mQGiBEnvgi0RBADLx1qQlXlrvHOo13dUvoWL97Ny/0s0S/GcMEgAqYvZzUPVcq8H -GUsOb4PLTfcL1H7Ptq9fqr02uIb5Bc/ltdwE9GFaT2nvdfBx9T8jr8LrW9JE2xJq -dCyFO5yP9YbZeFAxNO3yBxeP85lQ9CdWWLvyYdtQ+T84EYerqkcVbSvYRwCg6zyx -EE3jWYvyVv/3HTrVTYpgHgMD/2kMR1Z2vEYOSM7h4cnRnxiadhefqJ2WCm4L30Rx -/F9JBLAEuIuUndiOShoB043iDY+rrqCHqHQ/uI2D4piW9cDYMo7EJlsFtQ5g2SFg -PcS4+DLhU464dTQsTGAhvcv+F0VQV4iu1HdD2/kKJkCS/MZL4rr4emqsh6VIBDdG -ytPaA/9cyRJZe2BrBM2pECGncE5RUaM3g37Ka+VnmMVOXgZdzgCxwFZyVhyxzssD -kB4jcm75UEZx8BiaoPQDQEsBongdx5M4Vwv5XnvUq7sK7eZLmUzW9hmkPjgLea0/ -znchvPsLeTNqSfIcH14TbFt6B2y1G3Vbi5/6UiAaIqLrqjZlCrQXQ2xvdWRlcmEg -QXB0IFJlcG9zaXRvcnmIYAQTEQIAIAUCSe+CLQIbAwYLCQgHAwIEFQIIAwQWAgMB -Ah4BAheAAAoJEDJ1dO4CqBjdGQUAnitydC/NGEh0aZXDN1v22pWFpRzTAJ46N4gT -Zx25oWfyppX3R7fSH+7TPrkCDQRJ74ItEAgAq8s4iMsGhk9nnMF6wlarqHjws4Dw -NFZBzA1Ah8KnMtrdr8t99OfzY1b7PNzHXujcaTTqL6L881ezdsls9aHp2kr24Btr -8nqEZJHSjCnQscAGu+NrhoH2KvK+tMRCHGRcy5UNQbLTJi4Hf8Lo+zv0WUy9BCDu -7HoDlwrrh1Rw5oOwLFc2UXSTEB6BwYna0mZcNjVpfKNHa//wJcKR0AtsCwRT9znP -GS0Hpqi1l0/iU7sJhNWyyF427ANg+Jv2n4IP+dd734ZiFeJ9tWCtBjfc3MZJKETk -tiCtX7FVIIqBAmYLwPqcvZMGJMrNzLBtRuuiBv5bFcPpMEhoD40oQEG8uwADBQf/ -f3NpQbuAcZLMzbrHYu3FB/+4ETvDJXJIEUiQUdobWancSBUhuNPOqIgLzIWM1jRu -jWGIpkeP6iqNW9kDrq26CuMFP2CoVvnaMiLXUvyf62HWAiYXXlZle5O97bvhYMtM -Y4o5sMo2ktI9IcgYIFicFwcmuGyGL7nJ3Bo9FAUV2LvMe++O/f13jsPpygoTZgGT -6w0erglWgrgf5pXt8ajlI4TUrlMVg9Iy/tB9ZzVHnpk21o4vLHwZkgXe1WlK/Rze -ZCruXyXHaFyEJN2zlP2xNj2F2WisL+/HEnl/qzU4IpNI2LQV2aiY9Nt8MBXgSHAh -gWKWkjiB+tswgzuNsBOTM4hJBBgRAgAJBQJJ74ItAhsMAAoJEDJ1dO4CqBjd988A -oJ1WlEx2BcFA7W1RMyErejcvB6thAKCf3t0thSQvkoGi3AOJ4Haj/C3yUQ== -=H6IR ------END PGP PUBLIC KEY BLOCK----- diff --git a/core/src/main/resources/com/axemblr/provisionr/core/templates/jenkins-ci.org.key b/core/src/main/resources/com/axemblr/provisionr/core/templates/jenkins-ci.org.key deleted file mode 100644 index 7a6e812..0000000 --- a/core/src/main/resources/com/axemblr/provisionr/core/templates/jenkins-ci.org.key +++ /dev/null @@ -1,112 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.9 (GNU/Linux) - -mQGiBEmFQG0RBACXScOxb6BTV6rQE/tcJopAEWsdvmE0jNIRWjDDzB7HovX6Anrq -n7+Vq4spAReSFbBVaYiiOx2cGDymj2dyx2i9NAI/9/cQXJOU+RPdDzHVlO1Edksp -5rKn0cGPWY5sLxRf8s/tO5oyKgwCVgTaB5a8gBHaoGms3nNC4YYf+lqlpwCgjbti -3u1iMIx6Rs+dG0+xw1oi5FUD/2tLJMx7vCUQHhPRupeYFPoD8vWpcbGb5nHfHi4U -8/x4qZspAIwvXtGw0UBHildGpqe9onp22Syadn/7JgMWhHoFw5Ke/rTMlxREL7pa -TiXuagD2G84tjJ66oJP1FigslJzrnG61y85V7THL61OFqDg6IOP4onbsdqHby4VD -zZj9A/9uQxIn5250AGLNpARStAcNPJNJbHOQuv0iF3vnG8uO7/oscB0TYb8/juxr -hs9GdSN0U0BxENR+8KWy5lttpqLMKlKRknQYy34UstQiyFgAQ9Epncu9uIbVDgWt -y7utnqXN033EyYkcWx5EhLAgHkC7wSzeSWABV3JSXN7CeeOif7QiS29oc3VrZSBL -YXdhZ3VjaGkgPGtrQGtvaHN1a2Uub3JnPohjBBMRAgAjAhsDBgsJCAcDAgQVAggD -BBYCAwECHgECF4AFAko/7vYCGQEACgkQm30y8tUFguabhgCgi54IQR4rpJZ/uUHe -ZB879zUWTQwAniQDBO+Zly7Fsvm0Mcvqvl02UzxCtC1Lb2hzdWtlIEthd2FndWNo -aSA8a29oc3VrZS5rYXdhZ3VjaGlAc3VuLmNvbT6IYAQTEQIAIAUCSj/qbQIbAwYL -CQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEJt9MvLVBYLm38gAoIGR2+TQeJaCeEa8 -CQhZYzDoiJkQAJ0cpmD+0VA+leOAr5LEccNVd70Z/dHNy83JARAAAQEAAAAAAAAA -AAAAAAD/2P/gABBKRklGAAEBAQBgAGAAAP/hAGBFeGlmAABJSSoACAAAAAQAMQEC -ABkAAAA+AAAAEFEBAAEAAAABQ5AAEVEEAAEAAAASCwAAElEEAAEAAAASCwAAAAAA -AE1hY3JvbWVkaWEgRmlyZXdvcmtzIDQuMAAA/9sAQwAIBgYHBgUIBwcHCQkICgwU -DQwLCwwZEhMPFB0aHx4dGhwcICQuJyAiLCMcHCg3KSwwMTQ0NB8nOT04MjwuMzQy -/9sAQwEJCQkMCwwYDQ0YMiEcITIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy -MjIyMjIyMjIyMjIyMjIyMjIyMjIy/8AAEQgArgCWAwEiAAIRAQMRAf/EAB8AAAEF -AQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQEC -AwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkq -NDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqS -k5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk -5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkK -C//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGx -wQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFla -Y2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2 -t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQAC -EQMRAD8A9wEj/wB9vzpfMf8Avt+dRinCpGSeY398/nS72/vH86YKBQBJvb+8fzpd -7f3j+dMFLQA/e394/nS7j6n86ZSimA7cfU07cfU1HnFOFADtx9aXJ9TTKUUxD8n1 -pc+9Mp1AC5ozSUtAC0maKKADNFJ2ooAoCnCmilzWZQ6lFJSimAopaQUtAC54rOvN -dsLCTZPPGrdwXAry/wCKHxXfRppND0Mq16Bie5PIi9lHdv5V8/X+rXt/O8tzcyyy -MclnYkk0avYdl1PqPxT8VtH8NwqwzdXEuSkaHoB61wjftCXhlzHosBjHZpSCa8PW -O7uhuAkcDueaaYbhOqMMe1L5lcvWx9U+FPjJ4f8AEU0dpdhtLvXOFWdgY3PoH6fg -cV6MrZGa+EklIOJOPqK9i+G3xem0TytI8QSSXGnHCQXJO57f2Pqn6indrclq+x9G -5pwNVoLiO4hSaGRZIpFDKynIYHuKmBqyB+aWmg0uaAFopKKAFoozRQBQFLSUorMo -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 -=cjdq ------END PGP PUBLIC KEY BLOCK----- diff --git a/core/src/main/resources/com/axemblr/provisionr/core/templates/jenkins.xml b/core/src/main/resources/com/axemblr/provisionr/core/templates/jenkins.xml new file mode 100644 index 0000000..c7297f3 --- /dev/null +++ b/core/src/main/resources/com/axemblr/provisionr/core/templates/jenkins.xml @@ -0,0 +1,132 @@ + + \ No newline at end of file diff --git a/core/src/main/resources/features.xml b/core/src/main/resources/features.xml index 51b0355..01c06a9 100644 --- a/core/src/main/resources/features.xml +++ b/core/src/main/resources/features.xml @@ -54,5 +54,17 @@ mvn:com.axemblr.provisionr/provisionr-core/${project.version}/cfg/defaults + + + mvn:com.axemblr.provisionr/provisionr-core/${project.version}/cfg/fileinstall + + + + mvn:com.axemblr.provisionr/provisionr-core/${project.version}/template/cdh3 + + + + mvn:com.axemblr.provisionr/provisionr-core/${project.version}/template/jenkins + \ No newline at end of file diff --git a/core/src/main/resources/org.apache.felix.fileinstall-templates.cfg b/core/src/main/resources/org.apache.felix.fileinstall-templates.cfg new file mode 100644 index 0000000..4182045 --- /dev/null +++ b/core/src/main/resources/org.apache.felix.fileinstall-templates.cfg @@ -0,0 +1,12 @@ + +# +# FileInstall configurations for custom templates +# + +felix.fileinstall.dir = ./templates +felix.fileinstall.filter = .*\\.xml + +felix.fileinstall.poll = 1000 +felix.fileinstall.debug = -1 + +felix.fileinstall.bundles.new.start = false diff --git a/core/src/test/java/com/axemblr/provisionr/core/BaseJaxbTest.java b/core/src/test/java/com/axemblr/provisionr/core/BaseJaxbTest.java new file mode 100644 index 0000000..dbf55a5 --- /dev/null +++ b/core/src/test/java/com/axemblr/provisionr/core/BaseJaxbTest.java @@ -0,0 +1,41 @@ +package com.axemblr.provisionr.core; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import org.custommonkey.xmlunit.XMLUnit; +import org.junit.Before; + +public abstract class BaseJaxbTest { + + protected JAXBContext jaxb; + + static { + XMLUnit.setIgnoreWhitespace(true); + XMLUnit.setIgnoreComments(true); + XMLUnit.setIgnoreAttributeOrder(true); + } + + @Before + public void setUp() throws JAXBException { + jaxb = JAXBContext.newInstance(getContextClasses()); + } + + public abstract Class[] getContextClasses(); + + /** + * Marshal an object as XML using a standard JAXB Context + */ + protected String asXml(Object obj) throws Exception { + ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(outBytes); + + Marshaller marshaller = jaxb.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + + marshaller.marshal(obj, out); + return outBytes.toString(); + } +} diff --git a/core/src/test/java/com/axemblr/provisionr/core/activities/SpawnProcessForEachMachineTest.java b/core/src/test/java/com/axemblr/provisionr/core/activities/SpawnProcessForEachMachineTest.java index 451ea4c..2b26ae5 100644 --- a/core/src/test/java/com/axemblr/provisionr/core/activities/SpawnProcessForEachMachineTest.java +++ b/core/src/test/java/com/axemblr/provisionr/core/activities/SpawnProcessForEachMachineTest.java @@ -35,7 +35,7 @@ public class SpawnProcessForEachMachineTest { - private static final String SAMPLE_PROCESS_KEY = "sample"; + private static final String EMPTY_PROCESS_KEY = "empty"; private static final String RESULT = "result"; private static final String BUSINESS_KEY = UUID.randomUUID().toString(); @@ -59,10 +59,10 @@ public void testSpawnSampleProcessForLocalhost() throws Exception { ProcessEngine processEngine = new StandaloneInMemProcessEngineConfiguration() .setJobExecutorActivate(true).buildProcessEngine(); processEngine.getRepositoryService().createDeployment() - .addClasspathResource("diagrams/sample.bpmn20.xml").deploy(); + .addClasspathResource("diagrams/empty.bpmn20.xml").deploy(); try { - JavaDelegate delegate = new SpawnProcessForEachMachine(processEngine, SAMPLE_PROCESS_KEY, "test", RESULT); + JavaDelegate delegate = new SpawnProcessForEachMachine(processEngine, EMPTY_PROCESS_KEY, "test", RESULT); delegate.execute(execution); @SuppressWarnings("unchecked") diff --git a/core/src/test/java/com/axemblr/provisionr/core/templates/PoolTemplateInstallerTest.java b/core/src/test/java/com/axemblr/provisionr/core/templates/PoolTemplateInstallerTest.java new file mode 100644 index 0000000..8aaa772 --- /dev/null +++ b/core/src/test/java/com/axemblr/provisionr/core/templates/PoolTemplateInstallerTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012 S.C. Axemblr Software Solutions S.R.L + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.axemblr.provisionr.core.templates; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Dictionary; +import org.apache.ibatis.io.Resources; +import org.junit.Test; +import org.mockito.Matchers; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +public class PoolTemplateInstallerTest { + + @Test + public void testInstallAndUninstallTemplate() throws Exception { + BundleContext bundleContext = mock(BundleContext.class); + + ServiceRegistration registration = mock(ServiceRegistration.class); + when(bundleContext.registerService(eq(PoolTemplate.class.getName()), any(), + Matchers.>any())).thenReturn(registration); + + File file = getPathToCdh3Template(); + PoolTemplateInstaller installer = new PoolTemplateInstaller(bundleContext); + + installer.install(file); + verify(bundleContext).registerService(eq(PoolTemplate.class.getName()), + any(), (Dictionary) isNull()); + verifyZeroInteractions(registration); + + installer.uninstall(file); + verify(registration).unregister(); + } + + private File getPathToCdh3Template() throws URISyntaxException, IOException { + return new File(Resources.getResourceURL("com/axemblr/provisionr/core/templates/cdh3.xml").toURI()); + } +} diff --git a/core/src/test/java/com/axemblr/provisionr/core/templates/xml/XmlTemplateTest.java b/core/src/test/java/com/axemblr/provisionr/core/templates/xml/XmlTemplateTest.java new file mode 100644 index 0000000..fe5ef06 --- /dev/null +++ b/core/src/test/java/com/axemblr/provisionr/core/templates/xml/XmlTemplateTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2013 S.C. Axemblr Software Solutions S.R.L + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.axemblr.provisionr.core.templates.xml; + +import com.axemblr.provisionr.api.network.Network; +import com.axemblr.provisionr.api.network.Rule; +import com.axemblr.provisionr.api.software.Software; +import com.axemblr.provisionr.core.BaseJaxbTest; +import com.google.common.base.Charsets; +import static com.google.common.collect.Lists.newArrayList; +import com.google.common.io.Resources; +import java.io.IOException; +import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; +import static org.fest.assertions.api.Assertions.assertThat; +import org.junit.Test; + +public class XmlTemplateTest extends BaseJaxbTest { + + public static final String DEFAULT_JENKINS_TEMPLATE = "com/axemblr/provisionr/core/templates/jenkins.xml"; + + public static final String DEFAULT_CDH3_TEMPLATE = "com/axemblr/provisionr/core/templates/cdh3.xml"; + + @Test + public void testLoadDefaultCdh3Template() throws Exception { + XmlTemplate template = XmlTemplate.newXmlTemplate(readResource(DEFAULT_CDH3_TEMPLATE)); + + assertThat(template.getId()).isEqualTo("cdh3"); + assertThat(template.getPackages()).contains("hue"); + assertThat(template.getOsVersion()).isEqualTo("10.04 LTS"); + + assertThat(template.getRepositories()).hasSize(2); + assertThat(template.getFiles()).hasSize(1); + } + + @Test + public void testApplyCdh3TemplateToNetworkAndSoftware() throws Exception { + XmlTemplate template = XmlTemplate.newXmlTemplate(readResource(DEFAULT_CDH3_TEMPLATE)); + + Network network = template.apply(Network.builder().createNetwork()); + assertThat(network.getIngress()).contains( + Rule.builder().anySource().tcp().port(8080).createRule()); + + + Software software = template.apply(Software.builder().createSoftware()); + assertThat(software.getPackages()).contains("hue").contains("hadoop-0.20"); + + assertThat(software.getFiles()).hasSize(1); + assertThat(software.getRepositories()).hasSize(2); + } + + @Test + public void testLoadDefaultJenkinsTemplate() throws Exception { + XmlTemplate template = XmlTemplate.newXmlTemplate(readResource(DEFAULT_JENKINS_TEMPLATE)); + + assertThat(template.getPorts()).contains(8080); + assertThat(template.getRepositories()).hasSize(1); + + assertThat(template.getPackages()).contains("jenkins").contains("git-core"); + } + + @Test + public void testSerializeBasicTemplateAsXml() throws Exception { + XmlTemplate template = new XmlTemplate(); + template.setId("jenkins"); + + template.setDescription("Just testing"); + template.setOsVersion("10.04 LTS"); + + template.setPackages(newArrayList("jenkins", "git-core", "subversion")); + template.setPorts(newArrayList(8080, 22)); + + template.setFiles(newArrayList( + new FileEntry("http://google.com", "/opt/google.html") + )); + + template.setRepositories(newArrayList( + new RepositoryEntry("jenkins", newArrayList("deb ..."), "-----BEGIN PGP PUBLIC KEY BLOCK----- ...") + )); + + String actual = asXml(template); + assertXMLEqual(actual, readResource("templates/test.xml"), actual); + } + + private String readResource(String resource) throws IOException { + return Resources.toString(Resources.getResource(resource), Charsets.UTF_8); + } + + @Override + public Class[] getContextClasses() { + return new Class[]{XmlTemplate.class}; + } +} diff --git a/core/src/test/java/com/axemblr/provisionr/sample/SampleProvisioningProcessTest.java b/core/src/test/java/com/axemblr/provisionr/sample/SampleProvisioningProcessTest.java deleted file mode 100644 index 6901304..0000000 --- a/core/src/test/java/com/axemblr/provisionr/sample/SampleProvisioningProcessTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2012 S.C. Axemblr Software Solutions S.R.L - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.axemblr.provisionr.sample; - -import com.google.common.collect.Maps; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import org.activiti.engine.ProcessEngine; -import org.activiti.engine.ProcessEngineConfiguration; -import org.activiti.engine.RuntimeService; -import org.activiti.engine.runtime.ProcessInstance; -import org.junit.After; -import static org.junit.Assert.assertEquals; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -@Ignore -public class SampleProvisioningProcessTest { - - private static final String PROCESS_NAME = "sample"; - - private ProcessEngine engine; - private RuntimeService runtimeService; - - @Before - public void setUp() { - engine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration() - .buildProcessEngine(); - engine.getRepositoryService().createDeployment() - .addClasspathResource("diagrams/sample.bpmn20.xml").deploy(); - runtimeService = engine.getRuntimeService(); - } - - @After - public void tearDown() { - engine.close(); - } - - @Test - public void testBuildAndRunASimpleProcess() throws Exception { - String jobId = "j-" + UUID.randomUUID(); - - Map variables = Maps.newHashMap(); - variables.put("provisioningTimeout", "PT10M" /* 10 minutes */); - - ProcessInstance instance = runtimeService.startProcessInstanceByKey(PROCESS_NAME, jobId, variables); - assertEquals(instance.getBusinessKey(), jobId); - waitForProcessToFinish(instance); - } - - public void waitForProcessToFinish(ProcessInstance instance) throws InterruptedException { - while (!instance.isEnded()) { - TimeUnit.SECONDS.sleep(1); - } - } - -} diff --git a/core/src/test/java/com/axemblr/provisionr/sample/multiinstance/MultiInstanceIdempotentTask.java b/core/src/test/java/com/axemblr/provisionr/sample/multiinstance/MultiInstanceIdempotentTask.java deleted file mode 100644 index f7f4163..0000000 --- a/core/src/test/java/com/axemblr/provisionr/sample/multiinstance/MultiInstanceIdempotentTask.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2012 S.C. Axemblr Software Solutions S.R.L - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.axemblr.provisionr.sample.multiinstance; - -import java.util.concurrent.TimeUnit; -import org.activiti.engine.delegate.DelegateExecution; -import org.activiti.engine.delegate.JavaDelegate; - -public class MultiInstanceIdempotentTask implements JavaDelegate { - - @Override - public void execute(DelegateExecution execution) throws Exception { - final String aDude = String.class.cast(execution.getVariable("singlePerson")); - - if (aDude.equalsIgnoreCase("andrei")) { - System.err.println("Long wait start: " + aDude); - TimeUnit.SECONDS.sleep(5); - System.err.println("Long wait done: " + aDude); - - } else { - System.err.println("Short wait start: " + aDude); - TimeUnit.SECONDS.sleep(3); - System.err.println("Short wait done: " + aDude); - } - } -} diff --git a/core/src/test/java/com/axemblr/provisionr/sample/multiinstance/MultiInstanceProcessTest.java b/core/src/test/java/com/axemblr/provisionr/sample/multiinstance/MultiInstanceProcessTest.java deleted file mode 100644 index 7d110c0..0000000 --- a/core/src/test/java/com/axemblr/provisionr/sample/multiinstance/MultiInstanceProcessTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2012 S.C. Axemblr Software Solutions S.R.L - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.axemblr.provisionr.sample.multiinstance; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import org.activiti.engine.ProcessEngine; -import org.activiti.engine.ProcessEngineConfiguration; -import org.activiti.engine.RuntimeService; -import org.activiti.engine.history.HistoricProcessInstance; -import org.activiti.engine.runtime.ProcessInstance; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MultiInstanceProcessTest { - - private static final Logger LOG = LoggerFactory.getLogger(MultiInstanceProcessTest.class); - - private final String PROCESS_NAME = "multiInstance"; - - private ProcessEngine engine; - private RuntimeService runtimeService; - - @Before - public void setUp() { - engine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration() - // use MVCC to avoid locking issues and PersistenceExceptions - .setJdbcUrl("jdbc:h2:mem:activiti;MVCC=TRUE;DB_CLOSE_DELAY=1000") - .setJobExecutorActivate(true) // needed for async jobs - .setHistory(ProcessEngineConfiguration.HISTORY_FULL) - .buildProcessEngine(); - - engine.getRepositoryService() - .createDeployment() - .addClasspathResource("diagrams/multiInstance.bpmn20.xml") - .addClasspathResource("diagrams/helloDude.bpmn20.xml") - .deploy(); - - runtimeService = engine.getRuntimeService(); - } - - @After - public void tearDown() { - engine.close(); - } - - @Test - @Ignore - public void testBuildAndRunMultiInstanceProcess() throws Exception { - final String businessKey = "j-1234"; - - final List people = Lists.newArrayList("Andrei", "Ioan", - "Eugen", "Alina", "Mihai", "Ciociolina"); - - final Map variables = Maps.newHashMap(); - variables.put("people", people); - - SpawnProcesses.runtimeService.set(runtimeService); - ProcessInstance instance = runtimeService.startProcessInstanceByKey( - PROCESS_NAME, businessKey, variables); - - Assert.assertEquals(instance.getBusinessKey(), businessKey); - waitForProcess(instance); - - // after the process has ended we should not be able to get a - // ProcessInstance but a HistoricProcessInstance - - HistoricProcessInstance historicProcessInstance = engine - .getHistoryService().createHistoricProcessInstanceQuery() - .processInstanceBusinessKey(businessKey).singleResult(); - - LOG.info("Process took {} ms", historicProcessInstance.getDurationInMillis()); - } - - private void waitForProcess(final ProcessInstance instance) throws InterruptedException { - ProcessInstance localInstance; - boolean keepRunningQuery = true; - while (keepRunningQuery) { - localInstance = getProcessInstanceByBusinessKey(instance); - keepRunningQuery = computeWaitCondition(localInstance); - TimeUnit.SECONDS.sleep(1); - } - } - - private boolean computeWaitCondition(ProcessInstance localInstance) { - if (localInstance != null) { - return !localInstance.isEnded(); - } else { - return false; - } - } - - private ProcessInstance getProcessInstanceByBusinessKey( - final ProcessInstance instance) { - return engine.getRuntimeService().createProcessInstanceQuery() - .processInstanceBusinessKey(instance.getBusinessKey()) - .singleResult(); - } -} diff --git a/core/src/test/java/com/axemblr/provisionr/sample/multiinstance/SpawnProcesses.java b/core/src/test/java/com/axemblr/provisionr/sample/multiinstance/SpawnProcesses.java deleted file mode 100644 index d6c5b9d..0000000 --- a/core/src/test/java/com/axemblr/provisionr/sample/multiinstance/SpawnProcesses.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2012 S.C. Axemblr Software Solutions S.R.L - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.axemblr.provisionr.sample.multiinstance; - -import com.google.common.collect.ImmutableMap; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; -import org.activiti.engine.RuntimeService; -import org.activiti.engine.delegate.DelegateExecution; -import org.activiti.engine.delegate.JavaDelegate; -import org.activiti.engine.runtime.ProcessInstance; - -public class SpawnProcesses implements JavaDelegate { - - public static AtomicReference runtimeService = new AtomicReference(); - - @Override - public void execute(DelegateExecution execution) throws Exception { - @SuppressWarnings("unchecked") - List people = (List) execution.getVariable("people"); - - for (final String person : people) { - ProcessInstance instance = runtimeService.get().startProcessInstanceByKey("helloDude", - ImmutableMap.of("singlePerson", person)); - System.out.println("Started process with ID " + instance.getId() + " for person " + person); - } - } -} diff --git a/core/src/test/java/com/axemblr/provisionr/sample/suspend/FailingTask.java b/core/src/test/java/com/axemblr/provisionr/sample/suspend/FailingTask.java deleted file mode 100644 index aff8a20..0000000 --- a/core/src/test/java/com/axemblr/provisionr/sample/suspend/FailingTask.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2013 S.C. Axemblr Software Solutions S.R.L - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.axemblr.provisionr.sample.suspend; - -import java.io.Serializable; -import java.util.concurrent.atomic.AtomicInteger; -import org.activiti.engine.delegate.DelegateExecution; -import org.activiti.engine.delegate.JavaDelegate; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class FailingTask implements JavaDelegate, Serializable { - - public static final AtomicInteger FAIL_COUNT = new AtomicInteger(0); - - private static final Logger LOG = LoggerFactory.getLogger(FailingTask.class); - - @Override - public void execute(DelegateExecution execution) throws Exception { - if (FAIL_COUNT.get() > 3) { - LOG.info("Task failed {} times, not failing again", FAIL_COUNT.get()); - } else { - LOG.info("Failing the task one more time for a total of " + FAIL_COUNT.get()); - throw new RuntimeException("FailingTask failed " + FAIL_COUNT.incrementAndGet() + " times"); - } - } -} diff --git a/core/src/test/java/com/axemblr/provisionr/sample/suspend/JobFailAndResumeTest.java b/core/src/test/java/com/axemblr/provisionr/sample/suspend/JobFailAndResumeTest.java deleted file mode 100644 index c8876a5..0000000 --- a/core/src/test/java/com/axemblr/provisionr/sample/suspend/JobFailAndResumeTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2013 S.C. Axemblr Software Solutions S.R.L - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.axemblr.provisionr.sample.suspend; - -import static com.google.common.base.Preconditions.checkArgument; -import com.google.common.collect.ImmutableMap; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import org.activiti.engine.ProcessEngine; -import org.activiti.engine.ProcessEngineConfiguration; -import org.activiti.engine.RuntimeService; -import org.activiti.engine.impl.persistence.entity.JobEntity; -import org.activiti.engine.runtime.Job; -import org.activiti.engine.runtime.ProcessInstance; -import static org.fest.assertions.api.Assertions.assertThat; -import static org.fest.assertions.api.Assertions.fail; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class JobFailAndResumeTest { - - private static String PROCESS_NAME = "failAndResume"; - - private ProcessEngine engine; - private RuntimeService runtimeService; - - @Before - public void setUp() throws Exception { - engine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration() - .setJobExecutorActivate(true) - .buildProcessEngine(); - - engine.getRepositoryService().createDeployment() - .addClasspathResource("diagrams/failAndResume.bpmn20.xml").deploy(); - - runtimeService = engine.getRuntimeService(); - } - - @After - public void tearDown() throws Exception { - engine.close(); - } - - @Test - public void testProcessShouldSuspendAfter3FailsAndSucceedAfterActivation() throws Exception { - String jobId = UUID.randomUUID().toString(); - - ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(PROCESS_NAME, jobId, - ImmutableMap.of("failTask", new FailingTask())); - assertThat(processInstance.getBusinessKey()).isEqualTo(jobId); - - TimeUnit.SECONDS.sleep(1); - - assertThat(FailingTask.FAIL_COUNT.get()).isEqualTo(3); - Job job = engine.getManagementService().createJobQuery().withException().singleResult(); - engine.getManagementService().setJobRetries(job.getId(), JobEntity.DEFAULT_RETRIES); - - assertThatJobGetsExecutedBeforeTimeout(10); - assertThat(FailingTask.FAIL_COUNT.get()).isEqualTo(4); - } - - private void assertThatJobGetsExecutedBeforeTimeout(int timeoutInSeconds) throws InterruptedException { - checkArgument(timeoutInSeconds > 0, "supply positive"); - int i = 0; - while (i < timeoutInSeconds) { - if (FailingTask.FAIL_COUNT.get() == 4) return; - TimeUnit.SECONDS.sleep(1); - i++; - } - fail("Timeout exceeded"); - } -} diff --git a/core/src/test/java/com/axemblr/provisionr/sample/tasks/CheckCredentialsTask.java b/core/src/test/java/com/axemblr/provisionr/sample/tasks/CheckCredentialsTask.java deleted file mode 100644 index f9277a9..0000000 --- a/core/src/test/java/com/axemblr/provisionr/sample/tasks/CheckCredentialsTask.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2012 S.C. Axemblr Software Solutions S.R.L - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.axemblr.provisionr.sample.tasks; - -import java.util.concurrent.TimeUnit; - -import org.activiti.engine.delegate.DelegateExecution; -import org.activiti.engine.delegate.JavaDelegate; - -public class CheckCredentialsTask implements JavaDelegate { - - @Override - public void execute(DelegateExecution execution) throws Exception { - System.err.println("** Check cloud provider credentials"); - } -} diff --git a/core/src/test/java/com/axemblr/provisionr/sample/tasks/CheckParametersTask.java b/core/src/test/java/com/axemblr/provisionr/sample/tasks/CheckParametersTask.java deleted file mode 100644 index b8061dc..0000000 --- a/core/src/test/java/com/axemblr/provisionr/sample/tasks/CheckParametersTask.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2012 S.C. Axemblr Software Solutions S.R.L - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.axemblr.provisionr.sample.tasks; - -import org.activiti.engine.delegate.DelegateExecution; -import org.activiti.engine.delegate.JavaDelegate; - -public class CheckParametersTask implements JavaDelegate { - - @Override - public void execute(DelegateExecution execution) throws Exception { - System.err.println("** Check parameters"); - } - -} diff --git a/core/src/test/java/com/axemblr/provisionr/sample/tasks/ProvisionMachinesInBatches.java b/core/src/test/java/com/axemblr/provisionr/sample/tasks/ProvisionMachinesInBatches.java deleted file mode 100644 index 18667cc..0000000 --- a/core/src/test/java/com/axemblr/provisionr/sample/tasks/ProvisionMachinesInBatches.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2012 S.C. Axemblr Software Solutions S.R.L - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.axemblr.provisionr.sample.tasks; - -import org.activiti.engine.impl.pvm.delegate.ActivityBehavior; -import org.activiti.engine.impl.pvm.delegate.ActivityExecution; - -import com.google.common.collect.Lists; - -public class ProvisionMachinesInBatches implements ActivityBehavior { - - @Override - public void execute(ActivityExecution execution) throws Exception { - // ProcessDefinitionBuilder processBuilder = new - // ProcessDefinitionBuilder(); - // execution.createSubProcessInstance(processBuilder.buildProcessDefinition()).start(); - - System.err.println("** Provisioning machines in batches"); - execution.takeAll(execution.getActivity().getOutgoingTransitions(), Lists. newArrayList()); - } - -} diff --git a/core/src/test/java/com/axemblr/provisionr/sample/tasks/SetupAdminAccessTask.java b/core/src/test/java/com/axemblr/provisionr/sample/tasks/SetupAdminAccessTask.java deleted file mode 100644 index ebea9df..0000000 --- a/core/src/test/java/com/axemblr/provisionr/sample/tasks/SetupAdminAccessTask.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2012 S.C. Axemblr Software Solutions S.R.L - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.axemblr.provisionr.sample.tasks; - -import org.activiti.engine.delegate.DelegateExecution; -import org.activiti.engine.delegate.JavaDelegate; - -public class SetupAdminAccessTask implements JavaDelegate { - - @Override - public void execute(DelegateExecution execution) throws Exception { - System.err.println("** Setup admin access"); - } -} diff --git a/core/src/test/java/com/axemblr/provisionr/sample/tasks/SetupNetworkContextTask.java b/core/src/test/java/com/axemblr/provisionr/sample/tasks/SetupNetworkContextTask.java deleted file mode 100644 index 2716e5a..0000000 --- a/core/src/test/java/com/axemblr/provisionr/sample/tasks/SetupNetworkContextTask.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2012 S.C. Axemblr Software Solutions S.R.L - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.axemblr.provisionr.sample.tasks; - -import org.activiti.engine.delegate.DelegateExecution; -import org.activiti.engine.delegate.JavaDelegate; - -public class SetupNetworkContextTask implements JavaDelegate { - - @Override - public void execute(DelegateExecution execution) throws Exception { - System.err.println("** Setup network context for cluster"); - } - -} diff --git a/core/src/test/resources/diagrams/empty.bpmn20.xml b/core/src/test/resources/diagrams/empty.bpmn20.xml new file mode 100644 index 0000000..14ef1a0 --- /dev/null +++ b/core/src/test/resources/diagrams/empty.bpmn20.xml @@ -0,0 +1,26 @@ + + + + + + + + + + \ No newline at end of file diff --git a/core/src/test/resources/diagrams/helloDude.bpmn20.xml b/core/src/test/resources/diagrams/helloDude.bpmn20.xml deleted file mode 100644 index cdb6d87..0000000 --- a/core/src/test/resources/diagrams/helloDude.bpmn20.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/core/src/test/resources/diagrams/multiInstance.bpmn20.xml b/core/src/test/resources/diagrams/multiInstance.bpmn20.xml deleted file mode 100644 index c71f286..0000000 --- a/core/src/test/resources/diagrams/multiInstance.bpmn20.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/core/src/test/resources/diagrams/sample.bpmn20.xml b/core/src/test/resources/diagrams/sample.bpmn20.xml deleted file mode 100644 index cbda71b..0000000 --- a/core/src/test/resources/diagrams/sample.bpmn20.xml +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - - - - - - - - - - - PT1M - - - - - - - - - - - - PT5M - - - - - - - - - - - - PT10M - - - - - - - - - - - - PT10M - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/core/src/test/resources/templates/test.xml b/core/src/test/resources/templates/test.xml new file mode 100644 index 0000000..380a73a --- /dev/null +++ b/core/src/test/resources/templates/test.xml @@ -0,0 +1,24 @@ + + \ No newline at end of file diff --git a/karaf/assembly-tests/pom.xml b/karaf/assembly-tests/pom.xml index aae1ce7..eb726a9 100644 --- a/karaf/assembly-tests/pom.xml +++ b/karaf/assembly-tests/pom.xml @@ -30,6 +30,12 @@ jar + + com.axemblr.provisionr + provisionr-core + ${project.version} + test + com.axemblr.provisionr provisionr-assembly diff --git a/karaf/assembly-tests/src/test/java/com/axemblr/provisionr/karaf/CustomKarafDistributionTest.java b/karaf/assembly-tests/src/test/java/com/axemblr/provisionr/karaf/CustomKarafDistributionTest.java index 35a22b4..d7714e8 100644 --- a/karaf/assembly-tests/src/test/java/com/axemblr/provisionr/karaf/CustomKarafDistributionTest.java +++ b/karaf/assembly-tests/src/test/java/com/axemblr/provisionr/karaf/CustomKarafDistributionTest.java @@ -17,6 +17,7 @@ package com.axemblr.provisionr.karaf; import com.axemblr.provisionr.api.Provisionr; +import com.axemblr.provisionr.core.templates.PoolTemplate; import static com.axemblr.provisionr.test.KarafTests.getKarafVersionAsInProject; import com.google.common.base.Stopwatch; import com.google.common.io.CharStreams; @@ -70,7 +71,15 @@ public class CustomKarafDistributionTest { public static final int DEFAULT_JETTY_PORT = 8181; public static final int TIMEOUT_IN_MILLISECONDS = 1000; - public static final int EXPECTED_NUMBER_OF_PROVISIONR_SERVICES = 2; /* amazon & cloudstack */ + /** + * We are only starting Amazon by default. The support for cloudstack is not ready yet. + */ + public static final int EXPECTED_NUMBER_OF_PROVISIONR_SERVICES = 1; + + /** + * We only register two pool templates by default through the provisionr-core bundle + */ + public static final int EXPECTED_NUMBER_OF_POOL_TEMPLATES = 2; @Inject private FeaturesService features; @@ -102,7 +111,9 @@ public void testAllFeaturesStartAsExpected() throws Exception { assertAllBundlesAreActive(); assertJettyStartsInLessThan(5000 /* milliseconds */); + assertProvisionrServicesAreStartedInLessThan(5000 /* milliseconds */); + assertPoolTemplatesAreRegisteredInLessThan(5000 /* milliseconds */); assertActivitiExplorerIsRunningInLessThan(30000 /* milliseconds */); } @@ -129,31 +140,43 @@ private void assertActivitiExplorerIsRunningInLessThan(int timeoutInMilliseconds } } - private void assertProvisionrServicesAreStartedInLessThan(int timeoutInMilliseconds) throws InterruptedException { - final ServiceTracker tracker = new ServiceTracker(bundleContext, Provisionr.class.getCanonicalName(), null); + private void assertProvisionrServicesAreStartedInLessThan(int timeoutInMilliseconds) throws Exception { + assertServicesAreStartedInLessThan(Provisionr.class, + EXPECTED_NUMBER_OF_PROVISIONR_SERVICES, timeoutInMilliseconds); + } + + private void assertPoolTemplatesAreRegisteredInLessThan(int timeoutInMilliseconds) throws Exception { + assertServicesAreStartedInLessThan(PoolTemplate.class, + EXPECTED_NUMBER_OF_POOL_TEMPLATES, timeoutInMilliseconds); + + } + + private void assertServicesAreStartedInLessThan( + Class klass, int expectedCardinality, int timeoutInMilliseconds + ) throws Exception { + final ServiceTracker tracker = new ServiceTracker(bundleContext, klass.getName(), null); tracker.open(true); try { final Stopwatch stopwatch = new Stopwatch().start(); - final int expectedCount = EXPECTED_NUMBER_OF_PROVISIONR_SERVICES; while (true) { Object[] services = tracker.getServices(); - if (services == null || services.length < expectedCount) { + if (services == null || services.length < expectedCardinality) { final int actualCount = (services == null) ? 0 : services.length; if (stopwatch.elapsedMillis() > timeoutInMilliseconds) { - fail(String.format("Expected to find %d Provisionr services. Found only %d in %d milliseconds", - expectedCount, actualCount, timeoutInMilliseconds)); + fail(String.format("Expected to find %d %s services. Found only %d in %d milliseconds", + expectedCardinality, klass.getSimpleName(), actualCount, timeoutInMilliseconds)); } LOG.info(String.format("Found %d services implementing %s. Trying again in 1s.", - actualCount, Provisionr.class.getCanonicalName())); + actualCount, klass.getName())); TimeUnit.SECONDS.sleep(1); - } else if (services.length > expectedCount) { + } else if (services.length > expectedCardinality) { fail(String.format("Expected to find %d services implementing %s. Found %d (more than expected).", - expectedCount, Provisionr.class.getCanonicalName(), services.length)); + expectedCardinality, klass.getName(), services.length)); - } else if (services.length == expectedCount) { + } else if (services.length == expectedCardinality) { break; /* done - the test was successful */ } } diff --git a/karaf/assembly/src/main/assembly/unix.xml b/karaf/assembly/src/main/assembly/unix.xml index b5d77b9..725264d 100644 --- a/karaf/assembly/src/main/assembly/unix.xml +++ b/karaf/assembly/src/main/assembly/unix.xml @@ -33,7 +33,7 @@ etc/org.apache.karaf.features.cfg etc/custom.properties etc/startup.properties - etc/jre.properties* + etc/org.apache.karaf.features.repos.cfg readme.txt LICENSE @@ -75,6 +75,18 @@ 0644 + + + target/classes/templates + /templates/ + + *.* + + unix + 0644 + + + system diff --git a/karaf/assembly/src/main/filtered-resources/etc/jre.properties b/karaf/assembly/src/main/filtered-resources/etc/jre.properties.cxf similarity index 100% rename from karaf/assembly/src/main/filtered-resources/etc/jre.properties rename to karaf/assembly/src/main/filtered-resources/etc/jre.properties.cxf diff --git a/karaf/assembly/src/main/filtered-resources/etc/startup.properties b/karaf/assembly/src/main/filtered-resources/etc/startup.properties index 1329ca3..fc67fd9 100644 --- a/karaf/assembly/src/main/filtered-resources/etc/startup.properties +++ b/karaf/assembly/src/main/filtered-resources/etc/startup.properties @@ -72,5 +72,5 @@ org/apache/karaf/shell/org.apache.karaf.shell.ssh/2.2.10/org.apache.karaf.shell. org/apache/karaf/deployer/org.apache.karaf.deployer.spring/2.2.10/org.apache.karaf.deployer.spring-2.2.10.jar=28 org/apache/karaf/deployer/org.apache.karaf.deployer.blueprint/2.2.10/org.apache.karaf.deployer.blueprint-2.2.10.jar=28 org/apache/karaf/deployer/org.apache.karaf.deployer.features/2.2.10/org.apache.karaf.deployer.features-2.2.10.jar=30 -org/apache/karaf/deployer/org.apache.karaf.deployer.kar/2.2.10/org.apache.karaf.deployer.kar-2.2.10.jar=30 +#org/apache/karaf/deployer/org.apache.karaf.deployer.kar/2.2.10/org.apache.karaf.deployer.kar-2.2.10.jar=30 org/apache/karaf/deployer/org.apache.karaf.deployer.wrap/2.2.10/org.apache.karaf.deployer.wrap-2.2.10.jar=30 diff --git a/karaf/assembly/src/main/filtered-resources/templates/README b/karaf/assembly/src/main/filtered-resources/templates/README new file mode 100644 index 0000000..86427fb --- /dev/null +++ b/karaf/assembly/src/main/filtered-resources/templates/README @@ -0,0 +1,4 @@ + +A folder for pre-configure pool templates + +See cdh3.xml.sample to learn more about the expected format. \ No newline at end of file diff --git a/karaf/assembly/src/main/filtered-resources/templates/cdh3.xml.sample b/karaf/assembly/src/main/filtered-resources/templates/cdh3.xml.sample new file mode 100644 index 0000000..a625b80 --- /dev/null +++ b/karaf/assembly/src/main/filtered-resources/templates/cdh3.xml.sample @@ -0,0 +1,106 @@ + + \ No newline at end of file diff --git a/karaf/commands/src/main/java/com/axemblr/provisionr/commands/ListTemplatesCommand.java b/karaf/commands/src/main/java/com/axemblr/provisionr/commands/ListTemplatesCommand.java index 7dea452..80c8df3 100644 --- a/karaf/commands/src/main/java/com/axemblr/provisionr/commands/ListTemplatesCommand.java +++ b/karaf/commands/src/main/java/com/axemblr/provisionr/commands/ListTemplatesCommand.java @@ -41,7 +41,7 @@ public ListTemplatesCommand(List templates) { @Override protected Object doExecute() throws Exception { for (PoolTemplate template : templates) { - out.printf("%s\t\t%s\n", template.getId(), template.getDescription()); + out.printf("- %s\n\t%s\n", template.getId(), template.getDescription()); } return null; diff --git a/karaf/commands/src/test/java/com/axemblr/provisionr/commands/CreatePoolCommandTest.java b/karaf/commands/src/test/java/com/axemblr/provisionr/commands/CreatePoolCommandTest.java index eeeae22..e12b1d2 100644 --- a/karaf/commands/src/test/java/com/axemblr/provisionr/commands/CreatePoolCommandTest.java +++ b/karaf/commands/src/test/java/com/axemblr/provisionr/commands/CreatePoolCommandTest.java @@ -20,10 +20,14 @@ import com.axemblr.provisionr.api.access.AdminAccess; import com.axemblr.provisionr.api.pool.Pool; import com.axemblr.provisionr.api.provider.Provider; -import com.axemblr.provisionr.core.templates.JenkinsTemplate; import com.axemblr.provisionr.core.templates.PoolTemplate; +import com.axemblr.provisionr.core.templates.xml.XmlTemplate; +import com.google.common.base.Charsets; import com.google.common.base.Optional; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; +import com.google.common.io.Resources; +import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.NoSuchElementException; @@ -45,7 +49,7 @@ public void testCreatePoolStartsTheManagementProcess() throws Exception { final Pool pool = mock(Pool.class); final List services = ImmutableList.of(service); - final List templates = ImmutableList.of(new JenkinsTemplate()); + final List templates = ImmutableList.of(); CreatePoolCommand command = new CreatePoolCommand(services, templates) { @Override protected Pool createPoolFromArgumentsAndServiceDefaults(Provisionr service) { @@ -74,7 +78,8 @@ public void testProvisioningServiceNotFound() throws Exception { @Test public void testCreatePoolWithTemplate() { - final JenkinsTemplate template = new JenkinsTemplate(); + final PoolTemplate template = XmlTemplate.newXmlTemplate(readDefaultTemplate("jenkins")); + CreatePoolCommand command = new CreatePoolCommand(Collections.emptyList(), ImmutableList.of(template)) { @@ -102,4 +107,15 @@ private Provisionr newProvisionrMockWithId(String id) { when(service.getId()).thenReturn(id); return service; } + + + private String readDefaultTemplate(String name) { + try { + return Resources.toString(Resources.getResource(PoolTemplate.class, + String.format("/com/axemblr/provisionr/core/templates/%s.xml", name)), Charsets.UTF_8); + + } catch (IOException e) { + throw Throwables.propagate(e); + } + } } diff --git a/karaf/commands/src/test/java/com/axemblr/provisionr/commands/ListTemplatesCommandTest.java b/karaf/commands/src/test/java/com/axemblr/provisionr/commands/ListTemplatesCommandTest.java index 232923e..36678af 100644 --- a/karaf/commands/src/test/java/com/axemblr/provisionr/commands/ListTemplatesCommandTest.java +++ b/karaf/commands/src/test/java/com/axemblr/provisionr/commands/ListTemplatesCommandTest.java @@ -16,9 +16,12 @@ package com.axemblr.provisionr.commands; -import com.axemblr.provisionr.core.templates.JenkinsTemplate; import com.axemblr.provisionr.core.templates.PoolTemplate; +import com.axemblr.provisionr.core.templates.xml.XmlTemplate; +import com.google.common.base.Charsets; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; +import com.google.common.io.Resources; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; @@ -48,7 +51,10 @@ public void tearDown() throws IOException { @Test public void testListTemplates() throws Exception { - final ImmutableList templates = ImmutableList.of(new JenkinsTemplate()); + final ImmutableList templates = ImmutableList.of( + XmlTemplate.newXmlTemplate(readDefaultTemplate("jenkins")), + XmlTemplate.newXmlTemplate(readDefaultTemplate("cdh3"))); + ListTemplatesCommand command = new ListTemplatesCommand(templates); command.setOut(out); @@ -56,6 +62,16 @@ public void testListTemplates() throws Exception { out.flush(); - assertThat(outputStream.toString()).contains("jenkins"); + assertThat(outputStream.toString()).contains("jenkins").contains("cdh3"); + } + + private String readDefaultTemplate(String name) { + try { + return Resources.toString(Resources.getResource(PoolTemplate.class, + String.format("/com/axemblr/provisionr/core/templates/%s.xml", name)), Charsets.UTF_8); + + } catch (IOException e) { + throw Throwables.propagate(e); + } } } diff --git a/karaf/features/pom.xml b/karaf/features/pom.xml index d214b87..f26bf88 100644 --- a/karaf/features/pom.xml +++ b/karaf/features/pom.xml @@ -37,17 +37,17 @@ com.axemblr.provisionr - provisionr-console + provisionr-amazon provided com.axemblr.provisionr - provisionr-amazon + provisionr-cloudstack provided com.axemblr.provisionr - provisionr-cloudstack + provisionr-console provided diff --git a/karaf/features/src/main/resources/features.xml b/karaf/features/src/main/resources/features.xml index e349651..bc33782 100644 --- a/karaf/features/src/main/resources/features.xml +++ b/karaf/features/src/main/resources/features.xml @@ -63,12 +63,11 @@ axemblr-provisionr-core - - axemblr-provisionr-console axemblr-provisionr-commands - axemblr-provisionr-amazon - axemblr-provisionr-cloudstack + + + activiti-karaf-commands activiti-karaf-web-explorer diff --git a/parent/pom.xml b/parent/pom.xml index 0b867ca..751bbdb 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -65,7 +65,7 @@ UTF-8 - 4.3.1 + 4.2.0 5.10 1.3.168 3.0.7.RELEASE @@ -80,6 +80,7 @@ 2.2.10 2.7.2 3.2.2 + 3.2.6 1.3.14_1 3.1.1 1.8.6 @@ -101,6 +102,7 @@ 1.0.7_1 1.0.7 0.8.8 + 1.3 @@ -150,12 +152,6 @@ provisionr-branding ${project.version} - - com.axemblr.provisionr - provisionr-test-support - ${project.version} - test - org.activiti activiti-engine @@ -191,6 +187,11 @@ compiler ${mustache.version} + + org.apache.felix + org.apache.felix.fileinstall + ${felix.fileinstall.version} + org.slf4j slf4j-api @@ -201,6 +202,18 @@ h2 ${h2.version} + + com.axemblr.provisionr + provisionr-test-support + ${project.version} + test + + + xmlunit + xmlunit + ${xmlunit.version} + test + org.slf4j slf4j-simple diff --git a/providers/amazon-tests/src/test/java/com/axemblr/provisionr/amazon/AmazonProvisionrLiveTest.java b/providers/amazon-tests/src/test/java/com/axemblr/provisionr/amazon/AmazonProvisionrLiveTest.java index 16c87d5..19900b7 100644 --- a/providers/amazon-tests/src/test/java/com/axemblr/provisionr/amazon/AmazonProvisionrLiveTest.java +++ b/providers/amazon-tests/src/test/java/com/axemblr/provisionr/amazon/AmazonProvisionrLiveTest.java @@ -29,12 +29,15 @@ import com.axemblr.provisionr.api.software.Software; import com.axemblr.provisionr.core.PoolStatus; import com.axemblr.provisionr.core.Ssh; -import com.axemblr.provisionr.core.templates.JenkinsTemplate; +import com.axemblr.provisionr.core.templates.PoolTemplate; +import com.axemblr.provisionr.core.templates.xml.XmlTemplate; import static com.axemblr.provisionr.test.KarafTests.installProvisionrFeatures; import static com.axemblr.provisionr.test.KarafTests.installProvisionrTestSupportBundle; import static com.axemblr.provisionr.test.KarafTests.passThroughAllSystemPropertiesWithPrefix; import static com.axemblr.provisionr.test.KarafTests.useDefaultKarafAsInProjectWithJunitBundles; import com.axemblr.provisionr.test.ProvisionrLiveTestSupport; +import com.google.common.base.Charsets; +import com.google.common.io.Resources; import java.io.IOException; import java.util.List; import java.util.NoSuchElementException; @@ -62,6 +65,8 @@ public class AmazonProvisionrLiveTest extends ProvisionrLiveTestSupport { public static final int TEST_POOL_SIZE = 2; + public static final String DEFAULT_JENKINS_TEMPLATE_PATH = "/com/axemblr/provisionr/core/templates/jenkins.xml"; + public AmazonProvisionrLiveTest() { super(AmazonProvisionr.ID); } @@ -102,7 +107,9 @@ public void startProvisioningProcess() throws Exception { .file("http://axemblr.com", destinationPath) .createSoftware(); - JenkinsTemplate jenkins = new JenkinsTemplate(); + PoolTemplate jenkins = XmlTemplate.newXmlTemplate(Resources.toString(Resources + .getResource(PoolTemplate.class, DEFAULT_JENKINS_TEMPLATE_PATH), Charsets.UTF_8)); + final Pool pool = jenkins.apply(Pool.builder() .provider(provider) .network(network) diff --git a/test-support/pom.xml b/test-support/pom.xml index e28adf8..08d2776 100644 --- a/test-support/pom.xml +++ b/test-support/pom.xml @@ -15,7 +15,8 @@ ~ limitations under the License. --> - + provisionr-parent com.axemblr.provisionr @@ -31,8 +32,6 @@ com.axemblr.provisionr.test* - org.osgi.framework;version="[1.3, 2.0)", - org.osgi.util.tracker;version="[1.3, 2.0)", org.mockito*;resolution:=optional, * @@ -42,7 +41,6 @@ org.osgi org.osgi.core - 4.3.0 com.axemblr.provisionr diff --git a/test-support/src/main/java/com/axemblr/provisionr/test/ProvisionrLiveTestSupport.java b/test-support/src/main/java/com/axemblr/provisionr/test/ProvisionrLiveTestSupport.java index 2555f80..9d7a7d7 100644 --- a/test-support/src/main/java/com/axemblr/provisionr/test/ProvisionrLiveTestSupport.java +++ b/test-support/src/main/java/com/axemblr/provisionr/test/ProvisionrLiveTestSupport.java @@ -57,13 +57,13 @@ public ProvisionrLiveTestSupport(String provisionrId) { * Retrieve a reference to an OSGi service using the class name */ protected T getOsgiService(Class klass, int timeoutInMilliseconds) throws InterruptedException { - ServiceTracker tracker = new ServiceTracker(bundleContext, + ServiceTracker tracker = new ServiceTracker(bundleContext, klass.getCanonicalName(), null); tracker.open(true); try { - return checkNotNull(tracker.waitForService(timeoutInMilliseconds), "OSGi Service not available " - + klass.getCanonicalName()); + return (T) checkNotNull(tracker.waitForService(timeoutInMilliseconds), + "OSGi Service not available " + klass.getCanonicalName()); } finally { tracker.close(); }