You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by an...@apache.org on 2016/04/05 10:40:01 UTC

jclouds-labs git commit: Added volumesFrom to Docker template options

Repository: jclouds-labs
Updated Branches:
  refs/heads/master e95de6a70 -> 313819534


Added volumesFrom to Docker template options


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/31381953
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/31381953
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/31381953

Branch: refs/heads/master
Commit: 31381953466d9bb492d5c9493914f542a8061f76
Parents: e95de6a
Author: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Authored: Fri Apr 1 21:53:52 2016 +0100
Committer: Andrea Turli <an...@gmail.com>
Committed: Tue Apr 5 10:22:56 2016 +0200

----------------------------------------------------------------------
 .../compute/options/DockerTemplateOptions.java  | 84 ++++++++++++--------
 .../strategy/DockerComputeServiceAdapter.java   | 22 +++--
 .../java/org/jclouds/docker/domain/Config.java  | 40 +++++-----
 .../org/jclouds/docker/domain/HostConfig.java   | 53 ++++++------
 .../jclouds/docker/internal/NullSafeCopies.java | 12 +++
 .../functions/ContainerToNodeMetadataTest.java  |  1 -
 6 files changed, 124 insertions(+), 88 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/31381953/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java b/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java
index 8149a15..bff0d9c 100644
--- a/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java
+++ b/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java
@@ -17,11 +17,14 @@
 package org.jclouds.docker.compute.options;
 
 import static com.google.common.base.Objects.equal;
-import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.util.List;
 import java.util.Map;
 
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
 import org.jclouds.compute.options.TemplateOptions;
 import org.jclouds.docker.domain.Config;
 import org.jclouds.docker.internal.NullSafeCopies;
