http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/pool/ReusableMachineTemplate.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/pool/ReusableMachineTemplate.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/pool/ReusableMachineTemplate.java new file mode 100644 index 0000000..ea93685 --- /dev/null +++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/pool/ReusableMachineTemplate.java @@ -0,0 +1,182 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.location.jclouds.pool; + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.brooklyn.location.jclouds.templates.PortableTemplateBuilder; +import org.jclouds.compute.options.TemplateOptions; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * A facility for having a template we can declare without knowing the provider, + * then find matching instances, create instances, and generally manipulate them. + * <p> + * NB: to be sure of matching a specific template, you should provide a unique id in the constructor. + * (this will force 'strict' mode.) + */ +// TODO tags/metadata semantics are not quite right, as they could apply to the server _image_ or _instance_ + +// TODO we could use a hashcode over the values of template-builder and template-options fields, as a tag/usermetadata, +// to guarantee (virtually) matching only machines created from this template (instead of asking for unique id) +public class ReusableMachineTemplate extends PortableTemplateBuilder<ReusableMachineTemplate> { + + public static final String PREFIX = "brooklyn:template."; + public static final String NAME_METADATA_KEY = PREFIX+"name"; + public static final String DESCRIPTION_METADATA_KEY = PREFIX+"name"; + public static final String HASH_METADATA_KEY = PREFIX+"hash"; + public static final String TEMPLATE_OWNER_METADATA_KEY = PREFIX+"owner"; + + private String name = null; + private String templateOwner = null; + private String description = null; + private boolean strict; + + public ReusableMachineTemplate() { strict = false; } + public ReusableMachineTemplate(String name) { name(name); } + + /** see #getName() */ + public ReusableMachineTemplate name(String name) { + this.name = name; + strict = true; + return this; + } + + /** see #getDescription() */ + public ReusableMachineTemplate description(String description) { + this.description = description; + return this; + } + + /** whether this template only matches machines instances created from this template; + * defaults true if a name is set, otherwise false. + * if false, it will ignore name, owner, and hashcode */ + public ReusableMachineTemplate strict(boolean strict) { + this.strict = strict; + return this; + } + + /** no owner, means anyone can pick this up (default) */ + public ReusableMachineTemplate templateUnowned() { + return templateOwner(null); + } + /** adds user.name as owner of this template */ + public ReusableMachineTemplate templateOwnedByMe() { + return templateOwner(System.getProperty("user.name")); + } + /** adds an owner tag to this template */ + public ReusableMachineTemplate templateOwner(String owner) { + this.templateOwner = owner; + return this; + } + + /** human-friendly name for this template. should normally be unique, it is the primary differentiator for strict matching. */ + public String getName() { + return name; + } + + /** a description for this template; this is set on created machines but _not_ used to filter them + * (so you can change description freely). */ + public String getDescription() { + return description; + } + + public String getOwner() { + return templateOwner; + } + + public boolean isStrict() { + return strict; + } + + @Override + public List<TemplateOptions> getAdditionalOptions() { + List<TemplateOptions> result = new ArrayList<TemplateOptions>(); + result.addAll(super.getAdditionalOptions()); + if (isStrict()) addStrictOptions(result); + return result; + } + + @Override + public List<TemplateOptions> getAdditionalOptionalOptions() { + List<TemplateOptions> result = new ArrayList<TemplateOptions>(); + result.addAll(super.getAdditionalOptions()); + addStrictOptions(result); + return result; + } + + protected void addStrictOptions(List<TemplateOptions> result) { + if (name!=null) result.add(TemplateOptions.Builder.userMetadata(NAME_METADATA_KEY, name)); + if (templateOwner!=null) result.add(TemplateOptions.Builder.userMetadata(TEMPLATE_OWNER_METADATA_KEY, templateOwner)); + // this is too strict -- the hash code seems to change from run to run (would be nice to fix that) +// result.add(TemplateOptions.Builder.userMetadata(HASH_METADATA_KEY, ""+hashCode())); + } + + /** computes the user metadata that this template will set (argument true) or required to match (argument false) */ + public Map<String,String> getUserMetadata(boolean includeOptional) { + return ImmutableMap.copyOf(computeAggregatedOptions(includeOptional).getUserMetadata()); + } + + /** computes the tags that this template will set (argument true) or require to match (argument false) */ + public Set<String> getTags(boolean includeOptional) { + return ImmutableSet.copyOf(computeAggregatedOptions(includeOptional).getTags()); + } + + public ReusableMachineTemplate tag(String tag) { + return tags(tag); + } + public ReusableMachineTemplate tags(String ...tags) { + return addOptions(TemplateOptions.Builder.tags(Arrays.asList(tags))); + } + + public ReusableMachineTemplate metadata(String key, String value) { + return addOptions(TemplateOptions.Builder.userMetadata(key, value)); + } + public ReusableMachineTemplate metadata(Map<String,String> m) { + return addOptions(TemplateOptions.Builder.userMetadata(m)); + } + + public ReusableMachineTemplate tagOptional(String tag) { + return tagsOptional(tag); + } + public ReusableMachineTemplate tagsOptional(String ...tags) { + return addOptionalOptions(TemplateOptions.Builder.tags(Arrays.asList(tags))); + } + + public ReusableMachineTemplate metadataOptional(String key, String value) { + return addOptionalOptions(TemplateOptions.Builder.userMetadata(key, value)); + } + public ReusableMachineTemplate metadataOptional(Map<String,String> m) { + return addOptionalOptions(TemplateOptions.Builder.userMetadata(m)); + } + + @Override + public String toString() { + String s = makeNonTrivialArgumentsString(); + return (name!=null ? name : "Template") + " [ " + s + " ]"; + } + +}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/AbstractPortableTemplateBuilder.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/AbstractPortableTemplateBuilder.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/AbstractPortableTemplateBuilder.java new file mode 100644 index 0000000..b73e7ec --- /dev/null +++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/AbstractPortableTemplateBuilder.java @@ -0,0 +1,527 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.location.jclouds.templates; + +import java.util.ArrayList; +import java.util.List; + +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.OsFamily; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.options.TemplateOptions; + +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableList; + +public abstract class AbstractPortableTemplateBuilder<T extends AbstractPortableTemplateBuilder<?>> implements TemplateBuilder { + + /** list of commands supplied by user, excluding options */ + protected List<Function<TemplateBuilder,TemplateBuilder>> commands = new ArrayList<Function<TemplateBuilder,TemplateBuilder>>(); + + private Hardware hardware; + private Image image; + private Template template; + private String locationId; + private String imageId; + private String hardwareId; + private OsFamily os; + private String osNameRegex; + private String osDescriptionRegex; + private String osVersionRegex; + private String osArchitectureRegex; + private String hypervisorRegex; + private Boolean is64bit; + private String imageNameRegex; + private String imageDescriptionRegex; + private String imageVersionRegex; + private Double minCores; + private Integer minRam; + private Double minDisk; + private Predicate<Image> imageCondition; + private Function<Iterable<? extends Image>, Image> imageChooserFunction; + /** this is the last options instance set by a call to options(TemplateOptions) */ + private TemplateOptions options; + /** these are extra options that we want _added_, in order, on top of the last options set */ + private List<TemplateOptions> additionalOptions = new ArrayList<TemplateOptions>(); + + @Override + public T any() { + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.any(); }}); + return (T)this; + } + + @Override + public T fromHardware(final Hardware hardware) { + this.hardware = hardware; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.fromHardware(hardware); }}); + return (T)this; + } + + public Hardware getHardware() { + return hardware; + } + + @Override + public T fromImage(final Image image) { + this.image = image; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.fromImage(image); }}); + return (T)this; + } + + public Image getImage() { + return image; + } + + @Override + public T fromTemplate(final Template template) { + this.template = template; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.fromTemplate(template); }}); + return (T)this; + } + + public Template getTemplate() { + return template; + } + + @Override + public T smallest() { + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.smallest(); }}); + return (T)this; + } + + @Override + public T fastest() { + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.fastest(); }}); + return (T)this; + } + + @Override + public T biggest() { + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.biggest(); }}); + return (T)this; + } + + @Override + public T locationId(final String locationId) { + this.locationId = locationId; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.locationId(locationId); }}); + return (T)this; + } + + public String getLocationId() { + return locationId; + } + + @Override + public T imageId(final String imageId) { + this.imageId = imageId; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.imageId(imageId); }}); + return (T)this; + } + + public String getImageId() { + return imageId; + } + + @Override + public T hardwareId(final String hardwareId) { + this.hardwareId = hardwareId; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.hardwareId(hardwareId); }}); + return (T)this; + } + + public String getHardwareId() { + return hardwareId; + } + + @Override + public T osNameMatches(final String osNameRegex) { + this.osNameRegex = osNameRegex; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.osNameMatches(osNameRegex); }}); + return (T)this; + } + + public String getOsNameMatchesRegex() { + return osNameRegex; + } + + @Override + public T osDescriptionMatches(final String osDescriptionRegex) { + this.osDescriptionRegex = osDescriptionRegex; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.osDescriptionMatches(osDescriptionRegex); }}); + return (T)this; + } + + public String getOsDescriptionMatchesRegex() { + return osDescriptionRegex; + } + + @Override + public T osVersionMatches(final String osVersionRegex) { + this.osVersionRegex = osVersionRegex; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.osVersionMatches(osVersionRegex); }}); + return (T)this; + } + + public String getOsVersionMatchesRegex() { + return osVersionRegex; + } + + @Override + public T osArchMatches(final String osArchitectureRegex) { + this.osArchitectureRegex = osArchitectureRegex; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.osArchMatches(osArchitectureRegex); }}); + return (T)this; + } + + public String getOsArchitectureMatchesRegex() { + return osArchitectureRegex; + } + + @Override + public T os64Bit(final boolean is64bit) { + this.is64bit = is64bit; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.os64Bit(is64bit); }}); + return (T)this; + } + + public Boolean getIs64bit() { + return is64bit; + } + + @Override + public T osFamily(final OsFamily os) { + this.os = os; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.osFamily(os); }}); + return (T)this; + } + + public OsFamily getOsFamily() { + return os; + } + + @Override + public T hypervisorMatches(final String hypervisorRegex) { + this.hypervisorRegex = hypervisorRegex; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.hypervisorMatches(hypervisorRegex); }}); + return (T)this; + } + + public String getHypervisorMatchesRegex() { + return hypervisorRegex; + } + + @Override + public T imageNameMatches(final String imageNameRegex) { + this.imageNameRegex = imageNameRegex; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.imageNameMatches(imageNameRegex); }}); + return (T)this; + } + + public String getImageNameMatchesRegex() { + return imageNameRegex; + } + + @Override + public T imageDescriptionMatches(final String imageDescriptionRegex) { + this.imageDescriptionRegex = imageDescriptionRegex; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.imageDescriptionMatches(imageDescriptionRegex); }}); + return (T)this; + } + + public String getImageDescriptionMatchesRegex() { + return imageDescriptionRegex; + } + + @Override + public T imageVersionMatches(final String imageVersionRegex) { + this.imageVersionRegex = imageVersionRegex; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.imageVersionMatches(imageVersionRegex); }}); + return (T)this; + } + + public String getImageVersionMatchesRegex() { + return imageVersionRegex; + } + + @Override + public T imageMatches(final Predicate<Image> condition) { + this.imageCondition = condition; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.imageMatches(condition); }}); + return (T)this; + } + + public Predicate<Image> getImageMatchesCondition() { + return imageCondition; + } + + @Override + public T minCores(final double minCores) { + this.minCores = minCores; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.minCores(minCores); }}); + return (T)this; + } + + public Double getMinCores() { + return minCores; + } + + @Override + public T minRam(final int megabytes) { + this.minRam = megabytes; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.minRam(megabytes); }}); + return (T)this; + } + + /** megabytes */ + public Integer getMinRam() { + return minRam; + } + + @Override + public T minDisk(final double gigabytes) { + this.minDisk = gigabytes; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.minDisk(gigabytes); }}); + return (T)this; + } + + /** megabytes */ + public Double getMinDisk() { + return minDisk; + } + + public T imageChooser(final Function<Iterable<? extends Image>, Image> imageChooserFunction) { + this.imageChooserFunction = imageChooserFunction; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.imageChooser(imageChooserFunction); }}); + return (T)this; + } + + public Function<Iterable<? extends Image>, Image> imageChooser() { + return imageChooserFunction; + } + + /** clears everything set in this template, including any default from the compute service */ + // not sure this is that useful, as the default is only applied if there are no changes + public T blank() { + hardware = null; + image = null; + template = null; + hypervisorRegex = null; + os = null; + locationId = null; + imageId = null; + hardwareId = null; + osNameRegex = null; + osDescriptionRegex = null; + osVersionRegex = null; + osArchitectureRegex = null; + is64bit = null; + imageNameRegex = null; + imageDescriptionRegex = null; + imageVersionRegex = null; + imageCondition = null; + minCores = null; + minRam = null; + options = null; + additionalOptions.clear(); + + // clear all fields, and commands + commands.clear(); + // then add a command to clear osName + Version + 64bit + osFamily(null); + osVersionMatches(null); + // no way to turn off 64-bitness, but it won't usually be turned on +// os64bit(null); + // set _something_ to prevent the default from applying + minRam(1); + + return (T)this; + } + + /** true if the templateBuilder spec is blank (ignoring customization options e.g. tags for the resulting instance) */ + public boolean isBlank() { + if (commands.isEmpty()) return true; + //also "blank" if we've blanked it + if (commands.size()==1 && (minRam!=null && minRam==1)) return true; + return false; + } + + @Override + public T options(final TemplateOptions options) { + this.options = options; + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.options(options); }}); + return (T)this; + } + + /** sets customization options; may be null if not set. use addOptions(new TemplateOptions()) to set new ones. */ + public TemplateOptions getOptions() { + return options; + } + + /** adds customization options; if options have already been set, this will additively set selected options + * (but not all, see addTemplateOptions for more info) + */ + public T addOptions(final TemplateOptions options) { + this.additionalOptions.add(options); + commands.add(new Function<TemplateBuilder,TemplateBuilder>() { + public TemplateBuilder apply(TemplateBuilder b) { return b.options(options); }}); + return (T)this; + } + + public List<TemplateOptions> getAdditionalOptions() { + return ImmutableList.copyOf(additionalOptions); + } + + @Override + public int hashCode() { + return Objects.hashCode( + hypervisorRegex, + os, + locationId, + hardwareId, + imageId, + imageDescriptionRegex, + imageNameRegex, + imageVersionRegex, + // might not be implement hashCode, so ignore +// imageCondition, +// imageChooserFunction, + is64bit, + locationId, + osArchitectureRegex, + osDescriptionRegex, + osNameRegex, + osVersionRegex, + minCores, + minRam, + minDisk, + options, + additionalOptions, + // might not implement hashCode, so ignore +// template, + 0); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + AbstractPortableTemplateBuilder other = (AbstractPortableTemplateBuilder) obj; + if (!Objects.equal(additionalOptions, other.additionalOptions)) return false; + if (!Objects.equal(commands, other.commands)) return false; + if (!Objects.equal(locationId, other.locationId)) return false; + if (!Objects.equal(hardware, other.hardware)) return false; + if (!Objects.equal(hardwareId, other.hardwareId)) return false; + if (!Objects.equal(image, other.image)) return false; + if (!Objects.equal(imageId, other.imageId)) return false; + if (!Objects.equal(imageDescriptionRegex, other.imageDescriptionRegex)) return false; + if (!Objects.equal(imageNameRegex, other.imageNameRegex)) return false; + if (!Objects.equal(imageVersionRegex, other.imageVersionRegex)) return false; + if (!Objects.equal(imageCondition, other.imageCondition)) return false; + if (!Objects.equal(imageChooserFunction, other.imageChooserFunction)) return false; + if (!Objects.equal(os, other.os)) return false; + if (!Objects.equal(osArchitectureRegex, other.osArchitectureRegex)) return false; + if (!Objects.equal(osDescriptionRegex, other.osDescriptionRegex)) return false; + if (!Objects.equal(osNameRegex, other.osNameRegex)) return false; + if (!Objects.equal(osVersionRegex, other.osVersionRegex)) return false; + if (!Objects.equal(is64bit, other.is64bit)) return false; + if (!Objects.equal(hypervisorRegex, other.hypervisorRegex)) return false; + if (!Objects.equal(minCores, other.minCores)) return false; + if (!Objects.equal(minRam, other.minRam)) return false; + if (!Objects.equal(minDisk, other.minDisk)) return false; + if (!Objects.equal(options, other.options)) return false; + if (!Objects.equal(template, other.template)) return false; + return true; + } + + @Override + public String toString() { + return getClass().getSimpleName()+"["+makeNonTrivialArgumentsString()+"]"; + } + + protected String makeNonTrivialArgumentsString() { + String s = + (hardware != null ? "hardware=" + hardware + ", " : "") + + (image != null ? "image=" + image + ", " : "") + + (template != null ? "template=" + template + ", " : "") + + (hypervisorRegex != null ? "hypervisorRegex=" + + hypervisorRegex + ", " : "") + + (os != null ? "os=" + os + ", " : "") + + (locationId != null ? "locationId=" + locationId + ", " : "") + + (imageId != null ? "imageId=" + imageId + ", " : "") + + (hardwareId != null ? "hardwareId=" + hardwareId + ", " : "") + + (osNameRegex != null ? "osNameRegex=" + osNameRegex + ", " + : "") + + (osDescriptionRegex != null ? "osDescriptionRegex=" + + osDescriptionRegex + ", " : "") + + (osVersionRegex != null ? "osVersionRegex=" + osVersionRegex + + ", " : "") + + (osArchitectureRegex != null ? "osArchictectureRegex=" + + osArchitectureRegex + ", " : "") + + (is64bit != null ? "is64bit=" + is64bit + ", " : "") + + (imageNameRegex != null ? "imageNameRegex=" + imageNameRegex + + ", " : "") + + (imageDescriptionRegex != null ? "imageDescriptionRegex=" + + imageDescriptionRegex + ", " : "") + + (imageVersionRegex != null ? "imageVersionRegex=" + + imageVersionRegex + ", " : "") + + (imageCondition != null ? "imageCondition=" + imageCondition + + ", " : "") + + (imageChooserFunction != null ? "imageChooserFunction=" + imageChooserFunction + + ", " : "") + + (minCores != null ? "minCores=" + minCores + ", " : "") + + (minRam != null ? "minRam=" + minRam + ", " : "") + + (minDisk != null ? "minDisk=" + minDisk + ", " : ""); + if (s.endsWith(", ")) s = s.substring(0, s.length()-2); + return s; + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/PortableTemplateBuilder.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/PortableTemplateBuilder.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/PortableTemplateBuilder.java new file mode 100644 index 0000000..eaea03b --- /dev/null +++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/PortableTemplateBuilder.java @@ -0,0 +1,145 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.location.jclouds.templates; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.jclouds.compute.ComputeService; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.domain.TemplateBuilderSpec; +import org.jclouds.compute.options.TemplateOptions; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableList; +import com.google.common.primitives.Ints; + + +public class PortableTemplateBuilder<T extends PortableTemplateBuilder<?>> extends AbstractPortableTemplateBuilder<T> { + + ComputeService svc; + List<TemplateOptions> additionalOptionalOptions = new ArrayList<TemplateOptions>(); + + @Override + public synchronized Template build() { + if (svc!=null) return newJcloudsTemplate(svc); + throw new IllegalStateException("Cannot build a portable template until a compute service is attached"); + } + + public synchronized ComputeService attachComputeService(ComputeService svc) { + ComputeService old = this.svc; + this.svc = svc; + return old; + } + + public TemplateBuilder newJcloudsTemplateBuilder(ComputeService svc) { + TemplateBuilder tb = svc.templateBuilder(); + for (Function<TemplateBuilder,TemplateBuilder> c: commands) { + tb = c.apply(tb); + } + + tb.options(computeAggregatedOptions(true)); + + return tb; + } + + public Template newJcloudsTemplate(ComputeService svc) { + return newJcloudsTemplateBuilder(svc).build(); + } + + /** Adds template options which are used for building, but not for matching/filtering. + * (eg tags added here will be set on any machine created by this template, + * but will not be required when matching this template to existing machines) */ + @SuppressWarnings("unchecked") + public T addOptionalOptions(TemplateOptions options) { + additionalOptionalOptions.add(options); + return (T)this; + } + + protected TemplateOptions computeAggregatedOptions(boolean includeOptional) { + TemplateOptions result; + if (getOptions()!=null) result = getOptions().clone(); + else result = new TemplateOptions(); + if (includeOptional) + for (TemplateOptions moreOptions: getAdditionalOptionalOptions()) result = addTemplateOptions(result, moreOptions); + for (TemplateOptions moreOptions: getAdditionalOptions()) result = addTemplateOptions(result, moreOptions); + return result; + } + + public List<TemplateOptions> getAdditionalOptionalOptions() { + return ImmutableList.copyOf(additionalOptionalOptions); + } + + /** like TemplateOptions.copyTo but additive wrt arrays, collections, and maps, + * putting moreOptions in on top of / at the end of options. + * currently applies to inboundPorts, tags, and userMetadata. */ + public static TemplateOptions addTemplateOptions(TemplateOptions options, TemplateOptions moreOptions) { + TemplateOptions result = options.clone(); + moreOptions.copyTo(result); + + Set<String> tags = new LinkedHashSet<String>(options.getTags()); + tags.addAll(moreOptions.getTags()); + result.tags(tags); + + Map<String,String> userMetadata = new LinkedHashMap<String,String>(options.getUserMetadata()); + userMetadata.putAll(moreOptions.getUserMetadata()); + result.userMetadata(userMetadata); + + Set<Integer> inboundPorts = new TreeSet<Integer>(); + for (int port: options.getInboundPorts()) inboundPorts.add(port); + for (int port: moreOptions.getInboundPorts()) inboundPorts.add(port); + int[] inboundPortsArray = new int[inboundPorts.size()]; + int i=0; + for (Iterator<Integer> portI=inboundPorts.iterator(); portI.hasNext();) { + inboundPortsArray[i++] = portI.next(); + } + result.inboundPorts(inboundPortsArray); + + return result; + } + + protected String makeNonTrivialArgumentsString() { + String s = super.makeNonTrivialArgumentsString(); + TemplateOptions aggr = computeAggregatedOptions(false); + if (aggr.getInboundPorts().length>0) s = "ports="+Ints.asList(aggr.getInboundPorts())+(s!=null && s.length()>0 ? ", "+s : ""); + if (!aggr.getUserMetadata().isEmpty()) s = "metadata="+aggr.getUserMetadata()+(s!=null && s.length()>0 ? ", "+s : ""); + if (!aggr.getTags().isEmpty()) s = "tags="+aggr.getTags()+(s!=null && s.length()>0 ? ", "+s : ""); + return s; + } + + @Override + public TemplateBuilder from(TemplateBuilderSpec spec) { + TemplateOptions options = new TemplateOptions(); + addOptionalOptions(options); + TemplateBuilder result = spec.copyTo(this, options); + return result; + } + + @Override + public TemplateBuilder from(String spec) { + return from(TemplateBuilderSpec.parse(spec)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/zone/AwsAvailabilityZoneExtension.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/zone/AwsAvailabilityZoneExtension.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/zone/AwsAvailabilityZoneExtension.java new file mode 100644 index 0000000..dcb6b4c --- /dev/null +++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/zone/AwsAvailabilityZoneExtension.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.location.jclouds.zone; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.List; +import java.util.Set; + +import org.apache.brooklyn.api.management.ManagementContext; +import org.apache.brooklyn.location.Location; +import org.apache.brooklyn.location.cloud.AbstractAvailabilityZoneExtension; +import org.jclouds.aws.ec2.AWSEC2Api; +import org.jclouds.ec2.domain.AvailabilityZoneInfo; + +import org.apache.brooklyn.location.cloud.AvailabilityZoneExtension; +import org.apache.brooklyn.location.jclouds.JcloudsLocation; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; + +public class AwsAvailabilityZoneExtension extends AbstractAvailabilityZoneExtension implements AvailabilityZoneExtension { + + private final JcloudsLocation loc; + + public AwsAvailabilityZoneExtension(ManagementContext managementContext, JcloudsLocation loc) { + super(managementContext); + this.loc = checkNotNull(loc, "loc"); + checkArgument(loc.getProvider().equals("aws-ec2"), "provider not aws-ec2 (%s)", loc.getProvider()); + } + + @Override + protected List<Location> doGetAllSubLocations() { + List<Location> result = Lists.newArrayList(); + Set<AvailabilityZoneInfo> zones = getAvailabilityZones(); + for (AvailabilityZoneInfo zone : zones) { + result.add(newSubLocation(loc, zone)); + } + return result; + } + + @Override + protected boolean isNameMatch(Location loc, Predicate<? super String> namePredicate) { + return namePredicate.apply(((JcloudsLocation)loc).getRegion()); + } + + protected Set<AvailabilityZoneInfo> getAvailabilityZones() { + String regionName = loc.getRegion(); + AWSEC2Api ec2Client = loc.getComputeService().getContext().unwrapApi(AWSEC2Api.class); + return ec2Client.getAvailabilityZoneAndRegionApi().get().describeAvailabilityZonesInRegion(regionName); + } + + protected JcloudsLocation newSubLocation(Location parent, AvailabilityZoneInfo zone) { + return loc.newSubLocation(ImmutableMap.of(JcloudsLocation.CLOUD_REGION_ID, zone.getZone())); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/resources/META-INF/services/brooklyn.location.LocationResolver ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/resources/META-INF/services/brooklyn.location.LocationResolver b/locations/jclouds/src/main/resources/META-INF/services/brooklyn.location.LocationResolver deleted file mode 100644 index 5b1c084..0000000 --- a/locations/jclouds/src/main/resources/META-INF/services/brooklyn.location.LocationResolver +++ /dev/null @@ -1,2 +0,0 @@ -brooklyn.location.jclouds.JcloudsLocationResolver -brooklyn.location.jclouds.JcloudsByonLocationResolver http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/resources/META-INF/services/org.apache.brooklyn.location.LocationResolver ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/resources/META-INF/services/org.apache.brooklyn.location.LocationResolver b/locations/jclouds/src/main/resources/META-INF/services/org.apache.brooklyn.location.LocationResolver new file mode 100644 index 0000000..e29b717 --- /dev/null +++ b/locations/jclouds/src/main/resources/META-INF/services/org.apache.brooklyn.location.LocationResolver @@ -0,0 +1,2 @@ +org.apache.brooklyn.location.jclouds.JcloudsLocationResolver +org.apache.brooklyn.location.jclouds.JcloudsByonLocationResolver http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreCleaner.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreCleaner.java b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreCleaner.java index dcce68a..eb1654e 100644 --- a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreCleaner.java +++ b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreCleaner.java @@ -29,9 +29,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import brooklyn.config.BrooklynProperties; -import brooklyn.location.basic.LocationConfigKeys; -import brooklyn.location.cloud.CloudLocationConfig; -import brooklyn.location.jclouds.JcloudsLocation; +import org.apache.brooklyn.location.basic.LocationConfigKeys; +import org.apache.brooklyn.location.cloud.CloudLocationConfig; +import org.apache.brooklyn.location.jclouds.JcloudsLocation; /** Utility for cleaning up after test leaks. Most should not leak of course, but if they do... */ public class BlobStoreCleaner { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java index c29bf79..6260a8c 100644 --- a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java +++ b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java @@ -44,10 +44,10 @@ import org.testng.annotations.Test; import brooklyn.config.BrooklynProperties; import brooklyn.entity.basic.Entities; -import brooklyn.location.basic.LocationConfigKeys; -import brooklyn.location.cloud.CloudLocationConfig; -import brooklyn.location.jclouds.JcloudsLocation; -import brooklyn.location.jclouds.JcloudsUtil; +import org.apache.brooklyn.location.basic.LocationConfigKeys; +import org.apache.brooklyn.location.cloud.CloudLocationConfig; +import org.apache.brooklyn.location.jclouds.JcloudsLocation; +import org.apache.brooklyn.location.jclouds.JcloudsUtil; import brooklyn.util.collections.MutableMap; import brooklyn.util.http.HttpTool; import brooklyn.util.http.HttpToolResponse; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreTest.java b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreTest.java index f9ba3a9..0553fd0 100644 --- a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreTest.java +++ b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreTest.java @@ -36,10 +36,10 @@ import org.testng.annotations.Test; import brooklyn.config.BrooklynProperties; import brooklyn.entity.basic.Entities; -import brooklyn.location.basic.LocationConfigKeys; -import brooklyn.location.cloud.CloudLocationConfig; -import brooklyn.location.jclouds.JcloudsLocation; -import brooklyn.location.jclouds.JcloudsUtil; +import org.apache.brooklyn.location.basic.LocationConfigKeys; +import org.apache.brooklyn.location.cloud.CloudLocationConfig; +import org.apache.brooklyn.location.jclouds.JcloudsLocation; +import org.apache.brooklyn.location.jclouds.JcloudsUtil; import brooklyn.util.stream.Streams; import brooklyn.util.text.Identifiers; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsExpect100ContinueTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsExpect100ContinueTest.java b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsExpect100ContinueTest.java index eaaf0f8..556c3c3 100644 --- a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsExpect100ContinueTest.java +++ b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsExpect100ContinueTest.java @@ -30,8 +30,8 @@ import org.testng.annotations.Test; import brooklyn.config.BrooklynProperties; import brooklyn.entity.basic.Entities; -import brooklyn.location.jclouds.JcloudsLocation; -import brooklyn.location.jclouds.JcloudsUtil; +import org.apache.brooklyn.location.jclouds.JcloudsLocation; +import org.apache.brooklyn.location.jclouds.JcloudsUtil; import brooklyn.util.text.Identifiers; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java b/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java deleted file mode 100644 index d84ce5c..0000000 --- a/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 brooklyn.location.jclouds; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; - -import java.util.List; -import java.util.Map; - -import org.apache.brooklyn.test.entity.LocalManagementContextForTests; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeMethod; - -import brooklyn.config.BrooklynProperties; -import brooklyn.entity.basic.Entities; -import brooklyn.location.basic.SshMachineLocation; -import brooklyn.management.internal.LocalManagementContext; -import brooklyn.util.exceptions.CompoundRuntimeException; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; - -public class AbstractJcloudsLiveTest { - - private static final Logger LOG = LoggerFactory.getLogger(AbstractJcloudsLiveTest.class); - - public static final String BROOKLYN_PROPERTIES_PREFIX = "brooklyn.location.jclouds."; - public static final String BROOKLYN_PROPERTIES_LEGACY_PREFIX = "brooklyn.jclouds."; - - public static final String AWS_EC2_PROVIDER = "aws-ec2"; - public static final String AWS_EC2_MICRO_HARDWARE_ID = "t1.micro"; - public static final String AWS_EC2_SMALL_HARDWARE_ID = "m1.small"; - public static final String AWS_EC2_EUWEST_REGION_NAME = "eu-west-1"; - public static final String AWS_EC2_USEAST_REGION_NAME = "us-east-1"; - - public static final String RACKSPACE_PROVIDER = "rackspace-cloudservers-uk"; - - public static final String SOFTLAYER_PROVIDER = "softlayer"; - public static final String SOFTLAYER_AMS01_REGION_NAME = "ams01"; - - protected BrooklynProperties brooklynProperties; - protected LocalManagementContext managementContext; - - protected List<JcloudsSshMachineLocation> machines; - protected JcloudsLocation jcloudsLocation; - - @BeforeMethod(alwaysRun=true) - public void setUp() throws Exception { - machines = Lists.newCopyOnWriteArrayList(); - managementContext = newManagementContext(); - - // Don't let any defaults from brooklyn.properties (except credentials) interfere with test - brooklynProperties = managementContext.getBrooklynProperties(); - stripBrooklynProperties(brooklynProperties); - } - - @AfterMethod(alwaysRun=true) - public void tearDown() throws Exception { - List<Exception> exceptions = Lists.newArrayList(); - try { - if (machines != null) { - for (JcloudsSshMachineLocation machine : machines) { - try { - releaseMachine(machine); - } catch (Exception e) { - LOG.warn("Error releasing machine "+machine+"; continuing...", e); - exceptions.add(e); - } - } - machines.clear(); - } - } finally { - try { - if (managementContext != null) Entities.destroyAll(managementContext); - } catch (Exception e) { - LOG.warn("Error destroying management context", e); - exceptions.add(e); - } - } - - // TODO Debate about whether to: - // - use destroyAllCatching (i.e. not propagating exception) - // Benefit is that other tests in class will subsequently be run, rather than bailing out. - // - propagate exceptions from tearDown - // Benefit is that we don't hide errors; release(...) etc should not be throwing exceptions. - if (exceptions.size() > 0) { - throw new CompoundRuntimeException("Error in tearDown of "+getClass(), exceptions); - } - } - - protected LocalManagementContext newManagementContext() { - // loads properties, by default, but not OSGi or anything else - return LocalManagementContextForTests.builder(true).useDefaultProperties().build(); - } - - protected void stripBrooklynProperties(BrooklynProperties props) { - // remove all location properties except for identity and credential - // (so key, scripts, etc settings don't interfere with tests) - for (String key : ImmutableSet.copyOf(props.asMapWithStringKeys().keySet())) { - if (key.startsWith(BROOKLYN_PROPERTIES_PREFIX) && !(key.endsWith("identity") || key.endsWith("credential"))) { - props.remove(key); - } - if (key.startsWith(BROOKLYN_PROPERTIES_LEGACY_PREFIX) && !(key.endsWith("identity") || key.endsWith("credential"))) { - props.remove(key); - } - - // Also removes scriptHeader (e.g. if doing `. ~/.bashrc` and `. ~/.profile`, then that can cause "stdin: is not a tty") - if (key.startsWith("brooklyn.ssh")) { - props.remove(key); - } - } - } - - protected void assertSshable(SshMachineLocation machine) { - int result = machine.execScript("simplecommand", ImmutableList.of("true")); - assertEquals(result, 0); - } - - // Use this utility method to ensure machines are released on tearDown - protected JcloudsSshMachineLocation obtainMachine(Map<?, ?> conf) throws Exception { - assertNotNull(jcloudsLocation); - JcloudsSshMachineLocation result = (JcloudsSshMachineLocation)jcloudsLocation.obtain(conf); - machines.add(checkNotNull(result, "result")); - return result; - } - - protected JcloudsSshMachineLocation obtainMachine() throws Exception { - return obtainMachine(ImmutableMap.of()); - } - - protected void releaseMachine(JcloudsSshMachineLocation machine) { - assertNotNull(jcloudsLocation); - machines.remove(machine); - jcloudsLocation.release(machine); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java b/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java deleted file mode 100644 index 3b8a4f4..0000000 --- a/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 brooklyn.location.jclouds; - -import java.util.List; -import java.util.Set; - -import org.jclouds.compute.ComputeService; -import org.jclouds.compute.RunNodesException; -import org.jclouds.compute.domain.NodeMetadata; -import org.jclouds.compute.domain.NodeMetadata.Status; -import org.jclouds.compute.domain.NodeMetadataBuilder; -import org.jclouds.compute.domain.Template; -import org.jclouds.compute.options.TemplateOptions; -import org.jclouds.domain.LoginCredentials; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.annotations.BeforeMethod; - -import brooklyn.location.jclouds.ComputeServiceRegistry; -import brooklyn.location.jclouds.ComputeServiceRegistryImpl; -import brooklyn.location.jclouds.JcloudsLocation; -import brooklyn.location.jclouds.JcloudsLocationConfig; -import brooklyn.util.config.ConfigBag; - -import com.google.common.base.Predicate; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; - -/** - * The VM creation is stubbed out, but it still requires live access (i.e. real account credentials) - * to generate the template etc. - * - * We supply a ComputeServiceRegistry that delegates to the real instance for everything except - * VM creation and deletion. For those operations, it delegates to a NodeCreator that - * returns a dummy NodeMetadata, recording all calls made to it. - */ -public abstract class AbstractJcloudsStubbedLiveTest extends AbstractJcloudsLiveTest { - - @SuppressWarnings("unused") - private static final Logger LOG = LoggerFactory.getLogger(AbstractJcloudsStubbedLiveTest.class); - - public static final String LOCATION_SPEC = "jclouds:" + SOFTLAYER_PROVIDER + ":" + SOFTLAYER_AMS01_REGION_NAME; - - public static abstract class NodeCreator { - public final List<NodeMetadata> created = Lists.newCopyOnWriteArrayList(); - public final List<String> destroyed = Lists.newCopyOnWriteArrayList(); - - public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, Template template) throws RunNodesException { - Set<NodeMetadata> result = Sets.newLinkedHashSet(); - for (int i = 0; i < count; i++) { - NodeMetadata node = newNode(group, template); - created.add(node); - result.add(node); - } - return result; - } - public void destroyNode(String id) { - destroyed.add(id); - } - protected abstract NodeMetadata newNode(String group, Template template); - } - - public static class StubbedComputeService extends DelegatingComputeService { - private final NodeCreator nodeCreator; - - public StubbedComputeService(ComputeService delegate, NodeCreator nodeCreator) { - super(delegate); - this.nodeCreator = nodeCreator; - } - @Override - public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, Template template) throws RunNodesException { - return nodeCreator.createNodesInGroup(group, count, template); - } - @Override - public void destroyNode(String id) { - nodeCreator.destroyNode(id); - } - @Override - public Set<? extends NodeMetadata> createNodesInGroup(String group, int count) { - throw new UnsupportedOperationException(); - } - @Override - public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, TemplateOptions templateOptions) { - throw new UnsupportedOperationException(); - } - @Override - public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) { - throw new UnsupportedOperationException(); - } - } - - protected NodeCreator nodeCreator; - - @BeforeMethod(alwaysRun=true) - @Override - public void setUp() throws Exception { - super.setUp(); - nodeCreator = newNodeCreator(); - ComputeServiceRegistry computeServiceRegistry = new ComputeServiceRegistry() { - @Override - public ComputeService findComputeService(ConfigBag conf, boolean allowReuse) { - ComputeService delegate = ComputeServiceRegistryImpl.INSTANCE.findComputeService(conf, allowReuse); - return new StubbedComputeService(delegate, nodeCreator); - } - }; - jcloudsLocation = (JcloudsLocation) managementContext.getLocationRegistry().resolve( - LOCATION_SPEC, - ImmutableMap.of( - JcloudsLocationConfig.COMPUTE_SERVICE_REGISTRY, computeServiceRegistry, - JcloudsLocationConfig.WAIT_FOR_SSHABLE, "false")); - } - - protected abstract NodeCreator newNodeCreator(); -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/location/jclouds/BailOutJcloudsLocation.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/location/jclouds/BailOutJcloudsLocation.java b/locations/jclouds/src/test/java/brooklyn/location/jclouds/BailOutJcloudsLocation.java deleted file mode 100644 index d952c5b..0000000 --- a/locations/jclouds/src/test/java/brooklyn/location/jclouds/BailOutJcloudsLocation.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 brooklyn.location.jclouds; - -import java.util.Collections; -import java.util.Map; - -import javax.annotation.Nullable; - -import org.apache.brooklyn.api.management.ManagementContext; -import org.jclouds.compute.ComputeService; -import org.jclouds.compute.domain.Image; -import org.jclouds.compute.domain.Template; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Function; -import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import com.google.common.reflect.TypeToken; - -import brooklyn.config.BrooklynProperties; -import brooklyn.config.ConfigKey; -import brooklyn.entity.basic.ConfigKeys; -import brooklyn.location.LocationSpec; -import brooklyn.management.internal.LocalManagementContext; -import brooklyn.util.collections.MutableMap; -import brooklyn.util.config.ConfigBag; -import brooklyn.util.exceptions.CompoundRuntimeException; -import brooklyn.util.exceptions.Exceptions; - -public class BailOutJcloudsLocation extends JcloudsLocation { - - // Don't care which image; not actually provisioning - private static final String US_EAST_IMAGE_ID = "us-east-1/ami-7d7bfc14"; - public static final RuntimeException BAIL_OUT_FOR_TESTING = new RuntimeException("early termination for test"); - - public static final ConfigKey<Function<ConfigBag, Void>> BUILD_TEMPLATE_INTERCEPTOR = ConfigKeys.newConfigKey( - new TypeToken<Function<ConfigBag, Void>>() {}, - "buildtemplateinterceptor"); - - public static final ConfigKey<Boolean> BUILD_TEMPLATE = ConfigKeys.newBooleanConfigKey( - "buildtemplate"); - - private static final long serialVersionUID = -3373789512935057842L; - - ConfigBag lastConfigBag; - Template template; - - public BailOutJcloudsLocation() { - super(); - } - - public BailOutJcloudsLocation(Map<?, ?> conf) { - super(conf); - } - - @Override - public Template buildTemplate(ComputeService computeService, ConfigBag config) { - lastConfigBag = config; - if (getConfig(BUILD_TEMPLATE_INTERCEPTOR) != null) { - getConfig(BUILD_TEMPLATE_INTERCEPTOR).apply(config); - } - if (Boolean.TRUE.equals(getConfig(BUILD_TEMPLATE))) { - template = super.buildTemplate(computeService, config); - } - throw BAIL_OUT_FOR_TESTING; - } - - public Template getTemplate() { - return template; - } - - public void tryObtain() { - tryObtain(Collections.emptyMap()); - } - - public void tryObtain(Map<?, ?> flags) { - tryObtainAndCheck(flags, Predicates.alwaysTrue()); - } - - public void tryObtainAndCheck(Map<?, ?> flags, Predicate<? super ConfigBag> test) { - try { - obtain(flags); - } catch (Exception e) { - if (e == BAIL_OUT_FOR_TESTING || e.getCause() == BAIL_OUT_FOR_TESTING - || (e instanceof CompoundRuntimeException && ((CompoundRuntimeException) e).getAllCauses().contains(BAIL_OUT_FOR_TESTING))) { - test.apply(lastConfigBag); - } else { - throw Exceptions.propagate(e); - } - } - } - - @Override - @VisibleForTesting - public UserCreation createUserStatements(@Nullable Image image, ConfigBag config) { - return super.createUserStatements(image, config); - } - - - public static BailOutJcloudsLocation newBailOutJcloudsLocation(ManagementContext mgmt) { - return newBailOutJcloudsLocation(mgmt, Collections.<ConfigKey<?>, Object>emptyMap()); - } - - public static BailOutJcloudsLocation newBailOutJcloudsLocation(ManagementContext mgmt, Map<ConfigKey<?>, ?> config) { - Map<ConfigKey<?>, ?> allConfig = MutableMap.<ConfigKey<?>, Object>builder() - .put(IMAGE_ID, "bogus") - .put(CLOUD_PROVIDER, "aws-ec2") - .put(ACCESS_IDENTITY, "bogus") - .put(CLOUD_REGION_ID, "bogus") - .put(ACCESS_CREDENTIAL, "bogus") - .put(USER, "fred") - .put(MIN_RAM, 16) - .put(JcloudsLocation.MACHINE_CREATE_ATTEMPTS, 1) - .putAll(config) - .build(); - return mgmt.getLocationManager().createLocation( - LocationSpec.create(BailOutJcloudsLocation.class).configure(allConfig)); - } - - - // todo better name - - /** As {@link BailOutJcloudsLocation}, counting the number of {@link #buildTemplate} calls. */ - public static class CountingBailOutJcloudsLocation extends BailOutJcloudsLocation { - private static final long serialVersionUID = 2433684033045735773L; - int buildTemplateCount = 0; - @Override - public Template buildTemplate(ComputeService computeService, ConfigBag config) { - buildTemplateCount++; - return super.buildTemplate(computeService, config); - } - } - - public static CountingBailOutJcloudsLocation newCountingBailOutJcloudsLocation(ManagementContext mgmt, Map flags) { - LocationSpec<CountingBailOutJcloudsLocation> spec = LocationSpec.create(CountingBailOutJcloudsLocation.class) - .configure(flags); - return mgmt.getLocationManager().createLocation(spec); - } - - /** @see #newBailOutJcloudsLocationForLiveTest(LocalManagementContext, Map)} */ - public static BailOutJcloudsLocation newBailOutJcloudsLocationForLiveTest(LocalManagementContext mgmt) { - return newBailOutJcloudsLocationForLiveTest(mgmt, Collections.<ConfigKey<?>, Object>emptyMap()); - } - - /** - * Takes identity and access credential from management context's Brooklyn properties and sets - * inbound ports to [22, 80, 9999]. - */ - public static BailOutJcloudsLocation newBailOutJcloudsLocationForLiveTest(LocalManagementContext mgmt, Map<ConfigKey<?>, ?> config) { - BrooklynProperties brooklynProperties = mgmt.getBrooklynProperties(); - String identity = (String) brooklynProperties.get("brooklyn.location.jclouds.aws-ec2.identity"); - if (identity == null) identity = (String) brooklynProperties.get("brooklyn.jclouds.aws-ec2.identity"); - String credential = (String) brooklynProperties.get("brooklyn.location.jclouds.aws-ec2.credential"); - if (credential == null) credential = (String) brooklynProperties.get("brooklyn.jclouds.aws-ec2.credential"); - - Map<ConfigKey<?>, ?> allConfig = MutableMap.<ConfigKey<?>, Object>builder() - .put(CLOUD_PROVIDER, AbstractJcloudsLiveTest.AWS_EC2_PROVIDER) - .put(CLOUD_REGION_ID, AbstractJcloudsLiveTest.AWS_EC2_USEAST_REGION_NAME) - .put(IMAGE_ID, US_EAST_IMAGE_ID) // so Brooklyn does not attempt to load all EC2 images - .put(ACCESS_IDENTITY, identity) - .put(ACCESS_CREDENTIAL, credential) - .put(INBOUND_PORTS, "[22, 80, 9999]") - .put(BUILD_TEMPLATE, true) - .putAll(config) - .build(); - - return newBailOutJcloudsLocation(mgmt, allConfig); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java b/locations/jclouds/src/test/java/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java deleted file mode 100644 index 7a52f04..0000000 --- a/locations/jclouds/src/test/java/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 brooklyn.location.jclouds; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import brooklyn.location.basic.SshMachineLocation; -import brooklyn.location.jclouds.pool.MachinePoolPredicates; -import brooklyn.location.jclouds.pool.MachineSet; -import brooklyn.location.jclouds.pool.ReusableMachineTemplate; -import brooklyn.management.internal.LocalManagementContext; - -public class BrooklynMachinePoolLiveTest { - - public static final Logger log = LoggerFactory.getLogger(BrooklynMachinePoolLiveTest.class); - - public static class SamplePool extends BrooklynMachinePool { - public SamplePool(JcloudsLocation l) { - super(l); - } - - public final static ReusableMachineTemplate - USUAL_VM = - new ReusableMachineTemplate("usual").templateOwnedByMe(). - tagOptional("tagForUsualVm"). - metadataOptional("metadataForUsualVm", "12345"). - minRam(1024).minCores(2); - - public final static ReusableMachineTemplate - ANYONE_NOT_TINY_VM = - new ReusableMachineTemplate("anyone"). - minRam(512).minCores(1).strict(false); - - public static final ReusableMachineTemplate - VM_LARGE1 = - new ReusableMachineTemplate("vm.large1").templateOwnedByMe(). - minRam(16384).minCores(4), - VM_SMALL1 = - new ReusableMachineTemplate("vm.small1").templateOwnedByMe().smallest(); - - { registerTemplates(USUAL_VM, ANYONE_NOT_TINY_VM, VM_LARGE1, VM_SMALL1); } - } - - - private LocalManagementContext managementContext; - - @BeforeMethod(alwaysRun=true) - public void setUp() throws Exception { - managementContext = new LocalManagementContext(); - } - - @AfterMethod(alwaysRun=true) - public void tearDown() throws Exception { - if (managementContext != null) managementContext.terminate(); - } - - @Test(groups="Live") - public void buildClaimAndDestroy() { - SamplePool p = new SamplePool(resolve("aws-ec2:us-west-1")); - log.info("buildClaimAndDestroy: created pool"); - p.refresh(); - log.info("buildClaimAndDestroy: refreshed pool"); - p.ensureExists(2, SamplePool.USUAL_VM); - log.info("buildClaimAndDestroy: ensure have 2"); - SshMachineLocation l = p.obtain(SamplePool.USUAL_VM); - Assert.assertNotNull(l); - log.info("buildClaimAndDestroy: claimed 1"); - MachineSet unclaimedUsual = p.unclaimed(MachinePoolPredicates.matching(SamplePool.USUAL_VM)); - log.info("buildClaimAndDestroy: unclaimed now "+unclaimedUsual); - Assert.assertTrue(!unclaimedUsual.isEmpty(), "should have been unclaimed machines (can fail if there are some we cannot connect to, ie blacklisted)"); - p.destroy(unclaimedUsual); - p.destroy(l); - unclaimedUsual = p.unclaimed(MachinePoolPredicates.matching(SamplePool.USUAL_VM)); - log.info("buildClaimAndDestroy: destroyed, unclaimed now "+unclaimedUsual); - log.info("end"); - } - - - private JcloudsLocation resolve(String spec) { - return (JcloudsLocation) managementContext.getLocationRegistry().resolve(new JcloudsLocationResolver().getPrefix() + ":" + spec); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/location/jclouds/DelegatingComputeService.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/location/jclouds/DelegatingComputeService.java b/locations/jclouds/src/test/java/brooklyn/location/jclouds/DelegatingComputeService.java deleted file mode 100644 index 62f621e..0000000 --- a/locations/jclouds/src/test/java/brooklyn/location/jclouds/DelegatingComputeService.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 brooklyn.location.jclouds; - -import java.util.Map; -import java.util.Set; - -import org.jclouds.compute.ComputeService; -import org.jclouds.compute.ComputeServiceContext; -import org.jclouds.compute.RunNodesException; -import org.jclouds.compute.RunScriptOnNodesException; -import org.jclouds.compute.domain.ComputeMetadata; -import org.jclouds.compute.domain.ExecResponse; -import org.jclouds.compute.domain.Hardware; -import org.jclouds.compute.domain.Image; -import org.jclouds.compute.domain.NodeMetadata; -import org.jclouds.compute.domain.Template; -import org.jclouds.compute.domain.TemplateBuilder; -import org.jclouds.compute.extensions.ImageExtension; -import org.jclouds.compute.extensions.SecurityGroupExtension; -import org.jclouds.compute.options.RunScriptOptions; -import org.jclouds.compute.options.TemplateOptions; -import org.jclouds.domain.Location; -import org.jclouds.scriptbuilder.domain.Statement; - -import com.google.common.base.Optional; -import com.google.common.base.Predicate; -import com.google.common.util.concurrent.ListenableFuture; - -public class DelegatingComputeService implements ComputeService { - - private final ComputeService delegate; - - public DelegatingComputeService(ComputeService delegate) { - this.delegate = delegate; - } - - @Override - public ComputeServiceContext getContext() { - return delegate.getContext(); - } - - @Override - public TemplateBuilder templateBuilder() { - return delegate.templateBuilder(); - } - - @Override - public TemplateOptions templateOptions() { - return delegate.templateOptions(); - } - - @Override - public Set<? extends Hardware> listHardwareProfiles() { - return delegate.listHardwareProfiles(); - } - - @Override - public Set<? extends Image> listImages() { - return delegate.listImages(); - } - - @Override - public Image getImage(String id) { - return delegate.getImage(id); - } - - @Override - public Set<? extends ComputeMetadata> listNodes() { - return delegate.listNodes(); - } - - @Override - public Set<? extends NodeMetadata> listNodesByIds(Iterable<String> ids) { - return delegate.listNodesByIds(ids); - } - - @Override - public Set<? extends Location> listAssignableLocations() { - return delegate.listAssignableLocations(); - } - - @Override - public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, Template template) throws RunNodesException { - return delegate.createNodesInGroup(group, count, template); - } - - @Override - public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, TemplateOptions templateOptions) - throws RunNodesException { - return delegate.createNodesInGroup(group, count, templateOptions); - } - - @Override - public Set<? extends NodeMetadata> createNodesInGroup(String group, int count) throws RunNodesException { - return delegate.createNodesInGroup(group, count); - } - - @Override - public void resumeNode(String id) { - delegate.resumeNode(id); - } - - @Override - public Set<? extends NodeMetadata> resumeNodesMatching(Predicate<NodeMetadata> filter) { - return delegate.resumeNodesMatching(filter); - } - - @Override - public void suspendNode(String id) { - delegate.suspendNode(id); - } - - @Override - public Set<? extends NodeMetadata> suspendNodesMatching(Predicate<NodeMetadata> filter) { - return delegate.suspendNodesMatching(filter); - } - - @Override - public void destroyNode(String id) { - delegate.destroyNode(id); - } - - @Override - public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) { - return delegate.destroyNodesMatching(filter); - } - - @Override - public void rebootNode(String id) { - delegate.rebootNode(id); - } - - @Override - public Set<? extends NodeMetadata> rebootNodesMatching(Predicate<NodeMetadata> filter) { - return delegate.rebootNodesMatching(filter); - } - - @Override - public NodeMetadata getNodeMetadata(String id) { - return delegate.getNodeMetadata(id); - } - - @Override - public Set<? extends NodeMetadata> listNodesDetailsMatching(Predicate<ComputeMetadata> filter) { - return delegate.listNodesDetailsMatching(filter); - } - - @Override - public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, String runScript) - throws RunScriptOnNodesException { - return delegate.runScriptOnNodesMatching(filter, runScript); - } - - @Override - public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript) - throws RunScriptOnNodesException { - return delegate.runScriptOnNodesMatching(filter, runScript); - } - - @Override - public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, - String runScript, RunScriptOptions options) throws RunScriptOnNodesException { - return delegate.runScriptOnNodesMatching(filter, runScript, options); - } - - @Override - public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, - Statement runScript, RunScriptOptions options) throws RunScriptOnNodesException { - return delegate.runScriptOnNodesMatching(filter, runScript, options); - } - - @Override - public ExecResponse runScriptOnNode(String id, Statement runScript, RunScriptOptions options) { - return delegate.runScriptOnNode(id, runScript, options); - } - - @Override - public ListenableFuture<ExecResponse> submitScriptOnNode(String id, String runScript, RunScriptOptions options) { - return delegate.submitScriptOnNode(id, runScript, options); - } - - @Override - public ListenableFuture<ExecResponse> submitScriptOnNode(String id, Statement runScript, RunScriptOptions options) { - return delegate.submitScriptOnNode(id, runScript, options); - } - - @Override - public ExecResponse runScriptOnNode(String id, Statement runScript) { - return delegate.runScriptOnNode(id, runScript); - } - - @Override - public ExecResponse runScriptOnNode(String id, String runScript, RunScriptOptions options) { - return delegate.runScriptOnNode(id, runScript, options); - } - - @Override - public ExecResponse runScriptOnNode(String id, String runScript) { - return delegate.runScriptOnNode(id, runScript); - } - - @Override - public Optional<ImageExtension> getImageExtension() { - return delegate.getImageExtension(); - } - - @Override - public Optional<SecurityGroupExtension> getSecurityGroupExtension() { - return delegate.getSecurityGroupExtension(); - } - -}
