예제 #1
0
  public void destroyContainer(Container container, boolean force) {
    assertValid();
    String containerId = container.getId();
    LOGGER.info("Destroying container {}", containerId);
    boolean destroyed = false;
    try {
      ContainerProvider provider = getProvider(container, true);
      if (provider != null) {
        try {
          provider.stop(container);
        } catch (Exception ex) {
          // Ignore error while stopping and try to destroy.
        }
        provider.destroy(container);
        destroyed = true;
      }

    } finally {
      try {
        if (destroyed || force) {
          portService.get().unregisterPort(container);
          getDataStore().deleteContainer(container.getId());
        }
      } catch (Exception e) {
        LOGGER.warn(
            "Failed to cleanup container {} entries due to: {}. This will be ignored.",
            containerId,
            e.getMessage());
      }
    }
  }
예제 #2
0
  private void manageProfile(TaskContext context) {
    Container current = fabricService.get().getCurrentContainer();
    ProfileData profileData = createProfileData(context);
    String profileId = context.getConfiguration().get(TEMPLATE_PROFILE_PROPERTY_NAME) + "-" + name;
    Version version = current.getVersion();

    try {
      if (lock.acquire(60, TimeUnit.SECONDS)) {
        if (profileData.isEmpty()) {
          if (version.hasProfile(profileId)) {
            // Just delete the profile
            version.getProfile(profileId).delete(true);
          }
          return;
        } else if (!version.hasProfile(profileId)) {
          // Create the profile
          fabricService.get().getDataStore().createProfile(version.getId(), profileId);
        }

        Profile managedProfile = version.getProfile(profileId);
        // managedProfile.setConfigurations(profileData.getConfigs());
        managedProfile.setFileConfigurations(profileData.getFiles());
        current.addProfiles(managedProfile);
      } else {
        throw new TimeoutException("Timed out waiting for lock");
      }
    } catch (Exception e) {
      LOGGER.error("Error managing work items.", e);
    } finally {
      releaseLock();
    }
  }
예제 #3
0
 @Override
 public void stop(TaskContext context) {
   Container current = fabricService.get().getCurrentContainer();
   Version version = current.getVersion();
   String profileId = context.getConfiguration().get(TEMPLATE_PROFILE_PROPERTY_NAME) + "-" + name;
   if (version.hasProfile(profileId)) {
     // Just delete the profile
     version.getProfile(profileId).delete(true);
   }
 }
예제 #4
0
  /**
   * Creates a representation of the profile based on the assigned item for the specified
   * {@linkTaskContext}.
   *
   * @param context
   * @return
   */
  private ProfileData createProfileData(TaskContext context) {
    ProfileData profileData = new ProfileData();
    Set<WorkItem> workItems = assignedWorkItems.get(context);
    if (workItems.isEmpty()) {
      return profileData;
    }

    Container current = fabricService.get().getCurrentContainer();
    Version version = current.getVersion();
    String templateProfileName =
        String.valueOf(context.getConfiguration().get(TEMPLATE_PROFILE_PROPERTY_NAME));
    Profile templateProfile = version.getProfile(templateProfileName);
    Set<String> allFiles = templateProfile.getFileConfigurations().keySet();
    Iterable<String> mvelFiles = Iterables.filter(allFiles, MvelPredicate.INSTANCE);
    Iterable<String> plainFiles =
        Iterables.filter(allFiles, Predicates.not(MvelPredicate.INSTANCE));

    for (String mvelFile : mvelFiles) {
      Key key = new Key(templateProfile.getId(), mvelFile);
      synchronized (templates) {
        CompiledTemplate template = templates.get(key);
        if (template == null) {
          template =
              TemplateCompiler.compileTemplate(
                  new String(templateProfile.getFileConfigurations().get(mvelFile)), parserContext);
          templates.put(key, template);
        }
      }
    }

    for (WorkItem workItem : workItems) {
      Map<String, WorkItem> data = new HashMap<String, WorkItem>();
      data.put(WorkItem.ITEM, workItem);

      // Render templates
      for (String fileTemplate : mvelFiles) {
        String file = renderTemplateName(fileTemplate, workItem);
        Key key = new Key(templateProfile.getId(), fileTemplate);
        try {
          String renderedTemplate =
              TemplateRuntime.execute(templates.get(key), parserContext, data).toString();
          updateProfileData(file, renderedTemplate, profileData);
        } catch (Exception ex) {
          LOGGER.warn("Failed to render {}. Ignoring.", fileTemplate);
        }
      }

      // Copy plain files.
      for (String file : plainFiles) {
        String content = new String(templateProfile.getFileConfigurations().get(file));
        updateProfileData(file, content, profileData);
      }
    }
    return profileData;
  }