@@ -29,10 +32,6 @@ import org.jclouds.domain.LoginCredentials;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.scriptbuilder.domain.Statement;
 
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-
 /**
  * Contains options supported by the
  * {@link org.jclouds.compute.ComputeService#createNodesInGroup(String, int, TemplateOptions)
@@ -87,15 +86,15 @@ public class DockerTemplateOptions extends TemplateOptions implements Cloneable
    protected String hostname;
    protected Integer memory;
    protected Integer cpuShares;
-   protected List<String> entrypoint;
-   protected List<String> commands;
+   protected List<String> entrypoint = ImmutableList.of();
+   protected List<String> commands = ImmutableList.of();
    protected Map<String, String> volumes = ImmutableMap.of();
-   protected List<String> env;
+   protected List<String> env = ImmutableList.of();
    protected Map<Integer, Integer> portBindings = ImmutableMap.of();
    protected String networkMode;
    protected Map<String, String> extraHosts = ImmutableMap.of();
+   protected List<String> volumesFrom = ImmutableList.of();
    protected boolean privileged;
-
    protected Config.Builder configBuilder;
 
    @Override
@@ -110,27 +109,19 @@ public class DockerTemplateOptions extends TemplateOptions implements Cloneable
       super.copyTo(to);
       if (to instanceof DockerTemplateOptions) {
          DockerTemplateOptions eTo = DockerTemplateOptions.class.cast(to);
-         if (!volumes.isEmpty()) {
-            eTo.volumes(volumes);
-         }
+         eTo.volumes(volumes);
          eTo.hostname(hostname);
-         if (!dns.isEmpty()) {
-            eTo.dns(dns);
-         }
+         eTo.dns(dns);
          eTo.memory(memory);
          eTo.cpuShares(cpuShares);
          eTo.entrypoint(entrypoint);
          eTo.commands(commands);
          eTo.env(env);
-         if (!portBindings.isEmpty()) {
-            eTo.portBindings(portBindings);
-         }
+         eTo.portBindings(portBindings);
          eTo.networkMode(networkMode);
-         if (!extraHosts.isEmpty()) {
-            eTo.extraHosts(extraHosts);
-         }
+         eTo.extraHosts(extraHosts);
+         eTo.volumesFrom(volumesFrom);
          eTo.privileged(privileged);
-
          eTo.configBuilder(configBuilder);
       }
    }
@@ -142,16 +133,19 @@ public class DockerTemplateOptions extends TemplateOptions implements Cloneable
       if (o == null || getClass() != o.getClass())
          return false;
       DockerTemplateOptions that = DockerTemplateOptions.class.cast(o);
-      return super.equals(that) && equal(this.volumes, that.volumes) &&
+      return super.equals(that) &&
+              equal(this.volumes, that.volumes) &&
               equal(this.hostname, that.hostname) &&
               equal(this.dns, that.dns) &&
               equal(this.memory, that.memory) &&
+              equal(this.cpuShares, that.cpuShares) &&
               equal(this.entrypoint, that.entrypoint) &&
               equal(this.commands, that.commands) &&
-              equal(this.cpuShares, that.cpuShares) &&
               equal(this.env, that.env) &&
               equal(this.portBindings, that.portBindings) &&
+              equal(this.networkMode, that.networkMode) &&
               equal(this.extraHosts, that.extraHosts) &&
+              equal(this.volumesFrom, that.volumesFrom) &&
               equal(this.privileged, that.privileged) &&
               buildersEqual(this.configBuilder, that.configBuilder);
    }
@@ -173,32 +167,35 @@ public class DockerTemplateOptions extends TemplateOptions implements Cloneable
    @Override
    public String toString() {
       return Objects.toStringHelper(this)
-              .add("dns", dns)
+              .add("volumes", volumes)
               .add("hostname", hostname)
+              .add("dns", dns)
               .add("memory", memory)
               .add("cpuShares", cpuShares)
               .add("entrypoint", entrypoint)
               .add("commands", commands)
-              .add("volumes", volumes)
               .add("env", env)
               .add("portBindings", portBindings)
+              .add("networkMode", networkMode)
               .add("extraHosts", extraHosts)
+              .add("volumesFrom", volumesFrom)
               .add("configBuilder", configBuilder)
               .toString();
    }
 
    public DockerTemplateOptions volumes(Map<String, String> volumes) {
-      this.volumes = ImmutableMap.copyOf(checkNotNull(volumes, "volumes"));
+      this.volumes = NullSafeCopies.copyOf(volumes);
       return this;
    }
 
    public DockerTemplateOptions dns(Iterable<String> dns) {
-      this.dns = ImmutableList.copyOf(checkNotNull(dns, "dns"));
+      this.dns = NullSafeCopies.copyWithNullOf(dns);
       return this;
    }
 
    public DockerTemplateOptions dns(String...dns) {
-      return dns(ImmutableList.copyOf(checkNotNull(dns, "dns")));
+      this.dns = NullSafeCopies.copyWithNullOf(dns);
+      return this;
    }
 
    public DockerTemplateOptions hostname(@Nullable String hostname) {
@@ -257,7 +254,7 @@ public class DockerTemplateOptions extends TemplateOptions implements Cloneable
     * @param portBindings the map of host to container port bindings
     */
    public DockerTemplateOptions portBindings(Map<Integer, Integer> portBindings) {
-      this.portBindings = ImmutableMap.copyOf(checkNotNull(portBindings, "portBindings"));
+      this.portBindings = NullSafeCopies.copyOf(portBindings);
       return this;
    }
 
@@ -281,7 +278,17 @@ public class DockerTemplateOptions extends TemplateOptions implements Cloneable
     * @param extraHosts the map of host names to IP addresses
     */
    public DockerTemplateOptions extraHosts(Map<String, String> extraHosts) {
-      this.extraHosts = ImmutableMap.copyOf(checkNotNull(extraHosts, "extraHosts"));
+      this.extraHosts = NullSafeCopies.copyWithNullOf(extraHosts);
+      return this;
+   }
+
+   /**
+    * Set list of containers to mount volumes from onto this container.
+    *
+    * @param volumesFrom the list of container names
+    */
+   public DockerTemplateOptions volumesFrom(Iterable<String> volumesFrom) {
+      this.volumesFrom = NullSafeCopies.copyWithNullOf(volumesFrom);
       return this;
    }
 
