#!/usr/bin/python
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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.

import json
import subprocess
import os
import shutil
from tempfile import mkdtemp

ALL_BUILD_OPTIONS_JOB = "all-build-options-ub1604"
JENKINS_IMPALA_IO = "jenkins.impala.io"
M2_ARCHIVE_NAME = "m2_archive.tar.gz"


class JenkinsBuild(object):
  """
  Basic information about a Jenkins build (number, url) to allow retrieving
  more detailed information.
  """
  def __init__(self, number, url):
    self.number = number
    self.url = url


class JenkinsBuildDetails(object):
  """
  Detailed information about the parameters and artifacts for a particular
  Jenkins build.
  """
  def __init__(self, parameter_dict, artifact_dict):
    self.parameter_dict = parameter_dict
    self.artifact_dict = artifact_dict


def get_build_list(jenkins_server, job):
  """
  Get the list of recent builds for the specified job on the jenkins server.
  This returns a list of JenkinsBuild objects containing the build numbers
  and corresponding urls.
  """
  # Make a temporary directory
  tmpdir = mkdtemp()

  json_dict = {}
  try:
    # This uses Jenkin's JSON API to get the list of build numbers for this job
    # along with the URL to each build. This downloads the JSON to a temporary file
    # and reads it back. This uses wget to avoid any python dependencies.
    json_url_tmpl = "https://{0}/job/{1}/api/json?tree=builds[number,url]&pretty=true"
    json_url = json_url_tmpl.format(jenkins_server, job)
    json_filename = os.path.join(tmpdir, "job_{0}_build_list.json".format(job))
    subprocess.check_call(["wget", "-q", json_url, "-O", json_filename])
    # Open the JSON file
    with open(json_filename) as f:
      json_dict = json.load(f)
  finally:
    # Cleanup temporary directory
    shutil.rmtree(tmpdir)

  # Convert the JSON dictionaries to JenkinsBuild objects
  builds = []
  for build_info in json_dict["builds"]:
    builds.append(JenkinsBuild(build_info["number"], build_info["url"]))

  return builds


def get_build_details(build):
  """
  Download detailed build information for the build number at the provided URL using
  the Jenkins JSON API. This returns a JenkinsBuildDetails, which includes information
  about the parameters of the Jenkins job and the artifacts produced by the Jenkins job.
  """

  tmpdir = mkdtemp()
  json_dict = {}
  try:
    # This downloads a json job to the temporary directory
    json_url = "{0}/api/json?&pretty=true".format(build.url)
    json_filename = os.path.join(tmpdir, "build_details_{0}.json".format(build.number))
    subprocess.check_call(["wget", "-q", json_url, "-O", json_filename])
    # Parse the JSON file
    json_dict = {}
    with open(json_filename) as f:
      json_dict = json.load(f)
  finally:
    shutil.rmtree(tmpdir)

  # Convert the JSON dictionaries to a JenkinsBuildDetail object
  parameter_dict = {}
  parameter_section = None
  for section in json_dict["actions"]:
    if "parameters" in section:
      parameter_section = section["parameters"]
      break
  for parameter in parameter_section:
    parameter_dict[parameter["name"]] = parameter["value"]

  artifact_dict = {}
  for artifact in json_dict["artifacts"]:
    artifact_url = "{0}/artifact/{1}".format(build.url, artifact["relativePath"])
    artifact_dict[artifact["fileName"]] = artifact_url

  return JenkinsBuildDetails(parameter_dict, artifact_dict)


def get_m2_archive_url(jenkins_server, jenkins_job):
  # Get the JSON list of builds for the all-build-options-ub1604 job. This code
  # is specific to how the Jenkins job is structured (i.e. parameters, archives),
  # so this is not generic.
  build_list = get_build_list(jenkins_server, jenkins_job)

  for build in build_list:
    # Go get more detailed information about the job
    build_details = get_build_details(build)
    # There are two criteria for a valid m2 archive:
    # 1. The build is based on the master branch
    # 2. The build has the appropriate m2 archive artifact
    is_master_build = "IMPALA_REPO_BRANCH" in build_details.parameter_dict and \
        build_details.parameter_dict["IMPALA_REPO_BRANCH"] == "master"
    has_m2_archive = M2_ARCHIVE_NAME in build_details.artifact_dict
    if is_master_build and has_m2_archive:
      return build_details.artifact_dict[M2_ARCHIVE_NAME]

  return None


def download_and_unpack_m2_archive(url, directory):
  print("Downloading m2 archive from {0} to {1}".format(url, directory))
  tarball_name = os.path.basename(url)
  tmp_tarball_location = os.path.join(directory, tarball_name)
  subprocess.check_call(["wget", "-q", url, "-O", tmp_tarball_location])
  m2_directory = os.path.expanduser("~/.m2")
  if not os.path.exists(m2_directory):
    print("{0} does not exist, creating...".format(m2_directory))
    os.makedirs(m2_directory)
  print("Unpacking {0} to {1}".format(tarball_name, m2_directory))
  tar_command = ["tar", "-zxf", tmp_tarball_location]
  # Unpack into m2 directory, but don't overwrite any files
  tar_command.extend(["-C", m2_directory, "--skip-old-files"])
  subprocess.check_call(tar_command)


def main():
  m2_archive_url = get_m2_archive_url(JENKINS_IMPALA_IO, ALL_BUILD_OPTIONS_JOB)
  if not m2_archive_url:
    print("Could not find any m2 archive for {0} {1}".format(JENKINS_IMPALA_IO,
        ALL_BUILD_OPTIONS_JOB))
  tmpdir = mkdtemp()
  try:
    download_and_unpack_m2_archive(m2_archive_url, tmpdir)
  finally:
    shutil.rmtree(tmpdir)


if __name__ == "__main__":
    main()