예제 #5
0
 public T container(final Container container) {
   this.container = container;
   if (container != null) {
     id(container.getId());
   }
   return (T) this;
 }
예제 #6
0
 protected String getDockerContainerId(Container container) {
   CreateDockerContainerMetadata containerMetadata = getContainerMetadata(container);
   if (containerMetadata != null) {
     return containerMetadata.getId();
   }
   return container.getId();
 }
예제 #7
0
 protected static CreateDockerContainerMetadata getContainerMetadata(Container container) {
   CreateContainerMetadata<?> value = container.getMetadata();
   if (value instanceof CreateDockerContainerMetadata) {
     return (CreateDockerContainerMetadata) value;
   } else {
     return null;
   }
 }
 @Override
 public ChildContainerController getControllerForContainer(Container container) {
   Installation installation = getProcessManager().getInstallation(container.getId());
   ChildContainerController answer = null;
   if (installation != null) {
     answer = createProcessManagerController();
   }
   return answer;
 }
예제 #9
0
 @Override
 public String profileWebAppURL(String webAppId, String profileId, String versionId) {
   if (versionId == null || versionId.length() == 0) {
     Version version = getDefaultVersion();
     if (version != null) {
       versionId = version.getId();
     }
   }
   List<Container> containers =
       Containers.containersForProfile(getContainers(), profileId, versionId);
   for (Container container : containers) {
     String url = containerWebAppURL(webAppId, container.getId());
     if (url != null && url.length() > 0) {
       return url;
     }
   }
   return null;
 }
예제 #10
0
 private ContainerProvider getProvider(Container container, boolean returnNull) {
   CreateContainerMetadata metadata = container.getMetadata();
   String type = metadata != null ? metadata.getCreateOptions().getProviderType() : null;
   if (type == null) {
     if (returnNull) {
       return null;
     }
     throw new UnsupportedOperationException(
         "Container " + container.getId() + " has not been created using Fabric");
   }
   ContainerProvider provider = getProvider(type);
   if (provider == null) {
     if (returnNull) {
       return null;
     }
     throw new UnsupportedOperationException("Container provider " + type + " not supported");
   }
   return provider;
 }
    protected void recompile() {
        LOG.debug("Looking for XSDs to recompile");

        Set<String> urls = new TreeSet<String>();
        FabricService fabric = getFabricService();
        Container container = fabric.getCurrentContainer();
        String version = container.getVersion().getId();
        List<Profile> profiles = Containers.overlayProfiles(container);
        List<String> profileIds = Profiles.profileIds(profiles);
        Collection<String> names = fabric.getDataStore().listFiles(version, profileIds, schemaPath);
        for (String name : names) {
            if (name.endsWith(".xsd")) {
                String prefix = schemaPath;
                if (Strings.isNotBlank(prefix)) {
                    prefix += "/";
                }
                urls.add("profile:" + prefix + name);
            }
        }

        LOG.info("Recompiling XSDs at URLs: " + urls);
        startedFlag.set(false);

        ClassLoader classLoader = AriesFrameworkUtil.getClassLoader(bundleContext.getBundle());
        if (classLoader == null) {
            classLoader = getClass().getClassLoader();
        }
        DynamicXJC xjc = new DynamicXJC(classLoader);
        xjc.setSchemaUrls(new ArrayList<String>(urls));
        compileResults = xjc.compileSchemas();
        if (handler != null) {
            handler.onCompileResults(compileResults);
        }
        if (introspector != null) {
            introspector.setClassLoaderProvider("dynamic.jaxb", new ClassLoaderProvider() {
                @Override
                public ClassLoader getClassLoader() {
                    return compileResults.getClassLoader();
                }
            });
        }
    }
예제 #12
0
 @Override
 public String getWebConsoleUrl() {
   Container[] containers = null;
   try {
     containers = getContainers();
   } catch (Exception e) {
     LOGGER.debug("Ignored exception trying to find containers: " + e, e);
     return null;
   }
   for (Container aContainer : containers) {
     Profile[] profiles = aContainer.getProfiles();
     for (Profile aProfile : profiles) {
       String id = aProfile.getId();
       if (id.equals("fabric")) {
         return profileWebAppURL("io.hawt.hawtio-web", id, aProfile.getVersion());
       }
     }
   }
   return null;
 }
