LYPackage_S3Downloader.cmake 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #
  2. # Copyright (c) Contributors to the Open 3D Engine Project.
  3. # For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. #
  5. # SPDX-License-Identifier: Apache-2.0 OR MIT
  6. #
  7. include_guard()
  8. # You can download files from S3 if you use a url like s3:// instead of https://
  9. # in order for this to work, 'aws' CLI must be on your command line PATH, or you
  10. # can set LY_AWS_COMMAND to override the searching on your path and specify manually.
  11. # Note: it must be a real executable, not a script!
  12. # see: https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html
  13. set(LY_AWS_COMMAND "" CACHE FILEPATH
  14. "Overrides the location of the 'aws' program, leave blank to search the path for 'aws'. You can also use LY_AWS_COMMAND environment variable.")
  15. # You must have the appropriate credentials for it to actually function
  16. # see: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html
  17. # to configure which credentials to use, you can either set the machine environment var
  18. # LY_AWS_PROFILE, which would only apply to this script,
  19. # or, AWS_PROFILE, which would apply to other Amazon tools as well, or you can use the LY_AWS_PROFILE
  20. # CMake variable instead which would override the above two.
  21. # Specifying no profile will cause it to run the 'aws' command with no profile argument.
  22. # note that we leave it blank unless specified, so that the 'default' above doesn't actually
  23. # save / overwrite the environment until the user explicitly sets it.
  24. set(LY_AWS_PROFILE "" CACHE STRING
  25. "Profile to use for 'aws' CLI. Blank means do not use a profile. You can also use LY_AWS_PROFILE or AWS_PROFILE environment variables.")
  26. if (LY_AWS_PROFILE)
  27. ly_set(LY_PACKAGE_AWS_PROFILE_COMMAND "--profile" ${LY_AWS_PROFILE})
  28. elseif (DEFINED ENV{LY_AWS_PROFILE}) # if the CMake var isn't set (from the above cache), try the environment.
  29. ly_set(LY_PACKAGE_AWS_PROFILE_COMMAND "--profile" $ENV{LY_AWS_PROFILE})
  30. elseif (DEFINED ENV{AWS_PROFILE})
  31. ly_set(LY_PACKAGE_AWS_PROFILE_COMMAND "--profile" $ENV{AWS_PROFILE})
  32. endif()
  33. # not a cache variable, but a tweakable. We can use really short-lived credentials
  34. # and urls becuase we intend to presign and then immediately fetch.
  35. ly_set(LY_PACKAGE_PRESIGN_URL_EXPIRATION_TIME 120)
  36. # ly_is_s3_url
  37. # if the given URL is a s3 url of thr form "s3://(stuff)" then sets
  38. # the output_variable_name to TRUE otherwise unsets it.
  39. function (ly_is_s3_url download_url output_variable_name)
  40. if ("${download_url}" MATCHES "s3://.*")
  41. set(${output_variable_name} TRUE PARENT_SCOPE)
  42. else()
  43. unset(${output_variable_name} PARENT_SCOPE)
  44. endif()
  45. endfunction()
  46. # values set on command line or in cache override env.
  47. # however, we dont want to cache the path in case the env var changes:
  48. if (NOT LY_AWS_COMMAND)
  49. if (DEFINED ENV{LY_AWS_COMMAND})
  50. ly_set(LY_AWS_COMMAND $ENV{LY_AWS_COMMAND})
  51. else()
  52. find_program(LY_AWS_COMMAND_FIND "aws")
  53. if (NOT "${LY_AWS_COMMAND_FIND}" STREQUAL "LY_AWS_COMMAND_FIND-NOTFOUND")
  54. ly_set(LY_AWS_COMMAND ${LY_AWS_COMMAND_FIND})
  55. endif()
  56. unset(LY_AWS_COMMAND_FIND CACHE)
  57. endif()
  58. endif()
  59. # ly_s3_download
  60. # uses AWS CLI to pre-sign a s3://(bucket)/(object-key) url and turn it into a full https url.
  61. # then downloads the file using that url.
  62. # returns the download status object (which is a tuple of code;message)
  63. # just like file(DOWNLOAD ... does)
  64. function(ly_s3_download download_url download_target output_variable_name)
  65. if (NOT LY_AWS_COMMAND)
  66. set(${output_variable_name} "1;Cannot find the 'aws' CLI installed, either configure its location in cmake GUI, set LY_AWS_COMMAND or add it to your PATH." PARENT_SCOPE)
  67. message(FATAL_ERROR "Unable to get a required package from an s3 bucket - Cannot find the 'aws' CLI installed, either configure its location in cmake GUI, set LY_AWS_COMMAND or add it to your PATH.")
  68. return()
  69. endif()
  70. set(COMMAND_TO_RUN ${LY_AWS_COMMAND} "s3" "presign" ${download_url} --expires-in ${LY_PACKAGE_PRESIGN_URL_EXPIRATION_TIME} ${LY_PACKAGE_AWS_PROFILE_COMMAND})
  71. execute_process(COMMAND ${COMMAND_TO_RUN}
  72. RESULT_VARIABLE PRESIGN_RESULT
  73. ERROR_VARIABLE PRESIGN_ERRORS
  74. OUTPUT_VARIABLE SIGNED_URL
  75. OUTPUT_STRIP_TRAILING_WHITESPACE # the aws command can result in whitespace, trim it
  76. ERROR_STRIP_TRAILING_WHITESPACE
  77. )
  78. if (NOT ${PRESIGN_RESULT} EQUAL 0)
  79. # note that presign works even on non-existent URLS. It does not check
  80. # to see if the file is actually present or whether you have permission to pre-sign.
  81. # So the cause for pre-signing to fail are generally to do with your configuration of the
  82. # 'aws' command itself being wrong (ie, it doesn't exist, its not a real executable,
  83. # you specified a profile which does not exist, etc.)
  84. set(${output_variable_name} "1;Failed To use the AWS CLI to pre-sign: "
  85. "ERRORS: ${PRESIGN_ERRORS}\n"
  86. "Returned for: ${download_url}\n"
  87. "Make sure the AWS CLI is v2, and aws is available on your PATH. "
  88. "Alternatively, set LY_AWS_COMMAND in cmake or your environment to "
  89. "point at a valid AWS CLI." PARENT_SCOPE)
  90. return()
  91. endif()
  92. file(DOWNLOAD ${SIGNED_URL} ${download_target} STATUS result_status TLS_VERIFY ON LOG log)
  93. set(${output_variable_name} ${result_status} ${log} PARENT_SCOPE)
  94. endfunction()