# Copyright 2016 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 package manipulates OCI image configuration metadata."""
from collections import namedtuple
import copy
import json
import os
import os.path
import sys

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

gflags.DEFINE_string('base', None, 'The parent image')

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

gflags.DEFINE_multistring('layer', [],
                          'Layer sha256 hashes that make up this image')

gflags.DEFINE_list('entrypoint', None,
                   'Override the "Entrypoint" of the previous image')

gflags.DEFINE_list('command', None, 'Override the "Cmd" of the previous image')

gflags.DEFINE_string('user', None, 'The username to run commands under')

gflags.DEFINE_list('labels', None, 'Augment the "Label" of the previous image')

gflags.DEFINE_list('ports', None,
                   'Augment the "ExposedPorts" of the previous image')

gflags.DEFINE_list('volumes', None,
                   'Augment the "Volumes" of the previous image')

gflags.DEFINE_string('workdir', None, 'Set the working directory for the image')

gflags.DEFINE_list('env', None, 'Augment the "Env" of the previous image')

FLAGS = gflags.FLAGS

_ConfigOptionsT = namedtuple('ConfigOptionsT', ['layers', 'entrypoint', 'cmd',
                                                'env', 'labels', 'ports',
                                                'volumes', 'workdir', 'user'])


class ConfigOptions(_ConfigOptionsT):
  """Docker image configuration options."""

  def __new__(cls,
              layers=None,
              entrypoint=None,
              cmd=None,
              user=None,
              labels=None,
              env=None,
              ports=None,
              volumes=None,
              workdir=None):
    """Constructor."""
    return super(ConfigOptions, cls).__new__(cls,
                                             layers=layers,
                                             entrypoint=entrypoint,
                                             cmd=cmd,
                                             user=user,
                                             labels=labels,
                                             env=env,
                                             ports=ports,
                                             volumes=volumes,
                                             workdir=workdir)

_PROCESSOR_ARCHITECTURE = 'amd64'

_OPERATING_SYSTEM = 'linux'


def Resolve(value, environment):
  """Resolves environment variables embedded in the given value."""
  outer_env = os.environ
  try:
    os.environ = environment
    return os.path.expandvars(value)
  finally:
    os.environ = outer_env


def DeepCopySkipNull(data):
  """Do a deep copy, skipping null entry."""
  if isinstance(data, dict):
    return dict((DeepCopySkipNull(k), DeepCopySkipNull(v))
                for k, v in data.items() if v is not None)
  return copy.deepcopy(data)


def KeyValueToDict(pair):
  """Converts an iterable object of key=value pairs to dictionary."""
  d = dict()
  for kv in pair:
    (k, v) = kv.split('=', 1)
    d[k] = v
  return d


def CreateImageConfig(data, options):
  """Create an image config possibly based on an existing one.

  Args:
    data: A dict of Docker image config to base on top of.
    options: Options specific to this image which will be merged with any
             existing data

  Returns:
    Image config for the new image
  """
  defaults = DeepCopySkipNull(data)

  # dont propagate non-spec keys
  output = dict()
  output['created'] = '0001-01-01T00:00:00Z'
  output['author'] = 'Bazel'
  output['architecture'] = _PROCESSOR_ARCHITECTURE
  output['os'] = _OPERATING_SYSTEM

  output['config'] = defaults.get('config', {})

  if options.entrypoint:
    output['config']['Entrypoint'] = options.entrypoint
  if options.cmd:
    output['config']['Cmd'] = options.cmd
  if options.user:
    output['config']['User'] = options.user

  def Dict2ConfigValue(d):
    return ['%s=%s' % (k, d[k]) for k in sorted(d.keys())]

  if options.env:
    # Build a dictionary of existing environment variables (used by Resolve).
    environ_dict = KeyValueToDict(output['config'].get('Env', []))
    # Merge in new environment variables, resolving references.
    for k, v in options.env.items():
      # Resolve handles scenarios like "PATH=$PATH:...".
      environ_dict[k] = Resolve(v, environ_dict)
    output['config']['Env'] = Dict2ConfigValue(environ_dict)

  # TODO(babel-team) Label is currently docker specific
  if options.labels:
    label_dict = KeyValueToDict(output['config'].get('Label', []))
    for k, v in options.labels.items():
      label_dict[k] = v
    output['config']['Label'] = Dict2ConfigValue(label_dict)

  if options.ports:
    if 'ExposedPorts' not in output['config']:
      output['config']['ExposedPorts'] = {}
    for p in options.ports:
      if '/' in p:
        # The port spec has the form 80/tcp, 1234/udp
        # so we simply use it as the key.
        output['config']['ExposedPorts'][p] = {}
      else:
        # Assume tcp
        output['config']['ExposedPorts'][p + '/tcp'] = {}

  if options.volumes:
    if 'Volumes' not in output['config']:
      output['config']['Volumes'] = {}
    for p in options.volumes:
      output['config']['Volumes'][p] = {}

  if options.workdir:
    output['config']['WorkingDir'] = options.workdir

  # diff_ids are ordered from bottom-most to top-most
  diff_ids = defaults.get('rootfs', {}).get('diff_ids', [])
  layers = options.layers if options.layers else []
  diff_ids += ['sha256:%s' % l for l in layers]
  output['rootfs'] = {
      'type': 'layers',
      'diff_ids': diff_ids,
  }

  # history is ordered from bottom-most layer to top-most layer
  history = defaults.get('history', [])
  # docker only allows the child to have one more history entry than the parent
  history += [{
      'created': '0001-01-01T00:00:00Z',
      'created_by': 'bazel build ...',
      'author': 'Bazel'}]
  output['history'] = history

  return output


def main(unused_argv):
  base_json = '{}'
  manifest = utils.GetLatestManifestFromTar(FLAGS.base)
  if manifest:
    config_file = manifest['Config']
    base_json = utils.GetTarFile(FLAGS.base, config_file)
  data = json.loads(base_json)

  layers = []
  for layer in FLAGS.layer:
    layers.append(utils.ExtractValue(layer))

  labels = KeyValueToDict(FLAGS.labels)
  for label, value in labels.items():
    if value.startswith('@'):
      with open(value[1:], 'r') as f:
        labels[label] = f.read()

  output = CreateImageConfig(data,
                             ConfigOptions(layers=layers,
                                           entrypoint=FLAGS.entrypoint,
                                           cmd=FLAGS.command,
                                           user=FLAGS.user,
                                           labels=labels,
                                           env=KeyValueToDict(FLAGS.env),
                                           ports=FLAGS.ports,
                                           volumes=FLAGS.volumes,
                                           workdir=FLAGS.workdir))

  with open(FLAGS.output, 'w') as fp:
    json.dump(output, fp, sort_keys=True)
    fp.write('\n')


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