# Copyright 2015 The Bazel Authors. All rights reserved.
#
# Licensed 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.
"""This tool creates a docker image from a list of layers."""
# This is the main program to create a docker image. It expect to be run with:
# join_layers --output=output_file \
#             --layer=layer1 [--layer=layer2 ... --layer=layerN] \
#             --id=@identifier \
#             --name=myname --repository=repositoryName
# See the gflags declaration about the flags argument details.

import json
import os.path
import sys

from tools.build_defs.docker import utils
from tools.build_defs.pkg import archive
from third_party.py import gflags

gflags.DEFINE_string('output', None, 'The output file, mandatory')
gflags.MarkFlagAsRequired('output')

gflags.DEFINE_multistring('layer', [], 'The tar files for layers to join.')

gflags.DEFINE_multistring(
    'tags', [],
    'An associative list of fully qualified tag names and the layer they tag. '
    'e.g. ubuntu=deadbeef,gcr.io/blah/debian=baadf00d')

FLAGS = gflags.FLAGS


def _layer_filter(name):
  basename = os.path.basename(name)
  return basename not in ('manifest.json', 'top', 'repositories')


def _add_top(tar, repositories):
  # Don't add 'top' if there are multiple images in this bundle.
  if len(repositories) != 1:
    return

  # Walk the single-item dictionary, and if there is a single tag
  # for the single repository, then emit a 'top' file pointing to
  # the single image in this bundle.
  for (unused_x, tags) in repositories.items():
    if len(tags) != 1:
      continue
    for (unused_y, layer_id) in tags.items():
      tar.add_file('top', content=layer_id)


def _create_image(tar, layers, repositories=None):
  """Creates a Docker image from a list of layers.

  Args:
    tar: archive.TarFileWriter object for the docker image file to create.
    layers: the layers (tar files) to join to the image.
    repositories: the repositories two-level dictionary, which is keyed by
                  repo names at the top-level, and tag names at the second
                  level pointing to layer ids.
  """
  # Compute a map from layer tarball names to the tags that should apply to them
  layers_to_tag = {}
  for repo in repositories:
    tags = repositories[repo]
    for tag in tags:
      layer_name = tags[tag] + '/layer.tar'
      fq_name = '%s:%s' % (repo, tag)
      layer_tags = layers_to_tag.get(layer_name, [])
      layer_tags.append(fq_name)
      layers_to_tag[layer_name] = layer_tags

  manifests = []
  for layer in layers:
    tar.add_tar(layer, name_filter=_layer_filter)
    layer_manifests = utils.GetManifestFromTar(layer)

    # Augment each manifest with any tags that should apply to their top layer.
    for manifest in layer_manifests:
      top_layer = manifest['Layers'][-1]
      manifest['RepoTags'] = list(sorted(set(manifest['RepoTags'] +
                                             layers_to_tag.get(top_layer, []))))

    manifests += layer_manifests

  manifest_content = json.dumps(manifests, sort_keys=True)
  tar.add_file('manifest.json', content=manifest_content)

  # In addition to N layers of the form described above, there might be
  # a single file at the top of the image called repositories.
  # This file contains a JSON blob of the form:
  # {
  #   'repo':{
  #     'tag-name': 'top-most layer hex',
  #     ...
  #   },
  #   ...
  # }
  # This is the exact structure we expect repositories to have.
  if repositories:
    # If the identifier is not provided, then the resulted layer will be
    # created without a 'top' file.  Docker doesn't needs that file nor
    # the repository to load the image and for intermediate layer,
    # docker_build store the name of the layer in a separate artifact so
    # this 'top' file is not needed.
    _add_top(tar, repositories)
    tar.add_file('repositories',
                 content=json.dumps(repositories, sort_keys=True))


def create_image(output, layers, repositories=None):
  """Creates a Docker image from a list of layers.

  Args:
    output: the name of the docker image file to create.
    layers: the layers (tar files) to join to the image.
    repositories: the repositories two-level dictionary, which is keyed by
                  repo names at the top-level, and tag names at the second
                  level pointing to layer ids.
  """
  with archive.TarFileWriter(output) as tar:
    _create_image(tar, layers, repositories)


def resolve_layer(identifier):
  if not identifier:
    # TODO(mattmoor): This should not happen.
    return None

  if not identifier.startswith('@'):
    return identifier

  with open(identifier[1:], 'r') as f:
    return f.read()


def main(unused_argv):
  repositories = {}
  for entry in FLAGS.tags:
    elts = entry.split('=')
    if len(elts) != 2:
      raise Exception('Expected associative list key=value, got: %s' % entry)
    (fq_tag, layer_id) = elts

    tag_parts = fq_tag.rsplit(':', 2)
    if len(tag_parts) != 2:
      raise Exception('Expected fully-qualified tag name (e.g. ubuntu:latest), '
                      'got: %s' % fq_tag)
    (repository, tag) = tag_parts

    others = repositories.get(repository, {})
    others[tag] = resolve_layer(layer_id)
    repositories[repository] = others

  create_image(FLAGS.output, FLAGS.layer, repositories)


if __name__ == '__main__':
  main(FLAGS(sys.argv))
