<commit_before>// Copyright © 2016 <NAME>. All rights reserved.
// The following code is covered by the AGPL-3.0 license.

const Dockerode = require('dockerode');
const tar = require('tar-stream');
const stream = require('stream');
const stringdecoder = require('string_decoder');
const util = require('util');

const db = require('./db');
const hosts = require('./hosts');
const log = require('./log');

// Get client access to a given Docker host.
function getDocker (hostname, callback) {
  const host = hosts.get(hostname);
  if (!host) {
    callback(new Error('Unknown Docker host: ' + hostname));
    return;
  }

  const { ca, client } = db.get('tls');
  const docker = new Dockerode({
    protocol: 'https',
    host: hostname,
    port: Number(host.properties.port),
    ca: host.properties.ca || ca.crt,
    cert: host.properties.cert || host.properties.crt || client.crt,
    key: host.properties.key || client.key
  });

  callback(null, docker);
}

// Build a Docker image from a given Dockerfile.
exports.buildImage = function (parameters, callback) {
  const { host, tag, dockerfile } = parameters;

  getDocker(host, (error, docker) => {
    if (error) {
      callback(error);
      return;
    }

    // Add the Dockerfile to a tar stream for Docker's Remote API.
    const pack = tar.pack();
    pack.entry({ name: 'Dockerfile' }, dockerfile);
    pack.finalize();

    // FIXME: If `docker.buildImage()` ever supports streams, use the tar stream
    // directly instead of flushing it into a Buffer.
    const chunks = [];
    pack.on('data', chunk => { chunks.push(chunk); });
    pack.on('end', () => {
      const buffer = Buffer.concat(chunks);
      const options = {
        t: tag,
        nocache: true
      };

      docker.buildImage(buffer, options, (error, response) => {
        if (error) {
          callback(error);
          return;
        }

        // Transform Docker's response into a proper Node.js Stream.
        const dockerResponse = new DockerResponse();
        response.pipe(dockerResponse);

        callback(null, dockerResponse);
      });
    });
  });
};

// Delete a Docker image from a given host.
exports.removeImage = function (parameters, callback) {
  let { host, image: imageId } = parameters;

  getDocker(host, (error, docker) => {
    if (error) {
      callback(error);
      return;
    }

    const image = docker.getImage(imageId);
    image.remove((error, data) => {
      callback(error);
    });
  });
};

// Spawn a new Docker container from a given image.
exports.runContainer = function (parameters, callback) {
  const { host, image, ports } = parameters;

  getDocker(host, (error, docker) => {
    if (error) {
      callback(error);
      return;
    }
<commit_msg>Support pulling and tagging images on remote Docker hosts.<commit_after>// Copyright © 2016 <NAME>. All rights reserved.
// The following code is covered by the AGPL-3.0 license.

const Dockerode = require('dockerode');
const tar = require('tar-stream');
const stream = require('stream');
const stringdecoder = require('string_decoder');
const util = require('util');

const db = require('./db');
const hosts = require('./hosts');
const log = require('./log');

// Get client access to a given Docker host.
function getDocker (hostname, callback) {
  const host = hosts.get(hostname);
  if (!host) {
    callback(new Error('Unknown Docker host: ' + hostname));
    return;
  }

  const { ca, client } = db.get('tls');
  const docker = new Dockerode({
    protocol: 'https',
    host: hostname,
    port: Number(host.properties.port),
    ca: host.properties.ca || ca.crt,
    cert: host.properties.cert || host.properties.crt || client.crt,
    key: host.properties.key || client.key
  });

  callback(null, docker);
}

// Build a Docker image from a given Dockerfile.
exports.buildImage = function (parameters, callback) {
  const { host, tag, dockerfile } = parameters;

  getDocker(host, (error, docker) => {
    if (error) {
      callback(error);
      return;
    }

    // Add the Dockerfile to a tar stream for Docker's Remote API.
    const pack = tar.pack();
    pack.entry({ name: 'Dockerfile' }, dockerfile);
    pack.finalize();

    // FIXME: If `docker.buildImage()` ever supports streams, use the tar stream
    // directly instead of flushing it into a Buffer.
    const chunks = [];
    pack.on('data', chunk => { chunks.push(chunk); });
    pack.on('end', () => {
      const buffer = Buffer.concat(chunks);
      const options = {
        t: tag,
        nocache: true
      };

      docker.buildImage(buffer, options, (error, response) => {
        if (error) {
          callback(error);
          return;
        }

        // Transform Docker's response into a proper Node.js Stream.
        const dockerResponse = new DockerResponse();
        response.pipe(dockerResponse);

        callback(null, dockerResponse);
      });
    });
  });
};

// Pull a Docker image into a given host.
exports.pullImage = function (parameters, callback) {
  const { host, image: imageId } = parameters;

  getDocker(host, (error, docker) => {
    if (error) {
      callback(error);
      return;
    }

    docker.pull(imageId, function (error, stream) {
      if (error) {
        callback(error);
        return;
      }

      callback(null, stream);
    });
  });
};

// Tag a Docker image in a given host.
exports.tagImage = function (parameters, callback) {
  const { host, image: imageId, tag: tagId } = parameters;

  getDocker(host, (error, docker) => {
    if (error) {
      callback(error);
      return;
    }

    const image = docker.getImage(imageId);
    const [ repo, tag = 'latest' ] = tagId.split(':');
    image.tag({ repo, tag }, (error, data) => {
      callback(error);
    });
  });
};

// Delete a Docker image from a given host.
exports.removeImage = function (parameters, callback) {
  const { host, image: imageId } = parameters;

  getDocker(host, (error, docker) => {
    if (error) {
      callback(error);
      return;
    }

    const image = docker.getImage(imageId);
    image.remove((error, data) => {
      callback(error);
    });
  });
};

// Spawn a new Docker container from a given image.
exports.runContainer = function (parameters, callback) {
  const { host, image, ports } = parameters;

  getDocker(host, (error, docker) => {
    if (error) {
      callback(error);
      return;
    }

{'fraction_non_alphanumeric': 0.1439299123904881, 'fraction_numerical': 0.0018773466833541927, 'mean_word_length': 2.7963182897862233, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '173946', 'n_tokens_mistral': 1975, 'n_tokens_neox': 1871, 'n_words': 570}