예제 #13
0
 /** Returns true if the given container is a java or process child container */
 public static boolean isJavaOrProcessContainer(FabricService fabric, Container container) {
   if (container != null) {
     CreateContainerMetadata<?> metadata = container.getMetadata();
     if (metadata != null) {
       CreateContainerOptions createOptions = metadata.getCreateOptions();
       if (createOptions instanceof CreateContainerBasicOptions) {
         return isJavaOrProcessContainer(fabric, (CreateContainerBasicOptions) createOptions);
       }
     }
   }
   return false;
 }
 private int getCompletedExchangesCount(final Container c) {
   String response =
       new AnsiString(
               executeCommand(
                   "fabric:container-connect -u admin -p admin "
                       + c.getId()
                       + " camel:route-info fabric-client | grep \"Exchanges Completed\""))
           .getPlain()
           .toString();
   System.out.println(response);
   return Integer.parseInt(response.replaceAll("[^0-9]", ""));
 }
예제 #15
0
  @Override
  public void stop(Container container) {
    assertValid();
    String id = getDockerContainerId(container);
    if (!Strings.isNullOrBlank(id)) {
      LOG.info("stopping container " + id);
      CreateDockerContainerMetadata metadata = getContainerMetadata(container);
      if (metadata != null) {
        stopJolokiaKeepAlive(metadata);
      }

      Integer timeToWait = null;
      try {
        docker.containerStop(id, timeToWait);
      } catch (final Exception e) {
        LOG.info("Could not stop container " + id + ": " + e + Dockers.dockerErrorMessage(e), e);
        throw e;
      }
      container.setProvisionResult(Container.PROVISION_STOPPED);
    }
  }
  protected void checkProcessesStatus() {
    ProcessManager manager = getProcessManager();
    FabricService fabric = getFabricService();
    if (manager != null && fabric != null) {
      ImmutableMap<String, Installation> map = manager.listInstallationMap();
      ImmutableSet<Map.Entry<String, Installation>> entries = map.entrySet();
      for (Map.Entry<String, Installation> entry : entries) {
        String id = entry.getKey();
        Installation installation = entry.getValue();
        try {
          Container container = null;
          try {
            container = fabric.getContainer(id);
          } catch (Exception e) {
            LOG.debug("No container for id: " + id + ". " + e, e);
          }
          if (container != null) {
            Long pid = installation.getActivePid();
            if (LOG.isDebugEnabled()) {
              LOG.debug("Polling container " + id + " for its PID");
            }
            if (pid == null) {
              if (container.isAlive()) {
                container.setAlive(false);
              }
            } else if (pid != null && pid != 0) {
              if (!container.isAlive()) {
                container.setAlive(true);
              }
              if (!Objects.equal(container.getProvisionResult(), Container.PROVISION_SUCCESS)) {
                container.setProvisionResult(Container.PROVISION_SUCCESS);
              }

              JolokiaAgentHelper.jolokiaKeepAliveCheck(fabric, container);
            }
          }
        } catch (Exception e) {
          LOG.warn("Failed to get PID for process " + id + ". " + e, e);
        }
      }
    }
  }
