@Override
  public void execute(AbstractBuild build, ConsoleLogger console)
      throws DockerException, AbortException {
    if (!StringUtils.isNotBlank(image)) {
      throw new IllegalArgumentException("Image name must be provided");
    }

    // Don't include tag in the image name. Docker daemon can't handle it.
    // put tag in query string parameter.
    String imageRes =
        CommandUtils.imageFullNameFrom(
            Resolver.buildVar(build, registry), Resolver.buildVar(build, image), null);

    console.logInfo("Pushing image " + imageRes);
    DockerClient client = getClient(build, getAuthConfig(build.getParent()));
    PushImageCmd pushImageCmd =
        client.pushImageCmd(imageRes).withTag(Resolver.buildVar(build, tag));

    InputStream inputStream = pushImageCmd.exec();
    CommandUtils.logCommandResult(
        inputStream, console, "Failed to parse docker response when push image");

    // Why the code doesn't verify now if the image has been pushed to the
    // registry/repository:
    // 1. search image command doesn't support auth yet, so there is no way to
    //    see if images have been pushed successfully by examining the repository,
    //    if the repository is a private one.
    // 2. If the registry is a private one, it is not searchable, because docker
    //    search is for docker hub only.
    // 3. Even if the docker hub repository is public, I am not sure how fast
    //    that docker hub will index the newly pushed image and make it searchable.
    //
    // Another option to verify is to do a pull after push.
    // But since the image is already available locally when you do a push,
    // a pull isn't a very good idea (let's say the image in the repository
    // is stale and you want to update it by a push,
    // but the push for some reason failed but the InputStream returned by push
    // command doesn't show any error. If you do a pull now, and if the pull succeeds,
    // you will override your local fresh image with a stale version.

    console.logInfo("Done pushing image " + imageRes);
  }
  @Override
  public void execute(@SuppressWarnings("rawtypes") AbstractBuild build, ConsoleLogger console)
      throws DockerException {
    if (containerIds == null || containerIds.isEmpty()) {
      throw new IllegalArgumentException("At least one parameter is required");
    }

    String containerIdsRes = Resolver.buildVar(build, containerIds);

    List<String> ids = Arrays.asList(containerIdsRes.split(","));
    DockerClient client = getClient(build, null);
    for (String id : ids) {
      id = id.trim();
      client.killContainerCmd(id).exec();
      console.logInfo("killed container id " + id);
    }
  }
  @Override
  public void execute(@SuppressWarnings("rawtypes") AbstractBuild build, ConsoleLogger console)
      throws DockerException, AbortException {
    // TODO check it when submitting the form
    if (containerId == null || containerId.isEmpty()) {
      throw new IllegalArgumentException("At least one parameter is required");
    }

    String containerIdRes = Resolver.buildVar(build, containerId);

    CommitConfig cfg = new CommitConfig(containerIdRes);
    cfg.setRepo(repo);
    cfg.setTag(tag);
    cfg.setRun(runCmd);
    String imageId = getClient().commit(cfg);

    console.logInfo("Container " + containerIdRes + " commited as image " + imageId);
  }