fetch_from_npm.py 3.2 KB

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