fetch_from_npm.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. from __future__ import print_function
  2. from future.utils import raise_
  3. import os
  4. import sys
  5. import time
  6. import logging
  7. import argparse
  8. import hashlib
  9. import base64
  10. import sky
  11. import fetch_from
  12. NPM_BASEURL = "http://npm.yandex-team.ru"
  13. def parse_args():
  14. parser = argparse.ArgumentParser()
  15. fetch_from.add_common_arguments(parser)
  16. parser.add_argument("--tarball-url", required=True)
  17. parser.add_argument("--sky-id", required=True)
  18. parser.add_argument("--integrity", required=True)
  19. parser.add_argument("--integrity-algorithm", required=True)
  20. return parser.parse_args()
  21. def fetch(tarball_url, sky_id, integrity, integrity_algorithm, file_name, tries=5):
  22. """
  23. :param name: package name
  24. :type name: str
  25. :param version: package version
  26. :type version: str
  27. :param sky_id: sky id of tarball
  28. :type sky_id: str
  29. :param integrity: tarball integrity (hex)
  30. :type integrity: str
  31. :param integrity_algorithm: integrity algorithm (known for openssl)
  32. :type integrity_algorithm: str
  33. :param tries: tries count
  34. :type tries: int
  35. :return: path to fetched file
  36. :rtype: str
  37. """
  38. # if sky.is_avaliable() and 'NOTS_FETCH_FROM_HTTP_ONLY' not in os.environ:
  39. # fetcher = lambda: sky.fetch(sky_id, file_name)
  40. # else:
  41. # Отключаем походы через скай
  42. # TODO: https://st.yandex-team.ru/FBP-351
  43. if 'NOTS_FETCH_FROM_SKY' in os.environ and sky.is_avaliable():
  44. fetcher = lambda: sky.fetch(sky_id, file_name)
  45. else:
  46. fetcher = lambda: _fetch_via_http(tarball_url, integrity, integrity_algorithm, file_name)
  47. fetched_file = None
  48. exc_info = None
  49. for i in range(0, tries):
  50. try:
  51. fetched_file = fetcher()
  52. exc_info = None
  53. break
  54. except Exception as e:
  55. logging.exception(e)
  56. exc_info = exc_info or sys.exc_info()
  57. time.sleep(i)
  58. if exc_info:
  59. raise_(exc_info[0], exc_info[1], exc_info[2])
  60. return fetched_file
  61. def _fetch_via_http(tarball_url, integrity, integrity_algorithm, file_name):
  62. is_abs_url = tarball_url.startswith("https://") or tarball_url.startswith("http://")
  63. url_delim = "" if tarball_url.startswith("/") else "/"
  64. url = tarball_url if is_abs_url else NPM_BASEURL + url_delim + tarball_url
  65. hashobj = hashlib.new(integrity_algorithm)
  66. fetched_file = fetch_from.fetch_url(url, False, file_name, tries=1, writers=[hashobj.update])
  67. checksum = base64.b64encode(hashobj.digest()).decode('utf-8')
  68. if checksum != integrity:
  69. raise fetch_from.BadChecksumFetchError("Expected {}, but got {} for {}".format(
  70. integrity,
  71. checksum,
  72. file_name,
  73. ))
  74. return fetched_file
  75. def main(args):
  76. file_name = os.path.basename(args.copy_to)
  77. fetched_file = fetch(args.tarball_url, args.sky_id, args.integrity, args.integrity_algorithm, file_name)
  78. fetch_from.process(fetched_file, file_name, args)
  79. if __name__ == "__main__":
  80. args = parse_args()
  81. fetch_from.setup_logging(args, os.path.basename(__file__))
  82. try:
  83. main(args)
  84. except Exception as e:
  85. logging.exception(e)
  86. print(open(args.abs_log_path).read(), file=sys.stderr)
  87. sys.stderr.flush()
  88. import error
  89. sys.exit(error.ExitCodes.INFRASTRUCTURE_ERROR if fetch_from.is_temporary(e) else 1)