Notes:
task.payload.image = "..." // legacy support
task.payload.image = {
    kind:     'index-artifact',
    namespace: ".....",
    artifact: "..."
}
task.payload.image = {
    kind:     'task-artifact',
    taskId: ".....",
    artifact: "..."
}
task.payload.image = {
    kind:     'image-id',
    image:     ".....",
}

task.payload.image = "taskcluster/image-builder"
task.payload.env.INPUT = "<https://...../context.tar.gz>"
task.route = ["index.images.gecko.v1.<branch>.<last revision context folder changed>"]
task.payload.artifacts = {"<the-artifact-name>.tar.gz": {path: "/image.tar.gz", ...}}


class ImageManager {
    downloadImage(url) -> promise for imageId
    pullImage(imageName) -> promise for imageId
    _loadImage(tempFile) -> promise for imageId
    garbageCollect() -> promise for success
}

pullImage(imageName) {
  return this._ready = Promise.resolve(this._ready).catch(err => {}).then(async () => {
    if (!this._imageNames[imageName]) {
      this._imageNames[imageName] = await this.dockerConnection.pull(imageName).id;
    }
    return this._imageNames[imageName];
  });
}

downloadImage(url) {
  if (!this._imageUrls[url]) {
    this._imageUrls[url] = (async() => {
      var id = slugid.v4();
      await requst.get(url).magic().tarstream(assign id overwriting any existing tag).to.temp(file);
      await this._loadImage(url);
      return id;
    })();
  }
  return this._imageUrls[url];
}

_loadImage(tempFile) {
  return this._ready = Promise.resolve(this._ready).catch(err => {}).then(async () => {
    return this.dockerConnection.load(tempfilename);
  });
}



ensureImage({source, type}) {
  return this._lastImageEnsured = Promise.resolve(this._lastImageEnsured.catch(() => {})).then(async () => {
    if (!this._imagesLoaded[type + source]) {
      if (type === 'url') {
        var id = slugid.v4();
        await request.get(source).to.file(...).with.retries().pipe(tarStream);
        await this.dockerConnection.load(tempfilename);
        await fs.rmfile(tempfilename);
        this._imagesLoaded[type + source] = id;
      } else {
        var image = await this.dockerConnection.pull(imageName);
        this._imagesLoaded[type + source] = image.id;
      }
    }
    return this._imagesLoaded[type + source];
  });
}