<commit_before>/*
 * 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.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;

import javax.annotation.Resource;
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;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.docker.DockerApi;
import org.jclouds.docker.compute.options.DockerTemplateOptions;
import org.jclouds.docker.domain.Config;
import org.jclouds.docker.domain.Container;
import org.jclouds.docker.domain.ContainerSummary;
import org.jclouds.docker.domain.HostConfig;
import org.jclouds.docker.domain.Image;
import org.jclouds.docker.domain.ImageSummary;
import org.jclouds.docker.options.ListContainerOptions;
import org.jclouds.docker.options.RemoveContainerOptions;
import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.Logger;

/**
 * defines the connection between the {@link org.jclouds.docker.DockerApi} implementation and
 * the jclouds {@link org.jclouds.compute.ComputeService}
 */
@Singleton
public class DockerComputeServiceAdapter implements
        ComputeServiceAdapter<Container, Hardware, Image, Location> {

   @Resource
   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
   protected Logger logger = Logger.NULL;

   private final DockerApi api;

   @Inject
   public DockerComputeServiceAdapter(DockerApi api) {
      this.api = checkNotNull(api, "api");
   }

   @SuppressWarnings({ "rawtypes", "unchecked" })
   @Override
   public NodeAndInitialCredentials<Container> createNodeWithGroupEncodedIntoName(String group, String name,
                                                                                  Template template) {
      checkNotNull(template, "template was null");
      TemplateOptions options = template.getOptions();
      checkNotNull(options, "template options was null");

      String imageId = checkNotNull(template.getImage().getId(), "template image id must not be null");
      String loginUser = template.getImage().getDefaultCredentials().getUser();
      String loginUserPassword = template.getImage().getDefaultCredentials().getOptionalPassword().or("password");

      DockerTemplateOptions templateOptions = DockerTemplateOptions.class.cast(options);
      Config.Builder containerConfigBuilder = templateOptions.getConfigBuilder();
      if (containerConfigBuilder == null) {
         containerConfigBuilder = Config.builder();

         containerConfigBuilder.entrypoint(templateOptions.getEntrypoint());
         containerConfigBuilder.cmd(templateOptions.getCommands());
         containerConfigBuilder.memory(templateOptions.getMemory());
         containerConfigBuilder.hostname(templateOptions.getHostname());
         containerConfigBuilder.cpuShares(templateOptions.getCpuShares());
         containerConfigBuilder.env(templateOptions.getEnv());

         if (!templateOptions.getVolumes().isEmpty()) {
            Map<String, Object> volumes = Maps.newLinkedHashMap();
            for (String containerDir : templateOptions.getVolumes().values()) {
               volumes.put(containerDir, Maps.newHashMap());
            }
            containerConfigBuilder.volumes(volumes);
         }

         HostConfig.Builder hostConfigBuilder = HostConfig.builder()
                 .publishAllPorts(true)
                 .privileged( templateOptions.getPrivileged() );

         if (!templateOptions.getPortBindings().isEmpty()) {
            Map<String, List<Map<String, String>>> portBindings = Maps.newHashMap();
            for (Map.Entry<Integer, Integer> entry : templateOptions.getPortBindings().entrySet()) {
               portBindings.put(entry.getValue() + "/tcp",
                       Lists.<Map<String, String>>newArrayList(ImmutableMap.of("HostPort", Integer.toString(entry.getKey()))));
            }
            hostConfigBuilder.portBindings(portBindings);
         }

         if (!templateOptions.getDns().isEmpty()) {
            hostConfigBuilder.dns(templateOptions.getDns());
         }

         if (!templateOptions.getExtraHosts().isEmpty()) {
            List<String> extraHosts = Lists.newArrayList();
            for (Map.Entry<String, String> entry : templateOptions.getExtraHosts().entrySet()) {
               extraHosts.add(entry.getKey() + ":" + entry.getValue());
            }
            hostConfigBuilder.extraHosts(extraHosts);
         }

         if (!templateOptions.getVolumes().isEmpty()) {
            for (Map.Entry<String, String> entry : templateOptions.getVolumes().entrySet()) {
               hostConfigBuilder.binds(ImmutableList.of(entry.getKey() + ":" + entry.getValue()));
            }
         }

         if (!templateOptions.getVolumesFrom().isEmpty()) {
            hostConfigBuilder.volumesFrom(templateOptions.getVolumesFrom());
         }

         hostConfigBuilder.networkMode(templateOptions.getNetworkMode());

         containerConfigBuilder.hostConfig(hostConfigBuilder.build());
      }

      containerConfigBuilder.image(imageId);

      // add the inbound ports into exposed ports map
      Config containerConfig = containerConfigBuilder.build();
      Map<String, Object> exposedPorts = Maps.newHashMap();
      if (containerConfig.exposedPorts() == null) {
         exposedPorts.putAll(containerConfig.exposedPorts());
      }
      for (int inboundPort : templateOptions.getInboundPorts()) {
         String portKey = inboundPort + "/tcp";
         if (!exposedPorts.containsKey(portKey)) {
            exposedPorts.put(portKey, Maps.newHashMap());
         }
      }
      containerConfigBuilder.exposedPorts(exposedPorts);

      // build once more after setting inboundPorts
      containerConfig = containerConfigBuilder.build();

      logger.debug(">> creating new container with containerConfig(%s)", containerConfig);
      Container container = api.getContainerApi().createContainer(name, containerConfig);
      logger.trace("<< container(%s)", container.id());

      HostConfig hostConfig = containerConfig.hostConfig();

      api.getContainerApi().startContainer(container.id(), hostConfig);
      container = api.getContainerApi().inspectContainer(container.id());
      if (container.state().exitCode() != 0) {
         destroyNode(container.id());
         throw new IllegalStateException(String.format("Container %s has not started correctly", container.id()));
      }<commit_msg>Update HostConfig port bindings before creating container<commit_after>/*
 * 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.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;

import javax.annotation.Resource;
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;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.docker.DockerApi;
import org.jclouds.docker.compute.options.DockerTemplateOptions;
import org.jclouds.docker.domain.Config;
import org.jclouds.docker.domain.Container;
import org.jclouds.docker.domain.ContainerSummary;
import org.jclouds.docker.domain.HostConfig;
import org.jclouds.docker.domain.Image;
import org.jclouds.docker.domain.ImageSummary;
import org.jclouds.docker.options.ListContainerOptions;
import org.jclouds.docker.options.RemoveContainerOptions;
import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.Logger;

/**
 * defines the connection between the {@link org.jclouds.docker.DockerApi} implementation and
 * the jclouds {@link org.jclouds.compute.ComputeService}
 */
@Singleton
public class DockerComputeServiceAdapter implements
        ComputeServiceAdapter<Container, Hardware, Image, Location> {

   @Resource
   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
   protected Logger logger = Logger.NULL;

   private final DockerApi api;

   @Inject
   public DockerComputeServiceAdapter(DockerApi api) {
      this.api = checkNotNull(api, "api");
   }

   @SuppressWarnings({ "rawtypes", "unchecked" })
   @Override
   public NodeAndInitialCredentials<Container> createNodeWithGroupEncodedIntoName(String group, String name,
                                                                                  Template template) {
      checkNotNull(template, "template was null");
      TemplateOptions options = template.getOptions();
      checkNotNull(options, "template options was null");

      String imageId = checkNotNull(template.getImage().getId(), "template image id must not be null");
      String loginUser = template.getImage().getDefaultCredentials().getUser();
      String loginUserPassword = template.getImage().getDefaultCredentials().getOptionalPassword().or("password");

      DockerTemplateOptions templateOptions = DockerTemplateOptions.class.cast(options);
      Config.Builder containerConfigBuilder = templateOptions.getConfigBuilder();
      if (containerConfigBuilder == null) {
         containerConfigBuilder = Config.builder();

         containerConfigBuilder.entrypoint(templateOptions.getEntrypoint());
         containerConfigBuilder.cmd(templateOptions.getCommands());
         containerConfigBuilder.memory(templateOptions.getMemory());
         containerConfigBuilder.hostname(templateOptions.getHostname());
         containerConfigBuilder.cpuShares(templateOptions.getCpuShares());
         containerConfigBuilder.env(templateOptions.getEnv());

         if (!templateOptions.getVolumes().isEmpty()) {
            Map<String, Object> volumes = Maps.newLinkedHashMap();
            for (String containerDir : templateOptions.getVolumes().values()) {
               volumes.put(containerDir, Maps.newHashMap());
            }
            containerConfigBuilder.volumes(volumes);
         }

         HostConfig.Builder hostConfigBuilder = HostConfig.builder()
                 .publishAllPorts(true)
                 .privileged(templateOptions.getPrivileged());

         if (!templateOptions.getPortBindings().isEmpty()) {
            Map<String, List<Map<String, String>>> portBindings = Maps.newHashMap();
            for (Map.Entry<Integer, Integer> entry : templateOptions.getPortBindings().entrySet()) {
               portBindings.put(entry.getValue() + "/tcp",
                       Lists.<Map<String, String>>newArrayList(ImmutableMap.of("HostIp", "0.0.0.0", "HostPort", Integer.toString(entry.getKey()))));
            }
            hostConfigBuilder.portBindings(portBindings);
         }

         if (!templateOptions.getDns().isEmpty()) {
            hostConfigBuilder.dns(templateOptions.getDns());
         }

         if (!templateOptions.getExtraHosts().isEmpty()) {
            List<String> extraHosts = Lists.newArrayList();
            for (Map.Entry<String, String> entry : templateOptions.getExtraHosts().entrySet()) {
               extraHosts.add(entry.getKey() + ":" + entry.getValue());
            }
            hostConfigBuilder.extraHosts(extraHosts);
         }

         if (!templateOptions.getVolumes().isEmpty()) {
            for (Map.Entry<String, String> entry : templateOptions.getVolumes().entrySet()) {
               hostConfigBuilder.binds(ImmutableList.of(entry.getKey() + ":" + entry.getValue()));
            }
         }

         if (!templateOptions.getVolumesFrom().isEmpty()) {
            hostConfigBuilder.volumesFrom(templateOptions.getVolumesFrom());
         }

         hostConfigBuilder.networkMode(templateOptions.getNetworkMode());

         containerConfigBuilder.hostConfig(hostConfigBuilder.build());
      }

      containerConfigBuilder.image(imageId);

      // add the inbound ports into exposed ports
      Config containerConfig = containerConfigBuilder.build();
      Map<String, Object> exposedPorts = Maps.newHashMap();
      if (containerConfig.exposedPorts() == null) {
         exposedPorts.putAll(containerConfig.exposedPorts());
      }
      for (int inboundPort : templateOptions.getInboundPorts()) {
         String portKey = inboundPort + "/tcp";
         if (!exposedPorts.containsKey(portKey)) {
            exposedPorts.put(portKey, Maps.newHashMap());
         }
      }
      containerConfigBuilder.exposedPorts(exposedPorts);

      // build once more after setting inboundPorts
      containerConfig = containerConfigBuilder.build();

      // finally update port bindings
      Map<String, List<Map<String, String>>> portBindings = Maps.newHashMap();
      Map<String, List<Map<String, String>>> existingBindings = containerConfig.hostConfig().portBindings();
      if (existingBindings != null) {
          portBindings.putAll(existingBindings);
      }
      for (String exposedPort : containerConfig.exposedPorts().keySet()) {
         if (!portBindings.containsKey(exposedPort)) {
            portBindings.put(exposedPort, Lists.<Map<String, String>>newArrayList(ImmutableMap.of("HostIp", "0.0.0.0")));
         }
      }
      HostConfig.Builder hostConfigBuilder = HostConfig.builder().fromHostConfig(containerConfig.hostConfig());
      hostConfigBuilder.portBindings(portBindings);
      containerConfigBuilder.hostConfig(hostConfigBuilder.build());
      containerConfig = containerConfigBuilder.build();

      logger.debug(">> creating new container with containerConfig(%s)", containerConfig);
      Container container = api.getContainerApi().createContainer(name, containerConfig);
      logger.trace("<< container(%s)", container.id());

      HostConfig hostConfig = containerConfig.hostConfig();

      api.getContainerApi().startContainer(container.id(), hostConfig);
      container = api.getContainerApi().inspectContainer(container.id());
      if (container.state().exitCode() != 0) {
         destroyNode(container.id());
         throw new IllegalStateException(String.format("Container %s has not started correctly", container.id()));
      }
{'fraction_non_alphanumeric': 0.10884313258747917, 'fraction_numerical': 0.0010711735301118781, 'mean_word_length': 3.6282015973561004, 'pattern_counts': {'":': 4, '<': 41, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6444685', 'n_tokens_mistral': 4361, 'n_tokens_neox': 4308, 'n_words': 895}