@@ -318,6 +325,8 @@ public class DockerTemplateOptions extends TemplateOptions implements Cloneable
 
    public List<String> getDns() { return dns; }
 
+   public List<String> getVolumesFrom() { return volumesFrom; }
+
    public String getHostname() { return hostname; }
 
    public Integer getMemory() { return memory; }
@@ -359,7 +368,7 @@ public class DockerTemplateOptions extends TemplateOptions implements Cloneable
       }
 
       /**
-       * @see DockerTemplateOptions#dns(Iterable)
+       * @see DockerTemplateOptions#dns(List)
        */
       public static DockerTemplateOptions dns(Iterable<String> dns) {
          DockerTemplateOptions options = new DockerTemplateOptions();
@@ -470,12 +479,23 @@ public class DockerTemplateOptions extends TemplateOptions implements Cloneable
          return options.privileged(privileged);
       }
 
+      /**
+       * @see DockerTemplateOptions#configBuilder(Config.Builder)
+       */
       public static DockerTemplateOptions configBuilder(Config.Builder configBuilder) {
          DockerTemplateOptions options = new DockerTemplateOptions();
          return options.configBuilder(configBuilder);
       }
 
       /**
+       * @see DockerTemplateOptions#volumesFrom(Iterable)
+       */
+      public static DockerTemplateOptions volumesFrom(Iterable<String> volumesFrom) {
+         DockerTemplateOptions options = new DockerTemplateOptions();
+         return options.volumesFrom(volumesFrom);
+      }
+
+      /**
        * @see TemplateOptions#inboundPorts(int...)
        */
       public static DockerTemplateOptions inboundPorts(int... ports) {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/31381953/docker/src/main/java/org/jclouds/docker/compute/strategy/DockerComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/compute/strategy/DockerComputeServiceAdapter.java b/docker/src/main/java/org/jclouds/docker/compute/strategy/DockerComputeServiceAdapter.java
index 20567cd..ebd7f5b 100644
--- a/docker/src/main/java/org/jclouds/docker/compute/strategy/DockerComputeServiceAdapter.java
+++ b/docker/src/main/java/org/jclouds/docker/compute/strategy/DockerComputeServiceAdapter.java
@@ -18,6 +18,7 @@ package org.jclouds.docker.compute.strategy;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.Iterables.find;
+
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -27,6 +28,14 @@ import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
 import org.jclouds.compute.ComputeServiceAdapter;
 import org.jclouds.compute.domain.Hardware;
 import org.jclouds.compute.domain.HardwareBuilder;
@@ -48,14 +57,6 @@ import org.jclouds.domain.Location;
 import org.jclouds.domain.LoginCredentials;
 import org.jclouds.logging.Logger;
 
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
 /**
  * defines the connection between the {@link org.jclouds.docker.DockerApi} implementation and
  * the jclouds {@link org.jclouds.compute.ComputeService}
@@ -138,7 +139,12 @@ public class DockerComputeServiceAdapter implements
             }
          }
 
+         if (!templateOptions.getVolumesFrom().isEmpty()) {
+            hostConfigBuilder.volumesFrom(templateOptions.getVolumesFrom());
+         }
+
          hostConfigBuilder.networkMode(templateOptions.getNetworkMode());
+
          containerConfigBuilder.hostConfig(hostConfigBuilder.build());
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/31381953/docker/src/main/java/org/jclouds/docker/domain/Config.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/Config.java b/docker/src/main/java/org/jclouds/docker/domain/Config.java
index 2203a85..fbe07ca 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/Config.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/Config.java
@@ -64,7 +64,7 @@ public abstract class Config {
 
    public abstract String image();
 
-   public abstract Map<String, ?> volumes();
+   @Nullable public abstract Map<String, ?> volumes();
 
    @Nullable public abstract String workingDir();
 
@@ -76,9 +76,9 @@ public abstract class Config {
 
    @Nullable public abstract HostConfig hostConfig();
 
-   public abstract List<String> binds();
+   @Nullable public abstract List<String> binds();
 
-   public abstract List<String> links();
+   @Nullable public abstract List<String> links();
 
    public abstract List<Map<String, String>> lxcConf();
 
@@ -90,13 +90,13 @@ public abstract class Config {
 
    @Nullable public abstract List<String> dns();
 
-   @Nullable public abstract String dnsSearch();
+   @Nullable public abstract List<String> dnsSearch();
 
-   @Nullable public abstract String volumesFrom();
+   @Nullable public abstract List<String> volumesFrom();
 
-   public abstract List<String> capAdd();
+   @Nullable public abstract List<String> capAdd();
 
-   public abstract List<String> capDrop();
+   @Nullable public abstract List<String> capDrop();
 
    public abstract Map<String, String> restartPolicy();
 
@@ -117,14 +117,14 @@ public abstract class Config {
          String image, Map<String, ?> volumes, String workingDir, boolean networkDisabled,
          Map<String, ?> exposedPorts, List<String> securityOpts, HostConfig hostConfig, List<String> binds,
          List<String> links, List<Map<String, String>> lxcConf, Map<String, List<Map<String, String>>> portBindings,
-         boolean publishAllPorts, boolean privileged, List<String> dns, String dnsSearch, String volumesFrom,
+         boolean publishAllPorts, boolean privileged, List<String> dns, List<String> dnsSearch, List<String> volumesFrom,
          List<String> capAdd, List<String> capDrop, Map<String, String> restartPolicy) {
       return new AutoValue_Config(hostname, domainname, user, memory, memorySwap, cpuShares, attachStdin,
               attachStdout, attachStderr, tty, openStdin, stdinOnce, copyWithNullOf(env), copyWithNullOf(cmd),
-              copyWithNullOf(entrypoint), image, copyOf(volumes), workingDir, networkDisabled,
+              copyWithNullOf(entrypoint), image, copyWithNullOf(volumes), workingDir, networkDisabled,
               copyOf(exposedPorts), copyOf(securityOpts), hostConfig,
-              copyOf(binds), copyOf(links), copyOf(lxcConf), copyOf(portBindings), publishAllPorts, privileged,
-              copyWithNullOf(dns), dnsSearch, volumesFrom, copyOf(capAdd), copyOf(capDrop), copyOf(restartPolicy));
+              copyWithNullOf(binds), copyWithNullOf(links), copyOf(lxcConf), copyOf(portBindings), publishAllPorts, privileged,
+              copyWithNullOf(dns), copyWithNullOf(dnsSearch), copyWithNullOf(volumesFrom), copyWithNullOf(capAdd), copyWithNullOf(capDrop), copyOf(restartPolicy));
    }
 
    public static Builder builder() {
@@ -152,23 +152,23 @@ public abstract class Config {
       private List<String> cmd;
       private List<String> entrypoint;
       private String image;
-      private Map<String, ?> volumes = Maps.newHashMap();
+      private Map<String, ?> volumes;
       private String workingDir;
       private boolean networkDisabled;
       private Map<String, ?> exposedPorts = Maps.newHashMap();
       private List<String> securityOpts = Lists.newArrayList();
       private HostConfig hostConfig;
-      private List<String> binds = Lists.newArrayList();
-      private List<String> links = Lists.newArrayList();
+      private List<String> binds;
+      private List<String> links;
       private List<Map<String, String>> lxcConf = Lists.newArrayList();
       private Map<String, List<Map<String, String>>> portBindings = Maps.newHashMap();
       private boolean publishAllPorts;
       private boolean privileged;
       private List<String> dns;
-      private String dnsSearch;
-      private String volumesFrom;
-      private List<String> capAdd = Lists.newArrayList();
-      private List<String> capDrop = Lists.newArrayList();
+      private List<String> dnsSearch;
+      private List<String> volumesFrom;
+      private List<String> capAdd;
+      private List<String> capDrop;
       private Map<String, String> restartPolicy = Maps.newHashMap();
 
       public Builder hostname(String hostname) {
@@ -322,12 +322,12 @@ public abstract class Config {
          return this;
       }
 
-      public Builder dnsSearch(String dnsSearch) {
+      public Builder dnsSearch(List<String> dnsSearch) {
          this.dnsSearch = dnsSearch;
          return this;
       }
 
-      public Builder volumesFrom(String volumesFrom) {
+      public Builder volumesFrom(List<String> volumesFrom) {
          this.volumesFrom = volumesFrom;
          return this;
       }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/31381953/docker/src/main/java/org/jclouds/docker/domain/HostConfig.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/HostConfig.java b/docker/src/main/java/org/jclouds/docker/domain/HostConfig.java
index 1e655af..1ebdb2c 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/HostConfig.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/HostConfig.java
@@ -16,45 +16,44 @@
  */
 package org.jclouds.docker.domain;
 
-import static com.google.common.base.Preconditions.checkNotNull;
 import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
+import static org.jclouds.docker.internal.NullSafeCopies.copyWithNullOf;
 
 import java.util.List;
 import java.util.Map;
 
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.json.SerializedNames;
-
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
 @AutoValue
 public abstract class HostConfig {
    @Nullable public abstract String containerIDFile();
 
-   public abstract List<String> binds();
+   @Nullable public abstract List<String> binds();
 
    public abstract List<Map<String, String>> lxcConf();
 
    public abstract boolean privileged();
 
-   public abstract List<String> dns();
+   @Nullable public abstract List<String> dns();
 
    @Nullable public abstract List<String> dnsSearch();
 
    public abstract Map<String, List<Map<String, String>>> portBindings();
 
-   public abstract List<String> links();
+   @Nullable public abstract List<String> links();
 
-   public abstract List<String> extraHosts();
+   @Nullable public abstract List<String> extraHosts();
 
    public abstract boolean publishAllPorts();
 
-   public abstract List<String> volumesFrom();
+   @Nullable public abstract List<String> volumesFrom();
 
-   @Nullable
-   public abstract String networkMode();
+   @Nullable public abstract String networkMode();
 
    HostConfig() {
    }
@@ -64,8 +63,8 @@ public abstract class HostConfig {
    public static HostConfig create(String containerIDFile, List<String> binds, List<Map<String, String>> lxcConf,
          boolean privileged, List<String> dns, List<String> dnsSearch, Map<String, List<Map<String, String>>> portBindings,
          List<String> links, List<String> extraHosts, boolean publishAllPorts, List<String> volumesFrom, String networkMode) {
-      return new AutoValue_HostConfig(containerIDFile, copyOf(binds), copyOf(lxcConf), privileged, copyOf(dns), copyOf(dnsSearch),
-            copyOf(portBindings), copyOf(links), copyOf(extraHosts), publishAllPorts, copyOf(volumesFrom), networkMode);
+      return new AutoValue_HostConfig(containerIDFile, copyWithNullOf(binds), copyOf(lxcConf), privileged, copyWithNullOf(dns), copyWithNullOf(dnsSearch),
+            copyOf(portBindings), copyWithNullOf(links), copyWithNullOf(extraHosts), publishAllPorts, copyWithNullOf(volumesFrom), networkMode);
    }
 
    public static Builder builder() {
@@ -79,16 +78,16 @@ public abstract class HostConfig {
    public static final class Builder {
 
       private String containerIDFile;
-      private List<String> binds = Lists.newArrayList();
+      private List<String> binds;
       private List<Map<String, String>> lxcConf = Lists.newArrayList();
       private boolean privileged;
-      private List<String> dns = Lists.newArrayList();
-      private List<String> dnsSearch = Lists.newArrayList();
+      private List<String> dns;
+      private List<String> dnsSearch;
       private Map<String, List<Map<String, String>>> portBindings = Maps.newLinkedHashMap();
-      private List<String> links = Lists.newArrayList();
-      private List<String> extraHosts = Lists.newArrayList();
+      private List<String> links;
+      private List<String> extraHosts;
       private boolean publishAllPorts;
-      private List<String> volumesFrom = Lists.newArrayList();
+      private List<String> volumesFrom;
       private String networkMode;
 
       public Builder containerIDFile(String containerIDFile) {
@@ -97,12 +96,12 @@ public abstract class HostConfig {
       }
 
       public Builder binds(List<String> binds) {
-         this.binds.addAll(checkNotNull(binds, "binds"));
+         this.binds = binds;
          return this;
       }
 
       public Builder lxcConf(List<Map<String, String>> lxcConf) {
-         this.lxcConf.addAll(checkNotNull(lxcConf, "lxcConf"));
+         this.lxcConf = lxcConf;
          return this;
       }
 
@@ -112,27 +111,27 @@ public abstract class HostConfig {
       }
 
       public Builder dns(List<String> dns) {
-         this.dns.addAll(checkNotNull(dns, "dns"));
+         this.dns = dns;
          return this;
       }
 
       public Builder dnsSearch(List<String> dnsSearch) {
-         this.dnsSearch.addAll(checkNotNull(dnsSearch, "dnsSearch"));
+         this.dnsSearch = dnsSearch;
          return this;
       }
 
       public Builder links(List<String> links) {
-         this.links.addAll(checkNotNull(links, "links"));
+         this.links = links;
          return this;
       }
 
       public Builder extraHosts(List<String> extraHosts) {
-         this.extraHosts.addAll(checkNotNull(extraHosts, "extraHosts"));
+         this.extraHosts = extraHosts;
          return this;
       }
 
       public Builder portBindings(Map<String, List<Map<String, String>>> portBindings) {
-         this.portBindings.putAll(portBindings);
+         this.portBindings = portBindings;
          return this;
       }
 
@@ -142,7 +141,7 @@ public abstract class HostConfig {
       }
 
       public Builder volumesFrom(List<String> volumesFrom) {
-         this.volumesFrom.addAll(checkNotNull(volumesFrom, "volumesFrom"));
+         this.volumesFrom = volumesFrom;
          return this;
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/31381953/docker/src/main/java/org/jclouds/docker/internal/NullSafeCopies.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/internal/NullSafeCopies.java b/docker/src/main/java/org/jclouds/docker/internal/NullSafeCopies.java
index ad86bbb..b6e190c 100644
--- a/docker/src/main/java/org/jclouds/docker/internal/NullSafeCopies.java
+++ b/docker/src/main/java/org/jclouds/docker/internal/NullSafeCopies.java
@@ -47,6 +47,18 @@ public class NullSafeCopies {
    }
 
    /**
+    * Copies given Map with keeping null value if provided.
+    *
+    * @param map
+    *           instance to copy (maybe <code>null</code>)
+    * @return if the parameter is not-<code>null</code> then immutable copy;
+    *         <code>null</code> otherwise
+    */
+   public static <K, V> Map<K, V> copyWithNullOf(@Nullable Map<K, V> map) {
+      return map != null ? ImmutableMap.copyOf(map) : null;
+   }
+
+   /**
     * Copies given {@link Iterable} into immutable {@link List} with keeping null value if provided.
     *
     * @param iterable

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/31381953/docker/src/test/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadataTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadataTest.java b/docker/src/test/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadataTest.java
index 00cd836..d9fc464 100644
--- a/docker/src/test/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadataTest.java
+++ b/docker/src/test/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadataTest.java
@@ -84,7 +84,6 @@ public class ContainerToNodeMetadataTest {
               .env(null)
               .cmd(ImmutableList.of("/usr/sbin/sshd", "-D"))
               .image("jclouds/ubuntu")
-              .volumesFrom("")
               .workingDir("")
               .entrypoint(null)
               .networkDisabled(false)