CLI copy-state: support transformations
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/9dd50dac Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/9dd50dac Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/9dd50dac Branch: refs/heads/master Commit: 9dd50dacb52ec7b02796e85e3b428c64dda535af Parents: dd10a15 Author: Aled Sage <[email protected]> Authored: Mon Sep 15 18:15:42 2014 +0100 Committer: Aled Sage <[email protected]> Committed: Thu Sep 18 10:23:14 2014 +0100 ---------------------------------------------------------------------- .../rebind/transformer/CompoundTransformer.java | 6 ++ .../transformer/CompoundTransformerLoader.java | 65 ++++++++++++++++++++ .../CompoundTransformerLoaderTest.java | 52 ++++++++++++++++ usage/cli/src/main/java/brooklyn/cli/Main.java | 18 +++++- 4 files changed, 140 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9dd50dac/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java b/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java index 096d450..6cac668 100644 --- a/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java +++ b/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java @@ -15,6 +15,7 @@ import brooklyn.util.ResourceUtils; import brooklyn.util.collections.MutableMap; import brooklyn.util.text.TemplateProcessor; +import com.google.api.client.repackaged.com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.Beta; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableMap; @@ -150,4 +151,9 @@ public class CompoundTransformer { .enrichers(enrichers) .build(); } + + @VisibleForTesting + Multimap<BrooklynObjectType, RawDataTransformer> getRawDataTransformers() { + return ArrayListMultimap.create(rawDataTransformers); + } } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9dd50dac/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java b/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java new file mode 100644 index 0000000..98ac3b5 --- /dev/null +++ b/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java @@ -0,0 +1,65 @@ +package brooklyn.entity.rebind.transformer; + +import java.util.Map; + +import brooklyn.entity.rebind.transformer.CompoundTransformer.Builder; +import brooklyn.entity.rebind.transformer.impl.XsltTransformerTest; +import brooklyn.util.ResourceUtils; +import brooklyn.util.exceptions.Exceptions; +import brooklyn.util.text.TemplateProcessor; +import brooklyn.util.yaml.Yamls; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; + +@Beta +public class CompoundTransformerLoader { + + // TODO Improve error handing so get nicer errors. + // TODO Improve names (e.g. always camel case?) + // TODO Pass in classloader for reflectively loading rawDataTransformer? + + public static CompoundTransformer load(String contents) { + CompoundTransformer.Builder builder = CompoundTransformer.builder(); + Iterable<Object> toplevel = Yamls.parseAll(contents); + Map<String, Map<?,?>> rules = (Map<String, Map<?,?>>) ((Map<?,?>)Iterables.getOnlyElement(toplevel)); + for (Map.Entry<String, Map<?,?>> entry : rules.entrySet()) { + addRule(builder, entry.getKey(), entry.getValue()); + } + return builder.build(); + } + + private static void addRule(Builder builder, String name, Map<?,?> args) { + if (name.equals("renameClass")) { + String oldVal = (String) args.get("old_val"); + String newVal = (String) args.get("new_val"); + builder.renameClass(oldVal, newVal); + } else if (name.equals("renameType")) { + String oldVal = (String) args.get("old_val"); + String newVal = (String) args.get("new_val"); + builder.renameType(oldVal, newVal); + } else if (name.equals("renameField")) { + String clazz = (String) args.get("class_name"); + String oldVal = (String) args.get("old_val"); + String newVal = (String) args.get("new_val"); + builder.renameField(clazz, oldVal, newVal); + } else if (name.equals("xslt")) { + String url = (String) args.get("url"); + Map<String,?> substitutions = (Map<String, ?>) args.get("substitutions"); + String xsltTemplate = ResourceUtils.create(XsltTransformerTest.class).getResourceAsString(url); + String xslt = TemplateProcessor.processTemplateContents(xsltTemplate, substitutions == null ? ImmutableMap.<String, String>of() : substitutions); + builder.xsltTransformer(xslt); + } else if (name.equals("rawDataTransformer")) { + String type = (String) args.get("type"); + try { + Class<?> clazz = CompoundTransformerLoader.class.getClassLoader().loadClass(type); + builder.rawDataTransformer((RawDataTransformer) clazz.newInstance()); + } catch (Exception e) { + throw Exceptions.propagate(e); + } + } else { + throw new IllegalStateException("Unsupported transform '"+name+"' ("+args+")"); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9dd50dac/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoaderTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoaderTest.java b/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoaderTest.java new file mode 100644 index 0000000..bef4eb6 --- /dev/null +++ b/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoaderTest.java @@ -0,0 +1,52 @@ +package brooklyn.entity.rebind.transformer; + +import static org.testng.Assert.assertTrue; + +import java.util.Collection; + +import org.testng.annotations.Test; + +import brooklyn.entity.rebind.BrooklynObjectType; +import brooklyn.entity.rebind.transformer.impl.XsltTransformer; + +import com.google.common.collect.Iterables; + +public class CompoundTransformerLoaderTest { + + @Test + public void testLoadsTransformerFromYaml() throws Exception { + String contents = + "renameType:\n"+ + " old_val: myoldname\n"+ + " new_val: mynewname\n"+ + "renameClass:\n"+ + " old_val: myoldname\n"+ + " new_val: mynewname\n"+ + "renameField:\n"+ + " class_name: myclassname\n"+ + " old_val: myoldname\n"+ + " new_val: mynewname\n"+ + "xslt:\n"+ + " url: classpath://brooklyn/entity/rebind/transformer/renameType.xslt\n"+ + " substitutions:\n"+ + " old_val: myoldname\n"+ + " new_val: mynewname\n"+ + "rawDataTransformer:\n"+ + " type: "+MyRawDataTransformer.class.getName()+"\n"; + + CompoundTransformer transformer = CompoundTransformerLoader.load(contents); + Collection<RawDataTransformer> rawDataTransformers = transformer.getRawDataTransformers().get(BrooklynObjectType.ENTITY); + assertTrue(Iterables.get(rawDataTransformers, 0) instanceof XsltTransformer); + assertTrue(Iterables.get(rawDataTransformers, 1) instanceof XsltTransformer); + assertTrue(Iterables.get(rawDataTransformers, 2) instanceof XsltTransformer); + assertTrue(Iterables.get(rawDataTransformers, 3) instanceof XsltTransformer); + assertTrue(Iterables.get(rawDataTransformers, 4) instanceof MyRawDataTransformer); + } + + public static class MyRawDataTransformer implements RawDataTransformer { + @Override + public String transform(String input) throws Exception { + return input; // no-op + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9dd50dac/usage/cli/src/main/java/brooklyn/cli/Main.java ---------------------------------------------------------------------- diff --git a/usage/cli/src/main/java/brooklyn/cli/Main.java b/usage/cli/src/main/java/brooklyn/cli/Main.java index 4e1b99b..385fbbd 100644 --- a/usage/cli/src/main/java/brooklyn/cli/Main.java +++ b/usage/cli/src/main/java/brooklyn/cli/Main.java @@ -19,7 +19,6 @@ package brooklyn.cli; import static com.google.common.base.Preconditions.checkNotNull; - import groovy.lang.GroovyClassLoader; import groovy.lang.GroovyShell; import io.airlift.command.Cli; @@ -48,6 +47,8 @@ import brooklyn.entity.basic.Entities; import brooklyn.entity.basic.StartableApplication; import brooklyn.entity.proxying.EntitySpec; import brooklyn.entity.rebind.persister.PersistMode; +import brooklyn.entity.rebind.transformer.CompoundTransformer; +import brooklyn.entity.rebind.transformer.CompoundTransformerLoader; import brooklyn.entity.trait.Startable; import brooklyn.launcher.BrooklynLauncher; import brooklyn.launcher.BrooklynServerDetails; @@ -697,6 +698,10 @@ public class Main extends AbstractMain { description = "The location spec for an object store to copy data to") public String destinationLocation; + @Option(name = { "--transformations" }, title = "transformations", + description = "local transformations file, to be applied to the copy of the data before uploading it") + public String transformations; + @Override public Void call() throws Exception { checkNotNull(destinationDir, "destinationDir"); // presumably because required=true this will never be null! @@ -727,6 +732,8 @@ public class Main extends AbstractMain { try { BrooklynMementoRawData memento = launcher.retrieveState(); + CompoundTransformer transformer = loadTransformer(transformations); + BrooklynMementoRawData newMemento = transformer.transform(memento); launcher.persistState(memento, destinationDir, destinationLocation); } catch (FatalRuntimeException e) { @@ -749,6 +756,15 @@ public class Main extends AbstractMain { return null; } + protected CompoundTransformer loadTransformer(String transformations) { + if (transformations == null) { + return CompoundTransformer.NOOP; + } else { + String contents = ResourceUtils.create(this).getResourceAsString(transformations); + return CompoundTransformerLoader.load(contents); + } + } + @Override public ToStringHelper string() { return super.string()