예제 #17
0
 public void stopContainer(Container container, boolean force) {
   assertValid();
   LOGGER.info("Stopping container {}", container.getId());
   ContainerProvider provider = getProvider(container);
   provider.stop(container);
 }
  public String generateContainerImage(
      FabricService fabric,
      Container container,
      List<Profile> profileList,
      Docker docker,
      JavaContainerOptions options,
      JavaContainerConfig javaConfig,
      CreateDockerContainerOptions containerOptions,
      ExecutorService downloadExecutor,
      Map<String, String> envVars)
      throws Exception {
    String libDirAndSeparator = ensureEndsWithFileSeparator(options.getJavaLibraryPath());
    String homeDirAndSeparator = ensureEndsWithFileSeparator(options.getHomePath());
    Map<String, Parser> artifacts =
        JavaContainers.getJavaContainerArtifacts(fabric, profileList, downloadExecutor);

    URI mavenRepoURI = fabric.getMavenRepoURI();
    String repoTextPrefix = mavenRepoURI.toString();
    int idx = repoTextPrefix.indexOf("://");
    if (idx > 0) {
      repoTextPrefix = repoTextPrefix.substring(idx + 3);
    }
    repoTextPrefix =
        "http://"
            + fabric.getZooKeeperUser()
            + ":"
            + fabric.getZookeeperPassword()
            + "@"
            + repoTextPrefix;

    String baseImage = options.getBaseImage();
    String tag = options.getNewImageTag();

    DockerFileBuilder dockerFile = DockerFileBuilder.from(baseImage);

    Set<Map.Entry<String, Parser>> entries = artifacts.entrySet();
    for (Map.Entry<String, Parser> entry : entries) {
      Parser parser = entry.getValue();
      String path = parser.getArtifactPath();
      String url = repoTextPrefix + path;
      String version = parser.getVersion();
      String snapshotModifier = "";
      // avoid the use of the docker cache for snapshot dependencies
      if (version != null && version.contains("SNAPSHOT")) {
        long time = new Date().getTime();
        url += "?t=" + time;
        snapshotModifier = "-" + time;
      }
      String fileName =
          parser.getArtifact() + "-" + version + snapshotModifier + "." + parser.getType();
      String filePath = libDirAndSeparator + fileName;

      dockerFile.add(url, filePath);
    }

    if (container != null) {
      List<String> bundles = new ArrayList<String>();
      for (String name : artifacts.keySet()) {
        if (name.startsWith("fab:")) {
          name = name.substring(4);
        }
        bundles.add(name);
      }
      Collections.sort(bundles);
      container.setProvisionList(bundles);
    }

    String restAPI = fabric.getRestAPI();
    if (Strings.isNotBlank(restAPI)) {
      addContainerOverlays(
          dockerFile,
          restAPI,
          fabric,
          container,
          profileList,
          docker,
          options,
          javaConfig,
          containerOptions,
          envVars,
          homeDirAndSeparator);
    } else {
      LOGGER.error("Cannot perform container overlays as there is no REST API for fabric8!");
    }

    String[] copiedEnvVars = JavaContainerEnvironmentVariables.ALL_ENV_VARS;
    for (String envVarName : copiedEnvVars) {
      String value = envVars.get(envVarName);
      if (value != null) {
        dockerFile.env(envVarName, value);
      }
    }

    String entryPoint = options.getEntryPoint();
    if (Strings.isNotBlank(entryPoint)) {
      dockerFile.cmd(entryPoint);
    }

    // TODO we should keep a cache of the Dockerfile text for each profile so we don't create it
    // each time

    // lets use the command line for now....
    File tmpFile = File.createTempFile("fabric-", ".dockerfiledir");
    tmpFile.delete();
    tmpFile.mkdirs();

    dockerFile.writeTo(new File(tmpFile, "Dockerfile"));

    // lets use the docker command line for now...
    String[] commands = new String[] {"docker", "build", "-t", tag, tmpFile.getCanonicalPath()};

    String message = join(asList(commands), " ");
    LOGGER.info("Executing commands: " + message);
    String answer = null;
    String errors = null;
    String dockerHost = resolveDockerHost();
    try {
      ProcessBuilder dockerBuild = new ProcessBuilder().command(commands);
      Map<String, String> env = dockerBuild.environment();
      env.put("DOCKER_HOST", dockerHost);
      Process process = dockerBuild.start();
      answer = parseCreatedImage(process.getInputStream(), message);
      errors = processErrors(process.getErrorStream(), message);
    } catch (Exception e) {
      LOGGER.error("Failed to execute process " + "stdin" + " for " + message + ": " + e, e);
      throw e;
    }
    if (answer == null) {
      LOGGER.error("Failed to create image " + errors);
      throw new CreateDockerImageFailedException("Failed to create docker image: " + errors);
    } else {
      LOGGER.info("Created Image: " + answer);
      return answer;
    }
  }
