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 @@
+
+
+
+ Cloudera CDH3 template for Ubuntu 10.04 LTS (lucid) including the Cloudera Manager installer
+
+
+ cloudera-manager-agent
+ cloudera-manager-daemons
+ oracle-j2sdk1.6
+ hadoop-0.20
+ hadoop-0.20-native
+ hadoop-hive
+ hadoop-pig
+ oozie-client
+ oozie
+ hue-plugins
+ hue-common
+ hue-proxy
+ hue-about
+ hue-help
+ hue-filebrowser
+ hue-jobsub
+ hue-beeswax
+ hue-useradmin
+ hue-shell
+ hue
+
+
+ 7180
+ 8888
+ 8080
+
+
+
+
+
+
+
+ deb http://archive.cloudera.com/debian lucid-cdh3 contrib
+
+
+
+
+
+ deb http://archive.cloudera.com/cm4/ubuntu/lucid/amd64/cm lucid-cm4 contrib
+ deb-src http://archive.cloudera.com/cm4/ubuntu/lucid/amd64/cm lucid-cm4 contrib
+
+
+
+
+
\ 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 @@
+
+
+ A short template that installs the latest jenkins with git & svn
+
+ jenkins
+ git-core
+ subversion
+
+
+ 8080
+
+
+
+
+ deb http://pkg.jenkins-ci.org/debian binary/
+
+
+
+
+
\ 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 @@
+
+
+ Just testing
+
+
+
+
+ jenkins
+ git-core
+ subversion
+
+
+ 8080
+ 22
+
+
+
+
+ deb ...
+
+ -----BEGIN PGP PUBLIC KEY BLOCK----- ...
+
+
+
\ 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 @@
+
+
+ Cloudera CDH3 template for Ubuntu 10.04 LTS (lucid) including Cloudera Manager
+
+ cloudera-manager-agent
+ cloudera-manager-daemons
+ oracle-j2sdk1.6
+ hadoop-0.20
+ hadoop-0.20-native
+ hadoop-hive
+ hadoop-pig
+ oozie-client
+ oozie
+ hue-plugins
+ hue-common
+ hue-proxy
+ hue-about
+ hue-help
+ hue-filebrowser
+ hue-jobsub
+ hue-beeswax
+ hue-useradmin
+ hue-shell
+ hue
+
+
+ 7180
+ 8888
+ 8080
+
+
+
+
+
+
+
+ deb http://archive.cloudera.com/debian lucid-cdh3 contrib
+
+
+
+
+
+ deb http://archive.cloudera.com/cm4/ubuntu/lucid/amd64/cm lucid-cm4 contrib
+ deb-src http://archive.cloudera.com/cm4/ubuntu/lucid/amd64/cm lucid-cm4 contrib
+
+
+
+
+
\ 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();
}