| /******************************************************************************* |
| * Copyright (c) 2014, 2018 Red Hat. |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Red Hat - Initial Contribution |
| *******************************************************************************/ |
| package org.eclipse.linuxtools.internal.docker.core; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeSet; |
| |
| import org.eclipse.linuxtools.docker.core.IDockerContainerConfig; |
| |
| import com.spotify.docker.client.messages.ContainerConfig; |
| import com.spotify.docker.client.messages.HostConfig; |
| |
| public class DockerContainerConfig implements IDockerContainerConfig { |
| |
| private final String hostname; |
| private final String domainname; |
| private final String user; |
| private final Long memory; |
| private final Long memorySwap; |
| private final Long cpuShares; |
| private final String cpuset; |
| private final boolean attachStdin; |
| private final boolean attachStdout; |
| private final boolean attachStderr; |
| private final List<String> portSpecs; |
| private final Set<String> exposedPorts; |
| private final boolean tty; |
| private final boolean openStdin; |
| private final boolean stdinOnce; |
| private final List<String> env; |
| private String rawcmd; |
| private final List<String> cmd; |
| private final String image; |
| @SuppressWarnings("rawtypes") |
| private final Map<String, Map> volumes; |
| private final String workingDir; |
| private final List<String> entrypoint; |
| private final boolean networkDisabled; |
| private final List<String> onBuild; |
| private final Map<String, String> labels; |
| |
| public DockerContainerConfig(final ContainerConfig containerConfig) { |
| this.hostname = containerConfig != null ? containerConfig.hostname() |
| : null; |
| this.domainname = containerConfig != null ? containerConfig.domainname() |
| : null; |
| this.user = containerConfig != null ? containerConfig.user() : null; |
| final HostConfig hc = containerConfig != null |
| ? containerConfig.hostConfig() : null; |
| this.memory = hc != null ? hc.memory() : null; |
| this.memorySwap = hc != null ? hc.memorySwap() : null; |
| this.cpuShares = hc != null ? hc.cpuShares() : null; |
| this.cpuset = hc != null ? hc.cpusetCpus() : null; |
| this.attachStdin = containerConfig != null |
| && containerConfig.attachStdin() != null |
| ? containerConfig.attachStdin() : false; |
| this.attachStdout = containerConfig != null |
| && containerConfig.attachStdout() != null |
| ? containerConfig.attachStdout() : false; |
| this.attachStderr = containerConfig != null |
| && containerConfig.attachStderr() != null |
| ? containerConfig.attachStderr() : false; |
| this.portSpecs = containerConfig != null ? containerConfig.portSpecs() |
| : null; |
| this.exposedPorts = containerConfig != null |
| ? containerConfig.exposedPorts() : null; |
| this.tty = containerConfig != null && containerConfig.tty() != null |
| ? containerConfig.tty() |
| : false; |
| this.openStdin = containerConfig != null |
| && containerConfig.openStdin() != null |
| ? containerConfig.openStdin() : false; |
| this.stdinOnce = containerConfig != null |
| && containerConfig.stdinOnce() != null |
| ? containerConfig.stdinOnce() : false; |
| this.env = containerConfig != null ? containerConfig.env() : null; |
| this.cmd = containerConfig != null ? containerConfig.cmd() : null; |
| this.image = containerConfig != null ? containerConfig.image() : null; |
| |
| @SuppressWarnings("rawtypes") |
| Map<String, Map> res = new HashMap<>(); |
| try { |
| if (containerConfig != null && containerConfig.volumes() != null) { |
| containerConfig.volumes().forEach(v -> res.put(v, Collections.emptyMap())); |
| } |
| } catch (NullPointerException e) { |
| } |
| this.volumes = res; |
| this.workingDir = containerConfig != null ? containerConfig.workingDir() |
| : null; |
| this.entrypoint = containerConfig != null ? containerConfig.entrypoint() |
| : null; |
| this.networkDisabled = containerConfig != null |
| && containerConfig.networkDisabled() != null |
| ? containerConfig.networkDisabled() : false; |
| this.onBuild = containerConfig != null ? containerConfig.onBuild() |
| : null; |
| this.labels = containerConfig != null ? containerConfig.labels() : null; |
| } |
| |
| private DockerContainerConfig(final Builder builder) { |
| this.hostname = builder.hostname; |
| this.domainname = builder.domainname; |
| this.user = builder.user; |
| this.memory = builder.memory; |
| this.memorySwap = builder.memorySwap; |
| this.cpuShares = builder.cpuShares; |
| this.cpuset = builder.cpuset; |
| this.attachStdin = builder.attachStdin != null ? builder.attachStdin |
| : false; |
| this.attachStdout = builder.attachStdout != null ? builder.attachStdout |
| : false; |
| this.attachStderr = builder.attachStderr != null ? builder.attachStderr |
| : false; |
| this.portSpecs = builder.portSpecs; |
| this.exposedPorts = builder.exposedPorts; |
| this.tty = builder.tty != null ? builder.tty : false; |
| this.openStdin = builder.openStdin != null ? builder.openStdin : false; |
| this.stdinOnce = builder.stdinOnce != null ? builder.stdinOnce : false; |
| this.env = builder.env; |
| this.rawcmd = builder.rawcmd; |
| this.cmd = builder.cmd; |
| this.image = builder.image; |
| this.volumes = builder.volumes; |
| this.workingDir = builder.workingDir; |
| this.entrypoint = builder.entrypoint; |
| this.networkDisabled = builder.networkDisabled != null |
| ? builder.networkDisabled : false; |
| this.onBuild = builder.onBuild; |
| this.labels = builder.labels; |
| } |
| |
| @Override |
| public String hostname() { |
| return hostname; |
| } |
| |
| @Override |
| public String domainname() { |
| return domainname; |
| } |
| |
| @Override |
| public String user() { |
| return user; |
| } |
| |
| /** |
| * @see DockerHostConfig#memory() |
| */ |
| @Deprecated |
| @Override |
| public Long memory() { |
| return memory; |
| } |
| |
| @Deprecated |
| @Override |
| public Long memorySwap() { |
| return memorySwap; |
| } |
| |
| /** |
| * @see DockerHostConfig#cpuShares() |
| */ |
| @Deprecated |
| @Override |
| public Long cpuShares() { |
| return cpuShares; |
| } |
| |
| @Deprecated |
| @Override |
| public String cpuset() { |
| return cpuset; |
| } |
| |
| @Override |
| public boolean attachStdin() { |
| return attachStdin; |
| } |
| |
| @Override |
| public boolean attachStdout() { |
| return attachStdout; |
| } |
| |
| @Override |
| public boolean attachStderr() { |
| return attachStderr; |
| } |
| |
| @Override |
| public List<String> portSpecs() { |
| if (portSpecs == null) { |
| return Collections.emptyList(); |
| } |
| return portSpecs; |
| } |
| |
| @Override |
| public Set<String> exposedPorts() { |
| if (exposedPorts == null) { |
| return Collections.emptySet(); |
| } |
| return exposedPorts; |
| } |
| |
| @Override |
| public boolean tty() { |
| return tty; |
| } |
| |
| @Override |
| public boolean openStdin() { |
| return openStdin; |
| } |
| |
| @Override |
| public boolean stdinOnce() { |
| return stdinOnce; |
| } |
| |
| @Override |
| public List<String> env() { |
| if (env == null) { |
| return Collections.emptyList(); |
| } |
| return env; |
| } |
| |
| @Override |
| public List<String> cmd() { |
| if (cmd == null) { |
| return Collections.emptyList(); |
| } |
| return cmd; |
| } |
| |
| public String rawcmd() { |
| return rawcmd; |
| } |
| |
| @Override |
| public String image() { |
| return image; |
| } |
| |
| @SuppressWarnings("rawtypes") |
| @Override |
| public Map<String, Map> volumes() { |
| if (volumes == null) { |
| return Collections.emptyMap(); |
| } |
| return volumes; |
| } |
| |
| @Override |
| public String workingDir() { |
| return workingDir; |
| } |
| |
| @Override |
| public List<String> entrypoint() { |
| if (entrypoint == null) { |
| return Collections.emptyList(); |
| } |
| return entrypoint; |
| } |
| |
| @Override |
| public boolean networkDisabled() { |
| return networkDisabled; |
| } |
| |
| @Override |
| public List<String> onBuild() { |
| if (onBuild == null) { |
| return Collections.emptyList(); |
| } |
| return onBuild; |
| } |
| |
| // @Override |
| @Override |
| public Map<String, String> labels() { |
| if (this.labels == null) { |
| return Collections.emptyMap(); |
| } |
| return this.labels; |
| } |
| |
| public static class Builder { |
| |
| private String hostname; |
| private String domainname; |
| private String user; |
| private Long memory; |
| private Long memorySwap; |
| private Long cpuShares; |
| private String cpuset; |
| private Boolean attachStdin; |
| private Boolean attachStdout; |
| private Boolean attachStderr; |
| private List<String> portSpecs; |
| private Set<String> exposedPorts; |
| private Boolean tty; |
| private Boolean openStdin; |
| private Boolean stdinOnce; |
| private List<String> env; |
| private String rawcmd; |
| private List<String> cmd; |
| private String image; |
| @SuppressWarnings("rawtypes") |
| private Map<String, Map> volumes; |
| private String workingDir; |
| private List<String> entrypoint; |
| private Boolean networkDisabled; |
| private List<String> onBuild; |
| private Map<String, String> labels; |
| |
| public Builder hostname(final String hostname) { |
| this.hostname = hostname; |
| return this; |
| } |
| |
| public String hostname() { |
| return hostname; |
| } |
| |
| public Builder domainname(final String domainname) { |
| this.domainname = domainname; |
| return this; |
| } |
| |
| public String domainname() { |
| return domainname; |
| } |
| |
| public Builder user(final String user) { |
| this.user = user; |
| return this; |
| } |
| |
| public String user() { |
| return user; |
| } |
| |
| public Builder memory(final Long memory) { |
| this.memory = memory; |
| return this; |
| } |
| |
| public Long memory() { |
| return memory; |
| } |
| |
| public Builder memorySwap(final Long memorySwap) { |
| this.memorySwap = memorySwap; |
| return this; |
| } |
| |
| public Long memorySwap() { |
| return memorySwap; |
| } |
| |
| public Builder cpuShares(final Long cpuShares) { |
| this.cpuShares = cpuShares; |
| return this; |
| } |
| |
| public Long cpuShares() { |
| return cpuShares; |
| } |
| |
| public Builder cpuset(final String cpuset) { |
| this.cpuset = cpuset; |
| return this; |
| } |
| |
| public String cpuset() { |
| return cpuset; |
| } |
| |
| public Builder attachStdin(final Boolean attachStdin) { |
| this.attachStdin = attachStdin; |
| return this; |
| } |
| |
| public Boolean attachStdin() { |
| return attachStdin; |
| } |
| |
| public Builder attachStdout(final Boolean attachStdout) { |
| this.attachStdout = attachStdout; |
| return this; |
| } |
| |
| public Boolean attachStdout() { |
| return attachStdout; |
| } |
| |
| public Builder attachStderr(final Boolean attachStderr) { |
| this.attachStderr = attachStderr; |
| return this; |
| } |
| |
| public Boolean attachStderr() { |
| return attachStderr; |
| } |
| |
| public Builder portSpecs(final List<String> portSpecs) { |
| this.portSpecs = new ArrayList<>(portSpecs); |
| return this; |
| } |
| |
| public Builder portSpecs(final String... portSpecs) { |
| this.portSpecs = Arrays.asList(portSpecs); |
| return this; |
| } |
| |
| public List<String> portSpecs() { |
| return portSpecs; |
| } |
| |
| public Builder exposedPorts(final Set<String> exposedPorts) { |
| this.exposedPorts = new TreeSet<>(exposedPorts); |
| return this; |
| } |
| |
| public Builder exposedPorts(final String... exposedPorts) { |
| this.exposedPorts = new TreeSet<>(Arrays.asList(exposedPorts)); |
| return this; |
| } |
| |
| public Set<String> exposedPorts() { |
| return exposedPorts; |
| } |
| |
| public Builder tty(final Boolean tty) { |
| this.tty = tty; |
| return this; |
| } |
| |
| public Boolean tty() { |
| return tty; |
| } |
| |
| public Builder openStdin(final Boolean openStdin) { |
| this.openStdin = openStdin; |
| return this; |
| } |
| |
| public Boolean openStdin() { |
| return openStdin; |
| } |
| |
| public Builder stdinOnce(final Boolean stdinOnce) { |
| this.stdinOnce = stdinOnce; |
| return this; |
| } |
| |
| public Boolean stdinOnce() { |
| return stdinOnce; |
| } |
| |
| public Builder env(final List<String> env) { |
| this.env = new ArrayList<>(env); |
| return this; |
| } |
| |
| public Builder env(final String... env) { |
| this.env = Arrays.asList(env); |
| return this; |
| } |
| |
| public List<String> env() { |
| return env; |
| } |
| |
| public Builder cmd(final List<String> cmd) { |
| this.cmd = cmd; |
| return this; |
| } |
| |
| public Builder cmd(final String... cmd) { |
| return cmd(Arrays.asList(cmd)); |
| } |
| |
| public Builder cmd(final String cmd) { |
| this.rawcmd = cmd; |
| this.cmd = getCmdList(cmd); |
| return this; |
| } |
| |
| public List<String> cmd() { |
| return cmd; |
| } |
| |
| public Builder image(final String image) { |
| this.image = image; |
| return this; |
| } |
| |
| public String image() { |
| return image; |
| } |
| |
| public Builder volumes( |
| @SuppressWarnings("rawtypes") final Map<String, Map> volumes) { |
| this.volumes = volumes; |
| return this; |
| } |
| |
| @SuppressWarnings("rawtypes") |
| public Map<String, Map> volumes() { |
| return volumes; |
| } |
| |
| public Builder workingDir(final String workingDir) { |
| this.workingDir = workingDir; |
| return this; |
| } |
| |
| public String workingDir() { |
| return workingDir; |
| } |
| |
| public Builder entryPoint(final List<String> entrypoint) { |
| if (entrypoint != null && !entrypoint.isEmpty()) { |
| this.entrypoint = new ArrayList<>(entrypoint); |
| } |
| return this; |
| } |
| |
| public Builder entryPoint(final String... entrypoint) { |
| return entryPoint(Arrays.asList(entrypoint)); |
| } |
| |
| public Builder entryPoint(final String entrypoint) { |
| if (entrypoint != null && !entrypoint.isEmpty()) { |
| return entryPoint(entrypoint.split(" ")); |
| } else { |
| this.entrypoint = null; |
| } |
| return this; |
| } |
| |
| public List<String> entryPoint() { |
| return entrypoint; |
| } |
| |
| public Builder networkDisabled(final Boolean networkDisabled) { |
| this.networkDisabled = networkDisabled; |
| return this; |
| } |
| |
| public Boolean networkDisabled() { |
| return networkDisabled; |
| } |
| |
| public Builder onBuild(final List<String> onBuild) { |
| this.onBuild = new ArrayList<>(onBuild); |
| return this; |
| } |
| |
| public Builder onBuild(final String... onBuild) { |
| this.onBuild = Arrays.asList(onBuild); |
| return this; |
| } |
| |
| public List<String> onBuild() { |
| return onBuild; |
| } |
| |
| public Builder labels(final Map<String, String> labels) { |
| this.labels = labels; |
| return this; |
| } |
| |
| public DockerContainerConfig build() { |
| return new DockerContainerConfig(this); |
| } |
| |
| /** |
| * Create a proper command list after handling quotation. |
| * |
| * @param command |
| * the command as a single {@link String} |
| * @return the command splitted in a list of ars or <code>null</code> if |
| * the input <code>command</code> was <code>null</code>. |
| */ |
| private List<String> getCmdList(final String command) { |
| if (command == null) { |
| return null; |
| } |
| final List<String> list = new ArrayList<>(); |
| int length = command.length(); |
| boolean insideQuote1 = false; // single-quote |
| boolean insideQuote2 = false; // double-quote |
| boolean escaped = false; |
| StringBuilder buffer = new StringBuilder(); |
| // Parse the string and break it up into chunks that are |
| // separated by white-space or are quoted. Ignore characters |
| // that have been escaped, including the escape character. |
| for (int i = 0; i < length; ++i) { |
| char c = command.charAt(i); |
| if (escaped) { |
| buffer.append(c); |
| escaped = false; |
| } |
| switch (c) { |
| case '\'': |
| if (!insideQuote2) |
| insideQuote1 = insideQuote1 ^ true; |
| else |
| buffer.append(c); |
| break; |
| case '\"': |
| if (!insideQuote1) |
| insideQuote2 = insideQuote2 ^ true; |
| else |
| buffer.append(c); |
| break; |
| case '\\': |
| escaped = true; |
| break; |
| case ' ': |
| case '\t': |
| case '\r': |
| case '\n': |
| if (insideQuote1 || insideQuote2) |
| buffer.append(c); |
| else { |
| String item = buffer.toString(); |
| buffer.setLength(0); |
| if (item.length() > 0) |
| list.add(item); |
| } |
| break; |
| default: |
| buffer.append(c); |
| break; |
| } |
| } |
| // add last item of string that will be in the buffer |
| String item = buffer.toString(); |
| if (item.length() > 0) |
| list.add(item); |
| return list; |
| } |
| |
| } |
| } |