예제 #19
0
  @Test
  public void testRegistryEntries() throws Exception {
    int startingPort = 9090;
    System.err.println(executeCommand("fabric:create -n root"));
    CuratorFramework curator = getCurator();
    // Wait for zookeeper service to become available.
    System.err.println(
        executeCommand("fabric:profile-create --parents feature-camel fabric-camel"));
    System.err.println(
        executeCommand("fabric:profile-create --parents fabric-camel fabric-camel-server"));
    System.err.println(
        executeCommand("fabric:profile-create --parents fabric-camel fabric-camel-client"));
    System.err.println(
        executeCommand(
            "fabric:profile-edit --repositories mvn:org.fusesource.examples.fabric-camel-cluster/features/"
                + System.getProperty("fabric.version")
                + "/xml/features fabric-camel"));

    System.err.println(
        executeCommand("fabric:profile-edit --features camel-server fabric-camel-server"));
    executeCommand("fabric:profile-edit --features camel-client fabric-camel-client");

    Set<Container> containers =
        ContainerBuilder.create(3)
            .withName("fabric-camel")
            .withProfiles("fabric-camel")
            .assertProvisioningResult()
            .build();

    // We will use the first container as a client and the rest as servers.
    Container camelClientContainer = containers.iterator().next();
    containers.remove(camelClientContainer);
    Set<Container> camelServerContainers = new LinkedHashSet<Container>(containers);

    int index = 1;
    for (Container c : camelServerContainers) {
      setData(curator, ZkPath.CONTAINER_PROVISION_RESULT.getPath(c.getId()), "changing");
      executeCommand(
          "fabric:container-connect -u admin -p admin "
              + camelClientContainer.getId()
              + " log:set DEBUG");
      System.err.println(
          executeCommand(
              "fabric:profile-create --parents fabric-camel-server fabric-camel-server-" + index));
      System.err.println(
          executeCommand(
              "fabric:profile-edit --pid io.fabric8.examples.camel.loadbalancing.server/portNumber="
                  + (startingPort++)
                  + " fabric-camel-server-"
                  + index));
      System.err.println(executeCommand("fabric:profile-display fabric-camel-server-" + index));
      System.err.println(
          executeCommand(
              "fabric:container-change-profile "
                  + c.getId()
                  + " fabric-camel-server-"
                  + (index++)));
    }

    Provision.provisioningSuccess(camelServerContainers, PROVISION_TIMEOUT);
    setData(
        curator,
        ZkPath.CONTAINER_PROVISION_RESULT.getPath(camelClientContainer.getId()),
        "changing");
    System.err.println(
        executeCommand(
            "fabric:container-change-profile "
                + camelClientContainer.getId()
                + " fabric-camel-client"));
    Provision.provisioningSuccess(
        Arrays.asList(new Container[] {camelClientContainer}), PROVISION_TIMEOUT);

    System.err.println(executeCommand("fabric:container-list"));
    System.err.println(executeCommand("fabric:profile-display --overlay fabric-camel-server"));

    // Check that the entries have been properly propagated.
    Assert.assertNotNull(exists(curator, "/fabric/registry/camel/endpoints/"));
    Assert.assertEquals(1, getChildren(curator, "/fabric/registry/camel/endpoints/").size());
    Thread.sleep(5000);
    System.err.println(
        executeCommand(
            "fabric:container-connect -u admin -p admin "
                + camelClientContainer.getId()
                + " camel:route-list"));
    String response =
        new AnsiString(
                executeCommand(
                    "fabric:container-connect -u admin -p admin "
                        + camelClientContainer.getId()
                        + " camel:route-info fabric-client | grep Failed"))
            .getPlain()
            .toString();
    System.err.println(response);
    int failed = Integer.parseInt(response.replaceAll("[^0-9]", ""));
    Assert.assertEquals("Failed exchanges found on client", 0, failed);

    // We want to kill all but one server, so we take out the first and keep it to the end.
    Container lastActiveServerContainer = camelServerContainers.iterator().next();
    camelServerContainers.remove(lastActiveServerContainer);
    for (Container c : camelServerContainers) {
      c.destroy();
      Thread.sleep(25000);
      response =
          new AnsiString(
                  executeCommand(
                      "fabric:container-connect -u admin -p admin "
                          + camelClientContainer.getId()
                          + " camel:route-info fabric-client | grep Failed"))
              .getPlain()
              .toString();
      System.err.println(response);
      failed = Integer.parseInt(response.replaceAll("[^0-9]", ""));
      Assert.assertEquals(
          "Failed exchanges found after container:" + c.getId() + " shut down", 0, failed);
    }
  }
    public DockerCreateContainerParameters invoke() throws Exception {
      assertValid();

      String containerId = options.getName();
      containerConfig = createContainerConfig(options);

      // allow values to be extracted from the profile configuration
      // such as the image
      Set<String> profileIds = options.getProfiles();
      String versionId = options.getVersion();
      FabricService service = getFabricService();
      Map<String, String> configOverlay = new HashMap<>();
      Map<String, String> ports = null;
      Map<String, String> dockerProviderConfig = new HashMap<>();

      List<Profile> profileOverlays = new ArrayList<>();
      Version version = null;
      if (profileIds != null && versionId != null) {
        ProfileService profileService = service.adapt(ProfileService.class);
        version = profileService.getVersion(versionId);
        if (version != null) {
          for (String profileId : profileIds) {
            Profile profile = version.getRequiredProfile(profileId);
            if (profile != null) {
              Profile overlay = profileService.getOverlayProfile(profile);
              profileOverlays.add(overlay);
              Map<String, String> dockerConfig =
                  overlay.getConfiguration(DockerConstants.DOCKER_PROVIDER_PID);
              if (dockerConfig != null) {
                configOverlay.putAll(dockerConfig);
              }
              if (ports == null || ports.size() == 0) {
                ports = overlay.getConfiguration(Constants.PORTS_PID);
              }
            }
          }
          if (version.hasProfile(DockerConstants.DOCKER_PROVIDER_PROFILE_ID)) {
            Profile profile =
                version.getRequiredProfile(DockerConstants.DOCKER_PROVIDER_PROFILE_ID);
            if (profile != null) {
              Profile overlay = profileService.getOverlayProfile(profile);
              Map<String, String> dockerConfig =
                  overlay.getConfiguration(DockerConstants.DOCKER_PROVIDER_PID);
              if (dockerConfig != null) {
                dockerProviderConfig.putAll(dockerConfig);
              }
            }
          }
        }
      }
      if (ports == null || ports.size() == 0) {
        // lets find the defaults from the docker profile
        if (version == null) {
          version = service.getRequiredDefaultVersion();
        }
        Profile dockerProfile = version.getRequiredProfile("docker");
        ports = dockerProfile.getConfiguration(Constants.PORTS_PID);
        if (ports == null || ports.size() == 0) {
          LOG.warn("Could not a docker ports configuration for: " + Constants.PORTS_PID);
          ports = new HashMap<String, String>();
        }
      }
      LOG.info("Got port configuration: " + ports);

      environmentVariables =
          ChildContainers.getEnvironmentVariables(service, options, DockerConstants.SCHEME);

      DockerProviderConfig configOverlayDockerProvider =
          createDockerProviderConfig(configOverlay, environmentVariables);

      CuratorFramework curatorOptional = getCuratorFramework();
      String image =
          JolokiaAgentHelper.substituteVariableExpression(
              containerConfig.getImage(), environmentVariables, service, curatorOptional, true);

      if (Strings.isNullOrBlank(image)) {
        image = configOverlayDockerProvider.getImage();
        if (Strings.isNullOrBlank(image)) {
          DockerProviderConfig dockerProviderConfigObject =
              createDockerProviderConfig(dockerProviderConfig, environmentVariables);
          image = dockerProviderConfigObject.getImage();
        }
        if (Strings.isNullOrBlank(image)) {
          image = System.getenv(DockerConstants.EnvironmentVariables.FABRIC8_DOCKER_DEFAULT_IMAGE);
        }
        if (Strings.isNullOrBlank(image)) {
          image = DockerConstants.DEFAULT_IMAGE;
        }
        containerConfig.setImage(image);
      }
      containerType = "docker " + image;
      Container container = service.getContainer(containerId);
      if (container != null) {
        container.setType(containerType);
      }

      String[] cmd = containerConfig.getCmd();
      if (cmd == null || cmd.length == 0) {
        String value = configOverlayDockerProvider.getCmd();
        if (Strings.isNullOrBlank(value)) {
          cmd = null;
        } else {
          cmd = new String[] {value};
        }
        containerConfig.setCmd(cmd);
      }

      Map<String, Integer> internalPorts = options.getInternalPorts();
      Map<String, Integer> externalPorts = options.getExternalPorts();

      Map<String, Object> exposedPorts = new HashMap<>();
      Set<Integer> usedPortByHost = findUsedPortByHostAndDocker();
      Map<String, String> emptyMap = new HashMap<>();

      SortedMap<Integer, String> sortedInternalPorts = new TreeMap<>();
      for (Map.Entry<String, String> portEntry : ports.entrySet()) {
        String portName = portEntry.getKey();
        String portText = portEntry.getValue();
        if (portText != null && !Strings.isNullOrBlank(portText)) {
          Integer port = null;
          try {
            port = Integer.parseInt(portText);
          } catch (NumberFormatException e) {
            LOG.warn(
                "Ignoring bad port number for "
                    + portName
                    + " value '"
                    + portText
                    + "' in PID: "
                    + Constants.PORTS_PID);
          }
          if (port != null) {
            sortedInternalPorts.put(port, portName);
            internalPorts.put(portName, port);
            exposedPorts.put(portText + "/tcp", emptyMap);
          } else {
            LOG.info("No port for " + portName);
          }
        }
      }

      String dockerHost = dockerFactory.getDockerHost();
      jolokiaUrl = null;

      Map<String, String> javaContainerConfig =
          Profiles.getOverlayConfiguration(
              service, profileIds, versionId, Constants.JAVA_CONTAINER_PID);
      JavaContainerConfig javaConfig = new JavaContainerConfig();
      getConfigurer().configure(javaContainerConfig, javaConfig);

      boolean isJavaContainer = ChildContainers.isJavaContainer(getFabricService(), options);

      // lets create the ports in sorted order
      for (Map.Entry<Integer, String> entry : sortedInternalPorts.entrySet()) {
        Integer port = entry.getKey();
        String portName = entry.getValue();
        int externalPort = createExternalPort(containerId, portName, usedPortByHost, options);
        externalPorts.put(portName, externalPort);
        environmentVariables.put("FABRIC8_" + portName + "_PORT", "" + port);
        environmentVariables.put("FABRIC8_" + portName + "_PROXY_PORT", "" + externalPort);

        if (portName.equals(JolokiaAgentHelper.JOLOKIA_PORT_NAME)) {
          jolokiaUrl = "http://" + dockerHost + ":" + externalPort + "/jolokia/";
          LOG.info("Found Jolokia URL: " + jolokiaUrl);

          JolokiaAgentHelper.substituteEnvironmentVariables(
              javaConfig,
              environmentVariables,
              isJavaContainer,
              JolokiaAgentHelper.getJolokiaPortOverride(port),
              JolokiaAgentHelper.getJolokiaAgentIdOverride(getFabricService().getEnvironment()));
        } else {
          JolokiaAgentHelper.substituteEnvironmentVariables(
              javaConfig,
              environmentVariables,
              isJavaContainer,
              JolokiaAgentHelper.getJolokiaAgentIdOverride(getFabricService().getEnvironment()));
        }
      }
      javaConfig.updateEnvironmentVariables(environmentVariables, isJavaContainer);

      LOG.info("Passing in manual ip: " + dockerHost);
      environmentVariables.put(EnvironmentVariables.FABRIC8_MANUALIP, dockerHost);
      if (container != null) {
        container.setManualIp(dockerHost);
      }
      if (!environmentVariables.containsKey(EnvironmentVariables.FABRIC8_LISTEN_ADDRESS)) {
        environmentVariables.put(EnvironmentVariables.FABRIC8_LISTEN_ADDRESS, dockerHost);
      }
      environmentVariables.put(EnvironmentVariables.FABRIC8_GLOBAL_RESOLVER, ZkDefs.MANUAL_IP);
      environmentVariables.put(
          EnvironmentVariables.FABRIC8_FABRIC_ENVIRONMENT, DockerConstants.SCHEME);

      // now the environment variables are all set lets see if we need to make a custom image
      String libDir = configOverlayDockerProvider.getJavaLibraryPath();
      String deployDir = configOverlayDockerProvider.getJavaDeployPath();
      String homeDir = configOverlayDockerProvider.getHomePath();
      if (Strings.isNotBlank(libDir) || Strings.isNotBlank(deployDir)) {
        if (container != null) {
          container.setProvisionResult("preparing");
          container.setAlive(true);
        }
        String imageRepository = configOverlayDockerProvider.getImageRepository();
        String entryPoint = configOverlayDockerProvider.getImageEntryPoint();
        List<String> names = new ArrayList<String>(profileIds);
        names.add(versionId);
        String newImageName = "fabric8-" + Strings.join(names, "-").replace('.', '-');
        String customImageUserName = configOverlayDockerProvider.getCustomImageUserName();

        DockerProviderConfig currentContainerDockerProviderConfig = null;
        Container currentContainer = service.getCurrentContainer();
        if (currentContainer != null) {
          Map<String, String> configuration =
              currentContainer
                  .getOverlayProfile()
                  .getConfiguration(DockerConstants.DOCKER_PROVIDER_PID);
          if (configuration != null && !configuration.isEmpty()) {
            Map<String, Map<String, String>> configurations = new HashMap<>();
            configurations.put(DockerConstants.DOCKER_PROVIDER_PID, configuration);
            service.substituteConfigurations(configurations);
            configuration = configurations.get(DockerConstants.DOCKER_PROVIDER_PID);
            configuration =
                JolokiaAgentHelper.substituteEnvironmentVariableExpressionKeysAndValues(
                    configuration, System.getenv());
            currentContainerDockerProviderConfig = createDockerProviderConfig(configuration);
          }
        }
        if (Strings.isNullOrBlank(customImageUserName)
            && currentContainerDockerProviderConfig != null) {
          customImageUserName = currentContainerDockerProviderConfig.getCustomImageUserName();
        }
        Boolean customImagePushValue = configOverlayDockerProvider.getCustomImagePush();
        if (customImagePushValue == null && currentContainerDockerProviderConfig != null) {
          customImagePushValue = currentContainerDockerProviderConfig.getCustomImagePush();
        }
        boolean customImagePush =
            customImagePushValue != null && customImagePushValue.booleanValue();
        if (Strings.isNotBlank(customImageUserName)) {
          newImageName = customImageUserName + "/" + newImageName;
        } else {
          customImagePush = false;
        }

        CustomDockerContainerImageBuilder builder = new CustomDockerContainerImageBuilder();
        CustomDockerContainerImageOptions customDockerContainerImageOptions =
            new CustomDockerContainerImageOptions(
                image,
                imageRepository,
                newImageName,
                libDir,
                deployDir,
                homeDir,
                entryPoint,
                configOverlayDockerProvider.getOverlayFolder(),
                configOverlayDockerProvider.isMavenJavaLibraryPathLayout());

        String actualImage =
            builder.generateContainerImage(
                service,
                container,
                profileOverlays,
                docker,
                customDockerContainerImageOptions,
                options,
                downloadExecutor,
                environmentVariables);
        if (actualImage != null) {
          containerConfig.setImage(actualImage);

          if (customImagePush) {
            LOG.info(
                "Pushing image to repository " + newImageName + " actualImage: " + actualImage);
            Auth authConfig = new Auth();
            authConfig.setEmail("*****@*****.**");
            authConfig.setUsername(service.getZooKeeperUser());
            authConfig.setPassword(service.getZookeeperPassword());
            try {
              docker.imagePush(newImageName, "latest", authConfig);
              LOG.info("Image pushed to repository " + newImageName);
            } catch (Exception e) {
              LOG.info(
                  "Failed to push image " + newImageName + ": " + e + Dockers.dockerErrorMessage(e),
                  e);
              throw e;
            }
          }
        }
      }

      JolokiaAgentHelper.substituteEnvironmentVariableExpressions(
          environmentVariables, environmentVariables, service, curatorOptional, false);

      List<String> env = containerConfig.getEnv();
      if (env == null) {
        env = new ArrayList<>();
      }
      Dockers.addEnvironmentVariablesToList(env, environmentVariables);
      containerConfig.setExposedPorts(exposedPorts);
      containerConfig.setEnv(env);

      String name = options.getName();

      LOG.info(
          "Creating container on docker: "
              + getDockerAddress()
              + " name: "
              + name
              + " env vars: "
              + env);
      LOG.info("Creating container with config: " + containerConfig);
      return this;
    }
  @Test
  public void testRegistryEntries() throws Exception {
    System.out.println(executeCommand("fabric:create -n root"));
    System.out.println(executeCommand("fabric:profile-list"));

    ServiceProxy<FabricService> fabricProxy =
        ServiceProxy.createServiceProxy(bundleContext, FabricService.class);
    try {
      FabricService fabricService = fabricProxy.getService();
      CuratorFramework curator = fabricService.adapt(CuratorFramework.class);

      Set<ContainerProxy> containers =
          ContainerBuilder.create(fabricProxy, 3)
              .withName("fabric-camel")
              .withProfiles("feature-camel")
              .assertProvisioningResult()
              .build();
      try {
        // We will use the first container as a client and the rest as servers.
        LinkedList<Container> containerList = new LinkedList<Container>(containers);
        Container client = containerList.removeLast();

        LinkedList<Container> servers = new LinkedList<Container>(containerList);

        for (Container c : servers) {
          Profile p = c.getVersion().getProfile("example-camel-cluster.server");
          c.setProfiles(new Profile[] {p});
        }

        Provision.provisioningSuccess(servers, PROVISION_TIMEOUT);

        Profile p = client.getVersion().getProfile("example-camel-cluster.client");
        client.setProfiles(new Profile[] {p});

        Provision.provisioningSuccess(Arrays.asList(new Container[] {client}), PROVISION_TIMEOUT);

        System.out.println(executeCommand("fabric:container-list"));
        System.out.println(executeCommand("fabric:profile-display --overlay fabric-camel-server"));

        // Check that the entries have been properly propagated.
        Assert.assertNotNull(exists(curator, "/fabric/registry/camel/endpoints"));
        Assert.assertEquals(1, getChildren(curator, "/fabric/registry/camel/endpoints").size());

        Assert.assertTrue(
            Provision.waitForCondition(
                Arrays.asList(client),
                new ContainerCondition() {
                  @Override
                  public Boolean checkConditionOnContainer(final Container c) {
                    return getCompletedExchangesCount(c) > 0;
                  }
                },
                60000L));

        // We want to kill all but one server, so we take out the first and keep it to the end.
        Container lastActiveServerContainer = servers.removeLast();

        for (Container c : servers) {
          try {
            c.destroy(true);
          } catch (Exception ex) {
            // ignore.
          }
          // Get the number of exchanges completed before we kill the server.
          final int completed = getCompletedExchangesCount(client);

          // Ensure that we still have messages flowing
          Assert.assertTrue(
              Provision.waitForCondition(
                  Arrays.asList(client),
                  new ContainerCondition() {
                    @Override
                    public Boolean checkConditionOnContainer(final Container c) {
                      return getCompletedExchangesCount(c) > completed + 3;
                    }
                  },
                  60000L));
        }
        System.out.println(
            new AnsiString(
                    executeCommand(
                        "fabric:container-connect -u admin -p admin "
                            + client.getId()
                            + " camel:route-info fabric-client"))
                .getPlain()
                .toString());
      } finally {
        ContainerBuilder.destroy(containers);
      }
    } finally {
      fabricProxy.close();
    }
  }